eth: prepare and generate proto files for data streaming
What changed, and why it matters
This commit adds new message definitions and generated code to support streaming large Ethereum transaction data in chunks, but it does not implement the actual streaming logic. Existing tests are updated only to include the new optional field set to zero, meaning the current behavior is unchanged. There is no indication this is a security fix or introduces a vulnerability.
No immediate security action required. Treat as a feature scaffolding commit. When the streaming implementation is added, review it carefully for bounds checking on offset/length, chunk size limits, memory exhaustion, and consistency between data_length and delivered chunks.
Security signals we found
New protobuf fields added for future streaming feature
Streaming request type explicitly rejected with InvalidState in current code
No validation or processing logic implemented for data_length or chunk messages
Tests only exercise data_length=0 (legacy inline-data mode)
Evidence from the diff
The change extends the Ethereum protocol buffer schema with a data_length field on ETHSignRequest and ETHSignEIP1559Request, plus ETHSignDataRequestChunkResponse/ETHSignDataResponseChunkRequest messages and corresponding oneof variants in ETHRequest/ETHResponse. The Rust API handler now returns Error::InvalidState for the new DataResponseChunk request type, confirming the streaming path is not yet wired up. All generated Python/Rust/C files are regenerated. Tests are updated to populate data_length: 0 so existing non-streaming behavior is preserved.
Changed components
messages/eth.protopy/bitbox02/bitbox02/communication/generated/eth_pb2.pypy/bitbox02/bitbox02/communication/generated/eth_pb2.pyisrc/rust/bitbox02-rust/src/hww/api/ethereum.rssrc/rust/bitbox02-rust/src/hww/api/ethereum/sign.rssrc/rust/bitbox02-rust/src/shiftcrypto.bitbox02.rsInspect captured patch +154 / −44
diff --git a/messages/eth.proto b/messages/eth.proto
index b40295d..ebff5c1 100644
--- a/messages/eth.proto
+++ b/messages/eth.proto
@@ -51,6 +51,8 @@ message ETHSignRequest {
// If non-zero, `coin` is ignored and `chain_id` is used to identify the network.
uint64 chain_id = 10;
ETHAddressCase address_case = 11;
+ // For streaming: if non-zero, data field should be empty and data will be requested in chunks
+ uint32 data_length = 12;
}
// TX payload for an EIP-1559 (type 2) transaction: https://eips.ethereum.org/EIPS/eip-1559
@@ -66,6 +68,17 @@ message ETHSignEIP1559Request {
bytes data = 9;
AntiKleptoHostNonceCommitment host_nonce_commitment = 10;
ETHAddressCase address_case = 11;
+ // For streaming: if non-zero, data field should be empty and data will be requested in chunks
+ uint32 data_length = 12;
+}
+
+message ETHSignDataRequestChunkResponse {
+ uint32 offset = 1;
+ uint32 length = 2;
+}
+
+message ETHSignDataResponseChunkRequest {
+ bytes chunk = 1;
}
message ETHSignMessageRequest {
@@ -142,6 +155,7 @@ message ETHRequest {
ETHSignTypedMessageRequest sign_typed_msg = 5;
ETHTypedMessageValueRequest typed_msg_value = 6;
ETHSignEIP1559Request sign_eip1559 = 7;
+ ETHSignDataResponseChunkRequest data_response_chunk = 8;
}
}
@@ -151,5 +165,6 @@ message ETHResponse {
ETHSignResponse sign = 2;
AntiKleptoSignerCommitment antiklepto_signer_commitment = 3;
ETHTypedMessageValueResponse typed_msg_value = 4;
+ ETHSignDataRequestChunkResponse data_request_chunk = 5;
}
}
diff --git a/py/bitbox02/bitbox02/communication/generated/eth_pb2.py b/py/bitbox02/bitbox02/communication/generated/eth_pb2.py
index ce8cd40..3870633 100644
--- a/py/bitbox02/bitbox02/communication/generated/eth_pb2.py
+++ b/py/bitbox02/bitbox02/communication/generated/eth_pb2.py
@@ -15,47 +15,51 @@ from . import common_pb2 as common__pb2
from . import antiklepto_pb2 as antiklepto__pb2
-DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\teth.proto\x12\x14shiftcrypto.bitbox02\x1a\x0c\x63ommon.proto\x1a\x10\x61ntiklepto.proto\"\xf4\x01\n\rETHPubRequest\x12\x0f\n\x07keypath\x18\x01 \x03(\r\x12+\n\x04\x63oin\x18\x02 \x01(\x0e\x32\x1d.shiftcrypto.bitbox02.ETHCoin\x12\x43\n\x0boutput_type\x18\x03 \x01(\x0e\x32..shiftcrypto.bitbox02.ETHPubRequest.OutputType\x12\x0f\n\x07\x64isplay\x18\x04 \x01(\x08\x12\x18\n\x10\x63ontract_address\x18\x05 \x01(\x0c\x12\x10\n\x08\x63hain_id\x18\x06 \x01(\x04\"#\n\nOutputType\x12\x0b\n\x07\x41\x44\x44RESS\x10\x00\x12\x08\n\x04XPUB\x10\x01\"\xd5\x02\n\x0e\x45THSignRequest\x12+\n\x04\x63oin\x18\x01 \x01(\x0e\x32\x1d.shiftcrypto.bitbox02.ETHCoin\x12\x0f\n\x07keypath\x18\x02 \x03(\r\x12\r\n\x05nonce\x18\x03 \x01(\x0c\x12\x11\n\tgas_price\x18\x04 \x01(\x0c\x12\x11\n\tgas_limit\x18\x05 \x01(\x0c\x12\x11\n\trecipient\x18\x06 \x01(\x0c\x12\r\n\x05value\x18\x07 \x01(\x0c\x12\x0c\n\x04\x64\x61ta\x18\x08 \x01(\x0c\x12R\n\x15host_nonce_commitment\x18\t \x01(\x0b\x32\x33.shiftcrypto.bitbox02.AntiKleptoHostNonceCommitment\x12\x10\n\x08\x63hain_id\x18\n \x01(\x04\x12:\n\x0c\x61\x64\x64ress_case\x18\x0b \x01(\x0e\x32$.shiftcrypto.bitbox02.ETHAddressCase\"\xd7\x02\n\x15\x45THSignEIP1559Request\x12\x10\n\x08\x63hain_id\x18\x01 \x01(\x04\x12\x0f\n\x07keypath\x18\x02 \x03(\r\x12\r\n\x05nonce\x18\x03 \x01(\x0c\x12 \n\x18max_priority_fee_per_gas\x18\x04 \x01(\x0c\x12\x17\n\x0fmax_fee_per_gas\x18\x05 \x01(\x0c\x12\x11\n\tgas_limit\x18\x06 \x01(\x0c\x12\x11\n\trecipient\x18\x07 \x01(\x0c\x12\r\n\x05value\x18\x08 \x01(\x0c\x12\x0c\n\x04\x64\x61ta\x18\t \x01(\x0c\x12R\n\x15host_nonce_commitment\x18\n \x01(\x0b\x32\x33.shiftcrypto.bitbox02.AntiKleptoHostNonceCommitment\x12:\n\x0c\x61\x64\x64ress_case\x18\x0b \x01(\x0e\x32$.shiftcrypto.bitbox02.ETHAddressCase\"\xc8\x01\n\x15\x45THSignMessageRequest\x12+\n\x04\x63oin\x18\x01 \x01(\x0e\x32\x1d.shiftcrypto.bitbox02.ETHCoin\x12\x0f\n\x07keypath\x18\x02 \x03(\r\x12\x0b\n\x03msg\x18\x03 \x01(\x0c\x12R\n\x15host_nonce_commitment\x18\x04 \x01(\x0b\x32\x33.shiftcrypto.bitbox02.AntiKleptoHostNonceCommitment\x12\x10\n\x08\x63hain_id\x18\x05 \x01(\x04\"$\n\x0f\x45THSignResponse\x12\x11\n\tsignature\x18\x01 \x01(\x0c\"\xfb\x05\n\x1a\x45THSignTypedMessageRequest\x12\x10\n\x08\x63hain_id\x18\x01 \x01(\x04\x12\x0f\n\x07keypath\x18\x02 \x03(\r\x12J\n\x05types\x18\x03 \x03(\x0b\x32;.shiftcrypto.bitbox02.ETHSignTypedMessageRequest.StructType\x12\x14\n\x0cprimary_type\x18\x04 \x01(\t\x12R\n\x15host_nonce_commitment\x18\x05 \x01(\x0b\x32\x33.shiftcrypto.bitbox02.AntiKleptoHostNonceCommitment\x1a\xc9\x01\n\nMemberType\x12G\n\x04type\x18\x01 \x01(\x0e\x32\x39.shiftcrypto.bitbox02.ETHSignTypedMessageRequest.DataType\x12\x0c\n\x04size\x18\x02 \x01(\r\x12\x13\n\x0bstruct_name\x18\x03 \x01(\t\x12O\n\narray_type\x18\x04 \x01(\x0b\x32;.shiftcrypto.bitbox02.ETHSignTypedMessageRequest.MemberType\x1a\x61\n\x06Member\x12\x0c\n\x04name\x18\x01 \x01(\t\x12I\n\x04type\x18\x02 \x01(\x0b\x32;.shiftcrypto.bitbox02.ETHSignTypedMessageRequest.MemberType\x1a\x64\n\nStructType\x12\x0c\n\x04name\x18\x01 \x01(\t\x12H\n\x07members\x18\x02 \x03(\x0b\x32\x37.shiftcrypto.bitbox02.ETHSignTypedMessageRequest.Member\"o\n\x08\x44\x61taType\x12\x0b\n\x07UNKNOWN\x10\x00\x12\t\n\x05\x42YTES\x10\x01\x12\x08\n\x04UINT\x10\x02\x12\x07\n\x03INT\x10\x03\x12\x08\n\x04\x42OOL\x10\x04\x12\x0b\n\x07\x41\x44\x44RESS\x10\x05\x12\n\n\x06STRING\x10\x06\x12\t\n\x05\x41RRAY\x10\x07\x12\n\n\x06STRUCT\x10\x08\"\xb4\x01\n\x1c\x45THTypedMessageValueResponse\x12R\n\x0broot_object\x18\x01 \x01(\x0e\x32=.shiftcrypto.bitbox02.ETHTypedMessageValueResponse.RootObject\x12\x0c\n\x04path\x18\x02 \x03(\r\"2\n\nRootObject\x12\x0b\n\x07UNKNOWN\x10\x00\x12\n\n\x06\x44OMAIN\x10\x01\x12\x0b\n\x07MESSAGE\x10\x02\",\n\x1b\x45THTypedMessageValueRequest\x12\r\n\x05value\x18\x01 \x01(\x0c\"\xf3\x03\n\nETHRequest\x12\x32\n\x03pub\x18\x01 \x01(\x0b\x32#.shiftcrypto.bitbox02.ETHPubRequestH\x00\x12\x34\n\x04sign\x18\x02 \x01(\x0b\x32$.shiftcrypto.bitbox02.ETHSignRequestH\x00\x12?\n\x08sign_msg\x18\x03 \x01(\x0b\x32+.shiftcrypto.bitbox02.ETHSignMessageRequestH\x00\x12P\n\x14\x61ntiklepto_signature\x18\x04 \x01(\x0b\x32\x30.shiftcrypto.bitbox02.AntiKleptoSignatureRequestH\x00\x12J\n\x0esign_typed_msg\x18\x05 \x01(\x0b\x32\x30.shiftcrypto.bitbox02.ETHSignTypedMessageRequestH\x00\x12L\n\x0ftyped_msg_value\x18\x06 \x01(\x0b\x32\x31.shiftcrypto.bitbox02.ETHTypedMessageValueRequestH\x00\x12\x43\n\x0csign_eip1559\x18\x07 \x01(\x0b\x32+.shiftcrypto.bitbox02.ETHSignEIP1559RequestH\x00\x42\t\n\x07request\"\xab\x02\n\x0b\x45THResponse\x12\x30\n\x03pub\x18\x01 \x01(\x0b\x32!.shiftcrypto.bitbox02.PubResponseH\x00\x12\x35\n\x04sign\x18\x02 \x01(\x0b\x32%.shiftcrypto.bitbox02.ETHSignResponseH\x00\x12X\n\x1c\x61ntiklepto_signer_commitment\x18\x03 \x01(\x0b\x32\x30.shiftcrypto.bitbox02.AntiKleptoSignerCommitmentH\x00\x12M\n\x0ftyped_msg_value\x18\x04 \x01(\x0b\x32\x32.shiftcrypto.bitbox02.ETHTypedMessageValueResponseH\x00\x42\n\n\x08response*2\n\x07\x45THCoin\x12\x07\n\x03\x45TH\x10\x00\x12\x0e\n\nRopstenETH\x10\x01\x12\x0e\n\nRinkebyETH\x10\x02*d\n\x0e\x45THAddressCase\x12\x1a\n\x16\x45TH_ADDRESS_CASE_MIXED\x10\x00\x12\x1a\n\x16\x45TH_ADDRESS_CASE_UPPER\x10\x01\x12\x1a\n\x16\x45TH_ADDRESS_CASE_LOWER\x10\x02\x62\x06proto3')
+DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\teth.proto\x12\x14shiftcrypto.bitbox02\x1a\x0c\x63ommon.proto\x1a\x10\x61ntiklepto.proto\"\xf4\x01\n\rETHPubRequest\x12\x0f\n\x07keypath\x18\x01 \x03(\r\x12+\n\x04\x63oin\x18\x02 \x01(\x0e\x32\x1d.shiftcrypto.bitbox02.ETHCoin\x12\x43\n\x0boutput_type\x18\x03 \x01(\x0e\x32..shiftcrypto.bitbox02.ETHPubRequest.OutputType\x12\x0f\n\x07\x64isplay\x18\x04 \x01(\x08\x12\x18\n\x10\x63ontract_address\x18\x05 \x01(\x0c\x12\x10\n\x08\x63hain_id\x18\x06 \x01(\x04\"#\n\nOutputType\x12\x0b\n\x07\x41\x44\x44RESS\x10\x00\x12\x08\n\x04XPUB\x10\x01\"\xea\x02\n\x0e\x45THSignRequest\x12+\n\x04\x63oin\x18\x01 \x01(\x0e\x32\x1d.shiftcrypto.bitbox02.ETHCoin\x12\x0f\n\x07keypath\x18\x02 \x03(\r\x12\r\n\x05nonce\x18\x03 \x01(\x0c\x12\x11\n\tgas_price\x18\x04 \x01(\x0c\x12\x11\n\tgas_limit\x18\x05 \x01(\x0c\x12\x11\n\trecipient\x18\x06 \x01(\x0c\x12\r\n\x05value\x18\x07 \x01(\x0c\x12\x0c\n\x04\x64\x61ta\x18\x08 \x01(\x0c\x12R\n\x15host_nonce_commitment\x18\t \x01(\x0b\x32\x33.shiftcrypto.bitbox02.AntiKleptoHostNonceCommitment\x12\x10\n\x08\x63hain_id\x18\n \x01(\x04\x12:\n\x0c\x61\x64\x64ress_case\x18\x0b \x01(\x0e\x32$.shiftcrypto.bitbox02.ETHAddressCase\x12\x13\n\x0b\x64\x61ta_length\x18\x0c \x01(\r\"\xec\x02\n\x15\x45THSignEIP1559Request\x12\x10\n\x08\x63hain_id\x18\x01 \x01(\x04\x12\x0f\n\x07keypath\x18\x02 \x03(\r\x12\r\n\x05nonce\x18\x03 \x01(\x0c\x12 \n\x18max_priority_fee_per_gas\x18\x04 \x01(\x0c\x12\x17\n\x0fmax_fee_per_gas\x18\x05 \x01(\x0c\x12\x11\n\tgas_limit\x18\x06 \x01(\x0c\x12\x11\n\trecipient\x18\x07 \x01(\x0c\x12\r\n\x05value\x18\x08 \x01(\x0c\x12\x0c\n\x04\x64\x61ta\x18\t \x01(\x0c\x12R\n\x15host_nonce_commitment\x18\n \x01(\x0b\x32\x33.shiftcrypto.bitbox02.AntiKleptoHostNonceCommitment\x12:\n\x0c\x61\x64\x64ress_case\x18\x0b \x01(\x0e\x32$.shiftcrypto.bitbox02.ETHAddressCase\x12\x13\n\x0b\x64\x61ta_length\x18\x0c \x01(\r\"A\n\x1f\x45THSignDataRequestChunkResponse\x12\x0e\n\x06offset\x18\x01 \x01(\r\x12\x0e\n\x06length\x18\x02 \x01(\r\"0\n\x1f\x45THSignDataResponseChunkRequest\x12\r\n\x05\x63hunk\x18\x01 \x01(\x0c\"\xc8\x01\n\x15\x45THSignMessageRequest\x12+\n\x04\x63oin\x18\x01 \x01(\x0e\x32\x1d.shiftcrypto.bitbox02.ETHCoin\x12\x0f\n\x07keypath\x18\x02 \x03(\r\x12\x0b\n\x03msg\x18\x03 \x01(\x0c\x12R\n\x15host_nonce_commitment\x18\x04 \x01(\x0b\x32\x33.shiftcrypto.bitbox02.AntiKleptoHostNonceCommitment\x12\x10\n\x08\x63hain_id\x18\x05 \x01(\x04\"$\n\x0f\x45THSignResponse\x12\x11\n\tsignature\x18\x01 \x01(\x0c\"\xfb\x05\n\x1a\x45THSignTypedMessageRequest\x12\x10\n\x08\x63hain_id\x18\x01 \x01(\x04\x12\x0f\n\x07keypath\x18\x02 \x03(\r\x12J\n\x05types\x18\x03 \x03(\x0b\x32;.shiftcrypto.bitbox02.ETHSignTypedMessageRequest.StructType\x12\x14\n\x0cprimary_type\x18\x04 \x01(\t\x12R\n\x15host_nonce_commitment\x18\x05 \x01(\x0b\x32\x33.shiftcrypto.bitbox02.AntiKleptoHostNonceCommitment\x1a\xc9\x01\n\nMemberType\x12G\n\x04type\x18\x01 \x01(\x0e\x32\x39.shiftcrypto.bitbox02.ETHSignTypedMessageRequest.DataType\x12\x0c\n\x04size\x18\x02 \x01(\r\x12\x13\n\x0bstruct_name\x18\x03 \x01(\t\x12O\n\narray_type\x18\x04 \x01(\x0b\x32;.shiftcrypto.bitbox02.ETHSignTypedMessageRequest.MemberType\x1a\x61\n\x06Member\x12\x0c\n\x04name\x18\x01 \x01(\t\x12I\n\x04type\x18\x02 \x01(\x0b\x32;.shiftcrypto.bitbox02.ETHSignTypedMessageRequest.MemberType\x1a\x64\n\nStructType\x12\x0c\n\x04name\x18\x01 \x01(\t\x12H\n\x07members\x18\x02 \x03(\x0b\x32\x37.shiftcrypto.bitbox02.ETHSignTypedMessageRequest.Member\"o\n\x08\x44\x61taType\x12\x0b\n\x07UNKNOWN\x10\x00\x12\t\n\x05\x42YTES\x10\x01\x12\x08\n\x04UINT\x10\x02\x12\x07\n\x03INT\x10\x03\x12\x08\n\x04\x42OOL\x10\x04\x12\x0b\n\x07\x41\x44\x44RESS\x10\x05\x12\n\n\x06STRING\x10\x06\x12\t\n\x05\x41RRAY\x10\x07\x12\n\n\x06STRUCT\x10\x08\"\xb4\x01\n\x1c\x45THTypedMessageValueResponse\x12R\n\x0broot_object\x18\x01 \x01(\x0e\x32=.shiftcrypto.bitbox02.ETHTypedMessageValueResponse.RootObject\x12\x0c\n\x04path\x18\x02 \x03(\r\"2\n\nRootObject\x12\x0b\n\x07UNKNOWN\x10\x00\x12\n\n\x06\x44OMAIN\x10\x01\x12\x0b\n\x07MESSAGE\x10\x02\",\n\x1b\x45THTypedMessageValueRequest\x12\r\n\x05value\x18\x01 \x01(\x0c\"\xc9\x04\n\nETHRequest\x12\x32\n\x03pub\x18\x01 \x01(\x0b\x32#.shiftcrypto.bitbox02.ETHPubRequestH\x00\x12\x34\n\x04sign\x18\x02 \x01(\x0b\x32$.shiftcrypto.bitbox02.ETHSignRequestH\x00\x12?\n\x08sign_msg\x18\x03 \x01(\x0b\x32+.shiftcrypto.bitbox02.ETHSignMessageRequestH\x00\x12P\n\x14\x61ntiklepto_signature\x18\x04 \x01(\x0b\x32\x30.shiftcrypto.bitbox02.AntiKleptoSignatureRequestH\x00\x12J\n\x0esign_typed_msg\x18\x05 \x01(\x0b\x32\x30.shiftcrypto.bitbox02.ETHSignTypedMessageRequestH\x00\x12L\n\x0ftyped_msg_value\x18\x06 \x01(\x0b\x32\x31.shiftcrypto.bitbox02.ETHTypedMessageValueRequestH\x00\x12\x43\n\x0csign_eip1559\x18\x07 \x01(\x0b\x32+.shiftcrypto.bitbox02.ETHSignEIP1559RequestH\x00\x12T\n\x13\x64\x61ta_response_chunk\x18\x08 \x01(\x0b\x32\x35.shiftcrypto.bitbox02.ETHSignDataResponseChunkRequestH\x00\x42\t\n\x07request\"\x80\x03\n\x0b\x45THResponse\x12\x30\n\x03pub\x18\x01 \x01(\x0b\x32!.shiftcrypto.bitbox02.PubResponseH\x00\x12\x35\n\x04sign\x18\x02 \x01(\x0b\x32%.shiftcrypto.bitbox02.ETHSignResponseH\x00\x12X\n\x1c\x61ntiklepto_signer_commitment\x18\x03 \x01(\x0b\x32\x30.shiftcrypto.bitbox02.AntiKleptoSignerCommitmentH\x00\x12M\n\x0ftyped_msg_value\x18\x04 \x01(\x0b\x32\x32.shiftcrypto.bitbox02.ETHTypedMessageValueResponseH\x00\x12S\n\x12\x64\x61ta_request_chunk\x18\x05 \x01(\x0b\x32\x35.shiftcrypto.bitbox02.ETHSignDataRequestChunkResponseH\x00\x42\n\n\x08response*2\n\x07\x45THCoin\x12\x07\n\x03\x45TH\x10\x00\x12\x0e\n\nRopstenETH\x10\x01\x12\x0e\n\nRinkebyETH\x10\x02*d\n\x0e\x45THAddressCase\x12\x1a\n\x16\x45TH_ADDRESS_CASE_MIXED\x10\x00\x12\x1a\n\x16\x45TH_ADDRESS_CASE_UPPER\x10\x01\x12\x1a\n\x16\x45TH_ADDRESS_CASE_LOWER\x10\x02\x62\x06proto3')
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())
_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'eth_pb2', globals())
if _descriptor._USE_C_DESCRIPTORS == False:
DESCRIPTOR._options = None
- _ETHCOIN._serialized_start=3044
- _ETHCOIN._serialized_end=3094
- _ETHADDRESSCASE._serialized_start=3096
- _ETHADDRESSCASE._serialized_end=3196
+ _ETHCOIN._serialized_start=3374
+ _ETHCOIN._serialized_end=3424
+ _ETHADDRESSCASE._serialized_start=3426
+ _ETHADDRESSCASE._serialized_end=3526
_ETHPUBREQUEST._serialized_start=68
_ETHPUBREQUEST._serialized_end=312
_ETHPUBREQUEST_OUTPUTTYPE._serialized_start=277
_ETHPUBREQUEST_OUTPUTTYPE._serialized_end=312
_ETHSIGNREQUEST._serialized_start=315
- _ETHSIGNREQUEST._serialized_end=656
- _ETHSIGNEIP1559REQUEST._serialized_start=659
- _ETHSIGNEIP1559REQUEST._serialized_end=1002
- _ETHSIGNMESSAGEREQUEST._serialized_start=1005
- _ETHSIGNMESSAGEREQUEST._serialized_end=1205
- _ETHSIGNRESPONSE._serialized_start=1207
- _ETHSIGNRESPONSE._serialized_end=1243
- _ETHSIGNTYPEDMESSAGEREQUEST._serialized_start=1246
- _ETHSIGNTYPEDMESSAGEREQUEST._serialized_end=2009
- _ETHSIGNTYPEDMESSAGEREQUEST_MEMBERTYPE._serialized_start=1494
- _ETHSIGNTYPEDMESSAGEREQUEST_MEMBERTYPE._serialized_end=1695
- _ETHSIGNTYPEDMESSAGEREQUEST_MEMBER._serialized_start=1697
- _ETHSIGNTYPEDMESSAGEREQUEST_MEMBER._serialized_end=1794
- _ETHSIGNTYPEDMESSAGEREQUEST_STRUCTTYPE._serialized_start=1796
- _ETHSIGNTYPEDMESSAGEREQUEST_STRUCTTYPE._serialized_end=1896
- _ETHSIGNTYPEDMESSAGEREQUEST_DATATYPE._serialized_start=1898
- _ETHSIGNTYPEDMESSAGEREQUEST_DATATYPE._serialized_end=2009
- _ETHTYPEDMESSAGEVALUERESPONSE._serialized_start=2012
- _ETHTYPEDMESSAGEVALUERESPONSE._serialized_end=2192
- _ETHTYPEDMESSAGEVALUERESPONSE_ROOTOBJECT._serialized_start=2142
- _ETHTYPEDMESSAGEVALUERESPONSE_ROOTOBJECT._serialized_end=2192
- _ETHTYPEDMESSAGEVALUEREQUEST._serialized_start=2194
- _ETHTYPEDMESSAGEVALUEREQUEST._serialized_end=2238
- _ETHREQUEST._serialized_start=2241
- _ETHREQUEST._serialized_end=2740
- _ETHRESPONSE._serialized_start=2743
- _ETHRESPONSE._serialized_end=3042
+ _ETHSIGNREQUEST._serialized_end=677
+ _ETHSIGNEIP1559REQUEST._serialized_start=680
+ _ETHSIGNEIP1559REQUEST._serialized_end=1044
+ _ETHSIGNDATAREQUESTCHUNKRESPONSE._serialized_start=1046
+ _ETHSIGNDATAREQUESTCHUNKRESPONSE._serialized_end=1111
+ _ETHSIGNDATARESPONSECHUNKREQUEST._serialized_start=1113
+ _ETHSIGNDATARESPONSECHUNKREQUEST._serialized_end=1161
+ _ETHSIGNMESSAGEREQUEST._serialized_start=1164
+ _ETHSIGNMESSAGEREQUEST._serialized_end=1364
+ _ETHSIGNRESPONSE._serialized_start=1366
+ _ETHSIGNRESPONSE._serialized_end=1402
+ _ETHSIGNTYPEDMESSAGEREQUEST._serialized_start=1405
+ _ETHSIGNTYPEDMESSAGEREQUEST._serialized_end=2168
+ _ETHSIGNTYPEDMESSAGEREQUEST_MEMBERTYPE._serialized_start=1653
+ _ETHSIGNTYPEDMESSAGEREQUEST_MEMBERTYPE._serialized_end=1854
+ _ETHSIGNTYPEDMESSAGEREQUEST_MEMBER._serialized_start=1856
+ _ETHSIGNTYPEDMESSAGEREQUEST_MEMBER._serialized_end=1953
+ _ETHSIGNTYPEDMESSAGEREQUEST_STRUCTTYPE._serialized_start=1955
+ _ETHSIGNTYPEDMESSAGEREQUEST_STRUCTTYPE._serialized_end=2055
+ _ETHSIGNTYPEDMESSAGEREQUEST_DATATYPE._serialized_start=2057
+ _ETHSIGNTYPEDMESSAGEREQUEST_DATATYPE._serialized_end=2168
+ _ETHTYPEDMESSAGEVALUERESPONSE._serialized_start=2171
+ _ETHTYPEDMESSAGEVALUERESPONSE._serialized_end=2351
+ _ETHTYPEDMESSAGEVALUERESPONSE_ROOTOBJECT._serialized_start=2301
+ _ETHTYPEDMESSAGEVALUERESPONSE_ROOTOBJECT._serialized_end=2351
+ _ETHTYPEDMESSAGEVALUEREQUEST._serialized_start=2353
+ _ETHTYPEDMESSAGEVALUEREQUEST._serialized_end=2397
+ _ETHREQUEST._serialized_start=2400
+ _ETHREQUEST._serialized_end=2985
+ _ETHRESPONSE._serialized_start=2988
+ _ETHRESPONSE._serialized_end=3372
# @@protoc_insertion_point(module_scope)
diff --git a/py/bitbox02/bitbox02/communication/generated/eth_pb2.pyi b/py/bitbox02/bitbox02/communication/generated/eth_pb2.pyi
index 0eefed6..0e83542 100644
--- a/py/bitbox02/bitbox02/communication/generated/eth_pb2.pyi
+++ b/py/bitbox02/bitbox02/communication/generated/eth_pb2.pyi
@@ -123,6 +123,7 @@ class ETHSignRequest(google.protobuf.message.Message):
HOST_NONCE_COMMITMENT_FIELD_NUMBER: builtins.int
CHAIN_ID_FIELD_NUMBER: builtins.int
ADDRESS_CASE_FIELD_NUMBER: builtins.int
+ DATA_LENGTH_FIELD_NUMBER: builtins.int
coin: global___ETHCoin.ValueType
"""Deprecated: use chain_id instead."""
nonce: builtins.bytes
@@ -139,6 +140,8 @@ class ETHSignRequest(google.protobuf.message.Message):
chain_id: builtins.int
"""If non-zero, `coin` is ignored and `chain_id` is used to identify the network."""
address_case: global___ETHAddressCase.ValueType
+ data_length: builtins.int
+ """For streaming: if non-zero, data field should be empty and data will be requested in chunks"""
@property
def keypath(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]: ...
@property
@@ -157,9 +160,10 @@ class ETHSignRequest(google.protobuf.message.Message):
host_nonce_commitment: antiklepto_pb2.AntiKleptoHostNonceCommitment | None = ...,
chain_id: builtins.int = ...,
address_case: global___ETHAddressCase.ValueType = ...,
+ data_length: builtins.int = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["host_nonce_commitment", b"host_nonce_commitment"]) -> builtins.bool: ...
- def ClearField(self, field_name: typing.Literal["address_case", b"address_case", "chain_id", b"chain_id", "coin", b"coin", "data", b"data", "gas_limit", b"gas_limit", "gas_price", b"gas_price", "host_nonce_commitment", b"host_nonce_commitment", "keypath", b"keypath", "nonce", b"nonce", "recipient", b"recipient", "value", b"value"]) -> None: ...
+ def ClearField(self, field_name: typing.Literal["address_case", b"address_case", "chain_id", b"chain_id", "coin", b"coin", "data", b"data", "data_length", b"data_length", "gas_limit", b"gas_limit", "gas_price", b"gas_price", "host_nonce_commitment", b"host_nonce_commitment", "keypath", b"keypath", "nonce", b"nonce", "recipient", b"recipient", "value", b"value"]) -> None: ...
global___ETHSignRequest = ETHSignRequest
@@ -180,6 +184,7 @@ class ETHSignEIP1559Request(google.protobuf.message.Message):
DATA_FIELD_NUMBER: builtins.int
HOST_NONCE_COMMITMENT_FIELD_NUMBER: builtins.int
ADDRESS_CASE_FIELD_NUMBER: builtins.int
+ DATA_LENGTH_FIELD_NUMBER: builtins.int
chain_id: builtins.int
nonce: builtins.bytes
"""smallest big endian serialization, max. 16 bytes"""
@@ -195,6 +200,8 @@ class ETHSignEIP1559Request(google.protobuf.message.Message):
"""smallest big endian serialization, max. 32 bytes"""
data: builtins.bytes
address_case: global___ETHAddressCase.ValueType
+ data_length: builtins.int
+ """For streaming: if non-zero, data field should be empty and data will be requested in chunks"""
@property
def keypath(self) -> google.protobuf.internal.containers.RepeatedScalarFieldContainer[builtins.int]: ...
@property
@@ -213,12 +220,46 @@ class ETHSignEIP1559Request(google.protobuf.message.Message):
data: builtins.bytes = ...,
host_nonce_commitment: antiklepto_pb2.AntiKleptoHostNonceCommitment | None = ...,
address_case: global___ETHAddressCase.ValueType = ...,
+ data_length: builtins.int = ...,
) -> None: ...
def HasField(self, field_name: typing.Literal["host_nonce_commitment", b"host_nonce_commitment"]) -> builtins.bool: ...
- def ClearField(self, field_name: typing.Literal["address_case", b"address_case", "chain_id", b"chain_id", "data", b"data", "gas_limit", b"gas_limit", "host_nonce_commitment", b"host_nonce_commitment", "keypath", b"keypath", "max_fee_per_gas", b"max_fee_per_gas", "max_priority_fee_per_gas", b"max_priority_fee_per_gas", "nonce", b"nonce", "recipient", b"recipient", "value", b"value"]) -> None: ...
+ def ClearField(self, field_name: typing.Literal["address_case", b"address_case", "chain_id", b"chain_id", "data", b"data", "data_length", b"data_length", "gas_limit", b"gas_limit", "host_nonce_commitment", b"host_nonce_commitment", "keypath", b"keypath", "max_fee_per_gas", b"max_fee_per_gas", "max_priority_fee_per_gas", b"max_priority_fee_per_gas", "nonce", b"nonce", "recipient", b"recipient", "value", b"value"]) -> None: ...
global___ETHSignEIP1559Request = ETHSignEIP1559Request
+@typing.final
+class ETHSignDataRequestChunkResponse(google.protobuf.message.Message):
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
+
+ OFFSET_FIELD_NUMBER: builtins.int
+ LENGTH_FIELD_NUMBER: builtins.int
+ offset: builtins.int
+ length: builtins.int
+ def __init__(
+ self,
+ *,
+ offset: builtins.int = ...,
+ length: builtins.int = ...,
+ ) -> None: ...
+ def ClearField(self, field_name: typing.Literal["length", b"length", "offset", b"offset"]) -> None: ...
+
+global___ETHSignDataRequestChunkResponse = ETHSignDataRequestChunkResponse
+
+@typing.final
+class ETHSignDataResponseChunkRequest(google.protobuf.message.Message):
+ DESCRIPTOR: google.protobuf.descriptor.Descriptor
+
+ CHUNK_FIELD_NUMBER: builtins.int
+ chunk: builtins.bytes
+ def __init__(
+ self,
+ *,
+ chunk: builtins.bytes = ...,
+ ) -> None: ...
+ def ClearField(self, field_name: typing.Literal["chunk", b"chunk"]) -> None: ...
+
+global___ETHSignDataResponseChunkRequest = ETHSignDataResponseChunkRequest
+
@typing.final
class ETHSignMessageRequest(google.protobuf.message.Message):
DESCRIPTOR: google.protobuf.descriptor.Descriptor
@@ -447,6 +488,7 @@ class ETHRequest(google.protobuf.message.Message):
SIGN_TYPED_MSG_FIELD_NUMBER: builtins.int
TYPED_MSG_VALUE_FIELD_NUMBER: builtins.int
SIGN_EIP1559_FIELD_NUMBER: builtins.int
+ DATA_RESPONSE_CHUNK_FIELD_NUMBER: builtins.int
@property
def pub(self) -> global___ETHPubRequest: ...
@property
@@ -461,6 +503,8 @@ class ETHRequest(google.protobuf.message.Message):
def typed_msg_value(self) -> global___ETHTypedMessageValueRequest: ...
@property
def sign_eip1559(self) -> global___ETHSignEIP1559Request: ...
+ @property
+ def data_response_chunk(self) -> global___ETHSignDataResponseChunkRequest: ...
def __init__(
self,
*,
@@ -471,10 +515,11 @@ class ETHRequest(google.protobuf.message.Message):
sign_typed_msg: global___ETHSignTypedMessageRequest | None = ...,
typed_msg_value: global___ETHTypedMessageValueRequest | None = ...,
sign_eip1559: global___ETHSignEIP1559Request | None = ...,
+ data_response_chunk: global___ETHSignDataResponseChunkRequest | None = ...,
) -> None: ...
- def HasField(self, field_name: typing.Literal["antiklepto_signature", b"antiklepto_signature", "pub", b"pub", "request", b"request", "sign", b"sign", "sign_eip1559", b"sign_eip1559", "sign_msg", b"sign_msg", "sign_typed_msg", b"sign_typed_msg", "typed_msg_value", b"typed_msg_value"]) -> builtins.bool: ...
- def ClearField(self, field_name: typing.Literal["antiklepto_signature", b"antiklepto_signature", "pub", b"pub", "request", b"request", "sign", b"sign", "sign_eip1559", b"sign_eip1559", "sign_msg", b"sign_msg", "sign_typed_msg", b"sign_typed_msg", "typed_msg_value", b"typed_msg_value"]) -> None: ...
- def WhichOneof(self, oneof_group: typing.Literal["request", b"request"]) -> typing.Literal["pub", "sign", "sign_msg", "antiklepto_signature", "sign_typed_msg", "typed_msg_value", "sign_eip1559"] | None: ...
+ def HasField(self, field_name: typing.Literal["antiklepto_signature", b"antiklepto_signature", "data_response_chunk", b"data_response_chunk", "pub", b"pub", "request", b"request", "sign", b"sign", "sign_eip1559", b"sign_eip1559", "sign_msg", b"sign_msg", "sign_typed_msg", b"sign_typed_msg", "typed_msg_value", b"typed_msg_value"]) -> builtins.bool: ...
+ def ClearField(self, field_name: typing.Literal["antiklepto_signature", b"antiklepto_signature", "data_response_chunk", b"data_response_chunk", "pub", b"pub", "request", b"request", "sign", b"sign", "sign_eip1559", b"sign_eip1559", "sign_msg", b"sign_msg", "sign_typed_msg", b"sign_typed_msg", "typed_msg_value", b"typed_msg_value"]) -> None: ...
+ def WhichOneof(self, oneof_group: typing.Literal["request", b"request"]) -> typing.Literal["pub", "sign", "sign_msg", "antiklepto_signature", "sign_typed_msg", "typed_msg_value", "sign_eip1559", "data_response_chunk"] | None: ...
global___ETHRequest = ETHRequest
@@ -486,6 +531,7 @@ class ETHResponse(google.protobuf.message.Message):
SIGN_FIELD_NUMBER: builtins.int
ANTIKLEPTO_SIGNER_COMMITMENT_FIELD_NUMBER: builtins.int
TYPED_MSG_VALUE_FIELD_NUMBER: builtins.int
+ DATA_REQUEST_CHUNK_FIELD_NUMBER: builtins.int
@property
def pub(self) -> common_pb2.PubResponse: ...
@property
@@ -494,6 +540,8 @@ class ETHResponse(google.protobuf.message.Message):
def antiklepto_signer_commitment(self) -> antiklepto_pb2.AntiKleptoSignerCommitment: ...
@property
def typed_msg_value(self) -> global___ETHTypedMessageValueResponse: ...
+ @property
+ def data_request_chunk(self) -> global___ETHSignDataRequestChunkResponse: ...
def __init__(
self,
*,
@@ -501,9 +549,10 @@ class ETHResponse(google.protobuf.message.Message):
sign: global___ETHSignResponse | None = ...,
antiklepto_signer_commitment: antiklepto_pb2.AntiKleptoSignerCommitment | None = ...,
typed_msg_value: global___ETHTypedMessageValueResponse | None = ...,
+ data_request_chunk: global___ETHSignDataRequestChunkResponse | None = ...,
) -> None: ...
- def HasField(self, field_name: typing.Literal["antiklepto_signer_commitment", b"antiklepto_signer_commitment", "pub", b"pub", "response", b"response", "sign", b"sign", "typed_msg_value", b"typed_msg_value"]) -> builtins.bool: ...
- def ClearField(self, field_name: typing.Literal["antiklepto_signer_commitment", b"antiklepto_signer_commitment", "pub", b"pub", "response", b"response", "sign", b"sign", "typed_msg_value", b"typed_msg_value"]) -> None: ...
- def WhichOneof(self, oneof_group: typing.Literal["response", b"response"]) -> typing.Literal["pub", "sign", "antiklepto_signer_commitment", "typed_msg_value"] | None: ...
+ def HasField(self, field_name: typing.Literal["antiklepto_signer_commitment", b"antiklepto_signer_commitment", "data_request_chunk", b"data_request_chunk", "pub", b"pub", "response", b"response", "sign", b"sign", "typed_msg_value", b"typed_msg_value"]) -> builtins.bool: ...
+ def ClearField(self, field_name: typing.Literal["antiklepto_signer_commitment", b"antiklepto_signer_commitment", "data_request_chunk", b"data_request_chunk", "pub", b"pub", "response", b"response", "sign", b"sign", "typed_msg_value", b"typed_msg_value"]) -> None: ...
+ def WhichOneof(self, oneof_group: typing.Literal["response", b"response"]) -> typing.Literal["pub", "sign", "antiklepto_signer_commitment", "typed_msg_value", "data_request_chunk"] | None: ...
global___ETHResponse = ETHResponse
diff --git a/src/rust/bitbox02-rust/src/hww/api/ethereum.rs b/src/rust/bitbox02-rust/src/hww/api/ethereum.rs
index 4a78534..9fd1c60 100644
--- a/src/rust/bitbox02-rust/src/hww/api/ethereum.rs
+++ b/src/rust/bitbox02-rust/src/hww/api/ethereum.rs
@@ -74,8 +74,10 @@ pub async fn process_api(
Request::SignEip1559(request) => {
sign::process(hal, &sign::Transaction::Eip1559(request)).await
}
- Request::AntikleptoSignature(_) => Err(Error::InvalidInput),
Request::SignTypedMsg(request) => sign_typed_msg::process(hal, request).await,
- Request::TypedMsgValue(_) => Err(Error::InvalidInput),
+ // These are streamed asynchronously using the `next_request()` primitive
+ Request::AntikleptoSignature(_)
+ | Request::TypedMsgValue(_)
+ | Request::DataResponseChunk(_) => Err(Error::InvalidState),
}
}
diff --git a/src/rust/bitbox02-rust/src/hww/api/ethereum/sign.rs b/src/rust/bitbox02-rust/src/hww/api/ethereum/sign.rs
index 4c0a399..2c4ad13 100644
--- a/src/rust/bitbox02-rust/src/hww/api/ethereum/sign.rs
+++ b/src/rust/bitbox02-rust/src/hww/api/ethereum/sign.rs
@@ -545,6 +545,7 @@ mod tests {
host_nonce_commitment: None,
chain_id: 0,
address_case: pb::EthAddressCase::Mixed as _,
+ data_length: 0,
}))),
Ok(Response::Sign(pb::EthSignResponse {
signature: b"\xc3\xae\x24\xc1\x67\xe2\x16\xcf\xb7\x5c\x72\xb5\xe0\x3e\xf9\x7a\xcc\x2b\x60\x7f\x3a\xcf\x63\x86\x5f\x80\x96\x0f\x76\xf6\x56\x47\x0f\x8e\x23\xf1\xd2\x78\x8f\xb0\x07\x0e\x28\xc2\xa5\xc8\xaa\xf1\x5b\x5d\xbf\x30\xb4\x09\x07\xff\x6c\x50\x68\xfd\xcb\xc1\x1a\x2d\x00"
@@ -567,6 +568,7 @@ mod tests {
host_nonce_commitment: None,
chain_id: 1,
address_case: pb::EthAddressCase::Mixed as _,
+ data_length: 0,
}))),
Ok(Response::Sign(pb::EthSignResponse {
signature: b"\x28\x91\x11\x77\x0d\xc0\x67\x89\x57\x80\xde\x3e\x9b\x30\x45\x4e\x33\x1b\xa6\x66\x1f\x04\x6e\x9e\x26\x43\x15\x76\xd7\xf0\x8a\x49\x6f\xfe\x6d\xef\xfb\x07\xdd\x8d\x47\x13\xd8\xc5\x23\xb6\xc3\x3b\x53\xdd\x6e\xf2\xdc\x9c\x39\x4d\x6e\x21\xf6\x43\x07\xd2\xbc\xf0\x01"
@@ -601,6 +603,7 @@ mod tests {
host_nonce_commitment: None,
chain_id: 0,
address_case: pb::EthAddressCase::Mixed as _,
+ data_length: 0,
})))
.is_ok());
@@ -657,6 +660,7 @@ mod tests {
host_nonce_commitment: None,
chain_id: 1,
address_case: pb::EthAddressCase::Mixed as _,
+ data_length: 0,
})))
.is_ok());
@@ -711,6 +715,7 @@ mod tests {
host_nonce_commitment: None,
chain_id: 11155111,
address_case: pb::EthAddressCase::Mixed as _,
+ data_length: 0,
})))
.unwrap();
@@ -764,6 +769,7 @@ mod tests {
host_nonce_commitment: None,
chain_id: 0,
address_case: pb::EthAddressCase::Mixed as _,
+ data_length: 0,
}))),
Ok(Response::Sign(pb::EthSignResponse {
signature: b"\x7d\x3f\x37\x13\xe3\xcf\x10\x82\x79\x1d\x5c\x0f\xc6\x8e\xc2\x9e\xaf\xf5\xe1\xee\x84\x67\xa8\xec\x54\x7d\xc7\x96\xe8\x5a\x79\x04\x2b\x7c\x01\x69\x2f\xb7\x2f\x55\x76\xab\x50\xdc\xaa\x62\x1a\xd1\xee\xab\xd9\x97\x59\x73\xb8\x62\x56\xf4\x0c\x6f\x85\x50\xef\x44\x00"
@@ -830,6 +836,7 @@ mod tests {
host_nonce_commitment: None,
chain_id: 1,
address_case: pb::EthAddressCase::Mixed as _,
+ data_length: 0,
}))),
Ok(Response::Sign(pb::EthSignResponse {
signature: b"\xc5\xd9\x63\x9a\x77\x8a\x34\x15\xf6\x3a\x11\xc0\x3a\x58\xbe\xde\x6b\x3c\xaf\xff\x4f\x2c\xe6\xea\x16\x41\x1e\x76\xfb\xa9\x46\xf7\x21\x66\xf0\x9e\x31\x3c\x07\xe7\x8b\x7b\x1f\xff\x87\x45\x0c\x43\x21\x17\x0c\x02\xdf\x2d\x36\xc4\x4c\x3a\x02\x1a\xbf\x20\x54\x60\x01"
@@ -918,6 +925,7 @@ mod tests {
host_nonce_commitment: None,
chain_id: 1,
address_case: pb::EthAddressCase::Mixed as _,
+ data_length: 0,
}))),
Ok(Response::Sign(pb::EthSignResponse {
signature: b"\x67\x4e\x9a\x01\x70\xee\xe0\xca\x8c\x40\x6e\xc9\xa7\xdf\x2e\x3a\x6b\xdd\x17\x9c\xf6\x93\x85\x80\x0e\x1f\xd3\x78\xe7\xcf\xb1\x9c\x4d\x55\x16\x2c\x54\x7b\x04\xd1\x81\x8e\x43\x90\x16\x91\xae\xc9\x88\xef\x75\xcd\x67\xd9\xbb\x30\x1d\x14\x90\x2f\xd6\xe6\x92\x92\x01"
@@ -940,6 +948,7 @@ mod tests {
host_nonce_commitment: None,
chain_id: 1,
address_case: pb::EthAddressCase::Mixed as _,
+ data_length: 0,
}))),
Ok(Response::Sign(pb::EthSignResponse {
signature: b"\x31\x62\x48\x78\x80\xab\xde\xa1\xf3\x52\xd9\xa4\xe3\xd5\x60\x66\xf1\x22\xf0\x4f\xf1\x12\x11\x7c\x8c\xa3\xcd\x22\x0f\x16\x66\x30\x2d\xac\xd5\xe5\xe8\xda\x4c\xd3\x97\x04\xe3\x34\x43\xa9\xa7\xf3\x26\x02\xd3\x32\xbb\x52\x56\x7c\x2e\x34\xaa\xfe\x9e\xd4\x8f\xeb\x01"
@@ -989,6 +998,7 @@ mod tests {
host_nonce_commitment: None,
chain_id: 0,
address_case: pb::EthAddressCase::Mixed as _,
+ data_length: 0,
}))),
Ok(Response::Sign(pb::EthSignResponse {
signature: b"\xec\x6e\x53\x0c\x8e\xe2\x54\x34\xfc\x44\x0e\x9a\xc0\xf8\x88\xe9\xc6\x3c\xf0\x7e\xbc\xf1\xc2\xf8\xa8\x3e\x2e\x8c\x39\x83\x2c\x55\x15\x12\x71\x6f\x6e\x1a\x8b\x66\xce\x38\x11\xa7\x26\xbc\xb2\x44\x66\x4e\xf2\x6f\x98\xee\x35\xc0\xc9\xdb\x4c\xaa\xb0\x73\x98\x56\x00"
@@ -1011,6 +1021,7 @@ mod tests {
host_nonce_commitment: None,
chain_id: 1,
address_case: pb::EthAddressCase::Mixed as _,
+ data_length: 0,
}))),
Ok(Response::Sign(pb::EthSignResponse {
signature: b"\x82\x03\xd8\x0b\x60\x0d\xce\x8e\x77\xcd\xcb\x11\x9d\x45\xdb\x7f\x60\xd7\xca\x34\xe7\x36\x91\x40\xe9\x2d\x93\x91\x92\x21\xf8\x5a\x0a\x11\x9d\x24\x64\xdf\xab\x65\x83\x30\x95\xc1\x27\x63\xfe\xd3\x7c\x07\x2f\xeb\x29\x61\x0e\x14\x37\xf3\x88\x95\x8d\x77\x56\x28\x01"
@@ -1036,6 +1047,7 @@ mod tests {
host_nonce_commitment: None,
chain_id: 0,
address_case: pb::EthAddressCase::Mixed as _,
+ data_length: 0,
};
{
@@ -1191,6 +1203,7 @@ mod tests {
host_nonce_commitment: None,
chain_id: 1,
address_case: pb::EthAddressCase::Mixed as _,
+ data_length: 0,
};
{
@@ -1239,6 +1252,7 @@ mod tests {
host_nonce_commitment: None,
chain_id: 12345,
address_case: pb::EthAddressCase::Mixed as _,
+ data_length: 0,
}))),
Ok(Response::Sign(pb::EthSignResponse {
signature: b"\xb1\xb6\xb3\x4e\x15\xa0\x30\x9d\xdc\x26\x03\xdf\x4c\x40\x38\xea\x86\x65\xed\x85\xd3\xf2\xc8\x1e\x7f\x1a\xa0\x25\x4b\x21\x38\x72\x0d\x60\x1f\x42\x19\xfb\x29\xab\x3d\x5f\xf7\x76\xea\xe1\xbe\x15\x26\xb4\x67\xe2\xb0\xe6\x30\xe8\xe6\x34\xa4\xda\x4a\x82\x2e\x39\x00".to_vec()
@@ -1296,6 +1310,7 @@ mod tests {
host_nonce_commitment: None,
chain_id: 42161,
address_case: pb::EthAddressCase::Mixed as _,
+ data_length: 0,
})))
.unwrap();
@@ -1331,6 +1346,7 @@ mod tests {
host_nonce_commitment: None,
chain_id: 137,
address_case: pb::EthAddressCase::Mixed as _,
+ data_length: 0,
})))
.unwrap();
assert_eq!(
diff --git a/src/rust/bitbox02-rust/src/shiftcrypto.bitbox02.rs b/src/rust/bitbox02-rust/src/shiftcrypto.bitbox02.rs
index 28612df..bcdb680 100644
--- a/src/rust/bitbox02-rust/src/shiftcrypto.bitbox02.rs
+++ b/src/rust/bitbox02-rust/src/shiftcrypto.bitbox02.rs
@@ -1503,6 +1503,9 @@ pub struct EthSignRequest {
pub chain_id: u64,
#[prost(enumeration = "EthAddressCase", tag = "11")]
pub address_case: i32,
+ /// For streaming: if non-zero, data field should be empty and data will be requested in chunks
+ #[prost(uint32, tag = "12")]
+ pub data_length: u32,
}
/// TX payload for an EIP-1559 (type 2) transaction: <https://eips.ethereum.org/EIPS/eip-1559>
#[allow(clippy::derive_partial_eq_without_eq)]
@@ -1536,6 +1539,23 @@ pub struct EthSignEip1559Request {
pub host_nonce_commitment: ::core::option::Option<AntiKleptoHostNonceCommitment>,
#[prost(enumeration = "EthAddressCase", tag = "11")]
pub address_case: i32,
+ /// For streaming: if non-zero, data field should be empty and data will be requested in chunks
+ #[prost(uint32, tag = "12")]
+ pub data_length: u32,
+}
+#[allow(clippy::derive_partial_eq_without_eq)]
+#[derive(Clone, Copy, PartialEq, ::prost::Message)]
+pub struct EthSignDataRequestChunkResponse {
+ #[prost(uint32, tag = "1")]
+ pub offset: u32,
+ #[prost(uint32, tag = "2")]
+ pub length: u32,
+}
+#[allow(clippy::derive_partial_eq_without_eq)]
+#[derive(Clone, PartialEq, ::prost::Message)]
+pub struct EthSignDataResponseChunkRequest {
+ #[prost(bytes = "vec", tag = "1")]
+ pub chunk: ::prost::alloc::vec::Vec<u8>,
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
@@ -1723,7 +1743,7 @@ pub struct EthTypedMessageValueRequest {
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct EthRequest {
- #[prost(oneof = "eth_request::Request", tags = "1, 2, 3, 4, 5, 6, 7")]
+ #[prost(oneof = "eth_request::Request", tags = "1, 2, 3, 4, 5, 6, 7, 8")]
pub request: ::core::option::Option<eth_request::Request>,
}
/// Nested message and enum types in `ETHRequest`.
@@ -1745,12 +1765,14 @@ pub mod eth_request {
TypedMsgValue(super::EthTypedMessageValueRequest),
#[prost(message, tag = "7")]
SignEip1559(super::EthSignEip1559Request),
+ #[prost(message, tag = "8")]
+ DataResponseChunk(super::EthSignDataResponseChunkRequest),
}
}
#[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)]
pub struct EthResponse {
- #[prost(oneof = "eth_response::Response", tags = "1, 2, 3, 4")]
+ #[prost(oneof = "eth_response::Response", tags = "1, 2, 3, 4, 5")]
pub response: ::core::option::Option<eth_response::Response>,
}
/// Nested message and enum types in `ETHResponse`.
@@ -1766,6 +1788,8 @@ pub mod eth_response {
AntikleptoSignerCommitment(super::AntiKleptoSignerCommitment),
#[prost(message, tag = "4")]
TypedMsgValue(super::EthTypedMessageValueResponse),
+ #[prost(message, tag = "5")]
+ DataRequestChunk(super::EthSignDataRequestChunkResponse),
}
}
/// Kept for backwards compatibility. Use chain_id instead, introduced in v9.10.0.
Why this scored 11/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.