@@ -29,6 +29,7 @@ extern crate kvdb_rocksdb;
2929extern crate kvdb;
3030extern crate hash_db;
3131extern crate parking_lot;
32+ extern crate lru_cache;
3233extern crate substrate_state_machine as state_machine;
3334extern crate substrate_primitives as primitives;
3435extern crate sr_primitives as runtime_primitives;
@@ -52,6 +53,7 @@ extern crate kvdb_memorydb;
5253pub mod light;
5354
5455mod cache;
56+ mod storage_cache;
5557mod utils;
5658
5759use std:: sync:: Arc ;
@@ -75,10 +77,12 @@ use state_machine::{CodeExecutor, DBValue, ExecutionStrategy};
7577use utils:: { Meta , db_err, meta_keys, open_database, read_db, block_id_to_lookup_key, read_meta} ;
7678use client:: LeafSet ;
7779use state_db:: StateDb ;
80+ use storage_cache:: { CachingState , SharedCache , new_shared_cache} ;
7881pub use state_db:: PruningMode ;
7982
8083const CANONICALIZATION_DELAY : u64 = 256 ;
8184const MIN_BLOCKS_TO_KEEP_CHANGES_TRIES_FOR : u64 = 32768 ;
85+ const STATE_CACHE_SIZE_BYTES : usize = 16 * 1024 * 1024 ;
8286
8387/// DB-backed patricia trie state, transaction type is an overlay of changes to commit.
8488pub type DbState = state_machine:: TrieBackend < Arc < state_machine:: Storage < Blake2Hasher > > , Blake2Hasher > ;
@@ -270,8 +274,9 @@ impl<Block: BlockT> client::blockchain::Backend<Block> for BlockchainDb<Block> {
270274
271275/// Database transaction
272276pub struct BlockImportOperation < Block : BlockT , H : Hasher > {
273- old_state : DbState ,
274- updates : MemoryDB < H > ,
277+ old_state : CachingState < Blake2Hasher , DbState , Block > ,
278+ db_updates : MemoryDB < H > ,
279+ storage_updates : Vec < ( Vec < u8 > , Option < Vec < u8 > > ) > ,
275280 changes_trie_updates : MemoryDB < H > ,
276281 pending_block : Option < PendingBlock < Block > > ,
277282 aux_ops : Vec < ( Vec < u8 > , Option < Vec < u8 > > ) > ,
@@ -292,7 +297,7 @@ impl<Block> client::backend::BlockImportOperation<Block, Blake2Hasher>
292297for BlockImportOperation < Block , Blake2Hasher >
293298where Block : BlockT < Hash =H256 > ,
294299{
295- type State = DbState ;
300+ type State = CachingState < Blake2Hasher , DbState , Block > ;
296301
297302 fn state ( & self ) -> Result < Option < & Self :: State > , client:: error:: Error > {
298303 Ok ( Some ( & self . old_state ) )
@@ -319,8 +324,8 @@ where Block: BlockT<Hash=H256>,
319324 // currently authorities are not cached on full nodes
320325 }
321326
322- fn update_storage ( & mut self , update : MemoryDB < Blake2Hasher > ) -> Result < ( ) , client:: error:: Error > {
323- self . updates = update;
327+ fn update_db_storage ( & mut self , update : MemoryDB < Blake2Hasher > ) -> Result < ( ) , client:: error:: Error > {
328+ self . db_updates = update;
324329 Ok ( ( ) )
325330 }
326331
@@ -349,7 +354,7 @@ where Block: BlockT<Hash=H256>,
349354 let ( root, update) = self . old_state . storage_root ( top. into_iter ( ) . map ( |( k, v) | ( k, Some ( v) ) ) ) ;
350355 transaction. consolidate ( update) ;
351356
352- self . updates = transaction;
357+ self . db_updates = transaction;
353358 Ok ( root)
354359 }
355360
@@ -364,6 +369,11 @@ where Block: BlockT<Hash=H256>,
364369 self . aux_ops = ops. into_iter ( ) . collect ( ) ;
365370 Ok ( ( ) )
366371 }
372+
373+ fn update_storage ( & mut self , update : Vec < ( Vec < u8 > , Option < Vec < u8 > > ) > ) -> Result < ( ) , client:: error:: Error > {
374+ self . storage_updates = update;
375+ Ok ( ( ) )
376+ }
367377}
368378
369379struct StorageDb < Block : BlockT > {
@@ -503,6 +513,7 @@ pub struct Backend<Block: BlockT> {
503513 changes_tries_storage : DbChangesTrieStorage < Block > ,
504514 blockchain : BlockchainDb < Block > ,
505515 canonicalization_delay : u64 ,
516+ shared_cache : SharedCache < Block , Blake2Hasher > ,
506517}
507518
508519impl < Block : BlockT > Backend < Block > {
@@ -550,6 +561,7 @@ impl<Block: BlockT> Backend<Block> {
550561 changes_tries_storage,
551562 blockchain,
552563 canonicalization_delay,
564+ shared_cache : new_shared_cache ( STATE_CACHE_SIZE_BYTES ) ,
553565 } )
554566 }
555567
@@ -669,15 +681,16 @@ impl<Block> client::backend::AuxStore for Backend<Block> where Block: BlockT<Has
669681impl < Block > client:: backend:: Backend < Block , Blake2Hasher > for Backend < Block > where Block : BlockT < Hash =H256 > {
670682 type BlockImportOperation = BlockImportOperation < Block , Blake2Hasher > ;
671683 type Blockchain = BlockchainDb < Block > ;
672- type State = DbState ;
684+ type State = CachingState < Blake2Hasher , DbState , Block > ;
673685 type ChangesTrieStorage = DbChangesTrieStorage < Block > ;
674686
675687 fn begin_operation ( & self , block : BlockId < Block > ) -> Result < Self :: BlockImportOperation , client:: error:: Error > {
676688 let state = self . state_at ( block) ?;
677689 Ok ( BlockImportOperation {
678690 pending_block : None ,
679691 old_state : state,
680- updates : MemoryDB :: default ( ) ,
692+ db_updates : MemoryDB :: default ( ) ,
693+ storage_updates : Default :: default ( ) ,
681694 changes_trie_updates : MemoryDB :: default ( ) ,
682695 aux_ops : Vec :: new ( ) ,
683696 } )
@@ -697,6 +710,9 @@ impl<Block> client::backend::Backend<Block, Blake2Hasher> for Backend<Block> whe
697710 // blocks are keyed by number + hash.
698711 let lookup_key = :: utils:: number_and_hash_to_lookup_key ( number, hash) ;
699712
713+ let mut enacted = Vec :: default ( ) ;
714+ let mut retracted = Vec :: default ( ) ;
715+
700716 if pending_block. leaf_state . is_best ( ) {
701717 let meta = self . blockchain . meta . read ( ) ;
702718
@@ -710,28 +726,30 @@ impl<Block> client::backend::Backend<Block, Blake2Hasher> for Backend<Block> whe
710726
711727 // uncanonicalize: check safety violations and ensure the numbers no longer
712728 // point to these block hashes in the key mapping.
713- for retracted in tree_route. retracted ( ) {
714- if retracted. hash == meta. finalized_hash {
729+ for r in tree_route. retracted ( ) {
730+ retracted. push ( r. hash . clone ( ) ) ;
731+ if r. hash == meta. finalized_hash {
715732 warn ! ( "Potential safety failure: reverting finalized block {:?}" ,
716- ( & retracted . number, & retracted . hash) ) ;
733+ ( & r . number, & r . hash) ) ;
717734
718735 return Err ( :: client:: error:: ErrorKind :: NotInFinalizedChain . into ( ) ) ;
719736 }
720737
721738 :: utils:: remove_number_to_key_mapping (
722739 & mut transaction,
723740 columns:: KEY_LOOKUP ,
724- retracted . number
741+ r . number
725742 ) ;
726743 }
727744
728745 // canonicalize: set the number lookup to map to this block's hash.
729- for enacted in tree_route. enacted ( ) {
746+ for e in tree_route. enacted ( ) {
747+ enacted. push ( e. hash . clone ( ) ) ;
730748 :: utils:: insert_number_to_key_mapping (
731749 & mut transaction,
732750 columns:: KEY_LOOKUP ,
733- enacted . number ,
734- enacted . hash
751+ e . number ,
752+ e . hash
735753 ) ;
736754 }
737755 }
@@ -766,7 +784,7 @@ impl<Block> client::backend::Backend<Block, Blake2Hasher> for Backend<Block> whe
766784 }
767785
768786 let mut changeset: state_db:: ChangeSet < H256 > = state_db:: ChangeSet :: default ( ) ;
769- for ( key, ( val, rc) ) in operation. updates . drain ( ) {
787+ for ( key, ( val, rc) ) in operation. db_updates . drain ( ) {
770788 if rc > 0 {
771789 changeset. inserted . push ( ( key, val. to_vec ( ) ) ) ;
772790 } else if rc < 0 {
@@ -792,8 +810,8 @@ impl<Block> client::backend::Backend<Block, Blake2Hasher> for Backend<Block> whe
792810 self . force_delayed_canonicalize ( & mut transaction, hash, * pending_block. header . number ( ) ) ?
793811 }
794812
795- debug ! ( target : "db" , "DB Commit {:?} ({}), best = {}" , hash , number ,
796- pending_block . leaf_state . is_best ( ) ) ;
813+ let is_best = pending_block . leaf_state . is_best ( ) ;
814+ debug ! ( target : "db" , "DB Commit {:?} ({}), best = {}" , hash , number , is_best ) ;
797815
798816 {
799817 let mut leaves = self . blockchain . leaves . write ( ) ;
@@ -817,6 +835,16 @@ impl<Block> client::backend::Backend<Block, Blake2Hasher> for Backend<Block> whe
817835 pending_block. leaf_state . is_best ( ) ,
818836 finalized,
819837 ) ;
838+
839+ // sync canonical state cache
840+ operation. old_state . sync_cache (
841+ & enacted,
842+ & retracted,
843+ operation. storage_updates ,
844+ Some ( hash) ,
845+ Some ( number) ,
846+ || is_best
847+ ) ;
820848 }
821849 Ok ( ( ) )
822850 }
@@ -898,20 +926,30 @@ impl<Block> client::backend::Backend<Block, Blake2Hasher> for Backend<Block> whe
898926 BlockId :: Hash ( h) if h == Default :: default ( ) => {
899927 let genesis_storage = DbGenesisStorage :: new ( ) ;
900928 let root = genesis_storage. 0 . clone ( ) ;
901- return Ok ( DbState :: new ( Arc :: new ( genesis_storage) , root) ) ;
929+ let state = DbState :: new ( Arc :: new ( genesis_storage) , root) ;
930+ return Ok ( CachingState :: new ( state, self . shared_cache . clone ( ) , None ) ) ;
902931 } ,
903932 _ => { }
904933 }
905934
906935 match self . blockchain . header ( block) {
907936 Ok ( Some ( ref hdr) ) if !self . storage . state_db . is_pruned ( hdr. number ( ) . as_ ( ) ) => {
908937 let root = H256 :: from_slice ( hdr. state_root ( ) . as_ref ( ) ) ;
909- Ok ( DbState :: new ( self . storage . clone ( ) , root) )
938+ let state = DbState :: new ( self . storage . clone ( ) , root) ;
939+ Ok ( CachingState :: new ( state, self . shared_cache . clone ( ) , Some ( hdr. hash ( ) ) ) )
910940 } ,
911941 Err ( e) => Err ( e) ,
912942 _ => Err ( client:: error:: ErrorKind :: UnknownBlock ( format ! ( "{:?}" , block) ) . into ( ) ) ,
913943 }
914944 }
945+
946+ fn destroy_state ( & self , mut state : Self :: State ) -> Result < ( ) , client:: error:: Error > {
947+ if let Some ( hash) = state. parent_hash . clone ( ) {
948+ let is_best = || self . blockchain . meta . read ( ) . best_hash == hash;
949+ state. sync_cache ( & [ ] , & [ ] , vec ! [ ] , None , None , is_best) ;
950+ }
951+ Ok ( ( ) )
952+ }
915953}
916954
917955impl < Block > client:: backend:: LocalBackend < Block , Blake2Hasher > for Backend < Block >
@@ -1092,7 +1130,7 @@ mod tests {
10921130 ] ;
10931131
10941132 let ( root, overlay) = op. old_state . storage_root ( storage. iter ( ) . cloned ( ) ) ;
1095- op. update_storage ( overlay) . unwrap ( ) ;
1133+ op. update_db_storage ( overlay) . unwrap ( ) ;
10961134 header. state_root = root. into ( ) ;
10971135
10981136 op. set_block_data (
@@ -1138,7 +1176,7 @@ mod tests {
11381176
11391177 op. reset_storage ( storage. iter ( ) . cloned ( ) . collect ( ) , Default :: default ( ) ) . unwrap ( ) ;
11401178
1141- key = op. updates . insert ( b"hello" ) ;
1179+ key = op. db_updates . insert ( b"hello" ) ;
11421180 op. set_block_data (
11431181 header,
11441182 Some ( vec ! [ ] ) ,
@@ -1171,8 +1209,8 @@ mod tests {
11711209 ) . 0 . into ( ) ;
11721210 let hash = header. hash ( ) ;
11731211
1174- op. updates . insert ( b"hello" ) ;
1175- op. updates . remove ( & key) ;
1212+ op. db_updates . insert ( b"hello" ) ;
1213+ op. db_updates . remove ( & key) ;
11761214 op. set_block_data (
11771215 header,
11781216 Some ( vec ! [ ] ) ,
@@ -1204,7 +1242,7 @@ mod tests {
12041242 . map ( |( x, y) | ( x, Some ( y) ) )
12051243 ) . 0 . into ( ) ;
12061244
1207- op. updates . remove ( & key) ;
1245+ op. db_updates . remove ( & key) ;
12081246 op. set_block_data (
12091247 header,
12101248 Some ( vec ! [ ] ) ,
0 commit comments