Changeset View
Changeset View
Standalone View
Standalone View
src/script/sign.cpp
Show First 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | static bool CreateSig(const BaseSignatureCreator &creator, | ||||
// Could not make signature or signature not found, add keyid to missing | // Could not make signature or signature not found, add keyid to missing | ||||
sigdata.missing_sigs.push_back(keyid); | sigdata.missing_sigs.push_back(keyid); | ||||
return false; | return false; | ||||
} | } | ||||
/** | /** | ||||
* Sign scriptPubKey using signature made with creator. | * Sign scriptPubKey using signature made with creator. | ||||
* Signatures are returned in scriptSigRet (or returns false if scriptPubKey | * Signatures are returned in scriptSigRet (or returns false if scriptPubKey | ||||
* can't be signed), unless whichTypeRet is TX_SCRIPTHASH, in which case | * can't be signed), unless whichTypeRet is TxoutType::SCRIPTHASH, in which | ||||
* scriptSigRet is the redemption script. | * case scriptSigRet is the redemption script. | ||||
* Returns false if scriptPubKey could not be completely satisfied. | * Returns false if scriptPubKey could not be completely satisfied. | ||||
*/ | */ | ||||
static bool SignStep(const SigningProvider &provider, | static bool SignStep(const SigningProvider &provider, | ||||
const BaseSignatureCreator &creator, | const BaseSignatureCreator &creator, | ||||
const CScript &scriptPubKey, std::vector<valtype> &ret, | const CScript &scriptPubKey, std::vector<valtype> &ret, | ||||
txnouttype &whichTypeRet, SignatureData &sigdata) { | TxoutType &whichTypeRet, SignatureData &sigdata) { | ||||
CScript scriptRet; | CScript scriptRet; | ||||
uint160 h160; | uint160 h160; | ||||
ret.clear(); | ret.clear(); | ||||
std::vector<uint8_t> sig; | std::vector<uint8_t> sig; | ||||
std::vector<valtype> vSolutions; | std::vector<valtype> vSolutions; | ||||
whichTypeRet = Solver(scriptPubKey, vSolutions); | whichTypeRet = Solver(scriptPubKey, vSolutions); | ||||
switch (whichTypeRet) { | switch (whichTypeRet) { | ||||
case TX_NONSTANDARD: | case TxoutType::NONSTANDARD: | ||||
case TX_NULL_DATA: | case TxoutType::NULL_DATA: | ||||
return false; | return false; | ||||
case TX_PUBKEY: | case TxoutType::PUBKEY: | ||||
if (!CreateSig(creator, sigdata, provider, sig, | if (!CreateSig(creator, sigdata, provider, sig, | ||||
CPubKey(vSolutions[0]), scriptPubKey)) { | CPubKey(vSolutions[0]), scriptPubKey)) { | ||||
return false; | return false; | ||||
} | } | ||||
ret.push_back(std::move(sig)); | ret.push_back(std::move(sig)); | ||||
return true; | return true; | ||||
case TX_PUBKEYHASH: { | case TxoutType::PUBKEYHASH: { | ||||
CKeyID keyID = CKeyID(uint160(vSolutions[0])); | CKeyID keyID = CKeyID(uint160(vSolutions[0])); | ||||
CPubKey pubkey; | CPubKey pubkey; | ||||
if (!GetPubKey(provider, sigdata, keyID, pubkey)) { | if (!GetPubKey(provider, sigdata, keyID, pubkey)) { | ||||
// Pubkey could not be found, add to missing | // Pubkey could not be found, add to missing | ||||
sigdata.missing_pubkeys.push_back(keyID); | sigdata.missing_pubkeys.push_back(keyID); | ||||
return false; | return false; | ||||
} | } | ||||
if (!CreateSig(creator, sigdata, provider, sig, pubkey, | if (!CreateSig(creator, sigdata, provider, sig, pubkey, | ||||
scriptPubKey)) { | scriptPubKey)) { | ||||
return false; | return false; | ||||
} | } | ||||
ret.push_back(std::move(sig)); | ret.push_back(std::move(sig)); | ||||
ret.push_back(ToByteVector(pubkey)); | ret.push_back(ToByteVector(pubkey)); | ||||
return true; | return true; | ||||
} | } | ||||
case TX_SCRIPTHASH: | case TxoutType::SCRIPTHASH: | ||||
h160 = uint160(vSolutions[0]); | h160 = uint160(vSolutions[0]); | ||||
if (GetCScript(provider, sigdata, h160, scriptRet)) { | if (GetCScript(provider, sigdata, h160, scriptRet)) { | ||||
ret.push_back( | ret.push_back( | ||||
std::vector<uint8_t>(scriptRet.begin(), scriptRet.end())); | std::vector<uint8_t>(scriptRet.begin(), scriptRet.end())); | ||||
return true; | return true; | ||||
} | } | ||||
// Could not find redeemScript, add to missing | // Could not find redeemScript, add to missing | ||||
sigdata.missing_redeem_script = h160; | sigdata.missing_redeem_script = h160; | ||||
return false; | return false; | ||||
case TX_MULTISIG: { | case TxoutType::MULTISIG: { | ||||
size_t required = vSolutions.front()[0]; | size_t required = vSolutions.front()[0]; | ||||
// workaround CHECKMULTISIG bug | // workaround CHECKMULTISIG bug | ||||
ret.push_back(valtype()); | ret.push_back(valtype()); | ||||
for (size_t i = 1; i < vSolutions.size() - 1; ++i) { | for (size_t i = 1; i < vSolutions.size() - 1; ++i) { | ||||
CPubKey pubkey = CPubKey(vSolutions[i]); | CPubKey pubkey = CPubKey(vSolutions[i]); | ||||
// We need to always call CreateSig in order to fill sigdata | // We need to always call CreateSig in order to fill sigdata | ||||
// with all possible signatures that we can create. This will | // with all possible signatures that we can create. This will | ||||
// allow further PSBT processing to work as it needs all | // allow further PSBT processing to work as it needs all | ||||
Show All 34 Lines | |||||
bool ProduceSignature(const SigningProvider &provider, | bool ProduceSignature(const SigningProvider &provider, | ||||
const BaseSignatureCreator &creator, | const BaseSignatureCreator &creator, | ||||
const CScript &fromPubKey, SignatureData &sigdata) { | const CScript &fromPubKey, SignatureData &sigdata) { | ||||
if (sigdata.complete) { | if (sigdata.complete) { | ||||
return true; | return true; | ||||
} | } | ||||
std::vector<valtype> result; | std::vector<valtype> result; | ||||
txnouttype whichType; | TxoutType whichType; | ||||
bool solved = | bool solved = | ||||
SignStep(provider, creator, fromPubKey, result, whichType, sigdata); | SignStep(provider, creator, fromPubKey, result, whichType, sigdata); | ||||
CScript subscript; | CScript subscript; | ||||
if (solved && whichType == TX_SCRIPTHASH) { | if (solved && whichType == TxoutType::SCRIPTHASH) { | ||||
// Solver returns the subscript that needs to be evaluated; the final | // Solver returns the subscript that needs to be evaluated; the final | ||||
// scriptSig is the signatures from that and then the serialized | // scriptSig is the signatures from that and then the serialized | ||||
// subscript: | // subscript: | ||||
subscript = CScript(result[0].begin(), result[0].end()); | subscript = CScript(result[0].begin(), result[0].end()); | ||||
sigdata.redeem_script = subscript; | sigdata.redeem_script = subscript; | ||||
solved = solved && | solved = solved && | ||||
SignStep(provider, creator, subscript, result, whichType, | SignStep(provider, creator, subscript, result, whichType, | ||||
sigdata) && | sigdata) && | ||||
whichType != TX_SCRIPTHASH; | whichType != TxoutType::SCRIPTHASH; | ||||
result.push_back( | result.push_back( | ||||
std::vector<uint8_t>(subscript.begin(), subscript.end())); | std::vector<uint8_t>(subscript.begin(), subscript.end())); | ||||
} | } | ||||
sigdata.scriptSig = PushAll(result); | sigdata.scriptSig = PushAll(result); | ||||
// Test solution | // Test solution | ||||
sigdata.complete = | sigdata.complete = | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | SignatureData DataFromTransaction(const CMutableTransaction &tx, | ||||
if (VerifyScript(data.scriptSig, txout.scriptPubKey, | if (VerifyScript(data.scriptSig, txout.scriptPubKey, | ||||
STANDARD_SCRIPT_VERIFY_FLAGS, extractor_checker)) { | STANDARD_SCRIPT_VERIFY_FLAGS, extractor_checker)) { | ||||
data.complete = true; | data.complete = true; | ||||
return data; | return data; | ||||
} | } | ||||
// Get scripts | // Get scripts | ||||
std::vector<std::vector<uint8_t>> solutions; | std::vector<std::vector<uint8_t>> solutions; | ||||
txnouttype script_type = Solver(txout.scriptPubKey, solutions); | TxoutType script_type = Solver(txout.scriptPubKey, solutions); | ||||
CScript next_script = txout.scriptPubKey; | CScript next_script = txout.scriptPubKey; | ||||
if (script_type == TX_SCRIPTHASH && !stack.script.empty() && | if (script_type == TxoutType::SCRIPTHASH && !stack.script.empty() && | ||||
!stack.script.back().empty()) { | !stack.script.back().empty()) { | ||||
// Get the redeemScript | // Get the redeemScript | ||||
CScript redeem_script(stack.script.back().begin(), | CScript redeem_script(stack.script.back().begin(), | ||||
stack.script.back().end()); | stack.script.back().end()); | ||||
data.redeem_script = redeem_script; | data.redeem_script = redeem_script; | ||||
next_script = std::move(redeem_script); | next_script = std::move(redeem_script); | ||||
// Get redeemScript type | // Get redeemScript type | ||||
script_type = Solver(next_script, solutions); | script_type = Solver(next_script, solutions); | ||||
stack.script.pop_back(); | stack.script.pop_back(); | ||||
} | } | ||||
if (script_type == TX_MULTISIG && !stack.script.empty()) { | if (script_type == TxoutType::MULTISIG && !stack.script.empty()) { | ||||
// Build a map of pubkey -> signature by matching sigs to pubkeys: | // Build a map of pubkey -> signature by matching sigs to pubkeys: | ||||
assert(solutions.size() > 1); | assert(solutions.size() > 1); | ||||
unsigned int num_pubkeys = solutions.size() - 2; | unsigned int num_pubkeys = solutions.size() - 2; | ||||
unsigned int last_success_key = 0; | unsigned int last_success_key = 0; | ||||
for (const valtype &sig : stack.script) { | for (const valtype &sig : stack.script) { | ||||
for (unsigned int i = last_success_key; i < num_pubkeys; ++i) { | for (unsigned int i = last_success_key; i < num_pubkeys; ++i) { | ||||
const valtype &pubkey = solutions[i + 1]; | const valtype &pubkey = solutions[i + 1]; | ||||
// We either have a signature for this pubkey, or we have found | // We either have a signature for this pubkey, or we have found | ||||
▲ Show 20 Lines • Show All 180 Lines • Show Last 20 Lines |