Skip to content
This repository has been archived by the owner on Jan 11, 2024. It is now read-only.

Commit

Permalink
TEST: Hash checkpoint as tuple
Browse files Browse the repository at this point in the history
  • Loading branch information
aakoshh committed Oct 20, 2023
1 parent 0d33977 commit a4bac80
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 13 deletions.
14 changes: 5 additions & 9 deletions fendermint/testing/contract-test/tests/staking/machine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,8 @@ impl StateMachine for StakingMachine {
// eprintln!("\n> CMD: CKPT cn={}", checkpoint.next_configuration_number);

// Build the checkpoint payload.
// No messages.

// No messages in this test.
let cross_messages_hash = abi_hash::<Vec<subnet_manager::CrossMsg>>(Vec::new());

let (root, route) = subnet_id_to_eth(&system.subnet_id).unwrap();
Expand All @@ -255,14 +256,9 @@ impl StateMachine for StakingMachine {
cross_messages_hash,
};

let checkpoint_hash = abi_hash(checkpoint.clone());
// eprintln!("CHECKPOINT = {:?}", checkpoint);
// eprintln!("CHECKPOINT HASH = {}", hex::encode(checkpoint_hash));
// eprintln!(
// "CHECKPOINT ABI = {}",
// hex::encode(ethers::abi::encode(&checkpoint.clone().into_tokens()))
// );
// eprintln!("CHECKPOINT TOKENS = {:?}", checkpoint.clone().into_tokens());
// Checkpoint has to be a tuple to match Solidity.
let checkpoint_tuple = (checkpoint.clone(),);
let checkpoint_hash = abi_hash(checkpoint_tuple);

let mut signatures = Vec::new();

Expand Down
14 changes: 11 additions & 3 deletions fendermint/vm/actor_interface/src/ipc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ pub mod subnet {

#[cfg(test)]
mod tests {
use ethers::abi::Tokenize;
use ethers::abi::{AbiType, Tokenize};
use ethers::core::types::Bytes;
use ipc_actors_abis::subnet_actor_manager_facet::{BottomUpCheckpoint, SubnetID};

Expand Down Expand Up @@ -378,13 +378,21 @@ pub mod subnet {
],
};

let param_type = BottomUpCheckpoint::param_type();

// Captured value of `abi.encode` in Solidity.
let expected_abi: Bytes = "0x000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000156b736f342ab34d9afe4234a92bdb190c35b2e8d822d9601b00b9d7089b190f010000000000000000000000000000000000000000000000000000000000000001569e75fc77c1a856f6daaf9e69d8a9566ca34aa47f9133711ce065a571af0cfd000000000000000000000000000000000000000000000000abc8e314f58b4de5000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000007b11cf9ca8ccee13bb3d003c97af5c18434067a90000000000000000000000003d9019b8bf3bfd5e979ddc3b2761be54af867c47".parse().unwrap();

let observed_tokens = checkpoint.into_tokens();
// XXX: It doesn't work with `decode_whole`.
let expected_tokens =
ethers::abi::decode(&[param_type], &expected_abi).expect("invalid Solidity ABI");

// The data needs to be wrapped into a tuple.
let observed_tokens = (checkpoint,).into_tokens();
let observed_abi: Bytes = ethers::abi::encode(&observed_tokens).into();

assert_eq!(observed_abi, expected_abi)
assert_eq!(observed_tokens, expected_tokens);
assert_eq!(observed_abi, expected_abi);
}
}
}
Expand Down
9 changes: 8 additions & 1 deletion fendermint/vm/interpreter/src/fvm/state/ipc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ impl<DB: Blockstore> GatewayCaller<DB> {
height: u64,
) -> anyhow::Result<[u8; 32]> {
let msgs = self.bottom_up_msgs(state, height)?;

// TODO: Not sure this is the right way to hash a vector.
Ok(abi_hash(msgs))
}

Expand Down Expand Up @@ -154,7 +156,9 @@ impl<DB: Blockstore> GatewayCaller<DB> {
let height = checkpoint.block_height;
let weight = et::U256::from(validator.power.0);

let hash = abi_hash(checkpoint);
// Checkpoint has to be hashed as a tuple.
let hash = abi_hash((checkpoint,));

let signature = sign_secp256k1(secret_key, &hash);
let signature = from_fvm::to_eth_signature(&signature).context("invalid signature")?;
let signature = et::Bytes::from(signature.to_vec());
Expand Down Expand Up @@ -185,6 +189,9 @@ impl<DB: Blockstore> GatewayCaller<DB> {
}

/// Hash some value in the same way we'd hash it in Solidity.
///
/// Be careful that if we have to hash a single struct, Solidity's `abi.encode`
/// function will treat it as a tuple.
pub fn abi_hash<T: Tokenize>(value: T) -> [u8; 32] {
keccak256(ethers::abi::encode(&value.into_tokens()))
}

0 comments on commit a4bac80

Please sign in to comment.