Skip to content

Commit 0c8ea63

Browse files
committed
Abstract out IsSolvable from Witnessifier
1 parent 2214954 commit 0c8ea63

File tree

4 files changed

+45
-30
lines changed

4 files changed

+45
-30
lines changed

src/policy/policy.h

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -49,28 +49,28 @@ static const unsigned int DUST_RELAY_TX_FEE = 3000;
4949
* with. However scripts violating these flags may still be present in valid
5050
* blocks and we must accept those blocks.
5151
*/
52-
static const unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY_FLAGS |
53-
SCRIPT_VERIFY_DERSIG |
54-
SCRIPT_VERIFY_STRICTENC |
55-
SCRIPT_VERIFY_MINIMALDATA |
56-
SCRIPT_VERIFY_NULLDUMMY |
57-
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS |
58-
SCRIPT_VERIFY_CLEANSTACK |
59-
SCRIPT_VERIFY_MINIMALIF |
60-
SCRIPT_VERIFY_NULLFAIL |
61-
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY |
62-
SCRIPT_VERIFY_CHECKSEQUENCEVERIFY |
63-
SCRIPT_VERIFY_LOW_S |
64-
SCRIPT_VERIFY_WITNESS |
65-
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM |
66-
SCRIPT_VERIFY_WITNESS_PUBKEYTYPE;
52+
static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY_FLAGS |
53+
SCRIPT_VERIFY_DERSIG |
54+
SCRIPT_VERIFY_STRICTENC |
55+
SCRIPT_VERIFY_MINIMALDATA |
56+
SCRIPT_VERIFY_NULLDUMMY |
57+
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS |
58+
SCRIPT_VERIFY_CLEANSTACK |
59+
SCRIPT_VERIFY_MINIMALIF |
60+
SCRIPT_VERIFY_NULLFAIL |
61+
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY |
62+
SCRIPT_VERIFY_CHECKSEQUENCEVERIFY |
63+
SCRIPT_VERIFY_LOW_S |
64+
SCRIPT_VERIFY_WITNESS |
65+
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM |
66+
SCRIPT_VERIFY_WITNESS_PUBKEYTYPE;
6767

6868
/** For convenience, standard but not mandatory verify flags. */
69-
static const unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS;
69+
static constexpr unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS;
7070

7171
/** Used as the flags parameter to sequence and nLocktime checks in non-consensus code. */
72-
static const unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS = LOCKTIME_VERIFY_SEQUENCE |
73-
LOCKTIME_MEDIAN_TIME_PAST;
72+
static constexpr unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS = LOCKTIME_VERIFY_SEQUENCE |
73+
LOCKTIME_MEDIAN_TIME_PAST;
7474

7575
CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee);
7676

src/script/sign.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,3 +422,22 @@ bool DummySignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const
422422
vchSig[6 + 33 + 32] = SIGHASH_ALL;
423423
return true;
424424
}
425+
426+
bool IsSolvable(const CKeyStore& store, const CScript& script)
427+
{
428+
// This check is to make sure that the script we created can actually be solved for and signed by us
429+
// if we were to have the private keys. This is just to make sure that the script is valid and that,
430+
// if found in a transaction, we would still accept and relay that transaction. In particular,
431+
// it will reject witness outputs that require signing with an uncompressed public key.
432+
DummySignatureCreator creator(&store);
433+
SignatureData sigs;
434+
// Make sure that STANDARD_SCRIPT_VERIFY_FLAGS includes SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, the most
435+
// important property this function is designed to test for.
436+
static_assert(STANDARD_SCRIPT_VERIFY_FLAGS & SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, "IsSolvable requires standard script flags to include WITNESS_PUBKEYTYPE");
437+
if (ProduceSignature(creator, script, sigs)) {
438+
// VerifyScript check is just defensive, and should never fail.
439+
assert(VerifyScript(sigs.scriptSig, script, &sigs.scriptWitness, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker()));
440+
return true;
441+
}
442+
return false;
443+
}

src/script/sign.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,10 @@ SignatureData CombineSignatures(const CScript& scriptPubKey, const BaseSignature
8181
SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn);
8282
void UpdateTransaction(CMutableTransaction& tx, unsigned int nIn, const SignatureData& data);
8383

84+
/* Check whether we know how to sign for an output like this, assuming we
85+
* have all private keys. While this function does not need private keys, the passed
86+
* keystore is used to look up public keys and redeemscripts by hash.
87+
* Solvability is unrelated to whether we consider this output to be ours. */
88+
bool IsSolvable(const CKeyStore& store, const CScript& script);
89+
8490
#endif // BITCOIN_SCRIPT_SIGN_H

src/wallet/rpcwallet.cpp

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,12 +1204,7 @@ class Witnessifier : public boost::static_visitor<bool>
12041204
if (pwallet) {
12051205
CScript basescript = GetScriptForDestination(keyID);
12061206
CScript witscript = GetScriptForWitness(basescript);
1207-
SignatureData sigs;
1208-
// This check is to make sure that the script we created can actually be solved for and signed by us
1209-
// if we were to have the private keys. This is just to make sure that the script is valid and that,
1210-
// if found in a transaction, we would still accept and relay that transaction.
1211-
if (!ProduceSignature(DummySignatureCreator(pwallet), witscript, sigs) ||
1212-
!VerifyScript(sigs.scriptSig, witscript, &sigs.scriptWitness, MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, DummySignatureCreator(pwallet).Checker())) {
1207+
if (!IsSolvable(*pwallet, witscript)) {
12131208
return false;
12141209
}
12151210
return ExtractDestination(witscript, result);
@@ -1228,12 +1223,7 @@ class Witnessifier : public boost::static_visitor<bool>
12281223
return true;
12291224
}
12301225
CScript witscript = GetScriptForWitness(subscript);
1231-
SignatureData sigs;
1232-
// This check is to make sure that the script we created can actually be solved for and signed by us
1233-
// if we were to have the private keys. This is just to make sure that the script is valid and that,
1234-
// if found in a transaction, we would still accept and relay that transaction.
1235-
if (!ProduceSignature(DummySignatureCreator(pwallet), witscript, sigs) ||
1236-
!VerifyScript(sigs.scriptSig, witscript, &sigs.scriptWitness, MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_WITNESS_PUBKEYTYPE, DummySignatureCreator(pwallet).Checker())) {
1226+
if (!IsSolvable(*pwallet, witscript)) {
12371227
return false;
12381228
}
12391229
return ExtractDestination(witscript, result);

0 commit comments

Comments
 (0)