mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-22 06:18:07 +00:00
feat(core): Support external inputs in TxWeightCalculator.
This commit is contained in:
parent
f9f0b517e2
commit
56ac799626
@ -92,7 +92,7 @@ def verify_nonownership(
|
||||
|
||||
# Verify the BIP-322 SignatureProof.
|
||||
|
||||
proof_body = proof[: r.offset]
|
||||
proof_body = memoryview(proof)[: r.offset]
|
||||
sighash = hashlib.sha256(proof_body)
|
||||
sighash.update(script_pubkey)
|
||||
if commitment_data:
|
||||
@ -110,6 +110,26 @@ def verify_nonownership(
|
||||
return not_owned
|
||||
|
||||
|
||||
def read_scriptsig_witness(ownership_proof: bytes) -> tuple[memoryview, memoryview]:
|
||||
try:
|
||||
r = utils.BufferReader(ownership_proof)
|
||||
if r.read_memoryview(4) != _VERSION_MAGIC:
|
||||
raise wire.DataError("Unknown format of proof of ownership")
|
||||
|
||||
flags = r.get()
|
||||
if flags & 0b1111_1110:
|
||||
raise wire.DataError("Unknown flags in proof of ownership")
|
||||
|
||||
# Skip ownership IDs.
|
||||
id_count = read_bitcoin_varint(r)
|
||||
r.read_memoryview(_OWNERSHIP_ID_LEN * id_count)
|
||||
|
||||
return read_bip322_signature_proof(r)
|
||||
|
||||
except (ValueError, EOFError):
|
||||
raise wire.DataError("Invalid proof of ownership")
|
||||
|
||||
|
||||
def get_identifier(script_pubkey: bytes, keychain: Keychain) -> bytes:
|
||||
# k = Key(m/"SLIP-0019"/"Ownership identification key")
|
||||
node = keychain.derive_slip21(_OWNERSHIP_ID_KEY_PATH)
|
||||
|
@ -10,7 +10,7 @@ from micropython import const
|
||||
from trezor import wire
|
||||
from trezor.enums import InputScriptType
|
||||
|
||||
from .. import common
|
||||
from .. import common, ownership
|
||||
|
||||
if False:
|
||||
from trezor.messages import TxInput
|
||||
@ -87,6 +87,24 @@ class TxWeightCalculator:
|
||||
else:
|
||||
self.counter += 4 # empty script_sig (1 byte)
|
||||
self.counter += 1 + input_script_size # discounted witness
|
||||
elif i.script_type == InputScriptType.EXTERNAL:
|
||||
if i.ownership_proof:
|
||||
script_sig, witness = ownership.read_scriptsig_witness(
|
||||
i.ownership_proof
|
||||
)
|
||||
script_sig_size = len(script_sig)
|
||||
witness_size = len(witness)
|
||||
else:
|
||||
script_sig_size = len(i.script_sig or b"")
|
||||
witness_size = len(i.witness or b"")
|
||||
|
||||
if witness_size > 1:
|
||||
self.segwit_inputs_count += 1
|
||||
|
||||
self.counter += 4 * (self.varint_size(script_sig_size) + script_sig_size)
|
||||
self.counter += witness_size
|
||||
else:
|
||||
raise wire.DataError("Invalid script type")
|
||||
|
||||
def add_output(self, script: bytes) -> None:
|
||||
self.outputs_count += 1
|
||||
|
@ -304,5 +304,59 @@ class TestCalculateTxWeight(unittest.TestCase):
|
||||
# average length, so the caculator should estimate 285 bytes of witness data.
|
||||
self.assertEqual(calculator.get_total(), 4*477 + 285)
|
||||
|
||||
def test_external_txweight(self):
|
||||
coin = coins.by_name('Testnet')
|
||||
|
||||
inp1 = TxInput(
|
||||
amount=100000,
|
||||
prev_hash=unhexlify('e5b7e21b5ba720e81efd6bfa9f854ababdcddc75a43bfa60bf0fe069cfd1bb8a'),
|
||||
prev_index=0,
|
||||
script_type=InputScriptType.EXTERNAL,
|
||||
script_pubkey=unhexlify('00149c02608d469160a92f40fdf8c6ccced029493088'),
|
||||
ownership_proof=unhexlify(
|
||||
'534c001900016b2055d8190244b2ed2d46513c40658a574d3bc2deb6969c0535bb818b44d2c40002483045022100d4ad0374c922848c71d913fba59c81b9075e0d33e884d953f0c4b4806b8ffd0c022024740e6717a2b6a5aa03148c3a28b02c713b4e30fc8aeae67fa69eb20e8ddcd9012103505f0d82bbdd251511591b34f36ad5eea37d3220c2b81a1189084431ddb3aa3d'
|
||||
),
|
||||
)
|
||||
|
||||
inp2 = TxInput(
|
||||
address_n=[84 | 0x80000000, 1 | 0x80000000, 0 | 0x80000000, 0, 0],
|
||||
prev_hash=unhexlify('70f9871eb03a38405cfd7a01e0e1448678132d815e2c9f552ad83ae23969509e'),
|
||||
prev_index=0,
|
||||
amount=100000,
|
||||
script_type=InputScriptType.SPENDWITNESS,
|
||||
)
|
||||
|
||||
inp3 = TxInput(
|
||||
# tb1qldlynaqp0hy4zc2aag3pkenzvxy65saesxw3wd
|
||||
# address_n=parse_path("m/84h/1h/0h/0/1"),
|
||||
prev_hash=unhexlify('65b768dacccfb209eebd95a1fb80a04f1dd6a3abc6d7b41d5e9d9f91605b37d9'),
|
||||
prev_index=0,
|
||||
amount=10000,
|
||||
script_type=InputScriptType.EXTERNAL,
|
||||
script_pubkey=unhexlify('0014fb7e49f4017dc951615dea221b66626189aa43b9'),
|
||||
script_sig=bytes(0),
|
||||
witness=unhexlify(
|
||||
'024730440220432ac60461de52713ad543cbb1484f7eca1a72c615d539b3f42f5668da4501d2022063786a6d6940a5c1ed9c2d2fd02cef90b6c01ddd84829c946561e15be6c0aae1012103dcf3bc936ecb2ec57b8f468050abce8c8756e75fd74273c9977744b1a0be7d03'
|
||||
),
|
||||
)
|
||||
|
||||
out1 = TxOutput(
|
||||
address="tb1qnspxpr2xj9s2jt6qlhuvdnxw6q55jvygcf89r2",
|
||||
amount=100000 + 100000 + 10000,
|
||||
script_type=OutputScriptType.PAYTOWITNESS,
|
||||
)
|
||||
|
||||
calculator = TxWeightCalculator()
|
||||
calculator.add_input(inp1)
|
||||
calculator.add_input(inp2)
|
||||
calculator.add_input(inp3)
|
||||
calculator.add_output(output_derive_script(out1.address, coin))
|
||||
|
||||
self.assertEqual(calculator.get_total(), 4*164 + 325)
|
||||
# non-segwit: header, inputs, outputs, locktime 4*(4+1+3*41+1+31+4) = 4*164
|
||||
# segwit: segwit header, 2x estimated witness (including stack item count)
|
||||
# and 1x exact witness (including stack item count) 1*(2+108+108+107) = 325
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
Loading…
Reference in New Issue
Block a user