mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-11-26 09:28:13 +00:00
wallet/signing: codestyle
This commit is contained in:
parent
0e2bcd64e8
commit
165faaeba4
@ -2,6 +2,7 @@ from trezor import ui
|
|||||||
from trezor.utils import chunks
|
from trezor.utils import chunks
|
||||||
from trezor.ui.text import Text
|
from trezor.ui.text import Text
|
||||||
from trezor.messages import ButtonRequestType
|
from trezor.messages import ButtonRequestType
|
||||||
|
from trezor.messages import OutputScriptType
|
||||||
from apps.common.confirm import confirm
|
from apps.common.confirm import confirm
|
||||||
from apps.common.confirm import hold_to_confirm
|
from apps.common.confirm import hold_to_confirm
|
||||||
|
|
||||||
@ -15,11 +16,14 @@ def split_address(address):
|
|||||||
|
|
||||||
|
|
||||||
async def confirm_output(ctx, output, coin):
|
async def confirm_output(ctx, output, coin):
|
||||||
# TODO: handle OP_RETURN correctly
|
if output.script_type == OutputScriptType.PAYTOOPRETURN:
|
||||||
|
address = 'OP_RETURN' # TODO: handle OP_RETURN correctly
|
||||||
|
else:
|
||||||
|
address = output.address
|
||||||
content = Text('Confirm output', ui.ICON_RESET,
|
content = Text('Confirm output', ui.ICON_RESET,
|
||||||
ui.BOLD, format_amount(output.amount, coin),
|
ui.BOLD, format_amount(output.amount, coin),
|
||||||
ui.NORMAL, 'to',
|
ui.NORMAL, 'to',
|
||||||
ui.MONO, *split_address(output.address))
|
ui.MONO, *split_address(address))
|
||||||
return await confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
return await confirm(ctx, content, ButtonRequestType.ConfirmOutput)
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,7 +59,9 @@ class Bip143:
|
|||||||
# for P2WPKH this is always 0x1976a914{20-byte-pubkey-hash}88ac
|
# for P2WPKH this is always 0x1976a914{20-byte-pubkey-hash}88ac
|
||||||
def derive_script_code(self, txi: TxInputType, pubkeyhash: bytes) -> bytearray:
|
def derive_script_code(self, txi: TxInputType, pubkeyhash: bytes) -> bytearray:
|
||||||
# p2wpkh in p2sh or native p2wpkh
|
# p2wpkh in p2sh or native p2wpkh
|
||||||
if txi.script_type in (InputScriptType.SPENDP2SHWITNESS, InputScriptType.SPENDWITNESS):
|
is_segwit = (txi.script_type == InputScriptType.SPENDWITNESS or
|
||||||
|
txi.script_type == InputScriptType.SPENDP2SHWITNESS)
|
||||||
|
if is_segwit:
|
||||||
s = bytearray(25)
|
s = bytearray(25)
|
||||||
s[0] = 0x76 # OP_DUP
|
s[0] = 0x76 # OP_DUP
|
||||||
s[1] = 0xA9 # OP_HASH_160
|
s[1] = 0xA9 # OP_HASH_160
|
||||||
@ -69,5 +71,5 @@ class Bip143:
|
|||||||
s[24] = 0xAC # OP_CHECKSIG
|
s[24] = 0xAC # OP_CHECKSIG
|
||||||
return s
|
return s
|
||||||
else:
|
else:
|
||||||
raise Bip143Error(FailureType.SyntaxError,
|
raise Bip143Error(FailureType.DataError,
|
||||||
'Unknown input script type for bip143 script code')
|
'Unknown input script type for bip143 script code')
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from micropython import const
|
||||||
|
|
||||||
from trezor.crypto.hashlib import sha256, ripemd160
|
from trezor.crypto.hashlib import sha256, ripemd160
|
||||||
from trezor.crypto.curve import secp256k1
|
from trezor.crypto.curve import secp256k1
|
||||||
from trezor.crypto import base58, der, bech32
|
from trezor.crypto import base58, der, bech32
|
||||||
@ -66,8 +68,9 @@ async def check_tx_fee(tx: SignTx, root):
|
|||||||
write_tx_input_check(h_first, txi)
|
write_tx_input_check(h_first, txi)
|
||||||
bip143.add_prevouts(txi)
|
bip143.add_prevouts(txi)
|
||||||
bip143.add_sequence(txi)
|
bip143.add_sequence(txi)
|
||||||
if (txi.script_type == InputScriptType.SPENDWITNESS or
|
is_segwit = (txi.script_type == InputScriptType.SPENDWITNESS or
|
||||||
txi.script_type == InputScriptType.SPENDP2SHWITNESS):
|
txi.script_type == InputScriptType.SPENDP2SHWITNESS)
|
||||||
|
if is_segwit:
|
||||||
if not coin.segwit:
|
if not coin.segwit:
|
||||||
raise SigningError(FailureType.DataError,
|
raise SigningError(FailureType.DataError,
|
||||||
'Segwit not enabled on this coin')
|
'Segwit not enabled on this coin')
|
||||||
@ -140,29 +143,20 @@ async def sign_tx(tx: SignTx, root):
|
|||||||
tx_req.serialized = None
|
tx_req.serialized = None
|
||||||
|
|
||||||
for i_sign in range(tx.inputs_count):
|
for i_sign in range(tx.inputs_count):
|
||||||
# hash of what we are signing with this input
|
|
||||||
h_sign = HashWriter(sha256)
|
|
||||||
# same as h_first, checked at the end of this iteration
|
|
||||||
h_second = HashWriter(sha256)
|
|
||||||
|
|
||||||
txi_sign = None
|
txi_sign = None
|
||||||
key_sign = None
|
key_sign = None
|
||||||
key_sign_pub = None
|
key_sign_pub = None
|
||||||
|
|
||||||
write_uint32(h_sign, tx.version)
|
|
||||||
|
|
||||||
write_varint(h_sign, tx.inputs_count)
|
|
||||||
|
|
||||||
if segwit[i_sign]:
|
if segwit[i_sign]:
|
||||||
# STAGE_REQUEST_SEGWIT_INPUT
|
# STAGE_REQUEST_SEGWIT_INPUT
|
||||||
txi_sign = await request_tx_input(tx_req, i_sign)
|
txi_sign = await request_tx_input(tx_req, i_sign)
|
||||||
|
|
||||||
if (txi_sign.script_type != InputScriptType.SPENDWITNESS and
|
is_segwit = (txi_sign.script_type == InputScriptType.SPENDWITNESS or
|
||||||
txi_sign.script_type != InputScriptType.SPENDP2SHWITNESS):
|
txi_sign.script_type == InputScriptType.SPENDP2SHWITNESS)
|
||||||
|
if not is_segwit:
|
||||||
raise SigningError(FailureType.ProcessError,
|
raise SigningError(FailureType.ProcessError,
|
||||||
'Transaction has changed during signing')
|
'Transaction has changed during signing')
|
||||||
input_check_wallet_path(txi_sign, wallet_path)
|
input_check_wallet_path(txi_sign, wallet_path)
|
||||||
write_tx_input_check(h_second, txi_sign)
|
|
||||||
|
|
||||||
key_sign = node_derive(root, txi_sign.address_n)
|
key_sign = node_derive(root, txi_sign.address_n)
|
||||||
key_sign_pub = key_sign.public_key()
|
key_sign_pub = key_sign.public_key()
|
||||||
@ -176,6 +170,14 @@ async def sign_tx(tx: SignTx, root):
|
|||||||
tx_req.serialized = tx_ser
|
tx_req.serialized = tx_ser
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
# hash of what we are signing with this input
|
||||||
|
h_sign = HashWriter(sha256)
|
||||||
|
# same as h_first, checked before signing the digest
|
||||||
|
h_second = HashWriter(sha256)
|
||||||
|
|
||||||
|
write_uint32(h_sign, tx.version)
|
||||||
|
write_varint(h_sign, tx.inputs_count)
|
||||||
|
|
||||||
for i in range(tx.inputs_count):
|
for i in range(tx.inputs_count):
|
||||||
# STAGE_REQUEST_4_INPUT
|
# STAGE_REQUEST_4_INPUT
|
||||||
txi = await request_tx_input(tx_req, i)
|
txi = await request_tx_input(tx_req, i)
|
||||||
@ -232,7 +234,6 @@ async def sign_tx(tx: SignTx, root):
|
|||||||
txo = await request_tx_output(tx_req, o)
|
txo = await request_tx_output(tx_req, o)
|
||||||
txo_bin.amount = txo.amount
|
txo_bin.amount = txo.amount
|
||||||
txo_bin.script_pubkey = output_derive_script(txo, coin, root)
|
txo_bin.script_pubkey = output_derive_script(txo, coin, root)
|
||||||
write_tx_output(h_second, txo_bin) # for segwit (not yet checked)
|
|
||||||
|
|
||||||
# serialize output
|
# serialize output
|
||||||
w_txo_bin = bytearray_with_cap(
|
w_txo_bin = bytearray_with_cap(
|
||||||
@ -247,13 +248,17 @@ async def sign_tx(tx: SignTx, root):
|
|||||||
|
|
||||||
tx_req.serialized = tx_ser
|
tx_req.serialized = tx_ser
|
||||||
|
|
||||||
|
any_segwit = True in segwit.values()
|
||||||
|
|
||||||
for i in range(tx.inputs_count):
|
for i in range(tx.inputs_count):
|
||||||
if segwit[i]:
|
if segwit[i]:
|
||||||
# STAGE_REQUEST_SEGWIT_WITNESS
|
# STAGE_REQUEST_SEGWIT_WITNESS
|
||||||
txi = await request_tx_input(tx_req, i)
|
txi = await request_tx_input(tx_req, i)
|
||||||
input_check_wallet_path(txi, wallet_path)
|
input_check_wallet_path(txi, wallet_path)
|
||||||
|
|
||||||
if txi.amount > authorized_in:
|
is_segwit = (txi.script_type == InputScriptType.SPENDWITNESS or
|
||||||
|
txi.script_type == InputScriptType.SPENDP2SHWITNESS)
|
||||||
|
if not is_segwit or txi.amount > authorized_in:
|
||||||
raise SigningError(FailureType.ProcessError,
|
raise SigningError(FailureType.ProcessError,
|
||||||
'Transaction has changed during signing')
|
'Transaction has changed during signing')
|
||||||
authorized_in -= txi.amount
|
authorized_in -= txi.amount
|
||||||
@ -265,12 +270,15 @@ async def sign_tx(tx: SignTx, root):
|
|||||||
signature = ecdsa_sign(key_sign, bip143_hash)
|
signature = ecdsa_sign(key_sign, bip143_hash)
|
||||||
witness = get_p2wpkh_witness(signature, key_sign_pub)
|
witness = get_p2wpkh_witness(signature, key_sign_pub)
|
||||||
|
|
||||||
|
tx_ser.serialized_tx = witness
|
||||||
tx_ser.signature_index = i
|
tx_ser.signature_index = i
|
||||||
tx_ser.signature = signature
|
tx_ser.signature = signature
|
||||||
tx_ser.serialized_tx = witness
|
elif any_segwit:
|
||||||
tx_req.serialized = tx_ser
|
tx_ser.serialized_tx = bytearray(1) # empty witness for non-segwit inputs
|
||||||
else:
|
tx_ser.signature_index = None
|
||||||
pass # TODO: empty witness
|
tx_ser.signature = None
|
||||||
|
|
||||||
|
tx_req.serialized = tx_ser
|
||||||
|
|
||||||
write_uint32(tx_ser.serialized_tx, tx.lock_time)
|
write_uint32(tx_ser.serialized_tx, tx.lock_time)
|
||||||
|
|
||||||
@ -460,13 +468,10 @@ def output_is_change(o: TxOutputType, wallet_path: list) -> bool:
|
|||||||
def input_derive_script(i: TxInputType, pubkey: bytes, signature: bytes=None) -> bytes:
|
def input_derive_script(i: TxInputType, pubkey: bytes, signature: bytes=None) -> bytes:
|
||||||
if i.script_type == InputScriptType.SPENDADDRESS:
|
if i.script_type == InputScriptType.SPENDADDRESS:
|
||||||
return input_script_p2pkh_or_p2sh(pubkey, signature) # p2pkh or p2sh
|
return input_script_p2pkh_or_p2sh(pubkey, signature) # p2pkh or p2sh
|
||||||
|
|
||||||
if i.script_type == InputScriptType.SPENDP2SHWITNESS: # p2wpkh using p2sh
|
if i.script_type == InputScriptType.SPENDP2SHWITNESS: # p2wpkh using p2sh
|
||||||
return input_script_p2wpkh_in_p2sh(ecdsa_hash_pubkey(pubkey))
|
return input_script_p2wpkh_in_p2sh(ecdsa_hash_pubkey(pubkey))
|
||||||
|
|
||||||
elif i.script_type == InputScriptType.SPENDWITNESS: # native p2wpkh or p2wsh
|
elif i.script_type == InputScriptType.SPENDWITNESS: # native p2wpkh or p2wsh
|
||||||
return input_script_native_p2wpkh_or_p2wsh()
|
return input_script_native_p2wpkh_or_p2wsh()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise SigningError(FailureType.ProcessError, 'Invalid script type')
|
raise SigningError(FailureType.ProcessError, 'Invalid script type')
|
||||||
|
|
||||||
|
@ -19,12 +19,12 @@ def write_tx_input(w, i: TxInputType):
|
|||||||
def write_tx_input_check(w, i: TxInputType):
|
def write_tx_input_check(w, i: TxInputType):
|
||||||
write_bytes(w, i.prev_hash)
|
write_bytes(w, i.prev_hash)
|
||||||
write_uint32(w, i.prev_index)
|
write_uint32(w, i.prev_index)
|
||||||
|
write_uint32(w, i.script_type)
|
||||||
write_uint32(w, len(i.address_n))
|
write_uint32(w, len(i.address_n))
|
||||||
for n in i.address_n:
|
for n in i.address_n:
|
||||||
write_uint32(w, n)
|
write_uint32(w, n)
|
||||||
write_uint32(w, i.sequence)
|
write_uint32(w, i.sequence)
|
||||||
i_amount = i.amount if i.amount is not None else 0
|
write_uint32(w, i.amount or 0)
|
||||||
write_uint32(w, i_amount) # this is probably redundant, but better safe than sorry
|
|
||||||
|
|
||||||
|
|
||||||
def write_tx_output(w, o: TxOutputBinType):
|
def write_tx_output(w, o: TxOutputBinType):
|
||||||
|
Loading…
Reference in New Issue
Block a user