diff options
author | Pieter Wuille <pieter.wuille@gmail.com> | 2018-03-17 19:19:09 -0700 |
---|---|---|
committer | Pieter Wuille <pieter.wuille@gmail.com> | 2018-03-25 13:26:57 -0700 |
commit | d40f06a3da5e6b1fd065885b08513263fa930cb8 (patch) | |
tree | 80e3a485e4d9ecdc7a891ae3fd88f5fbd7011326 | |
parent | af20f9b1d485582b8c8aa8294bac4f2c540246d2 (diff) |
Introduce interface for signing providers
CKeyStore is a rich interface that provides many features, including knowledge
of scripts and pubkeys for solving, private keys for signing, in addition to
watch-only keys and scripts, and distinguishing lack of keys from them just
being encrypted.
The signing logic in script/sign does not actually need most of these features.
Here we introduce a simpler interface (SigningProvider) which *only* provides
keys and scripts. This is actually sufficient for signing.
In addtion, we swap the dependency between keystore and script/sign
(keystore now depends on script/script with CKeyStore deriving from
SigningProvider, rather than CKeyStore being the interface that signing
relies on).
-rw-r--r-- | src/keystore.h | 8 | ||||
-rw-r--r-- | src/script/sign.cpp | 23 | ||||
-rw-r--r-- | src/script/sign.h | 33 |
3 files changed, 35 insertions, 29 deletions
diff --git a/src/keystore.h b/src/keystore.h index ffd3238fd6..ff5613f617 100644 --- a/src/keystore.h +++ b/src/keystore.h @@ -9,35 +9,31 @@ #include <key.h> #include <pubkey.h> #include <script/script.h> +#include <script/sign.h> #include <script/standard.h> #include <sync.h> #include <boost/signals2/signal.hpp> /** A virtual base class for key stores */ -class CKeyStore +class CKeyStore : public SigningProvider { protected: mutable CCriticalSection cs_KeyStore; public: - virtual ~CKeyStore() {} - //! Add a key to the store. virtual bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey) =0; virtual bool AddKey(const CKey &key); //! Check whether a key corresponding to a given address is present in the store. virtual bool HaveKey(const CKeyID &address) const =0; - virtual bool GetKey(const CKeyID &address, CKey& keyOut) const =0; virtual std::set<CKeyID> GetKeys() const =0; - virtual bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const =0; //! Support for BIP 0013 : see https://github.com/bitcoin/bips/blob/master/bip-0013.mediawiki virtual bool AddCScript(const CScript& redeemScript) =0; virtual bool HaveCScript(const CScriptID &hash) const =0; virtual std::set<CScriptID> GetCScripts() const =0; - virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const =0; //! Support for Watch-only addresses virtual bool AddWatchOnly(const CScript &dest) =0; diff --git a/src/script/sign.cpp b/src/script/sign.cpp index baa712dc2d..d22d4e161b 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -6,7 +6,6 @@ #include <script/sign.h> #include <key.h> -#include <keystore.h> #include <policy/policy.h> #include <primitives/transaction.h> #include <script/standard.h> @@ -15,12 +14,12 @@ typedef std::vector<unsigned char> valtype; -TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, nIn, amountIn) {} +TransactionSignatureCreator::TransactionSignatureCreator(const SigningProvider* provider, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : BaseSignatureCreator(provider), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, nIn, amountIn) {} bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode, SigVersion sigversion) const { CKey key; - if (!keystore->GetKey(address, key)) + if (!m_provider->GetKey(address, key)) return false; // Signing with uncompressed keys is disabled in witness scripts @@ -91,12 +90,12 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP else { CPubKey vch; - creator.KeyStore().GetPubKey(keyID, vch); + creator.Provider().GetPubKey(keyID, vch); ret.push_back(ToByteVector(vch)); } return true; case TX_SCRIPTHASH: - if (creator.KeyStore().GetCScript(uint160(vSolutions[0]), scriptRet)) { + if (creator.Provider().GetCScript(uint160(vSolutions[0]), scriptRet)) { ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end())); return true; } @@ -112,7 +111,7 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP case TX_WITNESS_V0_SCRIPTHASH: CRIPEMD160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(h160.begin()); - if (creator.KeyStore().GetCScript(h160, scriptRet)) { + if (creator.Provider().GetCScript(h160, scriptRet)) { ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end())); return true; } @@ -206,12 +205,12 @@ void UpdateTransaction(CMutableTransaction& tx, unsigned int nIn, const Signatur UpdateInput(tx.vin[nIn], data); } -bool SignSignature(const CKeyStore &keystore, 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) { assert(nIn < txTo.vin.size()); CTransaction txToConst(txTo); - TransactionSignatureCreator creator(&keystore, &txToConst, nIn, amount, nHashType); + TransactionSignatureCreator creator(&provider, &txToConst, nIn, amount, nHashType); SignatureData sigdata; bool ret = ProduceSignature(creator, fromPubKey, sigdata); @@ -219,14 +218,14 @@ bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutabl return ret; } -bool SignSignature(const CKeyStore &keystore, 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) { assert(nIn < txTo.vin.size()); CTxIn& txin = txTo.vin[nIn]; assert(txin.prevout.n < txFrom.vout.size()); const CTxOut& txout = txFrom.vout[txin.prevout.n]; - return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType); + return SignSignature(provider, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType); } static std::vector<valtype> CombineMultisig(const CScript& scriptPubKey, const BaseSignatureChecker& checker, @@ -427,13 +426,13 @@ bool DummySignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const return true; } -bool IsSolvable(const CKeyStore& store, const CScript& script) +bool IsSolvable(const SigningProvider& provider, const CScript& script) { // This check is to make sure that the script we created can actually be solved for and signed by us // if we were to have the private keys. This is just to make sure that the script is valid and that, // if found in a transaction, we would still accept and relay that transaction. In particular, // it will reject witness outputs that require signing with an uncompressed public key. - DummySignatureCreator creator(&store); + DummySignatureCreator creator(&provider); SignatureData sigs; // Make sure that STANDARD_SCRIPT_VERIFY_FLAGS includes SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, the most // important property this function is designed to test for. diff --git a/src/script/sign.h b/src/script/sign.h index 2c749521cd..c301f0544f 100644 --- a/src/script/sign.h +++ b/src/script/sign.h @@ -8,21 +8,32 @@ #include <script/interpreter.h> +class CKey; class CKeyID; -class CKeyStore; class CScript; +class CScriptID; class CTransaction; struct CMutableTransaction; +/** An interface to be implemented by keystores that support signing. */ +class SigningProvider +{ +public: + virtual ~SigningProvider() {} + virtual bool GetCScript(const CScriptID &scriptid, CScript& script) const =0; + virtual bool GetPubKey(const CKeyID &address, CPubKey& pubkey) const =0; + virtual bool GetKey(const CKeyID &address, CKey& key) const =0; +}; + /** Virtual base class for signature creators. */ class BaseSignatureCreator { protected: - const CKeyStore* keystore; + const SigningProvider* m_provider; public: - explicit BaseSignatureCreator(const CKeyStore* keystoreIn) : keystore(keystoreIn) {} - const CKeyStore& KeyStore() const { return *keystore; }; + explicit BaseSignatureCreator(const SigningProvider* provider) : m_provider(provider) {} + const SigningProvider& Provider() const { return *m_provider; } virtual ~BaseSignatureCreator() {} virtual const BaseSignatureChecker& Checker() const =0; @@ -39,7 +50,7 @@ class TransactionSignatureCreator : public BaseSignatureCreator { const TransactionSignatureChecker checker; public: - TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn=SIGHASH_ALL); + TransactionSignatureCreator(const SigningProvider* provider, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn=SIGHASH_ALL); const BaseSignatureChecker& Checker() const override { return checker; } bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const override; }; @@ -48,13 +59,13 @@ class MutableTransactionSignatureCreator : public TransactionSignatureCreator { CTransaction tx; public: - MutableTransactionSignatureCreator(const CKeyStore* keystoreIn, const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : TransactionSignatureCreator(keystoreIn, &tx, nInIn, amountIn, nHashTypeIn), tx(*txToIn) {} + MutableTransactionSignatureCreator(const SigningProvider* provider, const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : TransactionSignatureCreator(provider, &tx, nInIn, amountIn, nHashTypeIn), tx(*txToIn) {} }; /** A signature creator that just produces 72-byte empty signatures. */ class DummySignatureCreator : public BaseSignatureCreator { public: - explicit DummySignatureCreator(const CKeyStore* keystoreIn) : BaseSignatureCreator(keystoreIn) {} + explicit DummySignatureCreator(const SigningProvider* provider) : BaseSignatureCreator(provider) {} const BaseSignatureChecker& Checker() const override; bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const override; }; @@ -71,8 +82,8 @@ struct SignatureData { bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& scriptPubKey, SignatureData& sigdata); /** Produce a script signature for a transaction. */ -bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType); -bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, 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); /** Combine two script signatures using a generic signature checker, intelligently, possibly with OP_0 placeholders. */ SignatureData CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker, const SignatureData& scriptSig1, const SignatureData& scriptSig2); @@ -84,8 +95,8 @@ void UpdateInput(CTxIn& input, const SignatureData& data); /* Check whether we know how to sign for an output like this, assuming we * have all private keys. While this function does not need private keys, the passed - * keystore is used to look up public keys and redeemscripts by hash. + * provider is used to look up public keys and redeemscripts by hash. * Solvability is unrelated to whether we consider this output to be ours. */ -bool IsSolvable(const CKeyStore& store, const CScript& script); +bool IsSolvable(const SigningProvider& provider, const CScript& script); #endif // BITCOIN_SCRIPT_SIGN_H |