From 70aaa30ce09bb35c7f036aad53583e2cf9a9eafb Mon Sep 17 00:00:00 2001 From: odudex Date: Wed, 29 Jan 2025 14:16:53 -0300 Subject: [PATCH 1/2] replace "set" objects with OrderedDict to ensure reproducible signatures --- src/embit/psbt.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/embit/psbt.py b/src/embit/psbt.py index 54497c2..db62200 100644 --- a/src/embit/psbt.py +++ b/src/embit/psbt.py @@ -977,22 +977,25 @@ def sign_with(self, root, sighash=SIGHASH.DEFAULT) -> int: continue # get all possible derivations with matching fingerprint - bip32_derivations = set() + bip32_derivations = OrderedDict() # OrderedDict to keep order if fingerprint: # if taproot derivations are present add them for pub in inp.taproot_bip32_derivations: (_leafs, derivation) = inp.taproot_bip32_derivations[pub] if derivation.fingerprint == fingerprint: - bip32_derivations.add((pub, derivation)) + # Add only if not already present + if (pub, derivation) not in bip32_derivations: + bip32_derivations[(pub, derivation)] = True # segwit and legacy derivations for pub in inp.bip32_derivations: derivation = inp.bip32_derivations[pub] if derivation.fingerprint == fingerprint: - bip32_derivations.add((pub, derivation)) + if (pub, derivation) not in bip32_derivations: + bip32_derivations[(pub, derivation)] = True # get derived keys for signing - derived_keypairs = set() # (prv, pub) + derived_keypairs = OrderedDict() # (prv, pub) for pub, derivation in bip32_derivations: der = derivation.derivation # descriptor key has origin derivation that we take into account @@ -1008,7 +1011,9 @@ def sign_with(self, root, sighash=SIGHASH.DEFAULT) -> int: if hdkey.xonly() != pub.xonly(): raise PSBTError("Derivation path doesn't look right") - derived_keypairs.add((hdkey.key, pub)) + # Insert into derived_keypairs if not present + if (hdkey.key, pub) not in derived_keypairs: + derived_keypairs[(hdkey.key, pub)] = True # sign with taproot key if inp.is_taproot: From 8fac33e99e75dafeb294e8bca4a6acad6fecf99c Mon Sep 17 00:00:00 2001 From: odudex Date: Thu, 30 Jan 2025 10:32:16 -0300 Subject: [PATCH 2/2] reproducible PSBT sigs - replicate object type replacement on psbtview --- src/embit/psbtview.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/embit/psbtview.py b/src/embit/psbtview.py index 8012654..4bcd664 100644 --- a/src/embit/psbtview.py +++ b/src/embit/psbtview.py @@ -14,6 +14,7 @@ Makes sense to run gc.collect() after processing of each scope to free memory. """ # TODO: refactor, a lot of code is duplicated here from transaction.py +from collections import OrderedDict import hashlib from . import compact from . import ec @@ -742,22 +743,25 @@ def sign_input( return 0 # get all possible derivations with matching fingerprint - bip32_derivations = set() + bip32_derivations = OrderedDict() if fingerprint: # if taproot derivations are present add them for pub in inp.taproot_bip32_derivations: (_leafs, derivation) = inp.taproot_bip32_derivations[pub] if derivation.fingerprint == fingerprint: - bip32_derivations.add((pub, derivation)) + # Add only if not already present + if (pub, derivation) not in bip32_derivations: + bip32_derivations[(pub, derivation)] = True # segwit and legacy derivations for pub in inp.bip32_derivations: derivation = inp.bip32_derivations[pub] if derivation.fingerprint == fingerprint: - bip32_derivations.add((pub, derivation)) + if (pub, derivation) not in bip32_derivations: + bip32_derivations[(pub, derivation)] = True # get derived keys for signing - derived_keypairs = set() # (prv, pub) + derived_keypairs = OrderedDict() # (prv, pub) for pub, derivation in bip32_derivations: der = derivation.derivation # descriptor key has origin derivation that we take into account @@ -773,7 +777,9 @@ def sign_input( if hdkey.xonly() != pub.xonly(): raise PSBTError("Derivation path doesn't look right") - derived_keypairs.add((hdkey.key, pub)) + # Insert into derived_keypairs if not present + if (hdkey.key, pub) not in derived_keypairs: + derived_keypairs[(hdkey.key, pub)] = True counter = 0 # sign with taproot key