1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-04-19 00:29:03 +00:00

feat(common/protobuf): add bitcoin-like transaction signing anti-exfil protocol messages

[no changelog]
This commit is contained in:
Ondřej Vejpustek 2025-03-04 15:34:48 +01:00
parent 7ff5c223a1
commit 98c317c34d
8 changed files with 1111 additions and 162 deletions

View File

@ -253,6 +253,7 @@ message TxRequest {
TXORIGINPUT = 5;
TXORIGOUTPUT = 6;
TXPAYMENTREQ = 7;
TXENTROPY = 8;
}
/**
* Structure representing request details
@ -262,6 +263,7 @@ message TxRequest {
optional bytes tx_hash = 2; // tx_hash of requested transaction
optional uint32 extra_data_len = 3; // length of requested extra data (only for Dash, Zcash)
optional uint32 extra_data_offset = 4; // offset of requested extra data (only for Dash, Zcash)
optional bytes nonce_commitment = 5; // commitment to signature nonce, used in anti-exfil protocol
}
/**
* Structure representing serialized data
@ -307,6 +309,11 @@ message TxAck {
optional uint32 version_group_id = 12; // only for Zcash, nVersionGroupId
optional uint32 timestamp = 13; // only for Peercoin
optional uint32 branch_id = 14; // only for Zcash, BRANCH_ID
optional TxEntropyType entropy = 15; // used in anti-exfil protocol
message TxEntropyType {
optional bytes entropy = 1; // host's entropy, used in anti-exfil protocol
}
/**
* Structure representing transaction input
*/
@ -331,6 +338,7 @@ message TxAck {
optional DecredStakingSpendType decred_staking_spend = 18; // if not None this holds the type of stake spend: revocation or stake generation
optional bytes script_pubkey = 19; // scriptPubKey of the previous output spent by this input, only set of EXTERNAL inputs
optional uint32 coinjoin_flags = 20 [default=0]; // bit field of CoinJoin-specific flags
optional bytes entropy_commitment = 21; // commitment to host's entropy, non-empty value indicates anti-exfil protocol will be used for this input
}
/**
* Structure representing compiled transaction output
@ -385,6 +393,7 @@ message TxInput {
optional DecredStakingSpendType decred_staking_spend = 18; // if not None this holds the type of stake spend: revocation or stake generation
optional bytes script_pubkey = 19; // scriptPubKey of the previous output spent by this input, only set of EXTERNAL inputs
optional uint32 coinjoin_flags = 20 [default=0]; // bit field of CoinJoin-specific flags
optional bytes entropy_commitment = 21; // commitment to host's entropy, used in anti-exfil protocol
}
/** Data type for transaction output to be signed.
@ -403,6 +412,13 @@ message TxOutput {
optional uint32 payment_req_index = 12 [(experimental_field)=true]; // index of the PaymentRequest containing this output
}
/** Data type for host's entropy, used in anti-exfil protocol.
* @embed
*/
message TxEntropy {
optional bytes entropy = 1; // host's entropy, used in anti-exfil protocol
}
/** Data type for metadata about previous transaction which contains the UTXO being spent.
* @embed
*/
@ -418,7 +434,7 @@ message PrevTx {
optional uint32 branch_id = 14; // only for Zcash, BRANCH_ID
// fields which are in use, or have been in the past, in TransactionType
reserved 2, 3, 5, 8, 11;
reserved 2, 3, 5, 8, 11, 15;
}
/** Data type for inputs of previous transactions.
@ -591,6 +607,23 @@ message TxAckPrevExtraData {
}
}
/**
* Request: Host's entropy, used in anti-exfil protocol
*
* Do not edit this type without considering compatibility with TxAck.
*
* @next TxRequest
*/
message TxAckEntropy {
option (wire_type) = 22;
required TxAckEntropyWrapper tx = 1;
message TxAckEntropyWrapper {
required TxEntropy entropy = 15;
}
}
/**
* Request: Ask device for a proof of ownership corresponding to address_n path
* @start

View File

@ -10,3 +10,4 @@ TXEXTRADATA = 4
TXORIGINPUT = 5
TXORIGOUTPUT = 6
TXPAYMENTREQ = 7
TXENTROPY = 8

View File

@ -111,6 +111,7 @@ if TYPE_CHECKING:
TXORIGINPUT = 5
TXORIGOUTPUT = 6
TXPAYMENTREQ = 7
TXENTROPY = 8
class CardanoDerivationType(IntEnum):
LEDGER = 0

View File

@ -738,6 +738,7 @@ if TYPE_CHECKING:
decred_staking_spend: "DecredStakingSpendType | None"
script_pubkey: "bytes | None"
coinjoin_flags: "int"
entropy_commitment: "bytes | None"
def __init__(
self,
@ -759,6 +760,7 @@ if TYPE_CHECKING:
decred_staking_spend: "DecredStakingSpendType | None" = None,
script_pubkey: "bytes | None" = None,
coinjoin_flags: "int | None" = None,
entropy_commitment: "bytes | None" = None,
) -> None:
pass
@ -796,6 +798,20 @@ if TYPE_CHECKING:
def is_type_of(cls, msg: Any) -> TypeGuard["TxOutput"]:
return isinstance(msg, cls)
class TxEntropy(protobuf.MessageType):
entropy: "bytes | None"
def __init__(
self,
*,
entropy: "bytes | None" = None,
) -> None:
pass
@classmethod
def is_type_of(cls, msg: Any) -> TypeGuard["TxEntropy"]:
return isinstance(msg, cls)
class PrevTx(protobuf.MessageType):
version: "int"
lock_time: "int"
@ -972,6 +988,20 @@ if TYPE_CHECKING:
def is_type_of(cls, msg: Any) -> TypeGuard["TxAckPrevExtraData"]:
return isinstance(msg, cls)
class TxAckEntropy(protobuf.MessageType):
tx: "TxAckEntropyWrapper"
def __init__(
self,
*,
tx: "TxAckEntropyWrapper",
) -> None:
pass
@classmethod
def is_type_of(cls, msg: Any) -> TypeGuard["TxAckEntropy"]:
return isinstance(msg, cls)
class GetOwnershipProof(protobuf.MessageType):
address_n: "list[int]"
coin_name: "str"
@ -1085,6 +1115,7 @@ if TYPE_CHECKING:
tx_hash: "bytes | None"
extra_data_len: "int | None"
extra_data_offset: "int | None"
nonce_commitment: "bytes | None"
def __init__(
self,
@ -1093,6 +1124,7 @@ if TYPE_CHECKING:
tx_hash: "bytes | None" = None,
extra_data_len: "int | None" = None,
extra_data_offset: "int | None" = None,
nonce_commitment: "bytes | None" = None,
) -> None:
pass
@ -1256,6 +1288,20 @@ if TYPE_CHECKING:
def is_type_of(cls, msg: Any) -> TypeGuard["TxAckPrevExtraDataWrapper"]:
return isinstance(msg, cls)
class TxAckEntropyWrapper(protobuf.MessageType):
entropy: "TxEntropy"
def __init__(
self,
*,
entropy: "TxEntropy",
) -> None:
pass
@classmethod
def is_type_of(cls, msg: Any) -> TypeGuard["TxAckEntropyWrapper"]:
return isinstance(msg, cls)
class CardanoBlockchainPointerType(protobuf.MessageType):
block_index: "int"
tx_index: "int"

View File

@ -29,6 +29,7 @@ TransactionType.inputs max_count:1
TransactionType.bin_outputs max_count:1
TransactionType.outputs max_count:1
TransactionType.extra_data max_size:1024
TransactionType.entropy max_size:32
TxInputType.address_n max_count:8
TxInputType.prev_hash max_size:32
@ -38,6 +39,7 @@ TxInputType.ownership_proof max_size:147
TxInputType.commitment_data max_size:70
TxInputType.orig_hash max_size:32
TxInputType.script_pubkey max_size:520
TxInputType.entropy_commitment max_size:32
TxOutputType.address max_size:130
TxOutputType.address_n max_count:8
@ -46,7 +48,10 @@ TxOutputType.orig_hash max_size:32
TxOutputBinType.script_pubkey max_size:520
TxEntropyType.entropy max_size:32
TxRequestDetailsType.tx_hash max_size:32
TxRequestDetailsType.nonce_commitment max_size:32
TxRequestSerializedType.signature max_size:73
TxRequestSerializedType.serialized_tx max_size:2048
@ -66,12 +71,15 @@ TxInput.ownership_proof max_size:147
TxInput.commitment_data max_size:70
TxInput.orig_hash max_size:32
TxInput.script_pubkey max_size:520
TxInput.entropy_commitment max_size:32
TxOutput.address max_size:130
TxOutput.address_n max_count:8
TxOutput.op_return_data max_size:150
TxOutput.orig_hash max_size:32
TxEntropy.entropy max_size:32
PrevInput.prev_hash max_size:32
PrevInput.script_sig max_size:1650
@ -79,6 +87,8 @@ PrevOutput.script_pubkey max_size:520
TxAckPrevExtraDataWrapper.extra_data_chunk type:FT_IGNORE
TxAckEntropyWrapper.entropy max_size:32
GetOwnershipId.address_n max_count:8
GetOwnershipId.coin_name max_size:21

View File

@ -123,6 +123,7 @@ class RequestType(IntEnum):
TXORIGINPUT = 5
TXORIGOUTPUT = 6
TXPAYMENTREQ = 7
TXENTROPY = 8
class CardanoDerivationType(IntEnum):
@ -1447,6 +1448,7 @@ class TxInput(protobuf.MessageType):
18: protobuf.Field("decred_staking_spend", "DecredStakingSpendType", repeated=False, required=False, default=None),
19: protobuf.Field("script_pubkey", "bytes", repeated=False, required=False, default=None),
20: protobuf.Field("coinjoin_flags", "uint32", repeated=False, required=False, default=0),
21: protobuf.Field("entropy_commitment", "bytes", repeated=False, required=False, default=None),
}
def __init__(
@ -1469,6 +1471,7 @@ class TxInput(protobuf.MessageType):
decred_staking_spend: Optional["DecredStakingSpendType"] = None,
script_pubkey: Optional["bytes"] = None,
coinjoin_flags: Optional["int"] = 0,
entropy_commitment: Optional["bytes"] = None,
) -> None:
self.address_n: Sequence["int"] = address_n if address_n is not None else []
self.prev_hash = prev_hash
@ -1487,6 +1490,7 @@ class TxInput(protobuf.MessageType):
self.decred_staking_spend = decred_staking_spend
self.script_pubkey = script_pubkey
self.coinjoin_flags = coinjoin_flags
self.entropy_commitment = entropy_commitment
class TxOutput(protobuf.MessageType):
@ -1527,6 +1531,20 @@ class TxOutput(protobuf.MessageType):
self.payment_req_index = payment_req_index
class TxEntropy(protobuf.MessageType):
MESSAGE_WIRE_TYPE = None
FIELDS = {
1: protobuf.Field("entropy", "bytes", repeated=False, required=False, default=None),
}
def __init__(
self,
*,
entropy: Optional["bytes"] = None,
) -> None:
self.entropy = entropy
class PrevTx(protobuf.MessageType):
MESSAGE_WIRE_TYPE = None
FIELDS = {
@ -1721,6 +1739,20 @@ class TxAckPrevExtraData(protobuf.MessageType):
self.tx = tx
class TxAckEntropy(protobuf.MessageType):
MESSAGE_WIRE_TYPE = 22
FIELDS = {
1: protobuf.Field("tx", "TxAckEntropyWrapper", repeated=False, required=True),
}
def __init__(
self,
*,
tx: "TxAckEntropyWrapper",
) -> None:
self.tx = tx
class GetOwnershipProof(protobuf.MessageType):
MESSAGE_WIRE_TYPE = 49
FIELDS = {
@ -1855,6 +1887,7 @@ class TxRequestDetailsType(protobuf.MessageType):
2: protobuf.Field("tx_hash", "bytes", repeated=False, required=False, default=None),
3: protobuf.Field("extra_data_len", "uint32", repeated=False, required=False, default=None),
4: protobuf.Field("extra_data_offset", "uint32", repeated=False, required=False, default=None),
5: protobuf.Field("nonce_commitment", "bytes", repeated=False, required=False, default=None),
}
def __init__(
@ -1864,11 +1897,13 @@ class TxRequestDetailsType(protobuf.MessageType):
tx_hash: Optional["bytes"] = None,
extra_data_len: Optional["int"] = None,
extra_data_offset: Optional["int"] = None,
nonce_commitment: Optional["bytes"] = None,
) -> None:
self.request_index = request_index
self.tx_hash = tx_hash
self.extra_data_len = extra_data_len
self.extra_data_offset = extra_data_offset
self.nonce_commitment = nonce_commitment
class TxRequestSerializedType(protobuf.MessageType):
@ -1908,6 +1943,7 @@ class TransactionType(protobuf.MessageType):
12: protobuf.Field("version_group_id", "uint32", repeated=False, required=False, default=None),
13: protobuf.Field("timestamp", "uint32", repeated=False, required=False, default=None),
14: protobuf.Field("branch_id", "uint32", repeated=False, required=False, default=None),
15: protobuf.Field("entropy", "TxEntropyType", repeated=False, required=False, default=None),
}
def __init__(
@ -1927,6 +1963,7 @@ class TransactionType(protobuf.MessageType):
version_group_id: Optional["int"] = None,
timestamp: Optional["int"] = None,
branch_id: Optional["int"] = None,
entropy: Optional["TxEntropyType"] = None,
) -> None:
self.inputs: Sequence["TxInputType"] = inputs if inputs is not None else []
self.bin_outputs: Sequence["TxOutputBinType"] = bin_outputs if bin_outputs is not None else []
@ -1942,6 +1979,21 @@ class TransactionType(protobuf.MessageType):
self.version_group_id = version_group_id
self.timestamp = timestamp
self.branch_id = branch_id
self.entropy = entropy
class TxEntropyType(protobuf.MessageType):
MESSAGE_WIRE_TYPE = None
FIELDS = {
1: protobuf.Field("entropy", "bytes", repeated=False, required=False, default=None),
}
def __init__(
self,
*,
entropy: Optional["bytes"] = None,
) -> None:
self.entropy = entropy
class TxInputType(protobuf.MessageType):
@ -1964,6 +2016,7 @@ class TxInputType(protobuf.MessageType):
18: protobuf.Field("decred_staking_spend", "DecredStakingSpendType", repeated=False, required=False, default=None),
19: protobuf.Field("script_pubkey", "bytes", repeated=False, required=False, default=None),
20: protobuf.Field("coinjoin_flags", "uint32", repeated=False, required=False, default=0),
21: protobuf.Field("entropy_commitment", "bytes", repeated=False, required=False, default=None),
}
def __init__(
@ -1986,6 +2039,7 @@ class TxInputType(protobuf.MessageType):
decred_staking_spend: Optional["DecredStakingSpendType"] = None,
script_pubkey: Optional["bytes"] = None,
coinjoin_flags: Optional["int"] = 0,
entropy_commitment: Optional["bytes"] = None,
) -> None:
self.address_n: Sequence["int"] = address_n if address_n is not None else []
self.prev_hash = prev_hash
@ -2004,6 +2058,7 @@ class TxInputType(protobuf.MessageType):
self.decred_staking_spend = decred_staking_spend
self.script_pubkey = script_pubkey
self.coinjoin_flags = coinjoin_flags
self.entropy_commitment = entropy_commitment
class TxOutputBinType(protobuf.MessageType):
@ -2208,6 +2263,20 @@ class TxAckPrevExtraDataWrapper(protobuf.MessageType):
self.extra_data_chunk = extra_data_chunk
class TxAckEntropyWrapper(protobuf.MessageType):
MESSAGE_WIRE_TYPE = None
FIELDS = {
15: protobuf.Field("entropy", "TxEntropy", repeated=False, required=True),
}
def __init__(
self,
*,
entropy: "TxEntropy",
) -> None:
self.entropy = entropy
class FirmwareErase(protobuf.MessageType):
MESSAGE_WIRE_TYPE = 6
FIELDS = {

View File

@ -316,6 +316,7 @@ impl<'a> SignTxProgress<'a> {
TxRequestType::TXORIGOUTPUT |
TxRequestType::TXPAYMENTREQ => unimplemented!(),
TxRequestType::TXFINISHED => unreachable!(),
TxRequestType::TXENTROPY => unimplemented!(),
}?;
self.ack_msg(ack)
}

File diff suppressed because it is too large Load Diff