Add P2WSH destination helper and use it instead of manual hashing
This commit is contained in:
parent
eaba1c111e
commit
bb582a59c7
5 changed files with 39 additions and 109 deletions
|
@ -637,9 +637,7 @@ static UniValue decodescript(const JSONRPCRequest& request)
|
||||||
} else {
|
} else {
|
||||||
// Scripts that are not fit for P2WPKH are encoded as P2WSH.
|
// Scripts that are not fit for P2WPKH are encoded as P2WSH.
|
||||||
// Newer segwit program versions should be considered when then become available.
|
// Newer segwit program versions should be considered when then become available.
|
||||||
uint256 scriptHash;
|
segwitScr = GetScriptForDestination(WitnessV0ScriptHash(script));
|
||||||
CSHA256().Write(script.data(), script.size()).Finalize(scriptHash.begin());
|
|
||||||
segwitScr = GetScriptForDestination(WitnessV0ScriptHash(scriptHash));
|
|
||||||
}
|
}
|
||||||
ScriptPubKeyToUniv(segwitScr, sr, true);
|
ScriptPubKeyToUniv(segwitScr, sr, true);
|
||||||
sr.pushKV("p2sh-segwit", EncodeDestination(CScriptID(segwitScr)));
|
sr.pushKV("p2sh-segwit", EncodeDestination(CScriptID(segwitScr)));
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include <script/standard.h>
|
#include <script/standard.h>
|
||||||
|
|
||||||
|
#include <crypto/sha256.h>
|
||||||
#include <pubkey.h>
|
#include <pubkey.h>
|
||||||
#include <script/script.h>
|
#include <script/script.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
@ -18,6 +19,11 @@ unsigned nMaxDatacarrierBytes = MAX_OP_RETURN_RELAY;
|
||||||
|
|
||||||
CScriptID::CScriptID(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {}
|
CScriptID::CScriptID(const CScript& in) : uint160(Hash160(in.begin(), in.end())) {}
|
||||||
|
|
||||||
|
WitnessV0ScriptHash::WitnessV0ScriptHash(const CScript& in)
|
||||||
|
{
|
||||||
|
CSHA256().Write(in.data(), in.size()).Finalize(begin());
|
||||||
|
}
|
||||||
|
|
||||||
const char* GetTxnOutputType(txnouttype t)
|
const char* GetTxnOutputType(txnouttype t)
|
||||||
{
|
{
|
||||||
switch (t)
|
switch (t)
|
||||||
|
@ -329,9 +335,7 @@ CScript GetScriptForWitness(const CScript& redeemscript)
|
||||||
return GetScriptForDestination(WitnessV0KeyHash(vSolutions[0]));
|
return GetScriptForDestination(WitnessV0KeyHash(vSolutions[0]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
uint256 hash;
|
return GetScriptForDestination(WitnessV0ScriptHash(redeemscript));
|
||||||
CSHA256().Write(&redeemscript[0], redeemscript.size()).Finalize(hash.begin());
|
|
||||||
return GetScriptForDestination(WitnessV0ScriptHash(hash));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsValidDestination(const CTxDestination& dest) {
|
bool IsValidDestination(const CTxDestination& dest) {
|
||||||
|
|
|
@ -77,6 +77,7 @@ struct WitnessV0ScriptHash : public uint256
|
||||||
{
|
{
|
||||||
WitnessV0ScriptHash() : uint256() {}
|
WitnessV0ScriptHash() : uint256() {}
|
||||||
explicit WitnessV0ScriptHash(const uint256& hash) : uint256(hash) {}
|
explicit WitnessV0ScriptHash(const uint256& hash) : uint256(hash) {}
|
||||||
|
explicit WitnessV0ScriptHash(const CScript& script);
|
||||||
using uint256::uint256;
|
using uint256::uint256;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -402,8 +402,7 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
|
||||||
// P2PK compressed
|
// P2PK compressed
|
||||||
{
|
{
|
||||||
CBasicKeyStore keystore;
|
CBasicKeyStore keystore;
|
||||||
scriptPubKey.clear();
|
scriptPubKey = GetScriptForRawPubKey(pubkeys[0]);
|
||||||
scriptPubKey << ToByteVector(pubkeys[0]) << OP_CHECKSIG;
|
|
||||||
|
|
||||||
// Keystore does not have key
|
// Keystore does not have key
|
||||||
result = IsMine(keystore, scriptPubKey);
|
result = IsMine(keystore, scriptPubKey);
|
||||||
|
@ -418,8 +417,7 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
|
||||||
// P2PK uncompressed
|
// P2PK uncompressed
|
||||||
{
|
{
|
||||||
CBasicKeyStore keystore;
|
CBasicKeyStore keystore;
|
||||||
scriptPubKey.clear();
|
scriptPubKey = GetScriptForRawPubKey(uncompressedPubkey);
|
||||||
scriptPubKey << ToByteVector(uncompressedPubkey) << OP_CHECKSIG;
|
|
||||||
|
|
||||||
// Keystore does not have key
|
// Keystore does not have key
|
||||||
result = IsMine(keystore, scriptPubKey);
|
result = IsMine(keystore, scriptPubKey);
|
||||||
|
@ -434,8 +432,7 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
|
||||||
// P2PKH compressed
|
// P2PKH compressed
|
||||||
{
|
{
|
||||||
CBasicKeyStore keystore;
|
CBasicKeyStore keystore;
|
||||||
scriptPubKey.clear();
|
scriptPubKey = GetScriptForDestination(pubkeys[0].GetID());
|
||||||
scriptPubKey << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
|
|
||||||
|
|
||||||
// Keystore does not have key
|
// Keystore does not have key
|
||||||
result = IsMine(keystore, scriptPubKey);
|
result = IsMine(keystore, scriptPubKey);
|
||||||
|
@ -450,8 +447,7 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
|
||||||
// P2PKH uncompressed
|
// P2PKH uncompressed
|
||||||
{
|
{
|
||||||
CBasicKeyStore keystore;
|
CBasicKeyStore keystore;
|
||||||
scriptPubKey.clear();
|
scriptPubKey = GetScriptForDestination(uncompressedPubkey.GetID());
|
||||||
scriptPubKey << OP_DUP << OP_HASH160 << ToByteVector(uncompressedPubkey.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
|
|
||||||
|
|
||||||
// Keystore does not have key
|
// Keystore does not have key
|
||||||
result = IsMine(keystore, scriptPubKey);
|
result = IsMine(keystore, scriptPubKey);
|
||||||
|
@ -467,11 +463,8 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
|
||||||
{
|
{
|
||||||
CBasicKeyStore keystore;
|
CBasicKeyStore keystore;
|
||||||
|
|
||||||
CScript redeemScript;
|
CScript redeemScript = GetScriptForDestination(pubkeys[0].GetID());
|
||||||
redeemScript << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
|
scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
|
||||||
|
|
||||||
scriptPubKey.clear();
|
|
||||||
scriptPubKey << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
|
|
||||||
|
|
||||||
// Keystore does not have redeemScript or key
|
// Keystore does not have redeemScript or key
|
||||||
result = IsMine(keystore, scriptPubKey);
|
result = IsMine(keystore, scriptPubKey);
|
||||||
|
@ -492,12 +485,9 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
|
||||||
{
|
{
|
||||||
CBasicKeyStore keystore;
|
CBasicKeyStore keystore;
|
||||||
|
|
||||||
CScript redeemscript, redeemscript_inner;
|
CScript redeemscript_inner = GetScriptForDestination(pubkeys[0].GetID());
|
||||||
redeemscript_inner << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
|
CScript redeemscript = GetScriptForDestination(CScriptID(redeemscript_inner));
|
||||||
redeemscript << OP_HASH160 << ToByteVector(CScriptID(redeemscript_inner)) << OP_EQUAL;
|
scriptPubKey = GetScriptForDestination(CScriptID(redeemscript));
|
||||||
|
|
||||||
scriptPubKey.clear();
|
|
||||||
scriptPubKey << OP_HASH160 << ToByteVector(CScriptID(redeemscript)) << OP_EQUAL;
|
|
||||||
|
|
||||||
keystore.AddCScript(redeemscript);
|
keystore.AddCScript(redeemscript);
|
||||||
keystore.AddCScript(redeemscript_inner);
|
keystore.AddCScript(redeemscript_inner);
|
||||||
|
@ -511,14 +501,9 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
|
||||||
{
|
{
|
||||||
CBasicKeyStore keystore;
|
CBasicKeyStore keystore;
|
||||||
|
|
||||||
CScript witnessscript, redeemscript;
|
CScript redeemscript = GetScriptForDestination(pubkeys[0].GetID());
|
||||||
redeemscript << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
|
CScript witnessscript = GetScriptForDestination(CScriptID(redeemscript));
|
||||||
witnessscript << OP_HASH160 << ToByteVector(CScriptID(redeemscript)) << OP_EQUAL;
|
scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
|
||||||
|
|
||||||
uint256 scripthash;
|
|
||||||
CSHA256().Write(witnessscript.data(), witnessscript.size()).Finalize(scripthash.begin());
|
|
||||||
scriptPubKey.clear();
|
|
||||||
scriptPubKey << OP_0 << ToByteVector(scripthash);
|
|
||||||
|
|
||||||
keystore.AddCScript(witnessscript);
|
keystore.AddCScript(witnessscript);
|
||||||
keystore.AddCScript(redeemscript);
|
keystore.AddCScript(redeemscript);
|
||||||
|
@ -532,13 +517,8 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
|
||||||
{
|
{
|
||||||
CBasicKeyStore keystore;
|
CBasicKeyStore keystore;
|
||||||
|
|
||||||
CScript witnessscript;
|
CScript witnessscript = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0].GetID()));
|
||||||
witnessscript << OP_0 << ToByteVector(pubkeys[0].GetID());
|
scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
|
||||||
|
|
||||||
scriptPubKey.clear();
|
|
||||||
uint256 scripthash;
|
|
||||||
CSHA256().Write(witnessscript.data(), witnessscript.size()).Finalize(scripthash.begin());
|
|
||||||
scriptPubKey << OP_0 << ToByteVector(scripthash);
|
|
||||||
|
|
||||||
keystore.AddCScript(witnessscript);
|
keystore.AddCScript(witnessscript);
|
||||||
keystore.AddCScript(scriptPubKey);
|
keystore.AddCScript(scriptPubKey);
|
||||||
|
@ -551,16 +531,9 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
|
||||||
{
|
{
|
||||||
CBasicKeyStore keystore;
|
CBasicKeyStore keystore;
|
||||||
|
|
||||||
CScript witnessscript_inner;
|
CScript witnessscript_inner = GetScriptForDestination(pubkeys[0].GetID());
|
||||||
witnessscript_inner << OP_DUP << OP_HASH160 << ToByteVector(pubkeys[0].GetID()) << OP_EQUALVERIFY << OP_CHECKSIG;
|
CScript witnessscript = GetScriptForDestination(WitnessV0ScriptHash(witnessscript_inner));
|
||||||
uint256 scripthash;
|
scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessscript));
|
||||||
CSHA256().Write(witnessscript_inner.data(), witnessscript_inner.size()).Finalize(scripthash.begin());
|
|
||||||
CScript witnessscript;
|
|
||||||
witnessscript << OP_0 << ToByteVector(scripthash);
|
|
||||||
|
|
||||||
scriptPubKey.clear();
|
|
||||||
CSHA256().Write(witnessscript.data(), witnessscript.size()).Finalize(scripthash.begin());
|
|
||||||
scriptPubKey << OP_0 << ToByteVector(scripthash);
|
|
||||||
|
|
||||||
keystore.AddCScript(witnessscript_inner);
|
keystore.AddCScript(witnessscript_inner);
|
||||||
keystore.AddCScript(witnessscript);
|
keystore.AddCScript(witnessscript);
|
||||||
|
@ -575,8 +548,7 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
|
||||||
CBasicKeyStore keystore;
|
CBasicKeyStore keystore;
|
||||||
keystore.AddKey(keys[0]);
|
keystore.AddKey(keys[0]);
|
||||||
|
|
||||||
scriptPubKey.clear();
|
scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(pubkeys[0].GetID()));
|
||||||
scriptPubKey << OP_0 << ToByteVector(pubkeys[0].GetID());
|
|
||||||
|
|
||||||
// Keystore implicitly has key and P2SH redeemScript
|
// Keystore implicitly has key and P2SH redeemScript
|
||||||
keystore.AddCScript(scriptPubKey);
|
keystore.AddCScript(scriptPubKey);
|
||||||
|
@ -589,8 +561,7 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
|
||||||
CBasicKeyStore keystore;
|
CBasicKeyStore keystore;
|
||||||
keystore.AddKey(uncompressedKey);
|
keystore.AddKey(uncompressedKey);
|
||||||
|
|
||||||
scriptPubKey.clear();
|
scriptPubKey = GetScriptForDestination(WitnessV0KeyHash(uncompressedPubkey.GetID()));
|
||||||
scriptPubKey << OP_0 << ToByteVector(uncompressedPubkey.GetID());
|
|
||||||
|
|
||||||
// Keystore has key, but no P2SH redeemScript
|
// Keystore has key, but no P2SH redeemScript
|
||||||
result = IsMine(keystore, scriptPubKey);
|
result = IsMine(keystore, scriptPubKey);
|
||||||
|
@ -606,11 +577,7 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
|
||||||
{
|
{
|
||||||
CBasicKeyStore keystore;
|
CBasicKeyStore keystore;
|
||||||
|
|
||||||
scriptPubKey.clear();
|
scriptPubKey = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
|
||||||
scriptPubKey << OP_2 <<
|
|
||||||
ToByteVector(uncompressedPubkey) <<
|
|
||||||
ToByteVector(pubkeys[1]) <<
|
|
||||||
OP_2 << OP_CHECKMULTISIG;
|
|
||||||
|
|
||||||
// Keystore does not have any keys
|
// Keystore does not have any keys
|
||||||
result = IsMine(keystore, scriptPubKey);
|
result = IsMine(keystore, scriptPubKey);
|
||||||
|
@ -641,14 +608,8 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
|
||||||
keystore.AddKey(uncompressedKey);
|
keystore.AddKey(uncompressedKey);
|
||||||
keystore.AddKey(keys[1]);
|
keystore.AddKey(keys[1]);
|
||||||
|
|
||||||
CScript redeemScript;
|
CScript redeemScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
|
||||||
redeemScript << OP_2 <<
|
scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
|
||||||
ToByteVector(uncompressedPubkey) <<
|
|
||||||
ToByteVector(pubkeys[1]) <<
|
|
||||||
OP_2 << OP_CHECKMULTISIG;
|
|
||||||
|
|
||||||
scriptPubKey.clear();
|
|
||||||
scriptPubKey << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
|
|
||||||
|
|
||||||
// Keystore has no redeemScript
|
// Keystore has no redeemScript
|
||||||
result = IsMine(keystore, scriptPubKey);
|
result = IsMine(keystore, scriptPubKey);
|
||||||
|
@ -666,18 +627,8 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
|
||||||
keystore.AddKey(keys[0]);
|
keystore.AddKey(keys[0]);
|
||||||
keystore.AddKey(keys[1]);
|
keystore.AddKey(keys[1]);
|
||||||
|
|
||||||
CScript witnessScript;
|
CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
|
||||||
witnessScript << OP_2 <<
|
scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
|
||||||
ToByteVector(pubkeys[0]) <<
|
|
||||||
ToByteVector(pubkeys[1]) <<
|
|
||||||
OP_2 << OP_CHECKMULTISIG;
|
|
||||||
|
|
||||||
uint256 scriptHash;
|
|
||||||
CSHA256().Write(&witnessScript[0], witnessScript.size())
|
|
||||||
.Finalize(scriptHash.begin());
|
|
||||||
|
|
||||||
scriptPubKey.clear();
|
|
||||||
scriptPubKey << OP_0 << ToByteVector(scriptHash);
|
|
||||||
|
|
||||||
// Keystore has keys, but no witnessScript or P2SH redeemScript
|
// Keystore has keys, but no witnessScript or P2SH redeemScript
|
||||||
result = IsMine(keystore, scriptPubKey);
|
result = IsMine(keystore, scriptPubKey);
|
||||||
|
@ -700,18 +651,8 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
|
||||||
keystore.AddKey(uncompressedKey);
|
keystore.AddKey(uncompressedKey);
|
||||||
keystore.AddKey(keys[1]);
|
keystore.AddKey(keys[1]);
|
||||||
|
|
||||||
CScript witnessScript;
|
CScript witnessScript = GetScriptForMultisig(2, {uncompressedPubkey, pubkeys[1]});
|
||||||
witnessScript << OP_2 <<
|
scriptPubKey = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
|
||||||
ToByteVector(uncompressedPubkey) <<
|
|
||||||
ToByteVector(pubkeys[1]) <<
|
|
||||||
OP_2 << OP_CHECKMULTISIG;
|
|
||||||
|
|
||||||
uint256 scriptHash;
|
|
||||||
CSHA256().Write(&witnessScript[0], witnessScript.size())
|
|
||||||
.Finalize(scriptHash.begin());
|
|
||||||
|
|
||||||
scriptPubKey.clear();
|
|
||||||
scriptPubKey << OP_0 << ToByteVector(scriptHash);
|
|
||||||
|
|
||||||
// Keystore has keys, but no witnessScript or P2SH redeemScript
|
// Keystore has keys, but no witnessScript or P2SH redeemScript
|
||||||
result = IsMine(keystore, scriptPubKey);
|
result = IsMine(keystore, scriptPubKey);
|
||||||
|
@ -732,21 +673,9 @@ BOOST_AUTO_TEST_CASE(script_standard_IsMine)
|
||||||
{
|
{
|
||||||
CBasicKeyStore keystore;
|
CBasicKeyStore keystore;
|
||||||
|
|
||||||
CScript witnessScript;
|
CScript witnessScript = GetScriptForMultisig(2, {pubkeys[0], pubkeys[1]});
|
||||||
witnessScript << OP_2 <<
|
CScript redeemScript = GetScriptForDestination(WitnessV0ScriptHash(witnessScript));
|
||||||
ToByteVector(pubkeys[0]) <<
|
scriptPubKey = GetScriptForDestination(CScriptID(redeemScript));
|
||||||
ToByteVector(pubkeys[1]) <<
|
|
||||||
OP_2 << OP_CHECKMULTISIG;
|
|
||||||
|
|
||||||
uint256 scriptHash;
|
|
||||||
CSHA256().Write(&witnessScript[0], witnessScript.size())
|
|
||||||
.Finalize(scriptHash.begin());
|
|
||||||
|
|
||||||
CScript redeemScript;
|
|
||||||
redeemScript << OP_0 << ToByteVector(scriptHash);
|
|
||||||
|
|
||||||
scriptPubKey.clear();
|
|
||||||
scriptPubKey << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL;
|
|
||||||
|
|
||||||
// Keystore has no witnessScript, P2SH redeemScript, or keys
|
// Keystore has no witnessScript, P2SH redeemScript, or keys
|
||||||
result = IsMine(keystore, scriptPubKey);
|
result = IsMine(keystore, scriptPubKey);
|
||||||
|
|
|
@ -4520,9 +4520,7 @@ CTxDestination CWallet::AddAndGetDestinationForScript(const CScript& script, Out
|
||||||
return CScriptID(script);
|
return CScriptID(script);
|
||||||
case OutputType::P2SH_SEGWIT:
|
case OutputType::P2SH_SEGWIT:
|
||||||
case OutputType::BECH32: {
|
case OutputType::BECH32: {
|
||||||
WitnessV0ScriptHash hash;
|
CTxDestination witdest = WitnessV0ScriptHash(script);
|
||||||
CSHA256().Write(script.data(), script.size()).Finalize(hash.begin());
|
|
||||||
CTxDestination witdest = hash;
|
|
||||||
CScript witprog = GetScriptForDestination(witdest);
|
CScript witprog = GetScriptForDestination(witdest);
|
||||||
// Check if the resulting program is solvable (i.e. doesn't use an uncompressed key)
|
// Check if the resulting program is solvable (i.e. doesn't use an uncompressed key)
|
||||||
if (!IsSolvable(*this, witprog)) return CScriptID(script);
|
if (!IsSolvable(*this, witprog)) return CScriptID(script);
|
||||||
|
|
Loading…
Add table
Reference in a new issue