/root/bitcoin/src/test/util/transaction_utils.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2019-2020 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 | 0 | { |
12 | 0 | CMutableTransaction txCredit; |
13 | 0 | txCredit.version = 1; |
14 | 0 | txCredit.nLockTime = 0; |
15 | 0 | txCredit.vin.resize(1); |
16 | 0 | txCredit.vout.resize(1); |
17 | 0 | txCredit.vin[0].prevout.SetNull(); |
18 | 0 | txCredit.vin[0].scriptSig = CScript() << CScriptNum(0) << CScriptNum(0); |
19 | 0 | txCredit.vin[0].nSequence = CTxIn::SEQUENCE_FINAL; |
20 | 0 | txCredit.vout[0].scriptPubKey = scriptPubKey; |
21 | 0 | txCredit.vout[0].nValue = nValue; |
22 | |
|
23 | 0 | return txCredit; |
24 | 0 | } |
25 | | |
26 | | CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CScriptWitness& scriptWitness, const CTransaction& txCredit) |
27 | 0 | { |
28 | 0 | CMutableTransaction txSpend; |
29 | 0 | txSpend.version = 1; |
30 | 0 | txSpend.nLockTime = 0; |
31 | 0 | txSpend.vin.resize(1); |
32 | 0 | txSpend.vout.resize(1); |
33 | 0 | txSpend.vin[0].scriptWitness = scriptWitness; |
34 | 0 | txSpend.vin[0].prevout.hash = txCredit.GetHash(); |
35 | 0 | txSpend.vin[0].prevout.n = 0; |
36 | 0 | txSpend.vin[0].scriptSig = scriptSig; |
37 | 0 | txSpend.vin[0].nSequence = CTxIn::SEQUENCE_FINAL; |
38 | 0 | txSpend.vout[0].scriptPubKey = CScript(); |
39 | 0 | txSpend.vout[0].nValue = txCredit.vout[0].nValue; |
40 | |
|
41 | 0 | return txSpend; |
42 | 0 | } |
43 | | |
44 | | std::vector<CMutableTransaction> SetupDummyInputs(FillableSigningProvider& keystoreRet, CCoinsViewCache& coinsRet, const std::array<CAmount,4>& nValues) |
45 | 0 | { |
46 | 0 | std::vector<CMutableTransaction> dummyTransactions; |
47 | 0 | dummyTransactions.resize(2); |
48 | | |
49 | | // Add some keys to the keystore: |
50 | 0 | CKey key[4]; |
51 | 0 | for (int i = 0; i < 4; i++) { |
52 | 0 | key[i].MakeNewKey(i % 2); |
53 | 0 | keystoreRet.AddKey(key[i]); |
54 | 0 | } |
55 | | |
56 | | // Create some dummy input transactions |
57 | 0 | dummyTransactions[0].vout.resize(2); |
58 | 0 | dummyTransactions[0].vout[0].nValue = nValues[0]; |
59 | 0 | dummyTransactions[0].vout[0].scriptPubKey << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG; |
60 | 0 | dummyTransactions[0].vout[1].nValue = nValues[1]; |
61 | 0 | dummyTransactions[0].vout[1].scriptPubKey << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG; |
62 | 0 | AddCoins(coinsRet, CTransaction(dummyTransactions[0]), 0); |
63 | |
|
64 | 0 | dummyTransactions[1].vout.resize(2); |
65 | 0 | dummyTransactions[1].vout[0].nValue = nValues[2]; |
66 | 0 | dummyTransactions[1].vout[0].scriptPubKey = GetScriptForDestination(PKHash(key[2].GetPubKey())); |
67 | 0 | dummyTransactions[1].vout[1].nValue = nValues[3]; |
68 | 0 | dummyTransactions[1].vout[1].scriptPubKey = GetScriptForDestination(PKHash(key[3].GetPubKey())); |
69 | 0 | AddCoins(coinsRet, CTransaction(dummyTransactions[1]), 0); |
70 | |
|
71 | 0 | return dummyTransactions; |
72 | 0 | } |
73 | | |
74 | | void BulkTransaction(CMutableTransaction& tx, int32_t target_weight) |
75 | 0 | { |
76 | 0 | tx.vout.emplace_back(0, CScript() << OP_RETURN); |
77 | 0 | auto unpadded_weight{GetTransactionWeight(CTransaction(tx))}; |
78 | 0 | assert(target_weight >= unpadded_weight); |
79 | | |
80 | | // determine number of needed padding bytes by converting weight difference to vbytes |
81 | 0 | 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 | 0 | dummy_vbytes -= GetSizeOfCompactSize(dummy_vbytes) - 1; |
85 | | |
86 | | // pad transaction by repeatedly appending a dummy opcode to the output script |
87 | 0 | 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 | 0 | assert(GetTransactionWeight(CTransaction(tx)) >= target_weight); |
91 | 0 | assert(GetTransactionWeight(CTransaction(tx)) <= target_weight + 3); |
92 | 0 | } |
93 | | |
94 | | bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType, SignatureData& sig_data) |
95 | 0 | { |
96 | 0 | assert(nIn < txTo.vin.size()); |
97 | | |
98 | 0 | MutableTransactionSignatureCreator creator(txTo, nIn, amount, nHashType); |
99 | |
|
100 | 0 | bool ret = ProduceSignature(provider, creator, fromPubKey, sig_data); |
101 | 0 | UpdateInput(txTo.vin.at(nIn), sig_data); |
102 | 0 | return ret; |
103 | 0 | } |
104 | | |
105 | | bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType, SignatureData& sig_data) |
106 | 0 | { |
107 | 0 | assert(nIn < txTo.vin.size()); |
108 | 0 | const CTxIn& txin = txTo.vin[nIn]; |
109 | 0 | assert(txin.prevout.n < txFrom.vout.size()); |
110 | 0 | const CTxOut& txout = txFrom.vout[txin.prevout.n]; |
111 | |
|
112 | 0 | return SignSignature(provider, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType, sig_data); |
113 | 0 | } |