package org.bitcoinj.core; import org.bitcoinj.params.UnitTestParams; import org.bitcoinj.script.ScriptBuilder; import org.bitcoinj.testing.FakeTxBuilder; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; /** * Just check the Transaction.verify() method. Most methods that have complicated logic in Transaction are tested * elsewhere, e.g. signing and hashing are well exercised by the wallet tests, the full block chain tests and so on. * The verify method is also exercised by the full block chain tests, but it can also be used by API users alone, * so we make sure to cover it here as well. */ public class TransactionTest { private static final NetworkParameters PARAMS = UnitTestParams.get(); private Transaction tx; private Transaction dummy; public static final Address ADDRESS = new ECKey().toAddress(PARAMS); @Before public void setUp() throws Exception { dummy = FakeTxBuilder.createFakeTx(PARAMS, Coin.COIN, ADDRESS); tx = new Transaction(PARAMS); tx.addOutput(Coin.COIN, ADDRESS); tx.addInput(dummy.getOutput(0)); } @Test(expected = VerificationException.EmptyInputsOrOutputs.class) public void emptyOutputs() throws Exception { tx.clearOutputs(); tx.verify(); } @Test(expected = VerificationException.EmptyInputsOrOutputs.class) public void emptyInputs() throws Exception { tx.clearInputs(); tx.verify(); } @Test(expected = VerificationException.LargerThanMaxBlockSize.class) public void tooHuge() throws Exception { tx.addInput(dummy.getOutput(0)).setScriptBytes(new byte[Block.MAX_BLOCK_SIZE]); tx.verify(); } @Test(expected = VerificationException.DuplicatedOutPoint.class) public void duplicateOutPoint() throws Exception { TransactionInput input = tx.getInput(0); input.setScriptBytes(new byte[1]); tx.addInput(input.duplicateDetached()); tx.verify(); } @Test(expected = VerificationException.NegativeValueOutput.class) public void negativeOutput() throws Exception { tx.getOutput(0).setValue(Coin.NEGATIVE_SATOSHI); tx.verify(); } @Test(expected = VerificationException.ExcessiveValue.class) public void exceedsMaxMoney2() throws Exception { Coin half = NetworkParameters.MAX_MONEY.divide(2).add(Coin.SATOSHI); tx.getOutput(0).setValue(half); tx.addOutput(half, ADDRESS); tx.verify(); } @Test(expected = VerificationException.UnexpectedCoinbaseInput.class) public void coinbaseInputInNonCoinbaseTX() throws Exception { tx.addInput(Sha256Hash.ZERO_HASH, 0xFFFFFFFFL, new ScriptBuilder().data(new byte[10]).build()); tx.verify(); } @Test(expected = VerificationException.CoinbaseScriptSizeOutOfRange.class) public void coinbaseScriptSigTooSmall() throws Exception { tx.clearInputs(); tx.addInput(Sha256Hash.ZERO_HASH, 0xFFFFFFFFL, new ScriptBuilder().build()); tx.verify(); } @Test(expected = VerificationException.CoinbaseScriptSizeOutOfRange.class) public void coinbaseScriptSigTooLarge() throws Exception { tx.clearInputs(); TransactionInput input = tx.addInput(Sha256Hash.ZERO_HASH, 0xFFFFFFFFL, new ScriptBuilder().data(new byte[99]).build()); assertEquals(101, input.getScriptBytes().length); tx.verify(); } }