@@ -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,32 @@ 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+ /// Leave witness metadata and payload keys unchanged.
48+ Skip ,
49+ /// Remove read-keys digest + Patricia proofs on revert.
50+ Delete ( BlockNumber ) ,
51+ /// Persist read-keys digest + Patricia proofs for this block.
52+ Set { height : BlockNumber , keys_digest : [ u8 ; 32 ] , witnesses : StarknetForestProofs } ,
53+ }
3254
3355#[ derive( Clone , Debug , Deserialize , Eq , PartialEq , Hash , Serialize ) ]
3456pub enum ForestMetadataType {
3557 CommitmentOffset ,
3658 StateDiffHash ( DbBlockNumber ) ,
3759 StateRoot ( DbBlockNumber ) ,
60+ /// Poseidon digest of the canonical OS-input read-key set for the block.
61+ #[ cfg( feature = "os_input" ) ]
62+ OsInputWitnessDigest ( DbBlockNumber ) ,
3863}
3964
4065#[ async_trait]
@@ -87,6 +112,31 @@ pub trait ForestReader {
87112 ) -> PatriciaStorageResult < StateRoots > ;
88113}
89114
115+ /// Reads committed OS-input witness payload (structured [`StarknetForestProofs`]) for a block
116+ /// height.
117+ #[ cfg( feature = "os_input" ) ]
118+ #[ async_trait]
119+ pub trait ForestReaderWithWitnesses :
120+ ForestReader < InitialReadContext : EmptyInitialReadContext > + Send
121+ {
122+ async fn read_witnesses (
123+ & mut self ,
124+ height : BlockNumber ,
125+ ) -> ForestResult < Option < StarknetForestProofs > > ;
126+
127+ /// Fetches Patricia witness paths for OS input, optionally staging serialized trie node KVs on
128+ /// an in-memory overlay so reads match post-commit state before the forest is persisted.
129+ async fn fetch_patricia_witnesses (
130+ & mut self ,
131+ classes_trie_root_hash : HashOutput ,
132+ contracts_trie_root_hash : HashOutput ,
133+ class_sorted_leaf_indices : SortedLeafIndices < ' _ > ,
134+ contract_sorted_leaf_indices : SortedLeafIndices < ' _ > ,
135+ contract_storage_sorted_leaf_indices : & HashMap < NodeIndex , SortedLeafIndices < ' _ > > ,
136+ staged_serialized_forest : Option < DbHashMap > ,
137+ ) -> TraversalResult < StarknetForestProofs > ;
138+ }
139+
90140/// Helper function containing layout-common read logic.
91141pub ( crate ) async fn read_forest < ' a , S , Layout > (
92142 storage : & mut S ,
@@ -219,6 +269,20 @@ pub trait ForestWriterWithMetadata: ForestWriter + ForestMetadata {
219269 }
220270}
221271
272+ /// Writes forest + metadata + deleted nodes, and optionally applies [`PatriciaProofsUpdates`] in
273+ /// the same batch.
274+ #[ cfg( feature = "os_input" ) ]
275+ #[ async_trait]
276+ pub trait ForestWriterWithMetadataAndWitnesses : ForestWriterWithMetadata + Send {
277+ async fn write_with_metadata_and_witnesses (
278+ & mut self ,
279+ filled_forest : & FilledForest ,
280+ metadata : HashMap < ForestMetadataType , DbValue > ,
281+ deleted_nodes : DeletedNodes ,
282+ patricia_proofs_updates : PatriciaProofsUpdates ,
283+ ) -> SerializationResult < usize > ;
284+ }
285+
222286pub trait StorageInitializer {
223287 type Storage : Storage ;
224288 fn new ( storage : Self :: Storage ) -> Self ;
@@ -257,3 +321,16 @@ impl<T> ForestStorageWithEmptyReadContext for T where
257321 T : ForestReaderWithEmptyContext + ForestWriterWithMetadata + StorageInitializer
258322{
259323}
324+
325+ /// Forest storage with empty [`ForestReader::InitialReadContext`] plus OS-input witness read/write.
326+ #[ cfg( feature = "os_input" ) ]
327+ pub trait ForestStorageWithWitnesses :
328+ ForestReaderWithWitnesses + ForestWriterWithMetadataAndWitnesses + StorageInitializer
329+ {
330+ }
331+
332+ #[ cfg( feature = "os_input" ) ]
333+ impl < T > ForestStorageWithWitnesses for T where
334+ T : ForestReaderWithWitnesses + ForestWriterWithMetadataAndWitnesses + StorageInitializer
335+ {
336+ }
0 commit comments