/ src / test / util / transaction_utils.cpp
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  }