mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-07-20 13:38:11 +00:00
feat(core): move Orchard parameters into a separate message
This commit is contained in:
parent
37aed5de58
commit
f1a90fcbc9
@ -198,11 +198,7 @@ message SignTx {
|
|||||||
optional uint32 branch_id = 10; // only for Zcash, BRANCH_ID
|
optional uint32 branch_id = 10; // only for Zcash, BRANCH_ID
|
||||||
optional AmountUnit amount_unit = 11 [default=BITCOIN]; // show amounts in
|
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 bool decred_staking_ticket = 12 [default=false]; // only for Decred, this is signing a ticket purchase
|
||||||
|
optional zcash.ZcashOrchardParams orchard_params = 13; // only for Zcash
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,6 +62,17 @@ message ZcashAddress {
|
|||||||
optional string address = 1;
|
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.
|
* Request: Specify transaction Orchard input.
|
||||||
* @next TxRequest
|
* @next TxRequest
|
||||||
|
@ -9,7 +9,6 @@ from trezor.messages import TxRequest, ZcashAck, ZcashOrchardInput, ZcashOrchard
|
|||||||
from trezor.wire import DataError
|
from trezor.wire import DataError
|
||||||
|
|
||||||
from apps.bitcoin.sign_tx import helpers
|
from apps.bitcoin.sign_tx import helpers
|
||||||
from apps.common.paths import HARDENED
|
|
||||||
|
|
||||||
from .. import unified
|
from .. import unified
|
||||||
from ..hasher import ZcashHasher
|
from ..hasher import ZcashHasher
|
||||||
@ -61,9 +60,13 @@ class OrchardSigner:
|
|||||||
tx_req: TxRequest,
|
tx_req: TxRequest,
|
||||||
) -> None:
|
) -> None:
|
||||||
assert tx_req.serialized is not None # typing
|
assert tx_req.serialized is not None # typing
|
||||||
|
params = tx_info.tx.orchard_params
|
||||||
self.inputs_count = tx_info.tx.orchard_inputs_count
|
if params is None:
|
||||||
self.outputs_count = tx_info.tx.orchard_outputs_count
|
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:
|
if self.inputs_count + self.outputs_count > 0:
|
||||||
self.actions_count = max(
|
self.actions_count = max(
|
||||||
@ -84,15 +87,9 @@ class OrchardSigner:
|
|||||||
self.tx_req = tx_req
|
self.tx_req = tx_req
|
||||||
assert isinstance(tx_info.sig_hasher, ZcashHasher)
|
assert isinstance(tx_info.sig_hasher, ZcashHasher)
|
||||||
self.sig_hasher: ZcashHasher = tx_info.sig_hasher
|
self.sig_hasher: ZcashHasher = tx_info.sig_hasher
|
||||||
|
assert params is not None
|
||||||
account = tx_info.tx.account
|
self.anchor = params.anchor
|
||||||
assert account is not None # typing
|
self.key_node = self.keychain.derive(params.address_n)
|
||||||
key_path = [
|
|
||||||
32 | HARDENED, # ZIP-32 constant
|
|
||||||
coin.slip44 | HARDENED, # purpose
|
|
||||||
account | HARDENED, # account
|
|
||||||
]
|
|
||||||
self.key_node = self.keychain.derive(key_path)
|
|
||||||
|
|
||||||
self.msg_acc = MessageAccumulator(
|
self.msg_acc = MessageAccumulator(
|
||||||
self.keychain.derive_slip21(
|
self.keychain.derive_slip21(
|
||||||
@ -175,15 +172,13 @@ class OrchardSigner:
|
|||||||
self.msg_acc.check()
|
self.msg_acc.check()
|
||||||
|
|
||||||
# hash orchard footer
|
# hash orchard footer
|
||||||
assert self.tx_info.tx.orchard_anchor is not None # typing
|
|
||||||
self.sig_hasher.orchard.finalize(
|
self.sig_hasher.orchard.finalize(
|
||||||
flags=FLAGS,
|
flags=FLAGS,
|
||||||
value_balance=self.approver.orchard_balance,
|
value_balance=self.approver.orchard_balance,
|
||||||
anchor=self.tx_info.tx.orchard_anchor,
|
anchor=self.anchor,
|
||||||
)
|
)
|
||||||
|
|
||||||
def derive_shielding_seed(self) -> bytes:
|
def derive_shielding_seed(self) -> bytes:
|
||||||
assert self.tx_info.tx.orchard_anchor is not None # typing
|
|
||||||
ss_slip21 = self.keychain.derive_slip21(
|
ss_slip21 = self.keychain.derive_slip21(
|
||||||
[b"Zcash Orchard", b"bundle_shielding_seed"],
|
[b"Zcash Orchard", b"bundle_shielding_seed"],
|
||||||
).key()
|
).key()
|
||||||
@ -191,7 +186,7 @@ class OrchardSigner:
|
|||||||
ss_hasher.update(self.sig_hasher.header.digest())
|
ss_hasher.update(self.sig_hasher.header.digest())
|
||||||
ss_hasher.update(self.sig_hasher.transparent.digest())
|
ss_hasher.update(self.sig_hasher.transparent.digest())
|
||||||
ss_hasher.update(self.msg_acc.state)
|
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)
|
ss_hasher.update(ss_slip21)
|
||||||
return ss_hasher.digest()
|
return ss_hasher.digest()
|
||||||
|
|
||||||
|
@ -63,11 +63,10 @@ class Zcash(Bitcoinlike):
|
|||||||
coin,
|
coin,
|
||||||
self.tx_req,
|
self.tx_req,
|
||||||
)
|
)
|
||||||
self.tx_info.wallet_path.attribute = [
|
if self.orchard.inputs_count > 0 and tx.inputs_count > 0:
|
||||||
44 | HARDENED, # BIP-44 constant
|
raise DataError(
|
||||||
coin.slip44 | HARDENED,
|
"Cannot spending transparent and Orchard inputs simultaneously is not supported."
|
||||||
tx.account | HARDENED,
|
)
|
||||||
]
|
|
||||||
|
|
||||||
def create_sig_hasher(self, tx: SignTx | PrevTx) -> ZcashHasher:
|
def create_sig_hasher(self, tx: SignTx | PrevTx) -> ZcashHasher:
|
||||||
return ZcashHasher(tx)
|
return ZcashHasher(tx)
|
||||||
|
@ -455,6 +455,26 @@ if TYPE_CHECKING:
|
|||||||
def is_type_of(cls, msg: Any) -> TypeGuard["ZcashAddress"]:
|
def is_type_of(cls, msg: Any) -> TypeGuard["ZcashAddress"]:
|
||||||
return isinstance(msg, cls)
|
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):
|
class ZcashOrchardInput(protobuf.MessageType):
|
||||||
recipient: "bytes"
|
recipient: "bytes"
|
||||||
value: "int"
|
value: "int"
|
||||||
@ -707,10 +727,7 @@ if TYPE_CHECKING:
|
|||||||
branch_id: "int | None"
|
branch_id: "int | None"
|
||||||
amount_unit: "AmountUnit"
|
amount_unit: "AmountUnit"
|
||||||
decred_staking_ticket: "bool"
|
decred_staking_ticket: "bool"
|
||||||
orchard_inputs_count: "int"
|
orchard_params: "ZcashOrchardParams | None"
|
||||||
orchard_outputs_count: "int"
|
|
||||||
orchard_anchor: "bytes | None"
|
|
||||||
account: "int"
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@ -726,10 +743,7 @@ if TYPE_CHECKING:
|
|||||||
branch_id: "int | None" = None,
|
branch_id: "int | None" = None,
|
||||||
amount_unit: "AmountUnit | None" = None,
|
amount_unit: "AmountUnit | None" = None,
|
||||||
decred_staking_ticket: "bool | None" = None,
|
decred_staking_ticket: "bool | None" = None,
|
||||||
orchard_inputs_count: "int | None" = None,
|
orchard_params: "ZcashOrchardParams | None" = None,
|
||||||
orchard_outputs_count: "int | None" = None,
|
|
||||||
orchard_anchor: "bytes | None" = None,
|
|
||||||
account: "int | None" = None,
|
|
||||||
) -> None:
|
) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -1021,6 +1021,29 @@ class ZcashAddress(protobuf.MessageType):
|
|||||||
self.address = address
|
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):
|
class ZcashOrchardInput(protobuf.MessageType):
|
||||||
MESSAGE_WIRE_TYPE = 906
|
MESSAGE_WIRE_TYPE = 906
|
||||||
FIELDS = {
|
FIELDS = {
|
||||||
@ -1307,10 +1330,7 @@ class SignTx(protobuf.MessageType):
|
|||||||
10: protobuf.Field("branch_id", "uint32", repeated=False, required=False),
|
10: protobuf.Field("branch_id", "uint32", repeated=False, required=False),
|
||||||
11: protobuf.Field("amount_unit", "AmountUnit", 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),
|
12: protobuf.Field("decred_staking_ticket", "bool", repeated=False, required=False),
|
||||||
13: protobuf.Field("orchard_inputs_count", "uint32", repeated=False, required=False),
|
13: protobuf.Field("orchard_params", "ZcashOrchardParams", 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),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@ -1328,10 +1348,7 @@ class SignTx(protobuf.MessageType):
|
|||||||
branch_id: Optional["int"] = None,
|
branch_id: Optional["int"] = None,
|
||||||
amount_unit: Optional["AmountUnit"] = AmountUnit.BITCOIN,
|
amount_unit: Optional["AmountUnit"] = AmountUnit.BITCOIN,
|
||||||
decred_staking_ticket: Optional["bool"] = False,
|
decred_staking_ticket: Optional["bool"] = False,
|
||||||
orchard_inputs_count: Optional["int"] = 0,
|
orchard_params: Optional["ZcashOrchardParams"] = None,
|
||||||
orchard_outputs_count: Optional["int"] = 0,
|
|
||||||
orchard_anchor: Optional["bytes"] = None,
|
|
||||||
account: Optional["int"] = 0,
|
|
||||||
) -> None:
|
) -> None:
|
||||||
self.outputs_count = outputs_count
|
self.outputs_count = outputs_count
|
||||||
self.inputs_count = inputs_count
|
self.inputs_count = inputs_count
|
||||||
@ -1345,10 +1362,7 @@ class SignTx(protobuf.MessageType):
|
|||||||
self.branch_id = branch_id
|
self.branch_id = branch_id
|
||||||
self.amount_unit = amount_unit
|
self.amount_unit = amount_unit
|
||||||
self.decred_staking_ticket = decred_staking_ticket
|
self.decred_staking_ticket = decred_staking_ticket
|
||||||
self.orchard_inputs_count = orchard_inputs_count
|
self.orchard_params = orchard_params
|
||||||
self.orchard_outputs_count = orchard_outputs_count
|
|
||||||
self.orchard_anchor = orchard_anchor
|
|
||||||
self.account = account
|
|
||||||
|
|
||||||
|
|
||||||
class TxRequest(protobuf.MessageType):
|
class TxRequest(protobuf.MessageType):
|
||||||
|
Loading…
Reference in New Issue
Block a user