transaction_utils.cpp raw
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, CAmount 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, {.sighash_type = 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 }
114