@@ -2,10 +2,16 @@ use std::collections::HashMap;
22
33use async_trait:: async_trait;
44use serde:: { Deserialize , Serialize } ;
5+ #[ cfg( feature = "os_input" ) ]
6+ use starknet_api:: block:: BlockNumber ;
57use starknet_api:: core:: ContractAddress ;
8+ #[ cfg( feature = "os_input" ) ]
9+ use starknet_api:: hash:: HashOutput ;
610use starknet_api:: hash:: StateRoots ;
711use starknet_patricia:: patricia_merkle_tree:: filled_tree:: tree:: FilledTree ;
812use starknet_patricia:: patricia_merkle_tree:: node_data:: leaf:: LeafModifications ;
13+ #[ cfg( feature = "os_input" ) ]
14+ use starknet_patricia:: patricia_merkle_tree:: traversal:: TraversalResult ;
915use starknet_patricia:: patricia_merkle_tree:: types:: NodeIndex ;
1016use starknet_patricia_storage:: db_object:: EmptyKeyContext ;
1117use starknet_patricia_storage:: errors:: SerializationResult ;
@@ -28,13 +34,30 @@ use crate::forest::filled_forest::FilledForest;
2834use crate :: forest:: forest_errors:: { ForestError , ForestResult } ;
2935use crate :: forest:: original_skeleton_forest:: { ForestSortedIndices , OriginalSkeletonForest } ;
3036use crate :: patricia_merkle_tree:: leaf:: leaf_impl:: ContractState ;
37+ #[ cfg( feature = "os_input" ) ]
38+ use crate :: patricia_merkle_tree:: tree:: SortedLeafIndices ;
3139use crate :: patricia_merkle_tree:: types:: CompiledClassHash ;
40+ #[ cfg( feature = "os_input" ) ]
41+ use crate :: patricia_merkle_tree:: types:: StarknetForestProofs ;
42+
43+ /// How Patricia proofs and read-keys digest metadata are updated in the same batch as a forest
44+ /// write.
45+ #[ cfg( feature = "os_input" ) ]
46+ pub enum PatriciaProofsUpdates {
47+ /// Remove read-keys digest + Patricia proofs on revert.
48+ Delete ( BlockNumber ) ,
49+ /// Persist read-keys digest + Patricia proofs for this block.
50+ Set { height : BlockNumber , keys_digest : [ u8 ; 32 ] , witnesses : StarknetForestProofs } ,
51+ }
3252
3353#[ derive( Clone , Debug , Deserialize , Eq , PartialEq , Hash , Serialize ) ]
3454pub enum ForestMetadataType {
3555 CommitmentOffset ,
3656 StateDiffHash ( DbBlockNumber ) ,
3757 StateRoot ( DbBlockNumber ) ,
58+ /// BLAKE2s digest of the canonical accessed-keys set for the block.
59+ #[ cfg( feature = "os_input" ) ]
60+ AccessedKeysDigest ( DbBlockNumber ) ,
3861}
3962
4063#[ async_trait]
@@ -87,6 +110,31 @@ pub trait ForestReader {
87110 ) -> PatriciaStorageResult < StateRoots > ;
88111}
89112
113+ /// Reads committed OS-input witness payload (structured [`StarknetForestProofs`]) for a block
114+ /// height.
115+ #[ cfg( feature = "os_input" ) ]
116+ #[ async_trait]
117+ pub trait ForestReaderWithWitnesses :
118+ ForestReader < InitialReadContext : EmptyInitialReadContext > + Send
119+ {
120+ async fn read_witnesses (
121+ & mut self ,
122+ height : BlockNumber ,
123+ ) -> ForestResult < Option < StarknetForestProofs > > ;
124+
125+ /// Fetches Patricia witness paths for OS input, optionally staging serialized trie node KVs on
126+ /// an in-memory overlay so reads match post-commit state before the forest is persisted.
127+ async fn fetch_patricia_witnesses (
128+ & mut self ,
129+ classes_trie_root_hash : HashOutput ,
130+ contracts_trie_root_hash : HashOutput ,
131+ class_sorted_leaf_indices : SortedLeafIndices < ' _ > ,
132+ contract_sorted_leaf_indices : SortedLeafIndices < ' _ > ,
133+ contract_storage_sorted_leaf_indices : & HashMap < NodeIndex , SortedLeafIndices < ' _ > > ,
134+ staged_serialized_forest : Option < DbHashMap > ,
135+ ) -> TraversalResult < StarknetForestProofs > ;
136+ }
137+
90138/// Helper function containing layout-common read logic.
91139pub ( crate ) async fn read_forest < ' a , S , Layout > (
92140 storage : & mut S ,
@@ -219,6 +267,20 @@ pub trait ForestWriterWithMetadata: ForestWriter + ForestMetadata {
219267 }
220268}
221269
270+ /// Writes forest + metadata + deleted nodes, and optionally applies [`PatriciaProofsUpdates`] in
271+ /// the same batch.
272+ #[ cfg( feature = "os_input" ) ]
273+ #[ async_trait]
274+ pub trait ForestWriterWithMetadataAndWitnesses : ForestWriterWithMetadata + Send {
275+ async fn write_with_metadata_and_witnesses (
276+ & mut self ,
277+ filled_forest : & FilledForest ,
278+ metadata : HashMap < ForestMetadataType , DbValue > ,
279+ deleted_nodes : DeletedNodes ,
280+ patricia_proofs_updates : PatriciaProofsUpdates ,
281+ ) -> SerializationResult < usize > ;
282+ }
283+
222284pub trait StorageInitializer {
223285 type Storage : Storage ;
224286 fn new ( storage : Self :: Storage ) -> Self ;
@@ -257,3 +319,16 @@ impl<T> ForestStorageWithEmptyReadContext for T where
257319 T : ForestReaderWithEmptyContext + ForestWriterWithMetadata + StorageInitializer
258320{
259321}
322+
323+ /// Forest storage with empty [`ForestReader::InitialReadContext`] plus OS-input witness read/write.
324+ #[ cfg( feature = "os_input" ) ]
325+ pub trait ForestStorageWithWitnesses :
326+ ForestReaderWithWitnesses + ForestWriterWithMetadataAndWitnesses + StorageInitializer
327+ {
328+ }
329+
330+ #[ cfg( feature = "os_input" ) ]
331+ impl < T > ForestStorageWithWitnesses for T where
332+ T : ForestReaderWithWitnesses + ForestWriterWithMetadataAndWitnesses + StorageInitializer
333+ {
334+ }
0 commit comments