mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-20 14:39:22 +00:00
chore(core/bitcoin): Add DecredApprover.
This commit is contained in:
parent
523b1051c5
commit
6de20a7dcd
@ -10,7 +10,7 @@ if not utils.BITCOIN_ONLY:
|
||||
from . import bitcoinlike, decred, zcash
|
||||
|
||||
if False:
|
||||
from typing import Optional, Union
|
||||
from typing import Protocol, Optional, Type, Union
|
||||
|
||||
from protobuf import FieldCache
|
||||
|
||||
@ -36,6 +36,19 @@ if False:
|
||||
TxAckPrevExtraData,
|
||||
]
|
||||
|
||||
class SignerClass(Protocol):
|
||||
def __init__(
|
||||
self,
|
||||
tx: SignTx,
|
||||
keychain: Keychain,
|
||||
coin: CoinInfo,
|
||||
approver: Optional[approvers.Approver],
|
||||
) -> None:
|
||||
...
|
||||
|
||||
async def signer(self) -> None:
|
||||
...
|
||||
|
||||
|
||||
@with_keychain
|
||||
async def sign_tx(
|
||||
@ -45,15 +58,12 @@ async def sign_tx(
|
||||
coin: CoinInfo,
|
||||
authorization: Optional[CoinJoinAuthorization] = None,
|
||||
) -> TxRequest:
|
||||
approver: Optional[approvers.Approver] = None
|
||||
if authorization:
|
||||
approver: approvers.Approver = approvers.CoinJoinApprover(
|
||||
msg, coin, authorization
|
||||
)
|
||||
else:
|
||||
approver = approvers.BasicApprover(msg, coin)
|
||||
approver = approvers.CoinJoinApprover(msg, coin, authorization)
|
||||
|
||||
if utils.BITCOIN_ONLY or coin.coin_name in BITCOIN_NAMES:
|
||||
signer_class = bitcoin.Bitcoin
|
||||
signer_class: Type[SignerClass] = bitcoin.Bitcoin
|
||||
else:
|
||||
if coin.decred:
|
||||
signer_class = decred.Decred
|
||||
|
@ -2,7 +2,6 @@ from micropython import const
|
||||
|
||||
from trezor import wire
|
||||
from trezor.messages import OutputScriptType
|
||||
from trezor.utils import ensure
|
||||
|
||||
from apps.common import safety_checks
|
||||
|
||||
@ -77,11 +76,6 @@ class Approver:
|
||||
self.weight.add_output(script_pubkey)
|
||||
self.total_out += txo.amount
|
||||
|
||||
async def add_decred_sstx_submission(
|
||||
self, txo: TxOutput, script_pubkey: bytes
|
||||
) -> None:
|
||||
raise NotImplementedError
|
||||
|
||||
def add_orig_external_output(self, txo: TxOutput) -> None:
|
||||
self.orig_total_out += txo.amount
|
||||
|
||||
@ -131,13 +125,6 @@ class BasicApprover(Approver):
|
||||
else:
|
||||
await helpers.confirm_output(txo, self.coin, self.amount_unit)
|
||||
|
||||
async def add_decred_sstx_submission(
|
||||
self, txo: TxOutput, script_pubkey: bytes
|
||||
) -> None:
|
||||
ensure(self.coin.decred)
|
||||
await super().add_external_output(txo, script_pubkey, None)
|
||||
await helpers.confirm_decred_sstx_submission(txo, self.coin, self.amount_unit)
|
||||
|
||||
async def approve_tx(self, tx_info: TxInfo, orig_txs: List[OriginalTxInfo]) -> None:
|
||||
fee = self.total_in - self.total_out
|
||||
|
||||
|
@ -73,12 +73,16 @@ class Bitcoin:
|
||||
tx: SignTx,
|
||||
keychain: Keychain,
|
||||
coin: CoinInfo,
|
||||
approver: approvers.Approver,
|
||||
approver: Optional[approvers.Approver],
|
||||
) -> None:
|
||||
self.tx_info = TxInfo(self, helpers.sanitize_sign_tx(tx, coin))
|
||||
self.keychain = keychain
|
||||
self.coin = coin
|
||||
self.approver = approver
|
||||
|
||||
if approver is not None:
|
||||
self.approver = approver
|
||||
else:
|
||||
self.approver = approvers.BasicApprover(tx, coin)
|
||||
|
||||
# set of indices of inputs which are segwit
|
||||
self.segwit: Set[int] = set()
|
||||
|
@ -11,6 +11,7 @@ from apps.common.writers import write_bitcoin_varint
|
||||
from .. import multisig, scripts_decred, writers
|
||||
from ..common import ecdsa_hash_pubkey, ecdsa_sign
|
||||
from . import approvers, helpers, progress
|
||||
from .approvers import BasicApprover
|
||||
from .bitcoin import Bitcoin
|
||||
|
||||
DECRED_SERIALIZE_FULL = const(0 << 16)
|
||||
@ -37,6 +38,16 @@ if False:
|
||||
from .hash143 import Hash143
|
||||
|
||||
|
||||
class DecredApprover(BasicApprover):
|
||||
async def add_decred_sstx_submission(
|
||||
self, txo: TxOutput, script_pubkey: bytes
|
||||
) -> None:
|
||||
# NOTE: The following calls Approver.add_external_output(), not BasicApprover.add_external_output().
|
||||
# This is needed to skip calling helpers.confirm_output(), which is what BasicApprover would do.
|
||||
await super(BasicApprover, self).add_external_output(txo, script_pubkey, None)
|
||||
await helpers.confirm_decred_sstx_submission(txo, self.coin, self.amount_unit)
|
||||
|
||||
|
||||
class DecredHash:
|
||||
def __init__(self, h_prefix: HashWriter) -> None:
|
||||
self.h_prefix = h_prefix
|
||||
@ -65,11 +76,13 @@ class Decred(Bitcoin):
|
||||
tx: SignTx,
|
||||
keychain: Keychain,
|
||||
coin: CoinInfo,
|
||||
approver: approvers.Approver,
|
||||
approver: Optional[approvers.Approver],
|
||||
) -> None:
|
||||
ensure(coin.decred)
|
||||
self.h_prefix = HashWriter(blake256())
|
||||
|
||||
ensure(approver is None)
|
||||
approver = DecredApprover(tx, coin)
|
||||
super().__init__(tx, keychain, coin, approver)
|
||||
|
||||
self.write_tx_header(self.serialized_tx, self.tx_info.tx, witness_marker=True)
|
||||
@ -233,6 +246,8 @@ class Decred(Bitcoin):
|
||||
return scripts_decred.output_script_paytoopreturn(op_return_data)
|
||||
|
||||
async def approve_staking_ticket(self) -> None:
|
||||
assert isinstance(self.approver, DecredApprover)
|
||||
|
||||
if self.tx_info.tx.outputs_count != 3:
|
||||
raise wire.DataError("Ticket has wrong number of outputs.")
|
||||
|
||||
|
@ -30,7 +30,6 @@ from apps.common import coins
|
||||
from apps.common.keychain import Keychain
|
||||
from apps.bitcoin.keychain import get_schemas_for_coin
|
||||
from apps.bitcoin.sign_tx import helpers, bitcoin
|
||||
from apps.bitcoin.sign_tx.approvers import BasicApprover
|
||||
|
||||
|
||||
EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray())
|
||||
@ -160,8 +159,7 @@ class TestSignSegwitTxNativeP2WPKH(unittest.TestCase):
|
||||
|
||||
ns = get_schemas_for_coin(coin)
|
||||
keychain = Keychain(seed, coin.curve_name, ns)
|
||||
approver = BasicApprover(tx, coin)
|
||||
signer = bitcoin.Bitcoin(tx, keychain, coin, approver).signer()
|
||||
signer = bitcoin.Bitcoin(tx, keychain, coin, None).signer()
|
||||
for request, response in chunks(messages, 2):
|
||||
res = signer.send(request)
|
||||
if isinstance(res, tuple):
|
||||
@ -289,8 +287,7 @@ class TestSignSegwitTxNativeP2WPKH(unittest.TestCase):
|
||||
|
||||
ns = get_schemas_for_coin(coin)
|
||||
keychain = Keychain(seed, coin.curve_name, ns)
|
||||
approver = BasicApprover(tx, coin)
|
||||
signer = bitcoin.Bitcoin(tx, keychain, coin, approver).signer()
|
||||
signer = bitcoin.Bitcoin(tx, keychain, coin, None).signer()
|
||||
for request, expected_response in chunks(messages, 2):
|
||||
response = signer.send(request)
|
||||
if isinstance(response, tuple):
|
||||
@ -350,8 +347,7 @@ class TestSignSegwitTxNativeP2WPKH(unittest.TestCase):
|
||||
|
||||
ns = get_schemas_for_coin(coin)
|
||||
keychain = Keychain(seed, coin.curve_name, ns)
|
||||
approver = BasicApprover(tx, coin)
|
||||
signer = bitcoin.Bitcoin(tx, keychain, coin, approver).signer()
|
||||
signer = bitcoin.Bitcoin(tx, keychain, coin, None).signer()
|
||||
for request, expected_response in chunks(messages, 2):
|
||||
if expected_response is None:
|
||||
with self.assertRaises(wire.DataError):
|
||||
|
@ -29,7 +29,6 @@ from apps.common import coins
|
||||
from apps.common.keychain import Keychain
|
||||
from apps.bitcoin.keychain import get_schemas_for_coin
|
||||
from apps.bitcoin.sign_tx import bitcoinlike, helpers
|
||||
from apps.bitcoin.sign_tx.approvers import BasicApprover
|
||||
|
||||
|
||||
EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray())
|
||||
@ -161,8 +160,7 @@ class TestSignSegwitTxNativeP2WPKH_GRS(unittest.TestCase):
|
||||
|
||||
ns = get_schemas_for_coin(coin)
|
||||
keychain = Keychain(seed, coin.curve_name, ns)
|
||||
approver = BasicApprover(tx, coin)
|
||||
signer = bitcoinlike.Bitcoinlike(tx, keychain, coin, approver).signer()
|
||||
signer = bitcoinlike.Bitcoinlike(tx, keychain, coin, None).signer()
|
||||
for request, expected_response in chunks(messages, 2):
|
||||
response = signer.send(request)
|
||||
if isinstance(response, tuple):
|
||||
@ -290,8 +288,7 @@ class TestSignSegwitTxNativeP2WPKH_GRS(unittest.TestCase):
|
||||
|
||||
ns = get_schemas_for_coin(coin)
|
||||
keychain = Keychain(seed, coin.curve_name, ns)
|
||||
approver = BasicApprover(tx, coin)
|
||||
signer = bitcoinlike.Bitcoinlike(tx, keychain, coin, approver).signer()
|
||||
signer = bitcoinlike.Bitcoinlike(tx, keychain, coin, None).signer()
|
||||
for request, expected_response in chunks(messages, 2):
|
||||
response = signer.send(request)
|
||||
if isinstance(response, tuple):
|
||||
|
@ -30,7 +30,6 @@ from apps.common import coins
|
||||
from apps.common.keychain import Keychain
|
||||
from apps.bitcoin.keychain import get_schemas_for_coin
|
||||
from apps.bitcoin.sign_tx import bitcoin, helpers
|
||||
from apps.bitcoin.sign_tx.approvers import BasicApprover
|
||||
|
||||
|
||||
EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray())
|
||||
@ -157,8 +156,7 @@ class TestSignSegwitTxP2WPKHInP2SH(unittest.TestCase):
|
||||
|
||||
ns = get_schemas_for_coin(coin)
|
||||
keychain = Keychain(seed, coin.curve_name, ns)
|
||||
approver = BasicApprover(tx, coin)
|
||||
signer = bitcoin.Bitcoin(tx, keychain, coin, approver).signer()
|
||||
signer = bitcoin.Bitcoin(tx, keychain, coin, None).signer()
|
||||
for request, expected_response in chunks(messages, 2):
|
||||
response = signer.send(request)
|
||||
if isinstance(response, tuple):
|
||||
@ -294,8 +292,7 @@ class TestSignSegwitTxP2WPKHInP2SH(unittest.TestCase):
|
||||
|
||||
ns = get_schemas_for_coin(coin)
|
||||
keychain = Keychain(seed, coin.curve_name, ns)
|
||||
approver = BasicApprover(tx, coin)
|
||||
signer = bitcoin.Bitcoin(tx, keychain, coin, approver).signer()
|
||||
signer = bitcoin.Bitcoin(tx, keychain, coin, None).signer()
|
||||
for request, expected_response in chunks(messages, 2):
|
||||
response = signer.send(request)
|
||||
if isinstance(response, tuple):
|
||||
@ -401,8 +398,7 @@ class TestSignSegwitTxP2WPKHInP2SH(unittest.TestCase):
|
||||
|
||||
ns = get_schemas_for_coin(coin)
|
||||
keychain = Keychain(seed, coin.curve_name, ns)
|
||||
approver = BasicApprover(tx, coin)
|
||||
signer = bitcoin.Bitcoin(tx, keychain, coin, approver).signer()
|
||||
signer = bitcoin.Bitcoin(tx, keychain, coin, None).signer()
|
||||
i = 0
|
||||
messages_count = int(len(messages) / 2)
|
||||
for request, expected_response in chunks(messages, 2):
|
||||
|
@ -29,7 +29,6 @@ from apps.common import coins
|
||||
from apps.common.keychain import Keychain
|
||||
from apps.bitcoin.keychain import get_schemas_for_coin
|
||||
from apps.bitcoin.sign_tx import bitcoinlike, helpers
|
||||
from apps.bitcoin.sign_tx.approvers import BasicApprover
|
||||
|
||||
|
||||
EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray())
|
||||
@ -161,8 +160,7 @@ class TestSignSegwitTxP2WPKHInP2SH_GRS(unittest.TestCase):
|
||||
|
||||
ns = get_schemas_for_coin(coin)
|
||||
keychain = Keychain(seed, coin.curve_name, ns)
|
||||
approver = BasicApprover(tx, coin)
|
||||
signer = bitcoinlike.Bitcoinlike(tx, keychain, coin, approver).signer()
|
||||
signer = bitcoinlike.Bitcoinlike(tx, keychain, coin, None).signer()
|
||||
for request, expected_response in chunks(messages, 2):
|
||||
response = signer.send(request)
|
||||
if isinstance(response, tuple):
|
||||
@ -298,8 +296,7 @@ class TestSignSegwitTxP2WPKHInP2SH_GRS(unittest.TestCase):
|
||||
|
||||
ns = get_schemas_for_coin(coin)
|
||||
keychain = Keychain(seed, coin.curve_name, ns)
|
||||
approver = BasicApprover(tx, coin)
|
||||
signer = bitcoinlike.Bitcoinlike(tx, keychain, coin, approver).signer()
|
||||
signer = bitcoinlike.Bitcoinlike(tx, keychain, coin, None).signer()
|
||||
for request, expected_response in chunks(messages, 2):
|
||||
response = signer.send(request)
|
||||
if isinstance(response, tuple):
|
||||
|
@ -28,7 +28,6 @@ from apps.common import coins
|
||||
from apps.common.keychain import Keychain
|
||||
from apps.common.paths import AlwaysMatchingSchema
|
||||
from apps.bitcoin.sign_tx import bitcoin, helpers
|
||||
from apps.bitcoin.sign_tx.approvers import BasicApprover
|
||||
|
||||
|
||||
EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray())
|
||||
@ -164,8 +163,7 @@ class TestSignTxFeeThreshold(unittest.TestCase):
|
||||
seed = bip39.seed('alcohol woman abuse must during monitor noble actual mixed trade anger aisle', '')
|
||||
|
||||
keychain = Keychain(seed, coin_bitcoin.curve_name, [AlwaysMatchingSchema])
|
||||
approver = BasicApprover(tx, coin_bitcoin)
|
||||
signer = bitcoin.Bitcoin(tx, keychain, coin_bitcoin, approver).signer()
|
||||
signer = bitcoin.Bitcoin(tx, keychain, coin_bitcoin, None).signer()
|
||||
for request, response in chunks(messages, 2):
|
||||
res = signer.send(request)
|
||||
if isinstance(res, tuple):
|
||||
|
@ -28,7 +28,6 @@ from apps.common import coins
|
||||
from apps.common.keychain import Keychain
|
||||
from apps.bitcoin.keychain import get_schemas_for_coin
|
||||
from apps.bitcoin.sign_tx import bitcoin, helpers
|
||||
from apps.bitcoin.sign_tx.approvers import BasicApprover
|
||||
|
||||
|
||||
EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray())
|
||||
@ -110,8 +109,7 @@ class TestSignTx(unittest.TestCase):
|
||||
seed = bip39.seed('alcohol woman abuse must during monitor noble actual mixed trade anger aisle', '')
|
||||
ns = get_schemas_for_coin(coin_bitcoin)
|
||||
keychain = Keychain(seed, coin_bitcoin.curve_name, ns)
|
||||
approver = BasicApprover(tx, coin_bitcoin)
|
||||
signer = bitcoin.Bitcoin(tx, keychain, coin_bitcoin, approver).signer()
|
||||
signer = bitcoin.Bitcoin(tx, keychain, coin_bitcoin, None).signer()
|
||||
|
||||
for request, response in chunks(messages, 2):
|
||||
res = signer.send(request)
|
||||
|
@ -1,7 +1,7 @@
|
||||
from common import *
|
||||
|
||||
from trezor.utils import chunks
|
||||
from trezor.crypto import bip32, bip39
|
||||
from trezor.crypto import bip39
|
||||
from trezor.messages.SignTx import SignTx
|
||||
from trezor.messages.TxAckInput import TxAckInput
|
||||
from trezor.messages.TxAckInputWrapper import TxAckInputWrapper
|
||||
@ -28,7 +28,6 @@ from apps.common import coins
|
||||
from apps.common.keychain import Keychain
|
||||
from apps.bitcoin.keychain import get_schemas_for_coin
|
||||
from apps.bitcoin.sign_tx import decred, helpers
|
||||
from apps.bitcoin.sign_tx.approvers import BasicApprover
|
||||
|
||||
|
||||
EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray())
|
||||
@ -190,8 +189,7 @@ class TestSignTxDecred(unittest.TestCase):
|
||||
)
|
||||
ns = get_schemas_for_coin(coin_decred)
|
||||
keychain = Keychain(seed, coin_decred.curve_name, ns)
|
||||
approver = BasicApprover(tx, coin_decred)
|
||||
signer = decred.Decred(tx, keychain, coin_decred, approver).signer()
|
||||
signer = decred.Decred(tx, keychain, coin_decred, None).signer()
|
||||
|
||||
for request, response in chunks(messages, 2):
|
||||
res = signer.send(request)
|
||||
@ -353,8 +351,7 @@ class TestSignTxDecred(unittest.TestCase):
|
||||
)
|
||||
ns = get_schemas_for_coin(coin_decred)
|
||||
keychain = Keychain(seed, coin_decred.curve_name, ns)
|
||||
approver = BasicApprover(tx, coin_decred)
|
||||
signer = decred.Decred(tx, keychain, coin_decred, approver).signer()
|
||||
signer = decred.Decred(tx, keychain, coin_decred, None).signer()
|
||||
|
||||
for request, response in chunks(messages, 2):
|
||||
res = signer.send(request)
|
||||
|
@ -28,7 +28,6 @@ from apps.common import coins
|
||||
from apps.common.keychain import Keychain
|
||||
from apps.bitcoin.keychain import get_schemas_for_coin
|
||||
from apps.bitcoin.sign_tx import bitcoinlike, helpers
|
||||
from apps.bitcoin.sign_tx.approvers import BasicApprover
|
||||
|
||||
|
||||
EMPTY_SERIALIZED = TxRequestSerializedType(serialized_tx=bytearray())
|
||||
@ -104,8 +103,7 @@ class TestSignTx_GRS(unittest.TestCase):
|
||||
seed = bip39.seed(' '.join(['all'] * 12), '')
|
||||
ns = get_schemas_for_coin(coin)
|
||||
keychain = Keychain(seed, coin.curve_name, ns)
|
||||
approver = BasicApprover(tx, coin)
|
||||
signer = bitcoinlike.Bitcoinlike(tx, keychain, coin, approver).signer()
|
||||
signer = bitcoinlike.Bitcoinlike(tx, keychain, coin, None).signer()
|
||||
for request, expected_response in chunks(messages, 2):
|
||||
response = signer.send(request)
|
||||
if isinstance(response, tuple):
|
||||
|
Loading…
Reference in New Issue
Block a user