Skip to content

Commit bf8fc7d

Browse files
committed
Merge #12714: Introduce interface for signing providers
d40f06a Introduce interface for signing providers (Pieter Wuille) Pull request description: `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). This is a very early step towards the design in https://gist.github.com/sipa/125cfa1615946d0c3f3eec2ad7f250a2, separating the concern between deciding what outputs are ours and signing. Tree-SHA512: d511b7b03eec0e513530db1d9ae5aacf6d0bfa1d3e1c03d06c5bde396bafb5824c4491b227d32bcda9288530caf49835da18e846ccf66538d6c0cc6ae27291c9
2 parents 2d97611 + d40f06a commit bf8fc7d

File tree

3 files changed

+35
-29
lines changed

3 files changed

+35
-29
lines changed

src/keystore.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,35 +9,31 @@
99
#include <key.h>
1010
#include <pubkey.h>
1111
#include <script/script.h>
12+
#include <script/sign.h>
1213
#include <script/standard.h>
1314
#include <sync.h>
1415

1516
#include <boost/signals2/signal.hpp>
1617

1718
/** A virtual base class for key stores */
18-
class CKeyStore
19+
class CKeyStore : public SigningProvider
1920
{
2021
protected:
2122
mutable CCriticalSection cs_KeyStore;
2223

2324
public:
24-
virtual ~CKeyStore() {}
25-
2625
//! Add a key to the store.
2726
virtual bool AddKeyPubKey(const CKey &key, const CPubKey &pubkey) =0;
2827
virtual bool AddKey(const CKey &key);
2928

3029
//! Check whether a key corresponding to a given address is present in the store.
3130
virtual bool HaveKey(const CKeyID &address) const =0;
32-
virtual bool GetKey(const CKeyID &address, CKey& keyOut) const =0;
3331
virtual std::set<CKeyID> GetKeys() const =0;
34-
virtual bool GetPubKey(const CKeyID &address, CPubKey& vchPubKeyOut) const =0;
3532

3633
//! Support for BIP 0013 : see https://github.com/bitcoin/bips/blob/master/bip-0013.mediawiki
3734
virtual bool AddCScript(const CScript& redeemScript) =0;
3835
virtual bool HaveCScript(const CScriptID &hash) const =0;
3936
virtual std::set<CScriptID> GetCScripts() const =0;
40-
virtual bool GetCScript(const CScriptID &hash, CScript& redeemScriptOut) const =0;
4137

4238
//! Support for Watch-only addresses
4339
virtual bool AddWatchOnly(const CScript &dest) =0;

src/script/sign.cpp

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
#include <script/sign.h>
77

88
#include <key.h>
9-
#include <keystore.h>
109
#include <policy/policy.h>
1110
#include <primitives/transaction.h>
1211
#include <script/standard.h>
@@ -15,12 +14,12 @@
1514

1615
typedef std::vector<unsigned char> valtype;
1716

18-
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) {}
17+
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) {}
1918

2019
bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode, SigVersion sigversion) const
2120
{
2221
CKey key;
23-
if (!keystore->GetKey(address, key))
22+
if (!m_provider->GetKey(address, key))
2423
return false;
2524

2625
// Signing with uncompressed keys is disabled in witness scripts
@@ -91,12 +90,12 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP
9190
else
9291
{
9392
CPubKey vch;
94-
creator.KeyStore().GetPubKey(keyID, vch);
93+
creator.Provider().GetPubKey(keyID, vch);
9594
ret.push_back(ToByteVector(vch));
9695
}
9796
return true;
9897
case TX_SCRIPTHASH:
99-
if (creator.KeyStore().GetCScript(uint160(vSolutions[0]), scriptRet)) {
98+
if (creator.Provider().GetCScript(uint160(vSolutions[0]), scriptRet)) {
10099
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
101100
return true;
102101
}
@@ -112,7 +111,7 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP
112111

113112
case TX_WITNESS_V0_SCRIPTHASH:
114113
CRIPEMD160().Write(&vSolutions[0][0], vSolutions[0].size()).Finalize(h160.begin());
115-
if (creator.KeyStore().GetCScript(h160, scriptRet)) {
114+
if (creator.Provider().GetCScript(h160, scriptRet)) {
116115
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
117116
return true;
118117
}
@@ -206,27 +205,27 @@ void UpdateTransaction(CMutableTransaction& tx, unsigned int nIn, const Signatur
206205
UpdateInput(tx.vin[nIn], data);
207206
}
208207

209-
bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType)
208+
bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType)
210209
{
211210
assert(nIn < txTo.vin.size());
212211

213212
CTransaction txToConst(txTo);
214-
TransactionSignatureCreator creator(&keystore, &txToConst, nIn, amount, nHashType);
213+
TransactionSignatureCreator creator(&provider, &txToConst, nIn, amount, nHashType);
215214

216215
SignatureData sigdata;
217216
bool ret = ProduceSignature(creator, fromPubKey, sigdata);
218217
UpdateTransaction(txTo, nIn, sigdata);
219218
return ret;
220219
}
221220

222-
bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
221+
bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
223222
{
224223
assert(nIn < txTo.vin.size());
225224
CTxIn& txin = txTo.vin[nIn];
226225
assert(txin.prevout.n < txFrom.vout.size());
227226
const CTxOut& txout = txFrom.vout[txin.prevout.n];
228227

229-
return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType);
228+
return SignSignature(provider, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType);
230229
}
231230

232231
static std::vector<valtype> CombineMultisig(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
@@ -427,13 +426,13 @@ bool DummySignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const
427426
return true;
428427
}
429428

430-
bool IsSolvable(const CKeyStore& store, const CScript& script)
429+
bool IsSolvable(const SigningProvider& provider, const CScript& script)
431430
{
432431
// This check is to make sure that the script we created can actually be solved for and signed by us
433432
// if we were to have the private keys. This is just to make sure that the script is valid and that,
434433
// if found in a transaction, we would still accept and relay that transaction. In particular,
435434
// it will reject witness outputs that require signing with an uncompressed public key.
436-
DummySignatureCreator creator(&store);
435+
DummySignatureCreator creator(&provider);
437436
SignatureData sigs;
438437
// Make sure that STANDARD_SCRIPT_VERIFY_FLAGS includes SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, the most
439438
// important property this function is designed to test for.

src/script/sign.h

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,32 @@
88

99
#include <script/interpreter.h>
1010

11+
class CKey;
1112
class CKeyID;
12-
class CKeyStore;
1313
class CScript;
14+
class CScriptID;
1415
class CTransaction;
1516

1617
struct CMutableTransaction;
1718

19+
/** An interface to be implemented by keystores that support signing. */
20+
class SigningProvider
21+
{
22+
public:
23+
virtual ~SigningProvider() {}
24+
virtual bool GetCScript(const CScriptID &scriptid, CScript& script) const =0;
25+
virtual bool GetPubKey(const CKeyID &address, CPubKey& pubkey) const =0;
26+
virtual bool GetKey(const CKeyID &address, CKey& key) const =0;
27+
};
28+
1829
/** Virtual base class for signature creators. */
1930
class BaseSignatureCreator {
2031
protected:
21-
const CKeyStore* keystore;
32+
const SigningProvider* m_provider;
2233

2334
public:
24-
explicit BaseSignatureCreator(const CKeyStore* keystoreIn) : keystore(keystoreIn) {}
25-
const CKeyStore& KeyStore() const { return *keystore; };
35+
explicit BaseSignatureCreator(const SigningProvider* provider) : m_provider(provider) {}
36+
const SigningProvider& Provider() const { return *m_provider; }
2637
virtual ~BaseSignatureCreator() {}
2738
virtual const BaseSignatureChecker& Checker() const =0;
2839

@@ -39,7 +50,7 @@ class TransactionSignatureCreator : public BaseSignatureCreator {
3950
const TransactionSignatureChecker checker;
4051

4152
public:
42-
TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn=SIGHASH_ALL);
53+
TransactionSignatureCreator(const SigningProvider* provider, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn=SIGHASH_ALL);
4354
const BaseSignatureChecker& Checker() const override { return checker; }
4455
bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const override;
4556
};
@@ -48,13 +59,13 @@ class MutableTransactionSignatureCreator : public TransactionSignatureCreator {
4859
CTransaction tx;
4960

5061
public:
51-
MutableTransactionSignatureCreator(const CKeyStore* keystoreIn, const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : TransactionSignatureCreator(keystoreIn, &tx, nInIn, amountIn, nHashTypeIn), tx(*txToIn) {}
62+
MutableTransactionSignatureCreator(const SigningProvider* provider, const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : TransactionSignatureCreator(provider, &tx, nInIn, amountIn, nHashTypeIn), tx(*txToIn) {}
5263
};
5364

5465
/** A signature creator that just produces 72-byte empty signatures. */
5566
class DummySignatureCreator : public BaseSignatureCreator {
5667
public:
57-
explicit DummySignatureCreator(const CKeyStore* keystoreIn) : BaseSignatureCreator(keystoreIn) {}
68+
explicit DummySignatureCreator(const SigningProvider* provider) : BaseSignatureCreator(provider) {}
5869
const BaseSignatureChecker& Checker() const override;
5970
bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const override;
6071
};
@@ -71,8 +82,8 @@ struct SignatureData {
7182
bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& scriptPubKey, SignatureData& sigdata);
7283

7384
/** Produce a script signature for a transaction. */
74-
bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType);
75-
bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType);
85+
bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType);
86+
bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType);
7687

7788
/** Combine two script signatures using a generic signature checker, intelligently, possibly with OP_0 placeholders. */
7889
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);
8495

8596
/* Check whether we know how to sign for an output like this, assuming we
8697
* have all private keys. While this function does not need private keys, the passed
87-
* keystore is used to look up public keys and redeemscripts by hash.
98+
* provider is used to look up public keys and redeemscripts by hash.
8899
* Solvability is unrelated to whether we consider this output to be ours. */
89-
bool IsSolvable(const CKeyStore& store, const CScript& script);
100+
bool IsSolvable(const SigningProvider& provider, const CScript& script);
90101

91102
#endif // BITCOIN_SCRIPT_SIGN_H

0 commit comments

Comments
 (0)