Skip to content

Commit

Permalink
Figure out what is missing during signing
Browse files Browse the repository at this point in the history
When signing an input, figure out what was requested for but was unable
to be found and store it in a SignatureData.

Return this information in SignPSBTInput.
  • Loading branch information
achow101 committed Feb 16, 2019
1 parent 08f749c commit cb40b3a
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 7 deletions.
20 changes: 16 additions & 4 deletions src/psbt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,13 +191,12 @@ void PSBTOutput::Merge(const PSBTOutput& output)
if (redeem_script.empty() && !output.redeem_script.empty()) redeem_script = output.redeem_script;
if (witness_script.empty() && !output.witness_script.empty()) witness_script = output.witness_script;
}

bool PSBTInputSigned(PSBTInput& input)
{
return !input.final_script_sig.empty() || !input.final_script_witness.IsNull();
}

bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, int sighash)
bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, int sighash, SignatureData* out_sigdata, bool use_dummy)
{
PSBTInput& input = psbt.inputs.at(index);
const CMutableTransaction& tx = *psbt.tx;
Expand Down Expand Up @@ -237,9 +236,14 @@ bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction&
return false;
}

MutableTransactionSignatureCreator creator(&tx, index, utxo.nValue, sighash);
sigdata.witness = false;
bool sig_complete = ProduceSignature(provider, creator, utxo.scriptPubKey, sigdata);
bool sig_complete;
if (use_dummy) {
sig_complete = ProduceSignature(provider, DUMMY_SIGNATURE_CREATOR, utxo.scriptPubKey, sigdata);
} else {
MutableTransactionSignatureCreator creator(&tx, index, utxo.nValue, sighash);
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);
Expand All @@ -250,6 +254,14 @@ bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction&
input.non_witness_utxo = nullptr;
}

// Fill in the missing info
if (out_sigdata) {
out_sigdata->missing_pubkeys = sigdata.missing_pubkeys;
out_sigdata->missing_sigs = sigdata.missing_sigs;
out_sigdata->missing_redeem_script = sigdata.missing_redeem_script;
out_sigdata->missing_witness_script = sigdata.missing_witness_script;
}

return sig_complete;
}

Expand Down
2 changes: 1 addition & 1 deletion src/psbt.h
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ struct PartiallySignedTransaction
bool PSBTInputSigned(PSBTInput& input);

/** Signs a PSBTInput, verifying that all provided data matches what is being signed. */
bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, int sighash = SIGHASH_ALL);
bool SignPSBTInput(const SigningProvider& provider, PartiallySignedTransaction& psbt, int index, int sighash = SIGHASH_ALL, SignatureData* out_sigdata = nullptr, bool use_dummy = false);

/**
* Finalizes a PSBT if possible, combining partial signatures.
Expand Down
15 changes: 13 additions & 2 deletions src/script/sign.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ static bool CreateSig(const BaseSignatureCreator& creator, SignatureData& sigdat
assert(i.second);
return true;
}
// Could not make signature or signature not found, add keyid to missing
sigdata.missing_sigs.push_back(keyid);
return false;
}

Expand Down Expand Up @@ -116,17 +118,24 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
case TX_PUBKEYHASH: {
CKeyID keyID = CKeyID(uint160(vSolutions[0]));
CPubKey pubkey;
if (!GetPubKey(provider, sigdata, keyID, pubkey)) return false;
if (!GetPubKey(provider, sigdata, keyID, pubkey)) {
// Pubkey could not be found, add to missing
sigdata.missing_pubkeys.push_back(keyID);
return false;
}
if (!CreateSig(creator, sigdata, provider, sig, pubkey, scriptPubKey, sigversion)) return false;
ret.push_back(std::move(sig));
ret.push_back(ToByteVector(pubkey));
return true;
}
case TX_SCRIPTHASH:
if (GetCScript(provider, sigdata, uint160(vSolutions[0]), scriptRet)) {
h160 = uint160(vSolutions[0]);
if (GetCScript(provider, sigdata, h160, scriptRet)) {
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
return true;
}
// Could not find redeemScript, add to missing
sigdata.missing_redeem_script = h160;
return false;

case TX_MULTISIG: {
Expand Down Expand Up @@ -154,6 +163,8 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
return true;
}
// Could not find witnessScript, add to missing
sigdata.missing_witness_script = uint256(vSolutions[0]);
return false;

default:
Expand Down
4 changes: 4 additions & 0 deletions src/script/sign.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ struct SignatureData {
CScriptWitness scriptWitness; ///< The scriptWitness of an input. Contains complete signatures or the traditional partial signatures format. scriptWitness is part of a transaction input per BIP 144.
std::map<CKeyID, SigPair> signatures; ///< BIP 174 style partial signatures for the input. May contain all signatures necessary for producing a final scriptSig or scriptWitness.
std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>> misc_pubkeys;
std::vector<CKeyID> missing_pubkeys; ///< KeyIDs of pubkeys which could not be found
std::vector<CKeyID> missing_sigs; ///< KeyIDs of pubkeys for signatures which could not be found
uint160 missing_redeem_script; ///< ScriptID of the missing redeemScript (if any)
uint256 missing_witness_script; ///< SHA256 of the missing witnessScript (if any)

SignatureData() {}
explicit SignatureData(const CScript& script) : scriptSig(script) {}
Expand Down

0 comments on commit cb40b3a

Please sign in to comment.