@@ -60,18 +60,22 @@ static unsigned char const BSM_SIGN_MAGIC[] = {'\x18', 'B', 'i', 't', 'c', 'o',
60
60
#error "COIN_VARIANT is not defined"
61
61
#elif COIN_VARIANT == COIN_VARIANT_ACRE
62
62
// Mainnet hash
63
- static const uint8_t domain_separator_hash [32 ] = {
64
- 0xc4 , 0x86 , 0x40 , 0x56 , 0xe2 , 0x10 , 0x22 , 0x91 , 0x3a , 0x49 , 0x88 , 0x4b , 0xa9 , 0xfb , 0x40 , 0x35 ,
65
- 0x36 , 0x4d , 0x5c , 0x2a , 0xb8 , 0xb4 , 0x0f , 0x03 , 0x05 , 0x58 , 0x3a , 0xe4 , 0x19 , 0xc7 , 0x2f , 0x86 };
63
+ static const uint8_t abi_encoded_chain_id [32 ] = {
64
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
65
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x01 };
66
66
#elif COIN_VARIANT == COIN_VARIANT_ACRE_TESTNET
67
67
// Testnet hash
68
- static const uint8_t domain_separator_hash [32 ] = {
69
- 0x19 , 0x2e , 0xfd , 0x34 , 0x00 , 0xda , 0x07 , 0xca , 0xf5 , 0xbd , 0x41 , 0x8f , 0xdd , 0xfc , 0x07 , 0x7a ,
70
- 0x97 , 0x88 , 0x1b , 0x26 , 0xb7 , 0xca , 0x63 , 0x8d , 0xda , 0x2d , 0x52 , 0x3f , 0xde , 0xf4 , 0xf8 , 0x4c };
68
+ static const uint8_t abi_encoded_chain_id [32 ] = {
69
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 ,
70
+ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x11 , 0x05 , 0x77 };
71
71
#else
72
72
#error "Unsupported COIN_VARIANT value"
73
73
#endif
74
74
75
+ static const uint8_t domain_separator_typehash [32 ] = {
76
+ 0x47 , 0xe7 , 0x95 , 0x34 , 0xa2 , 0x45 , 0x95 , 0x2e , 0x8b , 0x16 , 0x89 , 0x3a , 0x33 , 0x6b , 0x85 , 0xa3 ,
77
+ 0xd9 , 0xea , 0x9f , 0xa8 , 0xc5 , 0x73 , 0xf3 , 0xd8 , 0x03 , 0xaf , 0xb9 , 0x2a , 0x79 , 0x46 , 0x92 , 0x18 };
78
+
75
79
static const uint8_t safe_tx_typehash [32 ] = {
76
80
0xbb , 0x83 , 0x10 , 0xd4 , 0x86 , 0x36 , 0x8d , 0xb6 , 0xbd , 0x6f , 0x84 , 0x94 , 0x02 , 0xfd , 0xd7 , 0x3a ,
77
81
0xd5 , 0x3d , 0x31 , 0x6b , 0x5a , 0x4b , 0x26 , 0x44 , 0xad , 0x6e , 0xfe , 0x0f , 0x94 , 0x12 , 0x86 , 0xd8 };
@@ -427,11 +431,11 @@ void fetch_and_hash_tx_data(dispatcher_context_t* dc,
427
431
}
428
432
// Finalize the hash and store the result in output_hash
429
433
CX_THROW (cx_hash_no_throw ((cx_hash_t * ) hash_context ,
430
- CX_LAST , // final block mode
431
- NULL , // no more input
432
- 0 , // no more input length
433
- output_buffer , // output hash buffer
434
- 32 )); // output hash length (32 bytes)
434
+ CX_LAST , // final block mode
435
+ NULL , // no more input
436
+ 0 , // no more input length
437
+ output_buffer , // output hash buffer
438
+ KECCAK_256_HASH_SIZE )); // output hash length (32 bytes)
435
439
}
436
440
437
441
/**
@@ -514,6 +518,55 @@ bool fetch_and_abi_encode_tx_fields(dispatcher_context_t* dc,
514
518
return true;
515
519
}
516
520
521
+ /**
522
+ * @brief Computes the domain separator hash according to EIP-712 specification.
523
+ *
524
+ * This function computes the domain separator hash by combining and hashing:
525
+ * 1. The ABI-encoded EIP-712 domain separator typehash
526
+ * 2. The ABI-encoded chain ID
527
+ * 3. The ABI-encoded verifying contract address
528
+ *
529
+ * The function follows the EIP-712 specification for structured data hashing
530
+ * and signing. The computed hash is used as part of the transaction signing
531
+ * process.
532
+ *
533
+ * @param dc Pointer to the dispatcher context used for operations
534
+ * @param data_merkle_root Pointer to the Merkle root of the transaction data
535
+ * @param n_chunks Number of chunks in the Merkle tree
536
+ * @param output_buffer Buffer to store the computed domain separator hash (32 bytes)
537
+ */
538
+ void compute_domain_separator_hash (dispatcher_context_t * dc ,
539
+ uint8_t * data_merkle_root ,
540
+ size_t n_chunks ,
541
+ uint8_t * output_buffer ) {
542
+ cx_sha3_t hash_context ;
543
+ CX_THROW (cx_keccak_init_no_throw (& hash_context , 256 ));
544
+ // Add the EIP712 domain separator typehash to the hash context (it is already abi-encoded)
545
+ CX_THROW (cx_hash_no_throw ((cx_hash_t * ) & hash_context ,
546
+ 0 ,
547
+ domain_separator_typehash ,
548
+ sizeof (domain_separator_typehash ),
549
+ NULL ,
550
+ 0 ));
551
+
552
+ // add the abi encoded chainId to the hash context
553
+ CX_THROW (cx_hash_no_throw ((cx_hash_t * ) & hash_context ,
554
+ 0 ,
555
+ abi_encoded_chain_id ,
556
+ sizeof (abi_encoded_chain_id ),
557
+ NULL ,
558
+ 0 ));
559
+ // Add the verifying contract address to the hash context (it is already abi-encoded)
560
+ fetch_and_add_chunk_to_hash (dc , data_merkle_root , n_chunks , & hash_context , 7 , 0 , 32 );
561
+ // Compute the final hash
562
+ CX_THROW (cx_hash_no_throw ((cx_hash_t * ) & hash_context ,
563
+ CX_LAST ,
564
+ NULL ,
565
+ 0 ,
566
+ output_buffer ,
567
+ KECCAK_256_HASH_SIZE ));
568
+ }
569
+
517
570
/**
518
571
* @brief Computes the transaction hash using Keccak-256.
519
572
*
@@ -562,7 +615,9 @@ void compute_tx_hash(dispatcher_context_t* dc,
562
615
sizeof (abi_encoded_tx_fields ),
563
616
keccak_of_abi_encoded_tx_fields ,
564
617
sizeof (keccak_of_abi_encoded_tx_fields )));
565
-
618
+ // Compute domain_separator_hash
619
+ uint8_t domain_separator_hash [KECCAK_256_HASH_SIZE ];
620
+ compute_domain_separator_hash (dc , data_merkle_root , n_chunks , domain_separator_hash );
566
621
// Abi.encodePacked
567
622
// 2 bytes (0x1901) + 2 keccak256 hashes
568
623
u_int8_t abi_encode_packed [2 + (KECCAK_256_HASH_SIZE * 2 )] = {0x19 , 0x01 };
0 commit comments