1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-11-22 07:28:10 +00:00

fix(core): Fix Decred transaction weight calculation.

This commit is contained in:
Andrew Kozlik 2022-07-29 20:46:06 +02:00 committed by matejcik
parent 3b44d44a12
commit 90792eb438
5 changed files with 73 additions and 23 deletions

View File

@ -0,0 +1 @@
Fix Decred transaction weight calculation.

View File

@ -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:

View File

@ -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

View File

@ -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,

View File

@ -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",