Skip to content

Commit b1f5e2b

Browse files
committed
apollo_committer: test new edge bottom in witnesses
1 parent eae40db commit b1f5e2b

1 file changed

Lines changed: 192 additions & 2 deletions

File tree

crates/apollo_committer/src/request_paths_and_commit_block_tests.rs

Lines changed: 192 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,13 @@ use apollo_committer_types::committer_types::{
1010
use indexmap::indexmap;
1111
use starknet_api::block::BlockNumber;
1212
use starknet_api::block_hash::state_diff_hash::calculate_state_diff_hash;
13-
use starknet_api::core::{ClassHash, CompiledClassHash, ContractAddress, StateDiffCommitment};
13+
use starknet_api::core::{
14+
ClassHash,
15+
CompiledClassHash,
16+
ContractAddress,
17+
StateDiffCommitment,
18+
PATRICIA_KEY_UPPER_BOUND_FELT,
19+
};
1420
use starknet_api::hash::HashOutput;
1521
use starknet_api::state::ThinStateDiff;
1622
use starknet_committer::block_committer::input::{
@@ -30,9 +36,17 @@ use starknet_committer::patricia_merkle_tree::types::{
3036
CompiledClassHash as CommitterCompiledClassHash,
3137
StarknetForestProofs,
3238
};
39+
use starknet_patricia::patricia_merkle_tree::node_data::inner_node::{
40+
BinaryData,
41+
EdgeData,
42+
EdgePath,
43+
EdgePathLength,
44+
NodeData,
45+
PathToBottom,
46+
};
3347
use starknet_patricia::patricia_merkle_tree::node_data::leaf::Leaf;
3448
use starknet_patricia::patricia_merkle_tree::storage_proof_verification::verify_patricia_proof;
35-
use starknet_patricia::patricia_merkle_tree::types::NodeIndex;
49+
use starknet_patricia::patricia_merkle_tree::types::{NodeIndex, SubTreeHeight};
3650
use starknet_patricia::patricia_merkle_tree::updated_skeleton_tree::hash_function::TreeHashFunction;
3751

3852
use crate::committer::committer_test::{new_test_committer, ApolloTestCommitter};
@@ -359,3 +373,179 @@ async fn revert_removes_witnesses_and_digest() {
359373
assert_witnesses_and_digest_absent(&mut committer, BlockNumber(height_1)).await;
360374
assert_eq!(committer.offset, BlockNumber(height_1));
361375
}
376+
377+
/// Flow overview:
378+
/// 1. Commit block 0 with three class leaves that form this Patricia topology:
379+
/// ```text
380+
/// R
381+
/// / \
382+
/// E F
383+
/// | |
384+
/// G |
385+
/// / \ \
386+
/// A B D
387+
/// ```
388+
/// 2. Commit block 1 via [crate::committer::Committer::read_paths_and_commit_block], deleting `D`
389+
/// and requesting witnesses only for the deleted key.
390+
/// 3. Assert the returned classes-trie proof contains node `E` (this will allow verifying that G,
391+
/// which appears in the new edge A--G, indeed exists in the old tree).
392+
#[tokio::test]
393+
async fn test_bottom_of_new_edge_to_an_unmoidifed_subtree_is_present() {
394+
// Set the two leftmost and the rightmost leaves.
395+
let class_hash_a = ClassHash(0_u64.into());
396+
let class_hash_b = ClassHash(1_u64.into());
397+
let class_hash_d = ClassHash(PATRICIA_KEY_UPPER_BOUND_FELT - 1_u64);
398+
399+
let compiled_class_hash_a_felt = 100_u64.into();
400+
let compiled_class_hash_b_felt = 101_u64.into();
401+
let compiled_class_hash_d_felt = 102_u64.into();
402+
403+
let mut committer = new_test_committer().await;
404+
let height_0 = 0;
405+
let height_1 = 1;
406+
let block_0_state_diff = ThinStateDiff {
407+
class_hash_to_compiled_class_hash: indexmap! {
408+
class_hash_a => CompiledClassHash(compiled_class_hash_a_felt),
409+
class_hash_b => CompiledClassHash(compiled_class_hash_b_felt),
410+
class_hash_d => CompiledClassHash(compiled_class_hash_d_felt),
411+
},
412+
..Default::default()
413+
};
414+
let block_1_state_diff = ThinStateDiff {
415+
class_hash_to_compiled_class_hash: indexmap! {
416+
class_hash_d => CompiledClassHash(0_u64.into()),
417+
},
418+
..Default::default()
419+
};
420+
let accessed_keys = AccessedKeys {
421+
accessed_class_hashes: BTreeSet::from([class_hash_d]),
422+
..Default::default()
423+
};
424+
425+
committer
426+
.commit_block(CommitBlockRequest {
427+
state_diff: block_0_state_diff.clone(),
428+
state_diff_commitment: Some(calculate_state_diff_hash(&block_0_state_diff)),
429+
height: BlockNumber(height_0),
430+
})
431+
.await
432+
.unwrap();
433+
434+
let response = committer
435+
.read_paths_and_commit_block(read_paths_and_commit_block_request(
436+
block_1_state_diff.clone(),
437+
Some(calculate_state_diff_hash(&block_1_state_diff)),
438+
height_1,
439+
accessed_keys,
440+
))
441+
.await
442+
.unwrap();
443+
444+
let leaf_a_hash = TreeHashFunctionImpl::compute_leaf_hash(&CommitterCompiledClassHash(
445+
compiled_class_hash_a_felt,
446+
));
447+
let leaf_b_hash = TreeHashFunctionImpl::compute_leaf_hash(&CommitterCompiledClassHash(
448+
compiled_class_hash_b_felt,
449+
));
450+
let node_g_hash = TreeHashFunctionImpl::compute_node_hash(&NodeData::<
451+
CommitterCompiledClassHash,
452+
HashOutput,
453+
>::Binary(BinaryData {
454+
left_data: leaf_a_hash,
455+
right_data: leaf_b_hash,
456+
}));
457+
458+
// TODO(Ariel): the preimage of G is not really needed by the OS (it only needs R, F, and the
459+
// new root R', whose opening contains the hash of G). Change this to not contains or delete
460+
// this test after making request_paths_and_commit_block_request stricter.
461+
assert!(
462+
response.patricia_proofs.classes_trie_proof.contains_key(&node_g_hash),
463+
"missing bottom of a new edge node in a proof",
464+
);
465+
}
466+
467+
/// Flow overview:
468+
/// 1. Commit block 0 with three class leaves that form this Patricia topology:
469+
/// ```text
470+
/// R
471+
/// |
472+
/// T
473+
/// / \
474+
/// E F
475+
/// / \ \
476+
/// A B D
477+
/// ```
478+
/// 2. Commit block 1 via [crate::committer::Committer::read_paths_and_commit_block], deleting `D`
479+
/// and requesting witnesses only for the deleted key.
480+
/// 3. Assert the returned classes-trie proof contains node `E` (this will allow verifying that the
481+
/// new edge's bottom is not an edge).
482+
#[tokio::test]
483+
async fn test_bottom_of_new_edge_to_a_binary_unmodified_subtree_is_present() {
484+
let class_hash_a = ClassHash(0_u64.into());
485+
let class_hash_b = ClassHash(1_u64.into());
486+
let class_hash_d = ClassHash(3_u64.into());
487+
488+
let compiled_class_hash_a_felt = 100_u64.into();
489+
let compiled_class_hash_b_felt = 101_u64.into();
490+
let compiled_class_hash_d_felt = 102_u64.into();
491+
492+
let mut committer = new_test_committer().await;
493+
let height_0 = 0;
494+
let height_1 = 1;
495+
let block_0_state_diff = ThinStateDiff {
496+
class_hash_to_compiled_class_hash: indexmap! {
497+
class_hash_a => CompiledClassHash(compiled_class_hash_a_felt),
498+
class_hash_b => CompiledClassHash(compiled_class_hash_b_felt),
499+
class_hash_d => CompiledClassHash(compiled_class_hash_d_felt),
500+
},
501+
..Default::default()
502+
};
503+
let block_1_state_diff = ThinStateDiff {
504+
class_hash_to_compiled_class_hash: indexmap! {
505+
class_hash_d => CompiledClassHash(0_u64.into()),
506+
},
507+
..Default::default()
508+
};
509+
let accessed_keys = AccessedKeys {
510+
accessed_class_hashes: BTreeSet::from([class_hash_d]),
511+
..Default::default()
512+
};
513+
514+
committer
515+
.commit_block(CommitBlockRequest {
516+
state_diff: block_0_state_diff.clone(),
517+
state_diff_commitment: Some(calculate_state_diff_hash(&block_0_state_diff)),
518+
height: BlockNumber(height_0),
519+
})
520+
.await
521+
.unwrap();
522+
523+
let response = committer
524+
.read_paths_and_commit_block(read_paths_and_commit_block_request(
525+
block_1_state_diff.clone(),
526+
Some(calculate_state_diff_hash(&block_1_state_diff)),
527+
height_1,
528+
accessed_keys,
529+
))
530+
.await
531+
.unwrap();
532+
533+
let leaf_a_hash = TreeHashFunctionImpl::compute_leaf_hash(&CommitterCompiledClassHash(
534+
compiled_class_hash_a_felt,
535+
));
536+
let leaf_b_hash = TreeHashFunctionImpl::compute_leaf_hash(&CommitterCompiledClassHash(
537+
compiled_class_hash_b_felt,
538+
));
539+
let node_e_hash = TreeHashFunctionImpl::compute_node_hash(&NodeData::<
540+
CommitterCompiledClassHash,
541+
HashOutput,
542+
>::Binary(BinaryData {
543+
left_data: leaf_a_hash,
544+
right_data: leaf_b_hash,
545+
}));
546+
547+
assert!(
548+
response.patricia_proofs.classes_trie_proof.contains_key(&node_e_hash),
549+
"missing bottom of a new edge node in a proof",
550+
);
551+
}

0 commit comments

Comments
 (0)