Skip to content

Commit cb51c9b

Browse files
committed
Introduce interfaces signing providers and BaseSignatureCreator
1 parent e1e376e commit cb51c9b

File tree

10 files changed

+102
-95
lines changed

10 files changed

+102
-95
lines changed

src/keystore.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,21 +12,26 @@
1212
#include "sapling/address.h"
1313
#include "sapling/zip32.h"
1414
#include "sync.h"
15+
#include <key.h>
16+
#include <pubkey.h>
17+
#include <script/script.h>
18+
#include <script/sign.h>
19+
#include <script/standard.h>
20+
#include <sync.h>
1521

1622
#include <boost/signals2/signal.hpp>
1723

1824
class CScript;
1925
class CScriptID;
2026

2127
/** A virtual base class for key stores */
22-
class CKeyStore
28+
class CKeyStore : public SigningProvider
2329
{
2430
public:
2531
// todo: Make it protected again once we are more advanced in the wallet/spkm decoupling.
2632
mutable RecursiveMutex cs_KeyStore;
2733

28-
virtual ~CKeyStore() {}
29-
34+
public:
3035
//! Add a key to the store.
3136
virtual bool AddKeyPubKey(const CKey& key, const CPubKey& pubkey) = 0;
3237
virtual bool AddKey(const CKey& key);

src/pivx-tx.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,8 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& flagStr)
544544
// Only sign SIGHASH_SINGLE if there's a corresponding output:
545545
if (!fHashSingle || (i < mergedTx.vout.size()))
546546
ProduceSignature(
547-
MutableTransactionSignatureCreator(&keystore, &mergedTx, i, amount, nHashType),
547+
keystore,
548+
MutableTransactionSignatureCreator(&mergedTx, i, amount, nHashType),
548549
prevPubKey,
549550
sigdata,
550551
sigversion,

src/rpc/rawtransaction.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -766,7 +766,7 @@ UniValue signrawtransaction(const JSONRPCRequest& request)
766766
SigVersion sigversion = mergedTx.GetRequiredSigVersion();
767767
// Only sign SIGHASH_SINGLE if there's a corresponding output:
768768
if (!fHashSingle || (i < mergedTx.vout.size()))
769-
ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mergedTx, i, amount, nHashType),
769+
ProduceSignature(keystore, MutableTransactionSignatureCreator(&mergedTx, i, amount, nHashType),
770770
prevPubKey, sigdata, sigversion, fColdStake);
771771

772772
// ... and merge in other signatures:

src/rpc/rpcevo.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,9 @@ static OperationResult SignTransaction(CWallet* const pwallet, CMutableTransacti
355355
SigVersion sv = tx.GetRequiredSigVersion();
356356
txin.scriptSig.clear();
357357
SignatureData sigdata;
358-
if (!ProduceSignature(MutableTransactionSignatureCreator(pwallet, &tx, i, coin.out.nValue, SIGHASH_ALL),
358+
const CKeyStore& keys = *pwallet;
359+
if (!ProduceSignature(keys,
360+
MutableTransactionSignatureCreator(&tx, i, coin.out.nValue, SIGHASH_ALL),
359361
coin.out.scriptPubKey, sigdata, sv, false)) {
360362
return errorOut(TxInErrorToString(i, txin, "signature failed"));
361363
}

src/sapling/transaction_builder.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -332,9 +332,9 @@ TransactionBuilderResult TransactionBuilder::ProveAndSign()
332332
auto tIn = tIns[nIn];
333333
SignatureData sigdata;
334334
bool signSuccess = ProduceSignature(
335-
TransactionSignatureCreator(
336-
keystore, &txNewConst, nIn, tIn.value, SIGHASH_ALL),
337-
tIn.scriptPubKey, sigdata, SIGVERSION_SAPLING, false);
335+
*keystore,
336+
TransactionSignatureCreator(&txNewConst, nIn, tIn.value, SIGHASH_ALL),
337+
tIn.scriptPubKey, sigdata, SIGVERSION_SAPLING, false);
338338

339339
if (!signSuccess) {
340340
return TransactionBuilderResult("Failed to sign transaction");
@@ -366,7 +366,12 @@ TransactionBuilderResult TransactionBuilder::AddDummySignatures()
366366
for (int nIn = 0; nIn < (int) mtx.vin.size(); nIn++) {
367367
auto tIn = tIns[nIn];
368368
SignatureData sigdata;
369-
if (!ProduceSignature(DummySignatureCreator(keystore), tIn.scriptPubKey, sigdata, SIGVERSION_SAPLING, false)) {
369+
if (!ProduceSignature(*keystore,
370+
DUMMY_SIGNATURE_CREATOR,
371+
tIn.scriptPubKey,
372+
sigdata,
373+
SIGVERSION_SAPLING,
374+
false)) {
370375
return TransactionBuilderResult("Failed to sign transaction");
371376
} else {
372377
UpdateTransaction(mtx, nIn, sigdata);

src/script/sign.cpp

Lines changed: 54 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@
1616

1717
typedef std::vector<unsigned char> valtype;
1818

19-
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) {}
19+
TransactionSignatureCreator::TransactionSignatureCreator(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, nIn, amountIn) {}
2020

21-
bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode, SigVersion sigversion) const
21+
bool TransactionSignatureCreator::CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode, SigVersion sigversion) const
2222
{
2323
CKey key;
24-
if (!keystore->GetKey(address, key))
24+
if (!provider.GetKey(address, key))
2525
return false;
2626

2727
uint256 hash;
@@ -37,24 +37,24 @@ bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig,
3737
return true;
3838
}
3939

40-
static bool Sign1(const CKeyID& address, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector<valtype>& ret, SigVersion sigversion)
40+
static bool Sign1(const SigningProvider& provider, const CKeyID& address, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector<valtype>& ret, SigVersion sigversion)
4141
{
4242
std::vector<unsigned char> vchSig;
43-
if (!creator.CreateSig(vchSig, address, scriptCode, sigversion))
43+
if (!creator.CreateSig(provider, vchSig, address, scriptCode, sigversion))
4444
return false;
4545
ret.emplace_back(vchSig);
4646
return true;
4747
}
4848

49-
static bool SignN(const std::vector<valtype>& multisigdata, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector<valtype>& ret, SigVersion sigversion)
49+
static bool SignN(const SigningProvider& provider, const std::vector<valtype>& multisigdata, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector<valtype>& ret, SigVersion sigversion)
5050
{
5151
int nSigned = 0;
5252
int nRequired = multisigdata.front()[0];
5353
for (unsigned int i = 1; i < multisigdata.size()-1 && nSigned < nRequired; i++)
5454
{
5555
const valtype& pubkey = multisigdata[i];
5656
CKeyID keyID = CPubKey(pubkey).GetID();
57-
if (Sign1(keyID, creator, scriptCode, ret, sigversion))
57+
if (Sign1(provider, keyID, creator, scriptCode, ret, sigversion))
5858
++nSigned;
5959
}
6060
return nSigned==nRequired;
@@ -66,7 +66,7 @@ static bool SignN(const std::vector<valtype>& multisigdata, const BaseSignatureC
6666
* unless whichTypeRet is TX_SCRIPTHASH, in which case scriptSigRet is the redemption script.
6767
* Returns false if scriptPubKey could not be completely satisfied.
6868
*/
69-
static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptPubKey,
69+
static bool SignStep(const SigningProvider& provider, const BaseSignatureCreator& creator, const CScript& scriptPubKey,
7070
std::vector<valtype>& ret, txnouttype& whichTypeRet, SigVersion sigversion, bool fColdStake)
7171
{
7272
CScript scriptRet;
@@ -85,28 +85,28 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP
8585
return false;
8686
case TX_PUBKEY:
8787
keyID = CPubKey(vSolutions[0]).GetID();
88-
return Sign1(keyID, creator, scriptPubKey, ret, sigversion);
88+
return Sign1(provider, keyID, creator, scriptPubKey, ret, sigversion);
8989
case TX_PUBKEYHASH:
9090
keyID = CKeyID(uint160(vSolutions[0]));
91-
if (!Sign1(keyID, creator, scriptPubKey, ret, sigversion))
91+
if (!Sign1(provider, keyID, creator, scriptPubKey, ret, sigversion))
9292
return false;
9393
else
9494
{
9595
CPubKey vch;
96-
creator.KeyStore().GetPubKey(keyID, vch);
96+
provider.GetPubKey(keyID, vch);
9797
ret.push_back(ToByteVector(vch));
9898
}
9999
return true;
100100
case TX_SCRIPTHASH:
101-
if (creator.KeyStore().GetCScript(uint160(vSolutions[0]), scriptRet)) {
102-
ret.emplace_back(scriptRet.begin(), scriptRet.end());
101+
if (provider.GetCScript(uint160(vSolutions[0]), scriptRet)) {
102+
ret.push_back(std::vector<unsigned char>(scriptRet.begin(), scriptRet.end()));
103103
return true;
104104
}
105105
return false;
106106

107107
case TX_MULTISIG:
108108
ret.push_back(valtype()); // workaround CHECKMULTISIG bug
109-
return (SignN(vSolutions, creator, scriptPubKey, ret, sigversion));
109+
return (SignN(provider, vSolutions, creator, scriptPubKey, ret, sigversion));
110110

111111
case TX_COLDSTAKE:
112112
if (fColdStake) {
@@ -116,11 +116,11 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP
116116
// sign with the owner key
117117
keyID = CKeyID(uint160(vSolutions[1]));
118118
}
119-
if (!Sign1(keyID, creator, scriptPubKey, ret, sigversion))
119+
if (!Sign1(provider, keyID, creator, scriptPubKey, ret, sigversion))
120120
return error("*** %s: failed to sign with the %s key.",
121121
__func__, fColdStake ? "cold staker" : "owner");
122122
CPubKey vch;
123-
if (!creator.KeyStore().GetPubKey(keyID, vch))
123+
if (!provider.GetPubKey(keyID, vch))
124124
return error("%s : Unable to get public key from keyID", __func__);
125125

126126
valtype oper;
@@ -149,13 +149,13 @@ static CScript PushAll(const std::vector<valtype>& values)
149149
return result;
150150
}
151151

152-
bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPubKey, SignatureData& sigdata, SigVersion sigversion, bool fColdStake, ScriptError* serror)
152+
bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreator& creator, const CScript& fromPubKey, SignatureData& sigdata, SigVersion sigversion, bool fColdStake, ScriptError* serror)
153153
{
154154
CScript script = fromPubKey;
155155
bool solved = true;
156156
std::vector<valtype> result;
157157
txnouttype whichType;
158-
solved = SignStep(creator, script, result, whichType, sigversion, fColdStake);
158+
solved = SignStep(provider, creator, script, result, whichType, sigversion, fColdStake);
159159
CScript subscript;
160160

161161
if (solved && whichType == TX_SCRIPTHASH)
@@ -164,7 +164,7 @@ bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPu
164164
// the final scriptSig is the signatures from that
165165
// and then the serialized subscript:
166166
script = subscript = CScript(result[0].begin(), result[0].end());
167-
solved = solved && SignStep(creator, script, result, whichType, sigversion, fColdStake) && whichType != TX_SCRIPTHASH;
167+
solved = solved && SignStep(provider, creator, script, result, whichType, sigversion, fColdStake) && whichType != TX_SCRIPTHASH;
168168
result.emplace_back(subscript.begin(), subscript.end());
169169
}
170170

@@ -188,27 +188,27 @@ void UpdateTransaction(CMutableTransaction& tx, unsigned int nIn, const Signatur
188188
tx.vin[nIn].scriptSig = data.scriptSig;
189189
}
190190

191-
bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType, bool fColdStake)
191+
bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType, bool fColdStake)
192192
{
193193
assert(nIn < txTo.vin.size());
194194

195195
CTransaction txToConst(txTo);
196-
TransactionSignatureCreator creator(&keystore, &txToConst, nIn, amount, nHashType);
196+
TransactionSignatureCreator creator(&txToConst, nIn, amount, nHashType);
197197

198198
SignatureData sigdata;
199-
bool ret = ProduceSignature(creator, fromPubKey, sigdata, txToConst.GetRequiredSigVersion(), fColdStake);
199+
bool ret = ProduceSignature(provider, creator, fromPubKey, sigdata, txToConst.GetRequiredSigVersion(), fColdStake);
200200
UpdateTransaction(txTo, nIn, sigdata);
201201
return ret;
202202
}
203203

204-
bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType, bool fColdStake)
204+
bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType, bool fColdStake)
205205
{
206206
assert(nIn < txTo.vin.size());
207207
CTxIn& txin = txTo.vin[nIn];
208208
assert(txin.prevout.n < txFrom.vout.size());
209209
const CTxOut& txout = txFrom.vout[txin.prevout.n];
210210

211-
return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType, fColdStake);
211+
return SignSignature(provider, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType, fColdStake);
212212
}
213213

214214
static std::vector<valtype> CombineMultisig(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
@@ -343,40 +343,39 @@ SignatureData CombineSignatures(const CScript& scriptPubKey, const BaseSignature
343343
}
344344

345345
namespace {
346-
/** Dummy signature checker which accepts all signatures. */
347-
class DummySignatureChecker : public BaseSignatureChecker
348-
{
349-
public:
350-
DummySignatureChecker() {}
346+
/** Dummy signature checker which accepts all signatures. */
347+
class DummySignatureChecker final : public BaseSignatureChecker {
348+
public:
349+
DummySignatureChecker() {}
350+
351+
bool CheckSig(const std::vector<unsigned char> &scriptSig, const std::vector<unsigned char> &vchPubKey,
352+
const CScript &scriptCode, SigVersion sigversion) const override { return true; }
353+
};
351354

352-
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
355+
const DummySignatureChecker DUMMY_CHECKER;
356+
}
357+
class DummySignatureCreator final : public BaseSignatureCreator {
358+
public:
359+
DummySignatureCreator() {}
360+
const BaseSignatureChecker& Checker() const override { return DUMMY_CHECKER; }
361+
bool CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const override
353362
{
363+
// Create a dummy signature that is a valid DER-encoding
364+
vchSig.assign(72, '\000');
365+
vchSig[0] = 0x30;
366+
vchSig[1] = 69;
367+
vchSig[2] = 0x02;
368+
vchSig[3] = 33;
369+
vchSig[4] = 0x01;
370+
vchSig[4 + 33] = 0x02;
371+
vchSig[5 + 33] = 32;
372+
vchSig[6 + 33] = 0x01;
373+
vchSig[6 + 33 + 32] = SIGHASH_ALL;
354374
return true;
355375
}
356376
};
357-
const DummySignatureChecker dummyChecker;
358-
}
359377

360-
const BaseSignatureChecker& DummySignatureCreator::Checker() const
361-
{
362-
return dummyChecker;
363-
}
364-
365-
bool DummySignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const
366-
{
367-
// Create a dummy signature that is a valid DER-encoding
368-
vchSig.assign(72, '\000');
369-
vchSig[0] = 0x30;
370-
vchSig[1] = 69;
371-
vchSig[2] = 0x02;
372-
vchSig[3] = 33;
373-
vchSig[4] = 0x01;
374-
vchSig[4 + 33] = 0x02;
375-
vchSig[5 + 33] = 32;
376-
vchSig[6 + 33] = 0x01;
377-
vchSig[6 + 33 + 32] = SIGHASH_ALL;
378-
return true;
379-
}
378+
const BaseSignatureCreator& DUMMY_SIGNATURE_CREATOR = DummySignatureCreator();
380379

381380
template<typename M, typename K, typename V>
382381
bool LookupHelper(const M& map, const K& key, V& value)
@@ -389,16 +388,15 @@ bool LookupHelper(const M& map, const K& key, V& value)
389388
return false;
390389
}
391390

392-
bool IsSolvable(const CKeyStore& store, const CScript& script, bool fColdStaking)
391+
bool IsSolvable(const SigningProvider& provider, const CScript& script, bool fColdStaking)
393392
{
394393
// This check is to make sure that the script we created can actually be solved for and signed by us
395394
// if we were to have the private keys. This is just to make sure that the script is valid and that,
396395
// if found in a transaction, we would still accept and relay that transaction. In particular,
397-
DummySignatureCreator creator(&store);
398396
SignatureData sigs;
399-
if (ProduceSignature(creator, script, sigs, SIGVERSION_BASE, fColdStaking)) {
397+
if (ProduceSignature(provider, DUMMY_SIGNATURE_CREATOR, script, sigs, SIGVERSION_BASE, fColdStaking)) {
400398
// VerifyScript check is just defensive, and should never fail.
401-
assert(VerifyScript(sigs.scriptSig, script, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker(), SIGVERSION_BASE));
399+
assert(VerifyScript(sigs.scriptSig, script, STANDARD_SCRIPT_VERIFY_FLAGS, DUMMY_CHECKER, SIGVERSION_BASE));
402400
return true;
403401
}
404402
return false;

0 commit comments

Comments
 (0)