aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntoine Poinsot <darosior@protonmail.com>2023-02-11 12:57:52 +0100
committerAntoine Poinsot <darosior@protonmail.com>2023-02-13 15:39:25 +0100
commit6c7a17a8e0eec377f83ed1399f003ae70b898270 (patch)
tree3c3d8a5eb4d3078e287c27d6921a2c55611d65e4
parent840a396029316896beda46600aec3c1af09a899c (diff)
psbt: support externally provided preimages for Miniscript satisfaction
Co-Authored-By: Andrew Chow <github@achow101.com>
-rw-r--r--src/psbt.cpp12
-rwxr-xr-xtest/functional/wallet_miniscript.py25
2 files changed, 35 insertions, 2 deletions
diff --git a/src/psbt.cpp b/src/psbt.cpp
index 461987c503..701b085c20 100644
--- a/src/psbt.cpp
+++ b/src/psbt.cpp
@@ -132,6 +132,18 @@ void PSBTInput::FillSignatureData(SignatureData& sigdata) const
for (const auto& [pubkey, leaf_origin] : m_tap_bip32_paths) {
sigdata.taproot_misc_pubkeys.emplace(pubkey, leaf_origin);
}
+ for (const auto& [hash, preimage] : ripemd160_preimages) {
+ sigdata.ripemd160_preimages.emplace(std::vector<unsigned char>(hash.begin(), hash.end()), preimage);
+ }
+ for (const auto& [hash, preimage] : sha256_preimages) {
+ sigdata.sha256_preimages.emplace(std::vector<unsigned char>(hash.begin(), hash.end()), preimage);
+ }
+ for (const auto& [hash, preimage] : hash160_preimages) {
+ sigdata.hash160_preimages.emplace(std::vector<unsigned char>(hash.begin(), hash.end()), preimage);
+ }
+ for (const auto& [hash, preimage] : hash256_preimages) {
+ sigdata.hash256_preimages.emplace(std::vector<unsigned char>(hash.begin(), hash.end()), preimage);
+ }
}
void PSBTInput::FromSignatureData(const SignatureData& sigdata)
diff --git a/test/functional/wallet_miniscript.py b/test/functional/wallet_miniscript.py
index e8b89513d0..7e3cbcbda3 100755
--- a/test/functional/wallet_miniscript.py
+++ b/test/functional/wallet_miniscript.py
@@ -5,6 +5,7 @@
"""Test Miniscript descriptors integration in the wallet."""
from test_framework.descriptors import descsum_create
+from test_framework.psbt import PSBT, PSBT_IN_SHA256
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import assert_equal
@@ -60,6 +61,17 @@ MINISCRIPTS_PRIV = [
"sigs_count": 3,
"stack_size": 5,
},
+ # The same policy but we provide the preimage. This path will be chosen as it's a smaller witness.
+ {
+ "ms": f"andor(ndv:older(2),and_v(v:pk({TPRVS[0]}),sha256(61e33e9dbfefc45f6a194187684d278f789fd4d5e207a357e79971b6519a8b12)),and_v(v:pkh({TPRVS[1]}),pk({TPRVS[2]}/*)))",
+ "sequence": 2,
+ "locktime": None,
+ "sigs_count": 3,
+ "stack_size": 4,
+ "sha256_preimages": {
+ "61e33e9dbfefc45f6a194187684d278f789fd4d5e207a357e79971b6519a8b12": "e8774f330f5f330c23e8bbefc5595cb87009ddb7ac3b8deaaa8e9e41702d919c"
+ },
+ },
# Signature with a relative timelock
{
"ms": f"and_v(v:older(2),pk({TPRVS[0]}/*))",
@@ -167,7 +179,9 @@ class WalletMiniscriptTest(BitcoinTestFramework):
utxo = self.ms_wo_wallet.listunspent(minconf=0, addresses=[addr])[0]
assert utxo["txid"] == txid and utxo["solvable"]
- def signing_test(self, ms, sequence, locktime, sigs_count, stack_size):
+ def signing_test(
+ self, ms, sequence, locktime, sigs_count, stack_size, sha256_preimages
+ ):
self.log.info(f"Importing private Miniscript '{ms}'")
desc = descsum_create(f"wsh({ms})")
res = self.ms_sig_wallet.importdescriptors(
@@ -208,6 +222,12 @@ class WalletMiniscriptTest(BitcoinTestFramework):
)
self.log.info("Signing it and checking the satisfaction.")
+ if sha256_preimages is not None:
+ psbt = PSBT.from_base64(psbt)
+ for (h, preimage) in sha256_preimages.items():
+ k = PSBT_IN_SHA256.to_bytes(1, "big") + bytes.fromhex(h)
+ psbt.i[0].map[k] = bytes.fromhex(preimage)
+ psbt = psbt.to_base64()
res = self.ms_sig_wallet.walletprocesspsbt(psbt=psbt, finalize=False)
psbtin = self.nodes[0].rpc.decodepsbt(res["psbt"])["inputs"][0]
assert len(psbtin["partial_signatures"]) == sigs_count
@@ -258,7 +278,7 @@ class WalletMiniscriptTest(BitcoinTestFramework):
for ms in MINISCRIPTS:
self.watchonly_test(ms)
- # Test we can sign most Miniscript (all but ones requiring preimages, for now)
+ # Test we can sign for any Miniscript.
for ms in MINISCRIPTS_PRIV:
self.signing_test(
ms["ms"],
@@ -266,6 +286,7 @@ class WalletMiniscriptTest(BitcoinTestFramework):
ms["locktime"],
ms["sigs_count"],
ms["stack_size"],
+ ms.get("sha256_preimages"),
)