1
0
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:
Jan Pochyla 2017-11-21 16:13:33 +01:00 committed by Tomas Susanka
parent 0e2bcd64e8
commit 165faaeba4
4 changed files with 40 additions and 29 deletions

View File

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

View File

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

View File

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

View File

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