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();
}
}