transaction_utils.cpp
1 // Copyright (c) 2019-present The Bitcoin Core developers 2 // Distributed under the MIT software license, see the accompanying 3 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 5 #include <coins.h> 6 #include <consensus/validation.h> 7 #include <script/signingprovider.h> 8 #include <test/util/transaction_utils.h> 9 10 CMutableTransaction BuildCreditingTransaction(const CScript& scriptPubKey, int nValue) 11 { 12 CMutableTransaction txCredit; 13 txCredit.version = 1; 14 txCredit.nLockTime = 0; 15 txCredit.vin.resize(1); 16 txCredit.vout.resize(1); 17 txCredit.vin[0].prevout.SetNull(); 18 txCredit.vin[0].scriptSig = CScript() << CScriptNum(0) << CScriptNum(0); 19 txCredit.vin[0].nSequence = CTxIn::SEQUENCE_FINAL; 20 txCredit.vout[0].scriptPubKey = scriptPubKey; 21 txCredit.vout[0].nValue = nValue; 22 23 return txCredit; 24 } 25 26 CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CScriptWitness& scriptWitness, const CTransaction& txCredit) 27 { 28 CMutableTransaction txSpend; 29 txSpend.version = 1; 30 txSpend.nLockTime = 0; 31 txSpend.vin.resize(1); 32 txSpend.vout.resize(1); 33 txSpend.vin[0].scriptWitness = scriptWitness; 34 txSpend.vin[0].prevout.hash = txCredit.GetHash(); 35 txSpend.vin[0].prevout.n = 0; 36 txSpend.vin[0].scriptSig = scriptSig; 37 txSpend.vin[0].nSequence = CTxIn::SEQUENCE_FINAL; 38 txSpend.vout[0].scriptPubKey = CScript(); 39 txSpend.vout[0].nValue = txCredit.vout[0].nValue; 40 41 return txSpend; 42 } 43 44 std::vector<CMutableTransaction> SetupDummyInputs(FillableSigningProvider& keystoreRet, CCoinsViewCache& coinsRet, const std::array<CAmount,4>& nValues) 45 { 46 std::vector<CMutableTransaction> dummyTransactions; 47 dummyTransactions.resize(2); 48 49 // Add some keys to the keystore: 50 CKey key[4]; 51 for (int i = 0; i < 4; i++) { 52 key[i].MakeNewKey(i % 2); 53 keystoreRet.AddKey(key[i]); 54 } 55 56 // Create some dummy input transactions 57 dummyTransactions[0].vout.resize(2); 58 dummyTransactions[0].vout[0].nValue = nValues[0]; 59 dummyTransactions[0].vout[0].scriptPubKey << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG; 60 dummyTransactions[0].vout[1].nValue = nValues[1]; 61 dummyTransactions[0].vout[1].scriptPubKey << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG; 62 AddCoins(coinsRet, CTransaction(dummyTransactions[0]), 0); 63 64 dummyTransactions[1].vout.resize(2); 65 dummyTransactions[1].vout[0].nValue = nValues[2]; 66 dummyTransactions[1].vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[2].GetPubKey())); 67 dummyTransactions[1].vout[1].nValue = nValues[3]; 68 dummyTransactions[1].vout[1].scriptPubKey = GetScriptForDestination(PKHash(key[3].GetPubKey())); 69 AddCoins(coinsRet, CTransaction(dummyTransactions[1]), 0); 70 71 return dummyTransactions; 72 } 73 74 void BulkTransaction(CMutableTransaction& tx, int32_t target_weight) 75 { 76 tx.vout.emplace_back(0, CScript() << OP_RETURN); 77 auto unpadded_weight{GetTransactionWeight(CTransaction(tx))}; 78 assert(target_weight >= unpadded_weight); 79 80 // determine number of needed padding bytes by converting weight difference to vbytes 81 auto dummy_vbytes = (target_weight - unpadded_weight + (WITNESS_SCALE_FACTOR - 1)) / WITNESS_SCALE_FACTOR; 82 // compensate for the increase of the compact-size encoded script length 83 // (note that the length encoding of the unpadded output script needs one byte) 84 dummy_vbytes -= GetSizeOfCompactSize(dummy_vbytes) - 1; 85 86 // pad transaction by repeatedly appending a dummy opcode to the output script 87 tx.vout[0].scriptPubKey.insert(tx.vout[0].scriptPubKey.end(), dummy_vbytes, OP_1); 88 89 // actual weight should be at most 3 higher than target weight 90 assert(GetTransactionWeight(CTransaction(tx)) >= target_weight); 91 assert(GetTransactionWeight(CTransaction(tx)) <= target_weight + 3); 92 } 93 94 bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType, SignatureData& sig_data) 95 { 96 assert(nIn < txTo.vin.size()); 97 98 MutableTransactionSignatureCreator creator(txTo, nIn, amount, nHashType); 99 100 bool ret = ProduceSignature(provider, creator, fromPubKey, sig_data); 101 UpdateInput(txTo.vin.at(nIn), sig_data); 102 return ret; 103 } 104 105 bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType, SignatureData& sig_data) 106 { 107 assert(nIn < txTo.vin.size()); 108 const CTxIn& txin = txTo.vin[nIn]; 109 assert(txin.prevout.n < txFrom.vout.size()); 110 const CTxOut& txout = txFrom.vout[txin.prevout.n]; 111 112 return SignSignature(provider, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType, sig_data); 113 }