mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-24 15:28:10 +00:00
fix(core): Fix Decred transaction weight calculation.
This commit is contained in:
parent
3b44d44a12
commit
90792eb438
1
core/.changelog.d/2422.fixed
Normal file
1
core/.changelog.d/2422.fixed
Normal file
@ -0,0 +1 @@
|
||||
Fix Decred transaction weight calculation.
|
@ -7,6 +7,7 @@ from trezor.enums import DecredStakingSpendType, InputScriptType
|
||||
from trezor.messages import PrevOutput
|
||||
from trezor.utils import HashWriter, ensure
|
||||
|
||||
from apps.bitcoin.sign_tx.tx_weight import TxWeightCalculator
|
||||
from apps.common.writers import write_compact_size
|
||||
|
||||
from .. import multisig, scripts_decred, writers
|
||||
@ -40,7 +41,53 @@ if TYPE_CHECKING:
|
||||
from .sig_hasher import SigHasher
|
||||
|
||||
|
||||
# Decred input size (without script): 32 prevhash, 4 idx, 1 Decred tree, 4 sequence
|
||||
_TXSIZE_DECRED_INPUT = const(41)
|
||||
|
||||
# Decred script version: 2 bytes
|
||||
_TXSIZE_DECRED_SCRIPT_VERSION = const(2)
|
||||
|
||||
# Decred expiry size: 4 bytes in footer
|
||||
_TXSIZE_DECRED_EXPIRY = const(4)
|
||||
|
||||
# Decred witness size (without script): 8 byte amount, 4 byte block height, 4 byte block index
|
||||
_TXSIZE_DECRED_WITNESS = 16
|
||||
|
||||
|
||||
class DecredTxWeightCalculator(TxWeightCalculator):
|
||||
def get_base_weight(self) -> int:
|
||||
base_weight = super().get_base_weight()
|
||||
base_weight += 4 * _TXSIZE_DECRED_EXPIRY
|
||||
# Add witness input count.
|
||||
base_weight += 4 * self.compact_size_len(self.inputs_count)
|
||||
return base_weight
|
||||
|
||||
def add_input(self, i: TxInput) -> None:
|
||||
self.inputs_count += 1
|
||||
|
||||
# Input.
|
||||
self.counter += 4 * _TXSIZE_DECRED_INPUT
|
||||
|
||||
# Input witness.
|
||||
input_script_size = self.input_script_size(i)
|
||||
if i.script_type == InputScriptType.SPENDMULTISIG:
|
||||
# Decred fixed the the OP_FALSE bug in multisig.
|
||||
input_script_size -= 1 # Subtract one OP_FALSE byte.
|
||||
|
||||
self.counter += 4 * _TXSIZE_DECRED_WITNESS
|
||||
self.counter += 4 * self.compact_size_len(input_script_size)
|
||||
self.counter += 4 * input_script_size
|
||||
|
||||
def add_output(self, script: bytes) -> None:
|
||||
super().add_output(script)
|
||||
self.counter += 4 * _TXSIZE_DECRED_SCRIPT_VERSION
|
||||
|
||||
|
||||
class DecredApprover(BasicApprover):
|
||||
def __init__(self, tx: SignTx, coin: CoinInfo) -> None:
|
||||
super().__init__(tx, coin)
|
||||
self.weight = DecredTxWeightCalculator()
|
||||
|
||||
async def add_decred_sstx_submission(
|
||||
self, txo: TxOutput, script_pubkey: bytes
|
||||
) -> None:
|
||||
|
@ -48,9 +48,8 @@ class TxWeightCalculator:
|
||||
self.counter = 0
|
||||
self.segwit_inputs_count = 0
|
||||
|
||||
def add_input(self, i: TxInput) -> None:
|
||||
self.inputs_count += 1
|
||||
|
||||
@classmethod
|
||||
def input_script_size(cls, i: TxInput) -> int:
|
||||
script_type = i.script_type
|
||||
if common.input_is_external_unverified(i):
|
||||
assert i.script_pubkey is not None # checked in sanitize_tx_input
|
||||
@ -75,28 +74,31 @@ class TxWeightCalculator:
|
||||
n = len(i.multisig.nodes) if i.multisig.nodes else len(i.multisig.pubkeys)
|
||||
multisig_script_size = _TXSIZE_MULTISIGSCRIPT + n * (1 + _TXSIZE_PUBKEY)
|
||||
if script_type in common.SEGWIT_INPUT_SCRIPT_TYPES:
|
||||
multisig_script_size += self.compact_size_len(multisig_script_size)
|
||||
multisig_script_size += cls.compact_size_len(multisig_script_size)
|
||||
else:
|
||||
multisig_script_size += self.op_push_len(multisig_script_size)
|
||||
multisig_script_size += cls.op_push_len(multisig_script_size)
|
||||
|
||||
input_script_size = (
|
||||
return (
|
||||
1 # the OP_FALSE bug in multisig
|
||||
+ i.multisig.m * (1 + _TXSIZE_DER_SIGNATURE)
|
||||
+ multisig_script_size
|
||||
)
|
||||
elif script_type == InputScriptType.SPENDTAPROOT:
|
||||
input_script_size = 1 + _TXSIZE_SCHNORR_SIGNATURE
|
||||
return 1 + _TXSIZE_SCHNORR_SIGNATURE
|
||||
else:
|
||||
input_script_size = 1 + _TXSIZE_DER_SIGNATURE + 1 + _TXSIZE_PUBKEY
|
||||
return 1 + _TXSIZE_DER_SIGNATURE + 1 + _TXSIZE_PUBKEY
|
||||
|
||||
def add_input(self, i: TxInput) -> None:
|
||||
self.inputs_count += 1
|
||||
self.counter += 4 * _TXSIZE_INPUT
|
||||
input_script_size = self.input_script_size(i)
|
||||
|
||||
if script_type in common.NONSEGWIT_INPUT_SCRIPT_TYPES:
|
||||
if i.script_type in common.NONSEGWIT_INPUT_SCRIPT_TYPES:
|
||||
input_script_size += self.compact_size_len(input_script_size)
|
||||
self.counter += 4 * input_script_size
|
||||
elif script_type in common.SEGWIT_INPUT_SCRIPT_TYPES:
|
||||
elif i.script_type in common.SEGWIT_INPUT_SCRIPT_TYPES:
|
||||
self.segwit_inputs_count += 1
|
||||
if script_type == InputScriptType.SPENDP2SHWITNESS:
|
||||
if i.script_type == InputScriptType.SPENDP2SHWITNESS:
|
||||
# add script_sig size
|
||||
if i.multisig:
|
||||
self.counter += 4 * (2 + _TXSIZE_WITNESSSCRIPT)
|
||||
@ -105,7 +107,7 @@ class TxWeightCalculator:
|
||||
else:
|
||||
self.counter += 4 # empty script_sig (1 byte)
|
||||
self.counter += 1 + input_script_size # discounted witness
|
||||
elif script_type == InputScriptType.EXTERNAL:
|
||||
elif i.script_type == InputScriptType.EXTERNAL:
|
||||
if i.ownership_proof:
|
||||
script_sig, witness = ownership.read_scriptsig_witness(
|
||||
i.ownership_proof
|
||||
|
@ -86,8 +86,8 @@ class TestSignTxDecred(unittest.TestCase):
|
||||
outputs_count=1,
|
||||
)
|
||||
|
||||
# precomputed tx weight is 768
|
||||
fee_rate = 100_000 / (768 / 4)
|
||||
# precomputed tx weight is 864
|
||||
fee_rate = 100_000 / (864 / 4)
|
||||
|
||||
messages = [
|
||||
None,
|
||||
@ -246,8 +246,8 @@ class TestSignTxDecred(unittest.TestCase):
|
||||
decred_staking_ticket=True,
|
||||
)
|
||||
|
||||
# precomputed tx weight is 1076
|
||||
fee_rate = 100_000 / (1076 / 4)
|
||||
# precomputed tx weight is 1188
|
||||
fee_rate = 100_000 / (1188 / 4)
|
||||
|
||||
messages = [
|
||||
None,
|
||||
|
@ -631,11 +631,11 @@
|
||||
"TT_bitcoin-test_bgold.py::test_send_p2sh_witness_change": "56a5f215c03ea1dde5e4766ce61b056ca908ef2aad4870f886c7c47d002d1c04",
|
||||
"TT_bitcoin-test_dash.py::test_send_dash": "84e84912d470e4bba6aa5c2190b36fcbb766bc2720e6ca4c7c890923e774545c",
|
||||
"TT_bitcoin-test_dash.py::test_send_dash_dip2_input": "d27291f1e3e712fdc60df170dc1a78b42f70551885b613e822430b1b9a185835",
|
||||
"TT_bitcoin-test_decred.py::test_decred_multisig_change": "8fe54ce9dc6d0dc03045f4b1d16e33dde878605c7f6303f30ca21693712da5f7",
|
||||
"TT_bitcoin-test_decred.py::test_purchase_ticket_decred": "194e88db477e4c9fca40d17d2e4071388237d4d0ac22ccb153f1a1c88234dc02",
|
||||
"TT_bitcoin-test_decred.py::test_send_decred": "c6020c1167302ca39ed7876e3e5241dc8465ad1c9fb04ce1e684fef638511526",
|
||||
"TT_bitcoin-test_decred.py::test_send_decred_change": "70f940e83c6ffb4f26fbaf940ab327ee83eb23b6a752a122af38324ed4c6e571",
|
||||
"TT_bitcoin-test_decred.py::test_spend_from_stake_generation_and_revocation_decred": "2e280d383055c44cbcf8298d0fd31f1fe77af0c3265bb15805ffda23d627cbd4",
|
||||
"TT_bitcoin-test_decred.py::test_decred_multisig_change": "4de82f12102539c4deebef75899ae6e1599ad5e96586180af317d68a98b6b56e",
|
||||
"TT_bitcoin-test_decred.py::test_purchase_ticket_decred": "16b7fd6d4b88711b0932768432288df5357d16030de45c8520238322ab1d6a66",
|
||||
"TT_bitcoin-test_decred.py::test_send_decred": "7aac07b8fb2dd0d18ae22de8f35623819df32c1d82b1d603e0109d61abbe0a51",
|
||||
"TT_bitcoin-test_decred.py::test_send_decred_change": "1c450b76db5e0f4aa09bc078a9a6cc4a2f96851b7dfa81a5961df9e5a67833ec",
|
||||
"TT_bitcoin-test_decred.py::test_spend_from_stake_generation_and_revocation_decred": "884f24d36e2ddf4637c8c6011d5a2f339614b8b3047c32a3fd6342d2b1e7577a",
|
||||
"TT_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-0-InputScriptType.SPENDADDRESS-pkh([5-7a80e3db": "24290396b20f26b49204a5551676d6f3c831009e30582d92d5b44fcc3c12fdb7",
|
||||
"TT_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-0-InputScriptType.SPENDP2SHWITNESS-sh-03d56ac2": "8977c539f5680a5196ad0a4c6e16c44ca1bbdb79235dbf97e33aad8d47fe5d0c",
|
||||
"TT_bitcoin-test_descriptors.py::test_descriptors[Bitcoin-0-InputScriptType.SPENDTAPROOT-tr([5c-22751b2f": "3c31e8f9e396a1313c22480aac32f901086df23d8edf3f808d2f46a0d063034b",
|
||||
@ -898,9 +898,9 @@
|
||||
"TT_bitcoin-test_signtx_external.py::test_p2pkh_presigned": "8dd8089941ceb0d82c9425c69d54240f99e3ae7932ef24acd49313d28389b683",
|
||||
"TT_bitcoin-test_signtx_external.py::test_p2pkh_with_proof": "c09de07fbbf1e047442180e2facb5482d06a1a428891b875b7dd93c9e4704ae1",
|
||||
"TT_bitcoin-test_signtx_external.py::test_p2tr_external_presigned": "c714c4a4ea8b98dfbdd8185925adafbafc62570f415688972d6003a19d7b4d23",
|
||||
"TT_bitcoin-test_signtx_external.py::test_p2tr_external_unverified": "c488c412a6c58788530c5acc1e0c7d072aad19b5a62cad41220dfd93e4b0ae6b",
|
||||
"TT_bitcoin-test_signtx_external.py::test_p2tr_external_unverified": "d00df4d1001677c61d95b2cae7c32c4fd01c9c51995a7153d7dfe7ca103a44ba",
|
||||
"TT_bitcoin-test_signtx_external.py::test_p2tr_with_proof": "d6723e2243bc38231ec4eb9ed63afd39610460c0d859b4c576b12db1f7915d02",
|
||||
"TT_bitcoin-test_signtx_external.py::test_p2wpkh_external_unverified": "78b720588e1450972b38083857599d843f1b5ffae68de84dedf90a868d597bca",
|
||||
"TT_bitcoin-test_signtx_external.py::test_p2wpkh_external_unverified": "64d9b691b6442d44e008e1dca7ee4010820d569ff88f28ff1ce5291e79070537",
|
||||
"TT_bitcoin-test_signtx_external.py::test_p2wpkh_in_p2sh_presigned": "8313bff77e41aef142c3b25818ab58dcc7e9d658d38e2e8fc50629ebbe05869b",
|
||||
"TT_bitcoin-test_signtx_external.py::test_p2wpkh_in_p2sh_with_proof": "c09de07fbbf1e047442180e2facb5482d06a1a428891b875b7dd93c9e4704ae1",
|
||||
"TT_bitcoin-test_signtx_external.py::test_p2wpkh_presigned": "4608478b1d61415cf0ec93a0ea4397c35d17a91d4b6d25e9c024b77330e398eb",
|
||||
|
Loading…
Reference in New Issue
Block a user