Transaction extends ChildMessage { public void checkCoinBaseHeight(final int height) throws VerificationException { checkArgument(height >= Block.BLOCK_HEIGHT_GENESIS); checkState(isCoinBase()); final TransactionInput in = this.getInputs().get(0); final ScriptBuilder builder = new ScriptBuilder(); builder.number(height); final byte[] expected = builder.build().getProgram(); final byte[] actual = in.getScriptBytes(); if (actual.length < expected.length) { throw new VerificationException.CoinbaseHeightMismatch("Block height mismatch in coinbase."); } for (int scriptIdx = 0; scriptIdx < expected.length; scriptIdx++) { if (actual[scriptIdx] != expected[scriptIdx]) { throw new VerificationException.CoinbaseHeightMismatch("Block height mismatch in coinbase."); } } } Transaction(NetworkParameters params);  Transaction(NetworkParameters params, SpecialTxPayload specialTxPayload);  Transaction(NetworkParameters params, byte[] payloadBytes);  Transaction(NetworkParameters params, byte[] payload, int offset);  Transaction(NetworkParameters params, byte[] payload, int offset, @Nullable Message parent, MessageSerializer setSerializer, int length);  Transaction(NetworkParameters params, byte[] payload, @Nullable Message parent, MessageSerializer setSerializer, int length); @Override Sha256Hash getHash(); String getHashAsString(); Coin getInputSum(); Coin getValueSentToMe(TransactionBag transactionBag); @Nullable Map<Sha256Hash, Integer> getAppearsInHashes(); boolean isPending(); void setBlockAppearance(StoredBlock block, boolean bestChain, int relativityOffset); void addBlockAppearance(final Sha256Hash blockHash, int relativityOffset); Coin getValueSentFromMe(TransactionBag wallet); Coin getOutputSum(); Coin getValue(TransactionBag wallet); Coin getFee(); boolean isAnyOutputSpent(); boolean isEveryOwnedOutputSpent(TransactionBag transactionBag); Date getUpdateTime(); void setUpdateTime(Date updatedAt); int getOptimalEncodingMessageSize(); int getMessageSizeForPriorityCalc(); boolean isCoinBase(); boolean isMature(); @Override String toString(); String toString(@Nullable AbstractBlockChain chain); void clearInputs(); TransactionInput addInput(TransactionOutput from); TransactionInput addInput(TransactionInput input); TransactionInput addInput(Sha256Hash spendTxHash, long outputIndex, Script script); TransactionInput addSignedInput(TransactionOutPoint prevOut, Script scriptPubKey, ECKey sigKey,
                                           SigHash sigHash, boolean anyoneCanPay); TransactionInput addSignedInput(TransactionInput input, Script scriptPubKey, ECKey sigKey,
                                           SigHash sigHash, boolean anyoneCanPay); TransactionInput addSignedInput(TransactionOutPoint prevOut, Script scriptPubKey, ECKey sigKey); TransactionInput addSignedInput(TransactionOutput output, ECKey signingKey); TransactionInput addSignedInput(TransactionOutput output, ECKey signingKey, SigHash sigHash, boolean anyoneCanPay); void clearOutputs(); TransactionOutput addOutput(TransactionOutput to); TransactionOutput addOutput(Coin value, Address address); TransactionOutput addOutput(Coin value, ECKey pubkey); TransactionOutput addOutput(Coin value, Script script); TransactionSignature calculateSignature(int inputIndex, ECKey key,
                                                                byte[] redeemScript,
                                                                SigHash hashType, boolean anyoneCanPay); TransactionSignature calculateSignature(int inputIndex, ECKey key,
                                                                 Script redeemScript,
                                                                 SigHash hashType, boolean anyoneCanPay); Sha256Hash hashForSignature(int inputIndex, byte[] redeemScript,
                                                    SigHash type, boolean anyoneCanPay); Sha256Hash hashForSignature(int inputIndex, Script redeemScript,
                                                    SigHash type, boolean anyoneCanPay); Sha256Hash hashForSignature(int inputIndex, byte[] connectedScript, byte sigHashType); long getLockTime(); void setLockTime(long lockTime); long getVersion(); void setVersion(long version); void setVersionAndType(int versionShort, int type); void setVersionAndType(int versionShort, Type type); int getVersionShort(); Type getType(); void setType(int type); void setType(Type type); String getTypeString(); List<TransactionInput> getInputs(); List<TransactionOutput> getOutputs(); List<TransactionOutput> getWalletOutputs(TransactionBag transactionBag); void shuffleOutputs(); TransactionInput getInput(long index); TransactionOutput getOutput(long index); TransactionConfidence getConfidence(); TransactionConfidence getConfidence(Context context); TransactionConfidence getConfidence(TxConfidenceTable table); boolean hasConfidence(); @Override boolean equals(Object o); @Override int hashCode(); int getSigOpCount(); void checkCoinBaseHeight(final int height); void verify(); boolean isTimeLocked(); boolean hasRelativeLockTime(); boolean isFinal(int height, long blockTimeSeconds); Date estimateLockTime(AbstractBlockChain chain); Purpose getPurpose(); void setPurpose(Purpose purpose); @Nullable ExchangeRate getExchangeRate(); void setExchangeRate(ExchangeRate exchangeRate); String getMemo(); void setMemo(String memo); byte [] getExtraPayload(); SpecialTxPayload getExtraPayloadObject(); void setExtraPayload(byte [] extraPayload); void setExtraPayload(SpecialTxPayload specialTxPayload); boolean isSimple(); static final Comparator<Transaction> SORT_TX_BY_UPDATE_TIME; static final Comparator<Transaction> SORT_TX_BY_HEIGHT; static final int LOCKTIME_THRESHOLD; static final BigInteger LOCKTIME_THRESHOLD_BIG; static final int MAX_STANDARD_TX_SIZE; static final Coin REFERENCE_DEFAULT_MIN_TX_FEE; static final Coin DEFAULT_TX_FEE; static final Coin MIN_NONDUST_OUTPUT; static final int MAX_INITIAL_INPUTS_OUTPUTS_SIZE; static final int MAX_INPUTS_FOR_AUTO_IX; static final byte SIGHASH_ANYONECANPAY_VALUE; }
@Test public void testCoinbaseHeightCheck() throws VerificationException { final byte[] transactionBytes = HEX.decode("01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff4803e09304062f503253482f0403c86d53087ceca141295a00002e522cfabe6d6d7561cf262313da1144026c8f7a43e3899c44f6145f39a36507d36679a8b7006104000000000000000000000001c8704095000000001976a91480ad90d403581fa3bf46086a91b2d9d4125db6c188ac00000000"); final int height = 300000; final Transaction transaction = PARAMS.getDefaultSerializer().makeTransaction(transactionBytes); transaction.checkCoinBaseHeight(height); }
@Test public void testCoinbaseHeightCheckWithDamagedScript() throws VerificationException { final byte[] transactionBytes = HEX.decode( "010000000100000000000000000000000000000000000000000000000000000000" + "00000000ffffffff3b03ae6c0300044bd7031a0400000000522cfabe6d6d0000" + "0000000000b7b8bf0100000068692066726f6d20706f6f6c7365727665726aac" + "1eeeed88ffffffff01e0587597000000001976a91421c0d001728b3feaf11551" + "5b7c135e779e9f442f88ac00000000"); final int height = 224430; final Transaction transaction = PARAMS.getDefaultSerializer().makeTransaction(transactionBytes); transaction.checkCoinBaseHeight(height); }