Additional sanity checks in SignPSBTInput

This commit is contained in:
Pieter Wuille 2018-08-08 14:18:55 -07:00
parent c05712cb59
commit 8254e9950f
2 changed files with 17 additions and 1 deletions

View file

@ -244,17 +244,33 @@ bool SignPSBTInput(const SigningProvider& provider, const CMutableTransaction& t
input.FillSignatureData(sigdata); input.FillSignatureData(sigdata);
// Get UTXO // Get UTXO
bool require_witness_sig = false;
CTxOut utxo; CTxOut utxo;
if (input.non_witness_utxo) { if (input.non_witness_utxo) {
// If we're taking our information from a non-witness UTXO, verify that it matches the prevout.
if (input.non_witness_utxo->GetHash() != tx.vin[index].prevout.hash) return false;
// If both witness and non-witness UTXO are provided, verify that they match. This check shouldn't
// matter, as the PSBT deserializer enforces only one of both is provided, and the only way both
// can be present is when they're added simultaneously by FillPSBT (in which case they always match).
// Still, check in order to not rely on callers to enforce this.
if (!input.witness_utxo.IsNull() && input.non_witness_utxo->vout[tx.vin[index].prevout.n] != input.witness_utxo) return false;
utxo = input.non_witness_utxo->vout[tx.vin[index].prevout.n]; utxo = input.non_witness_utxo->vout[tx.vin[index].prevout.n];
} else if (!input.witness_utxo.IsNull()) { } else if (!input.witness_utxo.IsNull()) {
utxo = input.witness_utxo; utxo = input.witness_utxo;
// When we're taking our information from a witness UTXO, we can't verify it is actually data from
// the output being spent. This is safe in case a witness signature is produced (which includes this
// information directly in the hash), but not for non-witness signatures. Remember that we require
// a witness signature in this situation.
require_witness_sig = true;
} else { } else {
return false; return false;
} }
MutableTransactionSignatureCreator creator(&tx, index, utxo.nValue, sighash); MutableTransactionSignatureCreator creator(&tx, index, utxo.nValue, sighash);
sigdata.witness = false;
bool sig_complete = ProduceSignature(provider, creator, utxo.scriptPubKey, sigdata); bool sig_complete = ProduceSignature(provider, creator, utxo.scriptPubKey, sigdata);
// Verify that a witness signature was produced in case one was required.
if (require_witness_sig && !sigdata.witness) return false;
input.FromSignatureData(sigdata); input.FromSignatureData(sigdata);
return sig_complete; return sig_complete;
} }

View file

@ -678,7 +678,7 @@ bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreato
bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType); bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType);
bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType); bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType);
/** Signs a PSBTInput */ /** Signs a PSBTInput, verifying that all provided data matches what is being signed. */
bool SignPSBTInput(const SigningProvider& provider, const CMutableTransaction& tx, PSBTInput& input, SignatureData& sigdata, int index, int sighash = 1); bool SignPSBTInput(const SigningProvider& provider, const CMutableTransaction& tx, PSBTInput& input, SignatureData& sigdata, int index, int sighash = 1);
/** Extract signature data from a transaction input, and insert it. */ /** Extract signature data from a transaction input, and insert it. */