From b6edb4f5e6e0bf0f9c7dd26a125849f0103b44cd Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Sat, 9 Jun 2018 12:06:25 -0700 Subject: [PATCH 1/4] Inline Sign1 and SignN Sign1 and SignN are kind of redundant so remove them and inline their behavior into SignStep --- src/script/sign.cpp | 65 ++++++++++++++++++--------------------------- 1 file changed, 26 insertions(+), 39 deletions(-) diff --git a/src/script/sign.cpp b/src/script/sign.cpp index 6dbfbda02..05fde3b54 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -33,29 +33,6 @@ bool MutableTransactionSignatureCreator::CreateSig(const SigningProvider& provid return true; } -static bool Sign1(const SigningProvider& provider, const CKeyID& address, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector& ret, SigVersion sigversion) -{ - std::vector vchSig; - if (!creator.CreateSig(provider, vchSig, address, scriptCode, sigversion)) - return false; - ret.push_back(vchSig); - return true; -} - -static bool SignN(const SigningProvider& provider, const std::vector& multisigdata, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector& ret, SigVersion sigversion) -{ - int nSigned = 0; - int nRequired = multisigdata.front()[0]; - for (unsigned int i = 1; i < multisigdata.size()-1 && nSigned < nRequired; i++) - { - const valtype& pubkey = multisigdata[i]; - CKeyID keyID = CPubKey(pubkey).GetID(); - if (Sign1(provider, keyID, creator, scriptCode, ret, sigversion)) - ++nSigned; - } - return nSigned==nRequired; -} - /** * Sign scriptPubKey using signature made with creator. * Signatures are returned in scriptSigRet (or returns false if scriptPubKey can't be signed), @@ -68,12 +45,12 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator CScript scriptRet; uint160 h160; ret.clear(); + std::vector sig; std::vector vSolutions; if (!Solver(scriptPubKey, whichTypeRet, vSolutions)) return false; - CKeyID keyID; switch (whichTypeRet) { case TX_NONSTANDARD: @@ -81,19 +58,18 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator case TX_WITNESS_UNKNOWN: return false; case TX_PUBKEY: - keyID = CPubKey(vSolutions[0]).GetID(); - return Sign1(provider, keyID, creator, scriptPubKey, ret, sigversion); - case TX_PUBKEYHASH: - keyID = CKeyID(uint160(vSolutions[0])); - if (!Sign1(provider, keyID, creator, scriptPubKey, ret, sigversion)) - return false; - else - { - CPubKey vch; - provider.GetPubKey(keyID, vch); - ret.push_back(ToByteVector(vch)); - } + if (!creator.CreateSig(provider, sig, CPubKey(vSolutions[0]).GetID(), scriptPubKey, sigversion)) return false; + ret.push_back(std::move(sig)); return true; + case TX_PUBKEYHASH: { + CKeyID keyID = CKeyID(uint160(vSolutions[0])); + if (!creator.CreateSig(provider, sig, keyID, scriptPubKey, sigversion)) return false; + ret.push_back(std::move(sig)); + CPubKey pubkey; + provider.GetPubKey(keyID, pubkey); + ret.push_back(ToByteVector(pubkey)); + return true; + } case TX_SCRIPTHASH: if (provider.GetCScript(uint160(vSolutions[0]), scriptRet)) { ret.push_back(std::vector(scriptRet.begin(), scriptRet.end())); @@ -101,10 +77,21 @@ static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator } return false; - case TX_MULTISIG: + case TX_MULTISIG: { + size_t required = vSolutions.front()[0]; ret.push_back(valtype()); // workaround CHECKMULTISIG bug - return (SignN(provider, vSolutions, creator, scriptPubKey, ret, sigversion)); - + for (size_t i = 1; i < vSolutions.size() - 1; ++i) { + CPubKey pubkey = CPubKey(vSolutions[i]); + if (ret.size() < required + 1 && creator.CreateSig(provider, sig, pubkey.GetID(), scriptPubKey, sigversion)) { + ret.push_back(std::move(sig)); + } + } + bool ok = ret.size() == required + 1; + for (size_t i = 0; i + ret.size() < required + 1; ++i) { + ret.push_back(valtype()); + } + return ok; + } case TX_WITNESS_V0_KEYHASH: ret.push_back(vSolutions[0]); return true; From 0422beb9bdfcd7d1cc095ab681a760d8bc7a1918 Mon Sep 17 00:00:00 2001 From: Andrew Chow Date: Tue, 3 Jul 2018 17:18:52 -0700 Subject: [PATCH 2/4] Make SignatureData able to store signatures and scripts In addition to having the scriptSig and scriptWitness, have SignatureData also be able to store just the signatures (pubkeys mapped to sigs) and scripts (script ids mapped to scripts). Also have DataFromTransaction be able to extract signatures and scripts from the scriptSig and scriptWitness of an input to put them in SignatureData. Adds a new SignatureChecker which takes a SignatureData and puts pubkeys and signatures into it when it successfully verifies a signature. Adds a new field in SignatureData which stores whether the SignatureData was complete. This allows us to also update the scriptSig and scriptWitness to the final one when updating a SignatureData with another one. --- src/bench/verify_script.cpp | 1 + src/bitcoin-tx.cpp | 4 +- src/rpc/rawtransaction.cpp | 6 +- src/script/sign.cpp | 130 +++++++++++++++++++++++++++------ src/script/sign.h | 17 ++++- src/test/transaction_tests.cpp | 8 +- 6 files changed, 129 insertions(+), 37 deletions(-) diff --git a/src/bench/verify_script.cpp b/src/bench/verify_script.cpp index 4100519d4..ae60588c2 100644 --- a/src/bench/verify_script.cpp +++ b/src/bench/verify_script.cpp @@ -9,6 +9,7 @@ #endif #include