mirror of
https://github.com/SeedSigner/seedsigner.git
synced 2026-10-06 07:28:24 +00:00
more work
This commit is contained in:
@@ -80,23 +80,30 @@ class DecodeQR:
|
||||
|
||||
def getPSBT(self):
|
||||
if self.complete:
|
||||
try:
|
||||
if self.qr_type == QRType.PSBTUR2:
|
||||
cbor = self.ur_decoder.result_message().cbor
|
||||
return psbt.PSBT.parse(cbor_decode(cbor))
|
||||
elif self.qr_type == QRType.PSBTSPECTER:
|
||||
return psbt.PSBT.parse(self.specter_qr.getData())
|
||||
elif self.qr_type == QRType.PSBTURLEGACY:
|
||||
return psbt.PSBT.parse(self.legacy_ur.getData())
|
||||
elif self.qr_type == QRType.PSBTBASE64:
|
||||
return psbt.PSBT.parse(self.base64_qr.getData())
|
||||
except:
|
||||
return None
|
||||
data = self.getDataPSBT()
|
||||
if data != None:
|
||||
try:
|
||||
return psbt.PSBT.parse(data)
|
||||
except:
|
||||
return None
|
||||
return None
|
||||
|
||||
def getDataPSBT(self):
|
||||
if self.complete:
|
||||
if self.qr_type == QRType.PSBTUR2:
|
||||
cbor = self.ur_decoder.result_message().cbor
|
||||
return cbor_decode(cbor)
|
||||
elif self.qr_type == QRType.PSBTSPECTER:
|
||||
return self.specter_qr.getData()
|
||||
elif self.qr_type == QRType.PSBTURLEGACY:
|
||||
return self.legacy_ur.getData()
|
||||
elif self.qr_type == QRType.PSBTBASE64:
|
||||
return self.base64_qr.getData()
|
||||
return None
|
||||
|
||||
def getBase64PSBT(self):
|
||||
if self.complete:
|
||||
data = self.getData()
|
||||
data = self.getDataPSBT()
|
||||
b64_psbt = b2a_base64(data)
|
||||
|
||||
if b64_psbt[-1:] == b"\n":
|
||||
@@ -163,7 +170,7 @@ class DecodeQR:
|
||||
return QRType.PSBTURLEGACY
|
||||
elif re.search(r'\d{48,96}', s):
|
||||
return QRType.SEEDSSQR
|
||||
elif DecodePSBTQR.isBase64PSBT(s):
|
||||
elif DecodeQR.isBase64PSBT(s):
|
||||
return QRType.PSBTBASE64
|
||||
else:
|
||||
return QRType.INVALID
|
||||
|
||||
@@ -57,7 +57,7 @@ class UREncodePSBTQR:
|
||||
|
||||
def __init__(self, p, qr_density):
|
||||
self.psbt = p
|
||||
self.qr_max_fragement_size = 50
|
||||
self.qr_max_fragement_size = 10
|
||||
|
||||
cbor_encoder = CBOREncoder()
|
||||
cbor_encoder.encodeBytes(self.psbt.serialize())
|
||||
@@ -66,9 +66,9 @@ class UREncodePSBTQR:
|
||||
self.ur2_encode = UREncoder(qr_ur_bytes,self.qr_max_fragement_size,0)
|
||||
|
||||
if qr_density == EncodePSBTQRDensity.LOW:
|
||||
self.qr_max_fragement_size = 20
|
||||
self.qr_max_fragement_size = 10
|
||||
elif qr_density == EncodePSBTQRDensity.MEDIUM:
|
||||
self.qr_max_fragement_size = 50
|
||||
self.qr_max_fragement_size = 20
|
||||
elif qr_density == EncodePSBTQRDensity.HIGH:
|
||||
self.qr_max_fragement_size = 80
|
||||
|
||||
|
||||
@@ -14,28 +14,48 @@ class PSBTParser():
|
||||
self.spend_amount = 0
|
||||
self.change_amount = 0
|
||||
self.fee_amount = 0
|
||||
self.input_amount = 0
|
||||
self.destination_addresses = []
|
||||
self.self_addresses = []
|
||||
|
||||
self.seed = None
|
||||
self.root = None
|
||||
|
||||
if self.seed_phrase != None:
|
||||
self.parse(self.psbt,self.seed_phrase,self.passphrase,self.network)
|
||||
|
||||
def __setSeedRoot(self, seed_phrase, passphrase, network):
|
||||
self.seed = bip39.mnemonic_to_seed(" ".join(seed_phrase).strip(), passphrase)
|
||||
self.root = bip32.HDKey.from_seed(self.seed, version=NETWORKS[network]["xprv"])
|
||||
|
||||
def parse(self, p, seed_phrase=[], passphrase="", network="main"):
|
||||
if p == None:
|
||||
is_psbt_empty = False
|
||||
try:
|
||||
if p == None:
|
||||
is_psbt_empty = True
|
||||
except:
|
||||
pass
|
||||
|
||||
if is_psbt_empty:
|
||||
return False
|
||||
|
||||
if seed_phrase == None or len(seed_phrase) not in (12,24):
|
||||
if len(seed_phrase) == 0:
|
||||
return False
|
||||
|
||||
self.__setSeedRoot(seed_phrase,passphrase,network)
|
||||
|
||||
rt = self.__parseInputs()
|
||||
if rt == False:
|
||||
return False
|
||||
|
||||
rt = self.__parseOutputs(self.seed_phrase, self.passphrase, self.network)
|
||||
rt = self.__parseOutputs()
|
||||
if rt == False:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def __parseInputs(self):
|
||||
self.psbt.input_amount = 0
|
||||
self.input_amount = 0
|
||||
for inp in self.psbt.inputs:
|
||||
self.input_amount += inp.witness_utxo.value
|
||||
inp_policy = PSBTParser.__get_policy(inp, inp.witness_utxo.script_pubkey, self.psbt.xpubs)
|
||||
@@ -45,11 +65,7 @@ class PSBTParser():
|
||||
if self.policy != inp_policy:
|
||||
raise RuntimeError("Mixed inputs in the transaction")
|
||||
|
||||
def __parseOutputs(self, seed_phrase, passphrase, network):
|
||||
seed = bip39.mnemonic_to_seed((" ".join(seed_phrase)).strip(), passphrase)
|
||||
root = bip32.HDKey.from_seed(seed, version=NETWORKS[network]["xprv"])
|
||||
fingerprint = root.child(0).fingerprint
|
||||
|
||||
def __parseOutputs(self):
|
||||
self.spend_amount = 0
|
||||
self.change_amount = 0
|
||||
self.fee_amount = 0
|
||||
@@ -75,27 +91,30 @@ class PSBTParser():
|
||||
sc = script.p2wsh(out.witness_script)
|
||||
elif self.policy["type"] == "p2sh-p2wsh":
|
||||
sc = script.p2sh(script.p2wsh(out.witness_script))
|
||||
|
||||
# single-sig
|
||||
elif "pkh" in self.policy["type"] and fingerprint != None:
|
||||
for pub in out.bip32_derivations:
|
||||
# check if it is our key
|
||||
if out.bip32_derivations[pub].fingerprint == fingerprint:
|
||||
hdkey = root.derive(out.bip32_derivations[pub].derivation)
|
||||
mypub = hdkey.key.get_public_key()
|
||||
if mypub != pub:
|
||||
raise ValueError("Derivation path doesn't look right")
|
||||
# now check if provided scriptpubkey matches
|
||||
sc = script.p2wpkh(mypub)
|
||||
if sc == self.psbt.tx.vout[i].script_pubkey:
|
||||
is_change = True
|
||||
elif "pkh" in self.policy["type"]:
|
||||
my_pubkey = None
|
||||
# should be one or zero for single-key addresses
|
||||
if len(out.bip32_derivations.values()) > 0:
|
||||
der = list(out.bip32_derivations.values())[0].derivation
|
||||
my_pubkey = self.root.derive(der)
|
||||
if self.policy["type"] == "p2wpkh" and my_pubkey != None:
|
||||
sc = script.p2wpkh(my_pubkey)
|
||||
elif self.policy["type"] == "p2sh-p2wpkh" and my_pubkey != None:
|
||||
sc = script.p2sh(script.p2wpkh(my_pubkey))
|
||||
|
||||
if sc.data == self.psbt.tx.vout[i].script_pubkey.data:
|
||||
is_change = True
|
||||
|
||||
if sc.data == self.psbt.tx.vout[i].script_pubkey.data:
|
||||
is_change = True
|
||||
if is_change:
|
||||
self.change_amount += self.psbt.tx.vout[i].value
|
||||
self.self_addresses.append(self.psbt.tx.vout[i].script_pubkey.address(NETWORKS[network]))
|
||||
self.self_addresses.append(self.psbt.tx.vout[i].script_pubkey.address(NETWORKS[self.network]))
|
||||
else:
|
||||
self.spend_amount += self.tx.vout[i].value
|
||||
self.destination_addresses.append(self.tx.vout[i].script_pubkey.address(NETWORKS[network]))
|
||||
self.spend_amount += self.psbt.tx.vout[i].value
|
||||
self.destination_addresses.append(self.psbt.tx.vout[i].script_pubkey.address(NETWORKS[self.network]))
|
||||
|
||||
self.fee_amount = self.psbt.fee()
|
||||
return True
|
||||
@@ -132,10 +151,10 @@ class PSBTParser():
|
||||
if "p2wsh" in script_type and scope.witness_script is not None:
|
||||
m, n, pubkeys = PSBTParser.__parse_multisig(scope.witness_script)
|
||||
# check pubkeys are derived from cosigners
|
||||
if len(pubkeys) > 0:
|
||||
try:
|
||||
cosigners = PSBTParser.__get_cosigners(pubkeys, scope.bip32_derivations, xpubs)
|
||||
policy.update({"m": m, "n": n, "cosigners": cosigners})
|
||||
else:
|
||||
except:
|
||||
policy.update({"m": m, "n": n})
|
||||
return policy
|
||||
|
||||
|
||||
+44
-44
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user