psbt.cpp raw

   1  // Copyright (c) 2009-2022 The Limenka 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/amount.h>
   7  #include <consensus/tx_verify.h>
   8  #include <consensus/validation.h>
   9  #include <node/psbt.h>
  10  #include <policy/policy.h>
  11  #include <policy/settings.h>
  12  #include <tinyformat.h>
  13  
  14  #include <numeric>
  15  
  16  namespace node {
  17  PSBTAnalysis AnalyzePSBT(PartiallySignedTransaction psbtx)
  18  {
  19      // Go through each input and build status
  20      PSBTAnalysis result;
  21  
  22      bool calc_fee = true;
  23  
  24      CAmount in_amt = 0;
  25  
  26      result.inputs.resize(psbtx.tx->vin.size());
  27  
  28      const PrecomputedTransactionData txdata = PrecomputePSBTData(psbtx);
  29  
  30      for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
  31          PSBTInput& input = psbtx.inputs[i];
  32          PSBTInputAnalysis& input_analysis = result.inputs[i];
  33  
  34          // We set next role here and ratchet backwards as required
  35          input_analysis.next = PSBTRole::EXTRACTOR;
  36  
  37          // Check for a UTXO
  38          CTxOut utxo;
  39          if (psbtx.GetInputUTXO(utxo, i)) {
  40              if (!MoneyRange(utxo.nValue) || !MoneyRange(in_amt + utxo.nValue)) {
  41                  result.SetInvalid(strprintf("PSBT is not valid. Input %u has invalid value", i));
  42                  return result;
  43              }
  44              in_amt += utxo.nValue;
  45              input_analysis.has_utxo = true;
  46          } else {
  47              if (input.non_witness_utxo && psbtx.tx->vin[i].prevout.n >= input.non_witness_utxo->vout.size()) {
  48                  result.SetInvalid(strprintf("PSBT is not valid. Input %u specifies invalid prevout", i));
  49                  return result;
  50              }
  51              input_analysis.has_utxo = false;
  52              input_analysis.is_final = false;
  53              input_analysis.next = PSBTRole::UPDATER;
  54              calc_fee = false;
  55          }
  56  
  57          if (!utxo.IsNull() && utxo.scriptPubKey.IsUnspendable()) {
  58              result.SetInvalid(strprintf("PSBT is not valid. Input %u spends unspendable output", i));
  59              return result;
  60          }
  61  
  62          // Check if it is final
  63          if (!PSBTInputSignedAndVerified(psbtx, i, &txdata)) {
  64              input_analysis.is_final = false;
  65  
  66              // Figure out what is missing
  67              SignatureData outdata;
  68              bool complete = SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, &txdata, 1, &outdata);
  69  
  70              // Things are missing
  71              if (!complete) {
  72                  input_analysis.missing_pubkeys = outdata.missing_pubkeys;
  73                  input_analysis.missing_redeem_script = outdata.missing_redeem_script;
  74                  input_analysis.missing_witness_script = outdata.missing_witness_script;
  75                  input_analysis.missing_sigs = outdata.missing_sigs;
  76  
  77                  // If we are only missing signatures and nothing else, then next is signer
  78                  if (outdata.missing_pubkeys.empty() && outdata.missing_redeem_script.IsNull() && outdata.missing_witness_script.IsNull() && !outdata.missing_sigs.empty()) {
  79                      input_analysis.next = PSBTRole::SIGNER;
  80                  } else {
  81                      input_analysis.next = PSBTRole::UPDATER;
  82                  }
  83              } else {
  84                  input_analysis.next = PSBTRole::FINALIZER;
  85              }
  86          } else if (!utxo.IsNull()){
  87              input_analysis.is_final = true;
  88          }
  89      }
  90  
  91      // Calculate next role for PSBT by grabbing "minimum" PSBTInput next role
  92      result.next = PSBTRole::EXTRACTOR;
  93      for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
  94          PSBTInputAnalysis& input_analysis = result.inputs[i];
  95          result.next = std::min(result.next, input_analysis.next);
  96      }
  97      assert(result.next > PSBTRole::CREATOR);
  98  
  99      if (calc_fee) {
 100          // Get the output amount
 101          CAmount out_amt = std::accumulate(psbtx.tx->vout.begin(), psbtx.tx->vout.end(), CAmount(0),
 102              [](CAmount a, const CTxOut& b) {
 103                  if (!MoneyRange(a) || !MoneyRange(b.nValue) || !MoneyRange(a + b.nValue)) {
 104                      return CAmount(-1);
 105                  }
 106                  return a += b.nValue;
 107              }
 108          );
 109          if (!MoneyRange(out_amt)) {
 110              result.SetInvalid("PSBT is not valid. Output amount invalid");
 111              return result;
 112          }
 113  
 114          // Get the fee
 115          CAmount fee = in_amt - out_amt;
 116          result.fee = fee;
 117  
 118          // Estimate the size
 119          CMutableTransaction mtx(*psbtx.tx);
 120          CCoinsView view_dummy;
 121          CCoinsViewCache view(&view_dummy);
 122          bool success = true;
 123  
 124          for (unsigned int i = 0; i < psbtx.tx->vin.size(); ++i) {
 125              PSBTInput& input = psbtx.inputs[i];
 126              Coin newcoin;
 127  
 128              if (!SignPSBTInput(DUMMY_SIGNING_PROVIDER, psbtx, i, nullptr, 1) || !psbtx.GetInputUTXO(newcoin.out, i)) {
 129                  success = false;
 130                  break;
 131              } else {
 132                  mtx.vin[i].scriptSig = input.final_script_sig;
 133                  mtx.vin[i].scriptWitness = input.final_script_witness;
 134                  newcoin.nHeight = 1;
 135                  view.AddCoin(psbtx.tx->vin[i].prevout, std::move(newcoin), true);
 136              }
 137          }
 138  
 139          if (success) {
 140              CTransaction ctx = CTransaction(mtx);
 141              size_t size(GetVirtualTransactionSize(GetTransactionWeight(ctx) + CalculateExtraTxWeight(ctx, view, ::g_weight_per_data_byte), GetTransactionSigOpCost(ctx, view, STANDARD_SCRIPT_VERIFY_FLAGS), ::nBytesPerSigOp));
 142              result.estimated_vsize = size;
 143              // Estimate fee rate
 144              CFeeRate feerate(fee, size);
 145              result.estimated_feerate = feerate;
 146          }
 147  
 148      }
 149  
 150      return result;
 151  }
 152  } // namespace node
 153