@@ -15,7 +15,7 @@ use crate::{
1515 encoded_path_eq_nibs, encoded_path_strip_prefix, lcp, prefix_to_nibs,
1616 to_encoded_path_with_bump, to_nibs,
1717 } ,
18- node:: { BranchId , NodeData , NodeId , NodeRef } ,
18+ node:: { BranchChildren , NodeData , NodeId , NodeRef } ,
1919} ;
2020
2121/// OpenVM memory alignment word size.
@@ -57,11 +57,6 @@ pub struct Mpt<'a> {
5757 /// List of MPT nodes.
5858 nodes : Vec < NodeData < ' a > > ,
5959
60- /// Children arrays of branch nodes, indexed by [`BranchId`]. Kept out of [`NodeData`] so the
61- /// node list stays compact. Arrays orphaned by structural updates are never reclaimed, just
62- /// like the nodes themselves.
63- branches : Vec < [ Option < NodeId > ; 16 ] > ,
64-
6560 /// Cache. Hashing/encoding often needs "what would this node look like in its parent"
6661 cached_references : Vec < Cell < Option < NodeRef < ' a > > > > ,
6762
@@ -90,9 +85,6 @@ impl<'a> Mpt<'a> {
9085
9186 Self {
9287 nodes,
93- // Branch nodes are a small fraction of witness nodes (each resolved branch child is
94- // its own node, unresolved ones are digest nodes), so 1/8 leaves ample headroom.
95- branches : Vec :: with_capacity ( capacity / 8 ) ,
9688 rlp_scratch : RefCell :: new ( Vec :: with_capacity ( RLP_SCRATCH_INIT_CAPACITY ) ) ,
9789 cached_references,
9890 bump,
@@ -181,8 +173,8 @@ impl<'a> Mpt<'a> {
181173 }
182174
183175 match self . nodes [ node_id as usize ] {
184- NodeData :: Branch ( branch_id ) => {
185- for child_id in self . branches [ branch_id as usize ] . into_iter ( ) . flatten ( ) {
176+ NodeData :: Branch ( children ) => {
177+ for child_id in children . iter ( ) . filter_map ( Cell :: get ) {
186178 self . encode_trie_internal ( child_id, out) ;
187179 }
188180 }
@@ -390,8 +382,8 @@ impl<'a> Mpt<'a> {
390382 return Err ( Error :: ValueInBranch ) ;
391383 }
392384
393- let branch_id = self . add_branch ( childs) ;
394- let node_id = self . add_node ( NodeData :: Branch ( branch_id ) , Some ( node_ref) ) ;
385+ let children = self . alloc_branch ( childs) ;
386+ let node_id = self . add_node ( NodeData :: Branch ( children ) , Some ( node_ref) ) ;
395387 Ok ( node_id)
396388 }
397389}
@@ -444,11 +436,11 @@ impl<'a> Mpt<'a> {
444436 NodeData :: Null => {
445437 out. put_u8 ( alloy_rlp:: EMPTY_STRING_CODE ) ;
446438 }
447- NodeData :: Branch ( branch_id ) => {
439+ NodeData :: Branch ( children ) => {
448440 encode_header ( alloy_rlp:: EMPTY_LIST_CODE , payload_length, out) ;
449- for child_id in self . branches [ * branch_id as usize ] . iter ( ) {
450- match child_id {
451- Some ( id) => self . reference_encode ( * id, out) ,
441+ for child_id in children . iter ( ) {
442+ match child_id. get ( ) {
443+ Some ( id) => self . reference_encode ( id, out) ,
452444 None => out. put_u8 ( alloy_rlp:: EMPTY_STRING_CODE ) ,
453445 }
454446 }
@@ -498,10 +490,10 @@ impl<'a> Mpt<'a> {
498490 fn payload_length ( & self , node_id : NodeId ) -> usize {
499491 match & self . nodes [ node_id as usize ] {
500492 NodeData :: Null => 0 ,
501- NodeData :: Branch ( branch_id ) => {
502- 1 + self . branches [ * branch_id as usize ]
493+ NodeData :: Branch ( children ) => {
494+ 1 + children
503495 . iter ( )
504- . map ( |child| child. map_or ( 1 , |id| self . reference_length ( id) ) )
496+ . map ( |child| child. get ( ) . map_or ( 1 , |id| self . reference_length ( id) ) )
505497 . sum :: < usize > ( )
506498 }
507499 NodeData :: Leaf ( encoded_path, value) => encoded_path. length ( ) + value. length ( ) ,
@@ -613,7 +605,6 @@ impl<'a> Mpt<'a> {
613605 pub fn reserve ( & mut self , additional : usize ) {
614606 self . nodes . reserve ( additional) ;
615607 self . cached_references . reserve ( additional) ;
616- self . branches . reserve ( additional / 8 ) ;
617608 }
618609}
619610
@@ -627,13 +618,11 @@ impl<'a> Mpt<'a> {
627618 id
628619 }
629620
630- /// Adds a branch children array to the arena and returns its id , to be stored in a
631- /// [`NodeData::Branch`] of this trie .
621+ /// Allocates a branch children array in the bump arena , to be stored in a
622+ /// [`NodeData::Branch`].
632623 #[ inline]
633- pub ( crate ) fn add_branch ( & mut self , children : [ Option < NodeId > ; 16 ] ) -> BranchId {
634- let id = self . branches . len ( ) as BranchId ;
635- self . branches . push ( children) ;
636- id
624+ pub ( crate ) fn alloc_branch ( & self , children : [ Option < NodeId > ; 16 ] ) -> BranchChildren < ' a > {
625+ self . bump . alloc ( children. map ( Cell :: new) )
637626 }
638627
639628 /// Sets the root node ID. Used by the resolver and by tests to construct tries with specific
@@ -644,13 +633,15 @@ impl<'a> Mpt<'a> {
644633 self . root_id = root_id;
645634 }
646635
647- /// Adds a new node to the trie, copying any borrowed slices into the trie's bump arena, and
648- /// returns the new node 's ID. A `Branch`'s id must already refer to this trie 's branch arena .
636+ /// Adds a new node to the trie, copying any borrowed slices (and branch children) into the
637+ /// trie 's bump arena, and returns the new node 's ID .
649638 #[ cfg( feature = "host" ) ]
650639 pub ( crate ) fn add_node_copied ( & mut self , data : & NodeData < ' _ > ) -> NodeId {
651640 let data = match data {
652641 NodeData :: Null => NodeData :: Null ,
653- NodeData :: Branch ( branch_id) => NodeData :: Branch ( * branch_id) ,
642+ NodeData :: Branch ( children) => {
643+ NodeData :: Branch ( self . alloc_branch ( children. each_ref ( ) . map ( Cell :: get) ) )
644+ }
654645 NodeData :: Leaf ( prefix, value) => NodeData :: Leaf (
655646 self . bump . alloc_slice_copy ( prefix) ,
656647 self . bump . alloc_slice_copy ( value) ,
@@ -672,9 +663,9 @@ impl<'a> Mpt<'a> {
672663 fn get_internal ( & self , node_id : NodeId , key_nibs : & [ u8 ] ) -> Result < Option < & ' a [ u8 ] > , Error > {
673664 match & self . nodes [ node_id as usize ] {
674665 NodeData :: Null => Ok ( None ) ,
675- NodeData :: Branch ( branch_id ) => {
666+ NodeData :: Branch ( children ) => {
676667 if let Some ( ( i, tail) ) = key_nibs. split_first ( ) {
677- match self . branches [ * branch_id as usize ] [ * i as usize ] {
668+ match children [ * i as usize ] . get ( ) {
678669 Some ( id) => self . get_internal ( id, tail) ,
679670 None => Ok ( None ) ,
680671 }
@@ -715,14 +706,14 @@ impl<'a> Mpt<'a> {
715706 self . nodes [ node_id as usize ] = NodeData :: Leaf ( path, value) ;
716707 true
717708 }
718- NodeData :: Branch ( branch_id ) => {
709+ NodeData :: Branch ( children ) => {
719710 if let Some ( ( i, tail) ) = key_nibs. split_first ( ) {
720- match self . branches [ branch_id as usize ] [ * i as usize ] {
711+ match children [ * i as usize ] . get ( ) {
721712 Some ( id) => self . insert_internal ( id, tail, value) ?,
722713 None => {
723714 let path = to_encoded_path_with_bump ( self . bump , tail, true ) ;
724715 let new_leaf_id = self . add_node ( NodeData :: Leaf ( path, value) , None ) ;
725- self . branches [ branch_id as usize ] [ * i as usize ] = Some ( new_leaf_id) ;
716+ children [ * i as usize ] . set ( Some ( new_leaf_id) ) ;
726717 true
727718 }
728719 }
@@ -760,17 +751,18 @@ impl<'a> Mpt<'a> {
760751 children[ self_nibs[ common_len] as usize ] = Some ( leaf1_id) ;
761752 children[ key_nibs[ common_len] as usize ] = Some ( leaf2_id) ;
762753
763- let branch_id = self . add_branch ( children) ;
754+ let branch_children = self . alloc_branch ( children) ;
764755 let new_node_data = if common_len > 0 {
765- let branch_node_id = self . add_node ( NodeData :: Branch ( branch_id) , None ) ;
756+ let branch_node_id =
757+ self . add_node ( NodeData :: Branch ( branch_children) , None ) ;
766758 let ext_path_slice = to_encoded_path_with_bump (
767759 self . bump ,
768760 & self_nibs[ ..common_len] ,
769761 false ,
770762 ) ;
771763 NodeData :: Extension ( ext_path_slice, branch_node_id)
772764 } else {
773- NodeData :: Branch ( branch_id )
765+ NodeData :: Branch ( branch_children )
774766 } ;
775767 self . nodes [ node_id as usize ] = new_node_data;
776768 true
@@ -804,14 +796,14 @@ impl<'a> Mpt<'a> {
804796 let leaf_id = self . add_node ( NodeData :: Leaf ( leaf_path, value) , None ) ;
805797 children[ key_nibs[ common_len] as usize ] = Some ( leaf_id) ;
806798
807- let branch_id = self . add_branch ( children) ;
799+ let branch_children = self . alloc_branch ( children) ;
808800 let new_node_data = if common_len > 0 {
809- let branch_node_id = self . add_node ( NodeData :: Branch ( branch_id ) , None ) ;
801+ let branch_node_id = self . add_node ( NodeData :: Branch ( branch_children ) , None ) ;
810802 let parent_ext_path_slice =
811803 to_encoded_path_with_bump ( self . bump , & self_nibs[ ..common_len] , false ) ;
812804 NodeData :: Extension ( parent_ext_path_slice, branch_node_id)
813805 } else {
814- NodeData :: Branch ( branch_id )
806+ NodeData :: Branch ( branch_children )
815807 } ;
816808 self . nodes [ node_id as usize ] = new_node_data;
817809 true
@@ -833,18 +825,17 @@ impl<'a> Mpt<'a> {
833825 fn delete_internal ( & mut self , node_id : NodeId , key_nibs : & [ u8 ] ) -> Result < bool , Error > {
834826 let updated = match self . nodes [ node_id as usize ] {
835827 NodeData :: Null => false ,
836- NodeData :: Branch ( branch_id ) => {
828+ NodeData :: Branch ( children ) => {
837829 if let Some ( ( i, tail) ) = key_nibs. split_first ( ) {
838- let child_id = self . branches [ branch_id as usize ] [ * i as usize ] ;
839- match child_id {
830+ match children[ * i as usize ] . get ( ) {
840831 Some ( id) => {
841832 if !self . delete_internal ( id, tail) ? {
842833 return Ok ( false ) ;
843834 }
844835
845836 // if the node is now empty, remove it
846837 if matches ! ( self . nodes[ id as usize ] , NodeData :: Null ) {
847- self . branches [ branch_id as usize ] [ * i as usize ] = None ;
838+ children [ * i as usize ] . set ( None ) ;
848839 }
849840 }
850841 None => return Ok ( false ) ,
@@ -853,14 +844,13 @@ impl<'a> Mpt<'a> {
853844 return Err ( Error :: ValueInBranch ) ;
854845 }
855846
856- let mut remaining_iter = self . branches [ branch_id as usize ]
847+ let mut remaining_iter = children
857848 . iter ( )
858849 . enumerate ( )
859- . filter ( |( _ , n) | n. is_some ( ) ) ;
850+ . filter_map ( |( index , n) | n. get ( ) . map ( |id| ( index , id ) ) ) ;
860851
861852 // there will always be at least one remaining node
862853 let ( index, child_id) = remaining_iter. next ( ) . unwrap ( ) ;
863- let child_id = child_id. unwrap ( ) ;
864854
865855 // if there is only exactly one node left, we need to convert the branch
866856 if remaining_iter. next ( ) . is_none ( ) {
@@ -897,7 +887,7 @@ impl<'a> Mpt<'a> {
897887 } ;
898888 self . nodes [ node_id as usize ] = new_node_data;
899889 }
900- // otherwise the children were already updated in place in the branch arena
890+ // otherwise the children were already updated in place through their cells
901891
902892 true
903893 }
@@ -1010,8 +1000,8 @@ impl<'a> Mpt<'a> {
10101000 let child_id = self . decode_from_proof_rlp_internal ( & mut item) ?;
10111001 childs[ i] = if child_id == NULL_NODE_ID { None } else { Some ( child_id) } ;
10121002 }
1013- let branch_id = self . add_branch ( childs) ;
1014- self . add_node ( NodeData :: Branch ( branch_id ) , None )
1003+ let children = self . alloc_branch ( childs) ;
1004+ self . add_node ( NodeData :: Branch ( children ) , None )
10151005 }
10161006 _ => {
10171007 return Err ( Error :: RlpError ( alloy_rlp:: Error :: UnexpectedLength ) ) ;
@@ -1039,8 +1029,8 @@ impl<'a> Mpt<'a> {
10391029 payloads. push ( buffer_bytes) ;
10401030
10411031 match & self . nodes [ node_id as usize ] {
1042- NodeData :: Branch ( branch_id ) => {
1043- for child_id in self . branches [ * branch_id as usize ] . into_iter ( ) . flatten ( ) {
1032+ NodeData :: Branch ( children ) => {
1033+ for child_id in children . iter ( ) . filter_map ( Cell :: get ) {
10441034 self . payloads_internal ( child_id, payloads) ;
10451035 }
10461036 }
@@ -1063,12 +1053,12 @@ impl Mpt<'_> {
10631053 NodeData :: Null => {
10641054 println ! ( "{}Null" , indent) ;
10651055 }
1066- NodeData :: Branch ( branch_id ) => {
1056+ NodeData :: Branch ( children ) => {
10671057 println ! ( "{}Branch" , indent) ;
1068- for ( i, child) in self . branches [ * branch_id as usize ] . iter ( ) . enumerate ( ) {
1069- if let Some ( child_id) = child {
1058+ for ( i, child) in children . iter ( ) . enumerate ( ) {
1059+ if let Some ( child_id) = child. get ( ) {
10701060 println ! ( "{} [{}]:" , indent, hex:: encode( [ i as u8 ] ) ) ;
1071- self . print_trie_internal ( * child_id, depth + 2 ) ;
1061+ self . print_trie_internal ( child_id, depth + 2 ) ;
10721062 }
10731063 }
10741064 }
0 commit comments