1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-07-19 13:08:14 +00:00

feat(core): move Orchard parameters into a separate message

This commit is contained in:
Tomas Krnak 2022-11-17 13:44:46 +07:00
parent 37aed5de58
commit f1a90fcbc9
6 changed files with 76 additions and 47 deletions

View File

@ -198,11 +198,7 @@ message SignTx {
optional uint32 branch_id = 10; // only for Zcash, BRANCH_ID
optional AmountUnit amount_unit = 11 [default=BITCOIN]; // show amounts in
optional bool decred_staking_ticket = 12 [default=false]; // only for Decred, this is signing a ticket purchase
optional uint32 orchard_inputs_count = 13 [default = 0]; // only for Zcash, number of Orchard inputs
optional uint32 orchard_outputs_count = 14 [default = 0]; // only for Zcash, number of Orchard outputs
optional bytes orchard_anchor = 15; // only for Zcash, a root of Orchard Merkle tree
optional uint32 account = 16 [default = 0]; // only for Zcash
optional zcash.ZcashOrchardParams orchard_params = 13; // only for Zcash
}
/**

View File

@ -62,6 +62,17 @@ message ZcashAddress {
optional string address = 1;
}
/**
* Orchard signing params
* @embed
*/
message ZcashOrchardParams {
required uint32 inputs_count = 1;
required uint32 outputs_count = 2;
required bytes anchor = 3;
repeated uint32 address_n = 4;
}
/**
* Request: Specify transaction Orchard input.
* @next TxRequest

View File

@ -9,7 +9,6 @@ from trezor.messages import TxRequest, ZcashAck, ZcashOrchardInput, ZcashOrchard
from trezor.wire import DataError
from apps.bitcoin.sign_tx import helpers
from apps.common.paths import HARDENED
from .. import unified
from ..hasher import ZcashHasher
@ -61,9 +60,13 @@ class OrchardSigner:
tx_req: TxRequest,
) -> None:
assert tx_req.serialized is not None # typing
self.inputs_count = tx_info.tx.orchard_inputs_count
self.outputs_count = tx_info.tx.orchard_outputs_count
params = tx_info.tx.orchard_params
if params is None:
self.inputs_count = 0
self.outputs_count = 0
else:
self.inputs_count = params.inputs_count
self.outputs_count = params.outputs_count
if self.inputs_count + self.outputs_count > 0:
self.actions_count = max(
@ -84,15 +87,9 @@ class OrchardSigner:
self.tx_req = tx_req
assert isinstance(tx_info.sig_hasher, ZcashHasher)
self.sig_hasher: ZcashHasher = tx_info.sig_hasher
account = tx_info.tx.account
assert account is not None # typing
key_path = [
32 | HARDENED, # ZIP-32 constant
coin.slip44 | HARDENED, # purpose
account | HARDENED, # account
]
self.key_node = self.keychain.derive(key_path)
assert params is not None
self.anchor = params.anchor
self.key_node = self.keychain.derive(params.address_n)
self.msg_acc = MessageAccumulator(
self.keychain.derive_slip21(
@ -175,15 +172,13 @@ class OrchardSigner:
self.msg_acc.check()
# hash orchard footer
assert self.tx_info.tx.orchard_anchor is not None # typing
self.sig_hasher.orchard.finalize(
flags=FLAGS,
value_balance=self.approver.orchard_balance,
anchor=self.tx_info.tx.orchard_anchor,
anchor=self.anchor,
)
def derive_shielding_seed(self) -> bytes:
assert self.tx_info.tx.orchard_anchor is not None # typing
ss_slip21 = self.keychain.derive_slip21(
[b"Zcash Orchard", b"bundle_shielding_seed"],
).key()
@ -191,7 +186,7 @@ class OrchardSigner:
ss_hasher.update(self.sig_hasher.header.digest())
ss_hasher.update(self.sig_hasher.transparent.digest())
ss_hasher.update(self.msg_acc.state)
ss_hasher.update(self.tx_info.tx.orchard_anchor)
ss_hasher.update(self.anchor)
ss_hasher.update(ss_slip21)
return ss_hasher.digest()

View File

@ -63,11 +63,10 @@ class Zcash(Bitcoinlike):
coin,
self.tx_req,
)
self.tx_info.wallet_path.attribute = [
44 | HARDENED, # BIP-44 constant
coin.slip44 | HARDENED,
tx.account | HARDENED,
]
if self.orchard.inputs_count > 0 and tx.inputs_count > 0:
raise DataError(
"Cannot spending transparent and Orchard inputs simultaneously is not supported."
)
def create_sig_hasher(self, tx: SignTx | PrevTx) -> ZcashHasher:
return ZcashHasher(tx)

View File

@ -455,6 +455,26 @@ if TYPE_CHECKING:
def is_type_of(cls, msg: Any) -> TypeGuard["ZcashAddress"]:
return isinstance(msg, cls)
class ZcashOrchardParams(protobuf.MessageType):
inputs_count: "int"
outputs_count: "int"
anchor: "bytes"
address_n: "list[int]"
def __init__(
self,
*,
inputs_count: "int",
outputs_count: "int",
anchor: "bytes",
address_n: "list[int] | None" = None,
) -> None:
pass
@classmethod
def is_type_of(cls, msg: Any) -> TypeGuard["ZcashOrchardParams"]:
return isinstance(msg, cls)
class ZcashOrchardInput(protobuf.MessageType):
recipient: "bytes"
value: "int"
@ -707,10 +727,7 @@ if TYPE_CHECKING:
branch_id: "int | None"
amount_unit: "AmountUnit"
decred_staking_ticket: "bool"
orchard_inputs_count: "int"
orchard_outputs_count: "int"
orchard_anchor: "bytes | None"
account: "int"
orchard_params: "ZcashOrchardParams | None"
def __init__(
self,
@ -726,10 +743,7 @@ if TYPE_CHECKING:
branch_id: "int | None" = None,
amount_unit: "AmountUnit | None" = None,
decred_staking_ticket: "bool | None" = None,
orchard_inputs_count: "int | None" = None,
orchard_outputs_count: "int | None" = None,
orchard_anchor: "bytes | None" = None,
account: "int | None" = None,
orchard_params: "ZcashOrchardParams | None" = None,
) -> None:
pass

View File

@ -1021,6 +1021,29 @@ class ZcashAddress(protobuf.MessageType):
self.address = address
class ZcashOrchardParams(protobuf.MessageType):
MESSAGE_WIRE_TYPE = None
FIELDS = {
1: protobuf.Field("inputs_count", "uint32", repeated=False, required=True),
2: protobuf.Field("outputs_count", "uint32", repeated=False, required=True),
3: protobuf.Field("anchor", "bytes", repeated=False, required=True),
4: protobuf.Field("address_n", "uint32", repeated=True, required=False),
}
def __init__(
self,
*,
inputs_count: "int",
outputs_count: "int",
anchor: "bytes",
address_n: Optional[Sequence["int"]] = None,
) -> None:
self.address_n: Sequence["int"] = address_n if address_n is not None else []
self.inputs_count = inputs_count
self.outputs_count = outputs_count
self.anchor = anchor
class ZcashOrchardInput(protobuf.MessageType):
MESSAGE_WIRE_TYPE = 906
FIELDS = {
@ -1307,10 +1330,7 @@ class SignTx(protobuf.MessageType):
10: protobuf.Field("branch_id", "uint32", repeated=False, required=False),
11: protobuf.Field("amount_unit", "AmountUnit", repeated=False, required=False),
12: protobuf.Field("decred_staking_ticket", "bool", repeated=False, required=False),
13: protobuf.Field("orchard_inputs_count", "uint32", repeated=False, required=False),
14: protobuf.Field("orchard_outputs_count", "uint32", repeated=False, required=False),
15: protobuf.Field("orchard_anchor", "bytes", repeated=False, required=False),
16: protobuf.Field("account", "uint32", repeated=False, required=False),
13: protobuf.Field("orchard_params", "ZcashOrchardParams", repeated=False, required=False),
}
def __init__(
@ -1328,10 +1348,7 @@ class SignTx(protobuf.MessageType):
branch_id: Optional["int"] = None,
amount_unit: Optional["AmountUnit"] = AmountUnit.BITCOIN,
decred_staking_ticket: Optional["bool"] = False,
orchard_inputs_count: Optional["int"] = 0,
orchard_outputs_count: Optional["int"] = 0,
orchard_anchor: Optional["bytes"] = None,
account: Optional["int"] = 0,
orchard_params: Optional["ZcashOrchardParams"] = None,
) -> None:
self.outputs_count = outputs_count
self.inputs_count = inputs_count
@ -1345,10 +1362,7 @@ class SignTx(protobuf.MessageType):
self.branch_id = branch_id
self.amount_unit = amount_unit
self.decred_staking_ticket = decred_staking_ticket
self.orchard_inputs_count = orchard_inputs_count
self.orchard_outputs_count = orchard_outputs_count
self.orchard_anchor = orchard_anchor
self.account = account
self.orchard_params = orchard_params
class TxRequest(protobuf.MessageType):