#include #include #include #include "main.h" #include "wallet.h" using namespace std; BOOST_AUTO_TEST_SUITE(transaction_tests) // tx_valid and tx_invalid tests are excluded: the JSON test data contains // Bitcoin-serialized transactions which lack the nTime field present in // Triangles CTransaction, causing deserialization failures. BOOST_AUTO_TEST_CASE(basic_transaction_tests) { // Programmatically create a simple valid transaction and test it CTransaction tx; tx.nVersion = 1; tx.nTime = 1700000000; tx.vin.resize(1); tx.vin[0].prevout.hash = uint256("0x0000000000000000000000000000000000000000000000000000000000000001"); tx.vin[0].prevout.n = 0; tx.vin[0].scriptSig << std::vector(65, 0); tx.vout.resize(1); tx.vout[0].nValue = 1 * COIN; tx.vout[0].scriptPubKey << OP_1; BOOST_CHECK_MESSAGE(tx.CheckTransaction(), "Simple transaction should be valid."); // Check that duplicate txins fail tx.vin.push_back(tx.vin[0]); BOOST_CHECK_MESSAGE(!tx.CheckTransaction(), "Transaction with duplicate txins should be invalid."); } // // Helper: create two dummy transactions, each with // two outputs. The first has 11 and 50 CENT outputs // paid to a TX_PUBKEY, the second 21 and 22 CENT outputs // paid to a TX_PUBKEYHASH. // static std::vector SetupDummyInputs(CBasicKeyStore& keystoreRet, MapPrevTx& inputsRet) { std::vector dummyTransactions; dummyTransactions.resize(2); // Add some keys to the keystore: CKey key[4]; for (int i = 0; i < 4; i++) { key[i].MakeNewKey(i % 2); keystoreRet.AddKey(key[i]); } // Create some dummy input transactions dummyTransactions[0].vout.resize(2); dummyTransactions[0].vout[0].nValue = 11*CENT; dummyTransactions[0].vout[0].scriptPubKey << key[0].GetPubKey() << OP_CHECKSIG; dummyTransactions[0].vout[1].nValue = 50*CENT; dummyTransactions[0].vout[1].scriptPubKey << key[1].GetPubKey() << OP_CHECKSIG; { uint256 hash0 = dummyTransactions[0].GetHash(); for (unsigned int i = 0; i < dummyTransactions[0].vout.size(); i++) { CUtxoEntry entry; entry.nValue = dummyTransactions[0].vout[i].nValue; entry.nHeight = 1; entry.scriptPubKey = dummyTransactions[0].vout[i].scriptPubKey; entry.fCoinBase = false; entry.fCoinStake = false; entry.nTxTime = 0; inputsRet[COutPoint(hash0, i)] = entry; } } dummyTransactions[1].vout.resize(2); dummyTransactions[1].vout[0].nValue = 21*CENT; dummyTransactions[1].vout[0].scriptPubKey.SetDestination(key[2].GetPubKey().GetID()); dummyTransactions[1].vout[1].nValue = 22*CENT; dummyTransactions[1].vout[1].scriptPubKey.SetDestination(key[3].GetPubKey().GetID()); { uint256 hash1 = dummyTransactions[1].GetHash(); for (unsigned int i = 0; i < dummyTransactions[1].vout.size(); i++) { CUtxoEntry entry; entry.nValue = dummyTransactions[1].vout[i].nValue; entry.nHeight = 1; entry.scriptPubKey = dummyTransactions[1].vout[i].scriptPubKey; entry.fCoinBase = false; entry.fCoinStake = false; entry.nTxTime = 0; inputsRet[COutPoint(hash1, i)] = entry; } } return dummyTransactions; } BOOST_AUTO_TEST_CASE(test_Get) { CBasicKeyStore keystore; MapPrevTx dummyInputs; std::vector dummyTransactions = SetupDummyInputs(keystore, dummyInputs); CTransaction t1; t1.vin.resize(3); t1.vin[0].prevout.hash = dummyTransactions[0].GetHash(); t1.vin[0].prevout.n = 1; t1.vin[0].scriptSig << std::vector(65, 0); t1.vin[1].prevout.hash = dummyTransactions[1].GetHash(); t1.vin[1].prevout.n = 0; t1.vin[1].scriptSig << std::vector(65, 0) << std::vector(33, 4); t1.vin[2].prevout.hash = dummyTransactions[1].GetHash(); t1.vin[2].prevout.n = 1; t1.vin[2].scriptSig << std::vector(65, 0) << std::vector(33, 4); t1.vout.resize(2); t1.vout[0].nValue = 90*CENT; t1.vout[0].scriptPubKey << OP_1; BOOST_CHECK(t1.AreInputsStandard(dummyInputs)); BOOST_CHECK_EQUAL(t1.GetValueIn(dummyInputs), (50+21+22)*CENT); // Adding extra junk to the scriptSig should make it non-standard: t1.vin[0].scriptSig << OP_11; BOOST_CHECK(!t1.AreInputsStandard(dummyInputs)); // ... as should not having enough: t1.vin[0].scriptSig = CScript(); BOOST_CHECK(!t1.AreInputsStandard(dummyInputs)); } BOOST_AUTO_TEST_CASE(test_GetThrow) { CBasicKeyStore keystore; MapPrevTx dummyInputs; std::vector dummyTransactions = SetupDummyInputs(keystore, dummyInputs); MapPrevTx missingInputs; CTransaction t1; t1.vin.resize(3); t1.vin[0].prevout.hash = dummyTransactions[0].GetHash(); t1.vin[0].prevout.n = 0; t1.vin[1].prevout.hash = dummyTransactions[1].GetHash();; t1.vin[1].prevout.n = 0; t1.vin[2].prevout.hash = dummyTransactions[1].GetHash();; t1.vin[2].prevout.n = 1; t1.vout.resize(2); t1.vout[0].nValue = 90*CENT; t1.vout[0].scriptPubKey << OP_1; // AreInputsStandard returns false for missing inputs (no longer throws) BOOST_CHECK(!t1.AreInputsStandard(missingInputs)); BOOST_CHECK_THROW(t1.GetValueIn(missingInputs), runtime_error); } BOOST_AUTO_TEST_SUITE_END()