-
Notifications
You must be signed in to change notification settings - Fork 6
feat: proof verifyer #13
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
base: main
Are you sure you want to change the base?
Conversation
4b305d9 to
6824044
Compare
| Err(e) => { | ||
| Ok((atoms::error(), e).encode(env)) | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| } | |
| } | |
| } |
| }; | ||
|
|
||
| // Convert proof nodes to Vec<Vec<u8>> | ||
| let proof_nodes: Vec<Vec<u8>> = proof.iter().map(|b| b.as_slice().to_vec()).collect(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| let proof_nodes: Vec<Vec<u8>> = proof.iter().map(|b| b.as_slice().to_vec()).collect(); | |
| let proof_nodes = proof.iter().map(|b| b.as_slice()); |
| let proof_nodes: Vec<Vec<u8>> = proof.iter().map(|b| b.as_slice().to_vec()).collect(); | ||
|
|
||
| // Verify the proof | ||
| match mpt::verify_proof(root.as_slice(), &index_bytes, &proof_nodes) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| match mpt::verify_proof(root.as_slice(), &index_bytes, &proof_nodes) { | |
| match mpt::verify_proof(root.as_slice(), &index_bytes, proof_nodes) { |
| pub fn verify_proof( | ||
| root: &[u8], | ||
| key: &[u8], | ||
| proof: &[Vec<u8>], | ||
| ) -> Result<Vec<u8>, String> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| pub fn verify_proof( | |
| root: &[u8], | |
| key: &[u8], | |
| proof: &[Vec<u8>], | |
| ) -> Result<Vec<u8>, String> { | |
| pub fn verify_proof<'a>( | |
| root: &'a [u8], | |
| key: &'a [u8], | |
| proof: impl Iterator<Item = &'a [u8]>, | |
| ) -> Result<Vec<u8>, String> { |
| if proof.is_empty() { | ||
| return Err("Proof is empty".to_string()); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't be checked if proof is iterator, but should be covered with error below
| for (i, node) in proof.iter().enumerate() { | ||
| // Verify node hash matches expected | ||
| let node_hash = KeccakHasher::hash(node); | ||
| if node_hash.as_ref() != expected_hash.as_slice() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Vec compares to fixed array. if expected_hash != node_hash {
| if node_hash.as_ref() != expected_hash.as_slice() { | ||
| // For inline nodes (< 32 bytes), the node itself might be the "hash" | ||
| if node.len() < 32 && node == &expected_hash { | ||
| // Inline node, continue |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You've already explained what is being verified above, no need to add an empty branch with comment
| let item_count = rlp.item_count().map_err(|e| format!("RLP decode error at node {}: {}", i, e))?; | ||
|
|
||
| match item_count { | ||
| 2 => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's more clearer to have const defined above with an explanation
| /// # Returns | ||
| /// * `Ok(value)` - Proof is valid and value was found | ||
| /// * `Err(_)` - Proof is invalid | ||
| pub fn verify_proof( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This function requires proper tests to verify the logic inside
| if key_index >= key_nibbles.len() { | ||
| // We've consumed all key nibbles, value is in position 16 | ||
| let value_rlp = rlp.at(16) | ||
| .map_err(|e| format!("Failed to get value at branch node {}: {}", i, e))?; | ||
| if value_rlp.is_empty() { | ||
| return Err(format!("No value at branch node terminus at node {}", i)); | ||
| } | ||
| let value: Vec<u8> = value_rlp.as_val() | ||
| .map_err(|e| format!("Failed to decode value at branch node {}: {}", i, e))?; | ||
| return Ok(value); | ||
| } | ||
|
|
||
| let nibble = key_nibbles[key_index] as usize; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if key_index >= key_nibbles.len() { | |
| // We've consumed all key nibbles, value is in position 16 | |
| let value_rlp = rlp.at(16) | |
| .map_err(|e| format!("Failed to get value at branch node {}: {}", i, e))?; | |
| if value_rlp.is_empty() { | |
| return Err(format!("No value at branch node terminus at node {}", i)); | |
| } | |
| let value: Vec<u8> = value_rlp.as_val() | |
| .map_err(|e| format!("Failed to decode value at branch node {}: {}", i, e))?; | |
| return Ok(value); | |
| } | |
| let nibble = key_nibbles[key_index] as usize; | |
| let Some(&nibble) = key_nibbles.get(key_index) else { | |
| // We've consumed all key nibbles, value is in position 16 | |
| let value_rlp = rlp.at(16) | |
| .map_err(|e| format!("Failed to get value at branch node {}: {}", i, e))?; | |
| if value_rlp.is_empty() { | |
| return Err(format!("No value at branch node terminus at node {}", i)); | |
| } | |
| let value: Vec<u8> = value_rlp.as_val() | |
| .map_err(|e| format!("Failed to decode value at branch node {}: {}", i, e))?; | |
| return Ok(value); | |
| }; | |
| key_index += 1; | |
| let next = rlp.at(nibble as usize) |
| if key_index >= key_nibbles.len() { | ||
| return Err(format!("Key too short for path at node {}", i)); | ||
| } | ||
| if *nibble != key_nibbles[key_index] { | ||
| return Err(format!( | ||
| "Path mismatch at node {}, nibble {}: expected {}, got {}", | ||
| i, | ||
| key_index, | ||
| key_nibbles[key_index], | ||
| nibble | ||
| )); | ||
| } | ||
| key_index += 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if key_index >= key_nibbles.len() { | |
| return Err(format!("Key too short for path at node {}", i)); | |
| } | |
| if *nibble != key_nibbles[key_index] { | |
| return Err(format!( | |
| "Path mismatch at node {}, nibble {}: expected {}, got {}", | |
| i, | |
| key_index, | |
| key_nibbles[key_index], | |
| nibble | |
| )); | |
| } | |
| key_index += 1; | |
| match key_nibbles.get(key_index) { | |
| Some(expected_nibble) if nibble == expected_nibble => key_index += 1, | |
| Some(expected_nibble) => { | |
| return Err(format!( | |
| "Path mismatch at node {}, nibble {}: expected {}, got {}", | |
| i, key_index, expected_nibble, nibble | |
| )); | |
| } | |
| None => return Err(format!("Key too short for path at node {}", i)), | |
| } |
| if encoded.is_empty() { | ||
| return (vec![], false); | ||
| } | ||
|
|
||
| let first = encoded[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| if encoded.is_empty() { | |
| return (vec![], false); | |
| } | |
| let first = encoded[0]; | |
| let Some(&first) = encoded.first() else { | |
| return (vec![], false); | |
| }; |
No description provided.