Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(l1_receipt): trimmed hash #470

Merged
merged 3 commits into from
Jan 21, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 53 additions & 1 deletion crates/madara/primitives/receipt/src/to_starknet_types.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use primitive_types::H256;
use starknet_types_core::felt::Felt;

use crate::{
Expand Down Expand Up @@ -59,7 +60,9 @@ impl L1HandlerTransactionReceipt {
finality_status: starknet_types_rpc::TxnFinalityStatus,
) -> starknet_types_rpc::L1HandlerTxnReceipt<Felt> {
starknet_types_rpc::L1HandlerTxnReceipt::<Felt> {
message_hash: self.message_hash.to_string(),
// We have to manually convert the H256 bytes to a hex hash as the
// impl of Display for H256 skips the middle bytes.
message_hash: hash_as_string(self.message_hash),
common_receipt_properties: starknet_types_rpc::CommonReceiptProperties {
actual_fee: self.actual_fee.into(),
events: self.events.into_iter().map(starknet_types_rpc::Event::from).collect(),
Expand All @@ -73,6 +76,23 @@ impl L1HandlerTransactionReceipt {
}
}

/// Gets the **full** string hex representation of an [H256].
///
/// This is necessary as the default implementation of [ToString] for [H256]
/// will keep only the first and last 2 bytes, eliding the rest with '...'.
fn hash_as_string(message_hash: H256) -> String {
use std::fmt::Write;

// 32 bytes x 2 (1 hex char = 4 bits) + 2 (for 0x)
let mut acc = String::with_capacity(68);
acc.push_str("0x");

message_hash.as_fixed_bytes().iter().fold(acc, |mut acc, b| {
write!(&mut acc, "{b:02x}").expect("Pre-allocated");
acc
})
}

impl DeclareTransactionReceipt {
pub fn to_starknet_types(
self,
Expand Down Expand Up @@ -201,3 +221,35 @@ impl From<ExecutionResult> for starknet_types_rpc::ExecutionStatus {
}
}
}

#[cfg(test)]
mod test {
use primitive_types::H256;

use crate::{to_starknet_types::hash_as_string, L1HandlerTransactionReceipt};

#[test]
fn test_hash_as_string() {
let mut hash = String::with_capacity(68);
hash.push_str("0x");
hash.push_str(&"f".repeat(64));
assert_eq!(hash_as_string(H256::from_slice(&[u8::MAX; 32])), hash);
}

/// The default implementation of [ToString] for [H256] will keep only the
/// first and last 2 bytes, eliding the rest with '...'. This test makes
/// sure this is not the case and we are using [hash_as_string] instead.
#[test]
fn test_l1_tx_receipt_full_hash() {
let l1_transaction_receipt =
L1HandlerTransactionReceipt { message_hash: H256::from_slice(&[u8::MAX; 32]), ..Default::default() };
let message_hash =
l1_transaction_receipt.to_starknet_types(starknet_types_rpc::TxnFinalityStatus::L1).message_hash;

let mut hash = String::with_capacity(68);
hash.push_str("0x");
hash.push_str(&"f".repeat(64));
assert_eq!(message_hash, hash);
assert!(!message_hash.contains("."));
}
}
Loading