Skip to content

Commit

Permalink
Merge pull request #28 from vlayer-xyz/vlayer-main
Browse files Browse the repository at this point in the history
Refactor: extract verify_leaf_storage_node & verify_leaf_state_node functions
  • Loading branch information
ax0 authored Mar 19, 2024
2 parents b520e21 + 3f4e4e7 commit 170739c
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 23 deletions.
66 changes: 45 additions & 21 deletions lib/src/lib.nr
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,6 @@ impl<PROOF_LEN, MAX_VALUE_LEN> TrieProof<32, PROOF_LEN, MAX_VALUE_LEN>

let mut key_ptr: u64 = 0;

let (value, mut value_length) = byte_value(self.value); // Value to verify together with its byte length

let path = self.proof; // Proof path

let depth = self.depth; // Depth of proof path
Expand All @@ -85,12 +83,31 @@ impl<PROOF_LEN, MAX_VALUE_LEN> TrieProof<32, PROOF_LEN, MAX_VALUE_LEN>
verify_internal_node(&mut extracted_hash, &mut key_ptr, key_nibbles, path, depth, i);
}

let mut leaf_node = [0; MAX_TRIE_NODE_LENGTH];
self.verify_storage_leaf_node(extracted_hash, key.len(), key_ptr, key_nibbles);

true
}

/// Verifies that terminal storage node hashes to extracted hash. Extracts value and verifies it against the argument value.
///
/// # Arguments
/// * `hash` - Hash extracted from the preceding node
/// * `value` - Value to be verified
/// * `value_length` - Length of the value
/// * `key` - Key to be verified
/// * `key_ptr` - Pointer to current nibble in the key
/// * `key_nibbles` - Array containing the nibbles of the key
/// * `path` - RLP-encoded proof path
/// * `depth` - Depth of proof path
pub fn verify_storage_leaf_node(self, hash: [u8; KEY_LENGTH], key_len: Field, key_ptr: u64, key_nibbles: [u8; NIBBLE_LENGTH])
{
let (value, mut value_length) = byte_value(self.value); // Value to verify together with its byte length

let mut leaf_node = [0; MAX_TRIE_NODE_LENGTH];
// Treat final node as the preceding nodes...
memcpy(&mut leaf_node, path, (depth - 1)*MAX_TRIE_NODE_LENGTH);
memcpy(&mut leaf_node, self.proof, (self.depth - 1) * MAX_TRIE_NODE_LENGTH);

assert(verify_node_hash(leaf_node, extracted_hash), "Storage root: leaf node hash does not match the hash extracted from the preceding node");
assert(verify_node_hash(leaf_node, hash), "Storage root: leaf node hash does not match the hash extracted from the preceding node");

let rlp_list: rlp::RLP_List<2> = rlp::decode1_small_lis(leaf_node); // Terminal node must be a 2-node, and both slots contain less than 56 bytes.

Expand All @@ -99,17 +116,12 @@ impl<PROOF_LEN, MAX_VALUE_LEN> TrieProof<32, PROOF_LEN, MAX_VALUE_LEN>
assert(node_type == LEAF);

assert((extracted_value_length as u32) <= MAX_STORAGE_VALUE_LENGTH as u32 + 1); // Extracted value be at most 33 bytes with RLP header
key_ptr = terminal_key_ptr;

assert(key_ptr == 2 * key.len() as u64); // All of the key has been exhausted.
assert(terminal_key_ptr == 2 * key_len as u64); // All of the key has been exhausted.

// Decode extracted value
let (dec_value_offset, dec_value_len) = rlp::decode0(extracted_value);
assert(dec_value_len == value_length);

assert_subarray(value, extracted_value, value_length, dec_value_offset);

true
}
}

Expand All @@ -133,8 +145,6 @@ impl<PROOF_LEN, MAX_VALUE_LEN> TrieProof<20, PROOF_LEN, MAX_VALUE_LEN>

let mut key_ptr: u64 = 0;

let (value, mut value_length) = byte_value(self.value); // Value to verify together with its byte length

let path = self.proof; // Proof path

let depth = self.depth; // Depth of proof path
Expand All @@ -145,11 +155,30 @@ impl<PROOF_LEN, MAX_VALUE_LEN> TrieProof<20, PROOF_LEN, MAX_VALUE_LEN>
{
verify_internal_node(&mut extracted_hash, &mut key_ptr, key_nibbles, path, depth, i);
}

self.verify_state_leaf_node(extracted_hash, key.len(), key_ptr, key_nibbles);

let mut leaf_node = [0; MAX_TRIE_NODE_LENGTH];
true
}

/// Verifies that terminal state node hashes to extracted hash. Extracts value and verifies it against the argument value.
///
/// # Arguments
/// * `extracted_hash` - Hash extracted from the preceding node
/// * `value` - Value to be verified
/// * `value_length` - Length of the value
/// * `key` - Key to be verified
/// * `key_ptr` - Pointer to current nibble in the key
/// * `key_nibbles` - Array containing the nibbles of the key
/// * `path` - RLP-encoded proof path
/// * `depth` - Depth of proof path
fn verify_state_leaf_node(self, extracted_hash: [u8; KEY_LENGTH], key_len: Field, key_ptr: u64, key_nibbles: [u8; NIBBLE_LENGTH])
{
let (value, mut value_length) = byte_value(self.value); // Value to verify together with its byte length

let mut leaf_node = [0; MAX_TRIE_NODE_LENGTH];
// Treat final node as the preceding nodes...
memcpy(&mut leaf_node, path, (depth - 1)*MAX_TRIE_NODE_LENGTH);
memcpy(&mut leaf_node, self.proof, (self.depth - 1) * MAX_TRIE_NODE_LENGTH);

assert(verify_node_hash(leaf_node, extracted_hash), "State root: leaf node hash does not match the hash extracted from the preceding node");

Expand All @@ -160,17 +189,12 @@ impl<PROOF_LEN, MAX_VALUE_LEN> TrieProof<20, PROOF_LEN, MAX_VALUE_LEN>
assert(node_type == LEAF);

assert((extracted_value_length as u32) <= (MAX_VALUE_LEN as u32)); // Extracted value should fit in a byte array of length MAX_ACCOUNT_STATE_LENGTH.
key_ptr = terminal_key_ptr;

assert(key_ptr == 2 * key.len() as u64); // All of the key has been exhausted.
assert(terminal_key_ptr == 2 * key_len as u64); // All of the key has been exhausted.

// No need to decode data, but it ought to be a list.
assert(extracted_value[0] >= 0xc0);

assert(extracted_value_length == value_length);
assert_subarray(value, extracted_value, value_length, 0);

true
}
}

Expand Down
4 changes: 2 additions & 2 deletions lib/src/test.nr
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ fn test_assertion_message_for_invalid_storage_root()
let _ = trie_proof.verify_storage_root(invalid_storage_root);
}

#[test(should_fail_with="Leaf node hash does not match the hash extracted from the preceding node")]
fn test_assertion_message_for_invalid_leaf()
#[test(should_fail_with="Storage root: leaf node hash does not match the hash extracted from the preceding node")]
fn test_assertion_message_for_invalid_leaf()
{
let mut proof_with_modified_teminal_node = proof;
proof_with_modified_teminal_node[MAX_TRIE_NODE_LENGTH] += 0x01;
Expand Down

0 comments on commit 170739c

Please sign in to comment.