helios/src/execution/proof.rs

56 lines
1.4 KiB
Rust
Raw Normal View History

2022-08-19 00:33:44 +00:00
use ethers::utils::keccak256;
2022-08-20 20:33:32 +00:00
use ethers::utils::rlp::{decode_list, RlpStream};
2022-08-19 00:33:44 +00:00
2022-08-21 15:21:50 +00:00
use crate::execution::types::Proof;
2022-08-19 00:33:44 +00:00
2022-08-20 20:33:32 +00:00
pub fn verify_proof(proof: &Vec<Vec<u8>>, root: &Vec<u8>, path: &Vec<u8>, value: &Vec<u8>) -> bool {
2022-08-19 22:43:58 +00:00
let mut expected_hash = root.clone();
2022-08-19 22:02:06 +00:00
let mut path_offset = 0;
2022-08-19 00:33:44 +00:00
2022-08-19 22:02:06 +00:00
for (i, node) in proof.iter().enumerate() {
2022-08-19 22:43:58 +00:00
if expected_hash != keccak256(node).to_vec() {
2022-08-19 22:02:06 +00:00
return false;
}
2022-08-19 00:33:44 +00:00
2022-08-19 22:02:06 +00:00
let node_list: Vec<Vec<u8>> = decode_list(node);
2022-08-20 20:33:32 +00:00
if node_list.len() == 17 {
2022-08-19 22:02:06 +00:00
let nibble = get_nibble(&path, path_offset);
2022-08-19 22:43:58 +00:00
expected_hash = node_list[nibble as usize].clone();
2022-08-19 22:02:06 +00:00
path_offset += 1;
} else if node_list.len() == 2 {
if i == proof.len() - 1 {
if &node_list[1] != value {
return false;
}
} else {
2022-08-21 21:51:11 +00:00
panic!("not implemented");
2022-08-19 22:02:06 +00:00
}
} else {
return false;
}
}
true
}
fn get_nibble(path: &Vec<u8>, offset: usize) -> u8 {
let byte = path[offset / 2];
if offset % 2 == 0 {
byte >> 4
} else {
byte & 0xF
}
2022-08-19 00:33:44 +00:00
}
2022-08-20 14:10:28 +00:00
pub fn encode_account(proof: &Proof) -> Vec<u8> {
2022-08-19 00:33:44 +00:00
let mut stream = RlpStream::new_list(4);
stream.append(&proof.nonce);
stream.append(&proof.balance);
stream.append(&proof.storage_hash);
stream.append(&proof.code_hash);
let encoded = stream.out();
encoded.to_vec()
}