@@ -99,7 +99,8 @@ func (b *Blockchain) Network() *utils.Network {
9999// If blockchain is empty zero felt is returned.
100100func (b * Blockchain ) StateCommitment () (felt.Felt , error ) {
101101 b .listener .OnRead ("StateCommitment" )
102- batch := b .database .NewIndexedBatch () // this is a hack because we don't need to write to the db
102+ batch , closer := b .database .NewSnapshotBatch () // this is a hack because we don't need to write to the db
103+ defer closer ()
103104 return core .NewState (batch ).Commitment ()
104105}
105106
@@ -116,8 +117,9 @@ func (b *Blockchain) Head() (*core.Block, error) {
116117 return nil , err
117118 }
118119
119- txn := b .database .NewIndexedBatch ()
120- return core .GetBlockByNumber (txn , curHeight )
120+ snapshot := b .database .NewSnapshot ()
121+ defer snapshot .Close ()
122+ return core .GetBlockByNumber (snapshot , curHeight )
121123}
122124
123125func (b * Blockchain ) HeadsHeader () (* core.Header , error ) {
@@ -141,8 +143,9 @@ func headsHeader(txn db.KeyValueReader) (*core.Header, error) {
141143
142144func (b * Blockchain ) BlockByNumber (number uint64 ) (* core.Block , error ) {
143145 b .listener .OnRead ("BlockByNumber" )
144- txn := b .database .NewIndexedBatch ()
145- return core .GetBlockByNumber (txn , number )
146+ snapshot := b .database .NewSnapshot ()
147+ defer snapshot .Close ()
148+ return core .GetBlockByNumber (snapshot , number )
146149}
147150
148151func (b * Blockchain ) BlockHeaderByNumber (number uint64 ) (* core.Header , error ) {
@@ -157,8 +160,9 @@ func (b *Blockchain) BlockByHash(hash *felt.Felt) (*core.Block, error) {
157160 return nil , err
158161 }
159162
160- txn := b .database .NewIndexedBatch ()
161- return core .GetBlockByNumber (txn , blockNum )
163+ snapshot := b .database .NewSnapshot ()
164+ defer snapshot .Close ()
165+ return core .GetBlockByNumber (snapshot , blockNum )
162166}
163167
164168func (b * Blockchain ) BlockHeaderByHash (hash * felt.Felt ) (* core.Header , error ) {
@@ -244,48 +248,51 @@ func (b *Blockchain) Store(
244248 stateUpdate * core.StateUpdate ,
245249 newClasses map [felt.Felt ]core.ClassDefinition ,
246250) error {
247- err := b .database .Update (func (txn db.IndexedBatch ) error {
248- if err := verifyBlock (txn , block ); err != nil {
249- return err
250- }
251-
252- if err := core .NewState (txn ).Update (block .Number , stateUpdate , newClasses , false ); err != nil {
253- return err
254- }
255- if err := core .WriteBlockHeader (txn , block .Header ); err != nil {
256- return err
257- }
251+ txn , closer := b .database .NewSnapshotBatch ()
252+ defer closer ()
253+ if err := verifyBlock (txn , block ); err != nil {
254+ return err
255+ }
258256
259- for i , tx := range block .Transactions {
260- if err := core . WriteTxAndReceipt ( txn , block . Number , uint64 ( i ), tx ,
261- block . Receipts [ i ]); err != nil {
262- return err
263- }
264- }
257+ if err := core . NewState ( txn ). Update ( block .Number , stateUpdate , newClasses , false ); err != nil {
258+ return err
259+ }
260+ if err := core . WriteBlockHeader ( txn , block . Header ); err != nil {
261+ return err
262+ }
265263
266- if err := core .WriteStateUpdateByBlockNum (txn , block .Number , stateUpdate ); err != nil {
264+ for i , tx := range block .Transactions {
265+ if err := core .WriteTxAndReceipt (txn , block .Number , uint64 (i ), tx ,
266+ block .Receipts [i ]); err != nil {
267267 return err
268268 }
269+ }
269270
270- if err := core .WriteBlockCommitment (txn , block .Number , blockCommitments ); err != nil {
271- return err
272- }
271+ if err := core .WriteStateUpdateByBlockNum (txn , block .Number , stateUpdate ); err != nil {
272+ return err
273+ }
273274
274- if err := core .WriteL1HandlerMsgHashes (txn , block .Transactions ); err != nil {
275- return err
276- }
275+ if err := core .WriteBlockCommitment (txn , block .Number , blockCommitments ); err != nil {
276+ return err
277+ }
277278
278- err := storeCasmClassHashesV2ForBlock (txn , block .ProtocolVersion , newClasses , stateUpdate )
279- if err != nil {
280- return err
281- }
279+ if err := core .WriteL1HandlerMsgHashes (txn , block .Transactions ); err != nil {
280+ return err
281+ }
282282
283- return core .WriteChainHeight (txn , block .Number )
284- })
283+ err := storeCasmClassHashesV2ForBlock (txn , block .ProtocolVersion , newClasses , stateUpdate )
285284 if err != nil {
286285 return err
287286 }
288287
288+ if err := core .WriteChainHeight (txn , block .Number ); err != nil {
289+ return err
290+ }
291+
292+ if err := txn .Write (); err != nil {
293+ return err
294+ }
295+
289296 return b .runningFilter .Insert (
290297 block .EventsBloom ,
291298 block .Number ,
@@ -296,7 +303,7 @@ func (b *Blockchain) Store(
296303// For versions < 0.14.1, it computes hashes from class definitions.
297304// For versions >= 0.14.1, it uses pre-computed hashes from the state update.
298305func storeCasmClassHashesV2ForBlock (
299- txn db.IndexedBatch ,
306+ txn db.KeyValueWriter ,
300307 protocolVersion string ,
301308 newClasses map [felt.Felt ]core.ClassDefinition ,
302309 stateUpdate * core.StateUpdate ,
@@ -315,7 +322,7 @@ func storeCasmClassHashesV2ForBlock(
315322
316323// computeAndStoreCasmClassHashesV2 computes and stores CASM class hashes V2 from class definitions.
317324func computeAndStoreCasmClassHashesV2 (
318- txn db.IndexedBatch ,
325+ txn db.KeyValueWriter ,
319326 declaredClasses map [felt.Felt ]core.ClassDefinition ,
320327) error {
321328 for classHash , classDefinition := range declaredClasses {
@@ -336,7 +343,7 @@ func computeAndStoreCasmClassHashesV2(
336343
337344// storeCasmClassHashesV2 stores pre-computed CASM class hashes V2 from the state update.
338345func storeCasmClassHashesV2 (
339- txn db.IndexedBatch ,
346+ txn db.KeyValueWriter ,
340347 declaredV1Classes map [felt.Felt ]* felt.Felt ,
341348) error {
342349 for classHash , casmClassHashV2 := range declaredV1Classes {
@@ -405,33 +412,32 @@ func (b *Blockchain) SanityCheckNewHeight(block *core.Block, stateUpdate *core.S
405412
406413type StateCloser = func () error
407414
408- var noopStateCloser = func () error { return nil } // TODO: remove this once we refactor the state
409-
410415// HeadState returns a StateReader that provides a stable view to the latest state
411416func (b * Blockchain ) HeadState () (core.StateReader , StateCloser , error ) {
412417 b .listener .OnRead ("HeadState" )
413- txn := b .database .NewIndexedBatch ()
418+ snapshot := b .database .NewSnapshot ()
414419
415- _ , err := core .GetChainHeight (txn )
420+ _ , err := core .GetChainHeight (snapshot )
416421 if err != nil {
417422 return nil , nil , err
418423 }
419424
420- return core .NewState ( txn ), noopStateCloser , nil
425+ return core .NewStateSnapshotReader ( snapshot ), snapshot . Close , nil
421426}
422427
423428// StateAtBlockNumber returns a StateReader that provides
424429// a stable view to the state at the given block number
425430func (b * Blockchain ) StateAtBlockNumber (blockNumber uint64 ) (core.StateReader , StateCloser , error ) {
426431 b .listener .OnRead ("StateAtBlockNumber" )
427- txn := b .database .NewIndexedBatch ()
432+ snapshot := b .database .NewSnapshot ()
428433
429- _ , err := core .GetBlockHeaderByNumber (txn , blockNumber )
434+ _ , err := core .GetBlockHeaderByNumber (snapshot , blockNumber )
430435 if err != nil {
431436 return nil , nil , err
432437 }
433438
434- return core .NewDeprecatedStateHistory (core .NewState (txn ), blockNumber ), noopStateCloser , nil
439+ stateReader := core .NewStateSnapshotReader (snapshot )
440+ return core .NewDeprecatedStateHistory (stateReader , blockNumber ), snapshot .Close , nil
435441}
436442
437443// StateAtBlockHash returns a StateReader that provides
@@ -440,18 +446,19 @@ func (b *Blockchain) StateAtBlockHash(blockHash *felt.Felt) (core.StateReader, S
440446 b .listener .OnRead ("StateAtBlockHash" )
441447 if blockHash .IsZero () {
442448 memDB := memory .New ()
443- txn := memDB .NewIndexedBatch ()
444- emptyState := core .NewState ( txn )
445- return emptyState , noopStateCloser , nil
449+ snapshot := memDB .NewSnapshot ()
450+ emptyState := core .NewStateSnapshotReader ( snapshot )
451+ return emptyState , snapshot . Close , nil
446452 }
447453
448- txn := b .database .NewIndexedBatch ()
449- header , err := core .GetBlockHeaderByHash (txn , blockHash )
454+ snapshot := b .database .NewSnapshot ()
455+ header , err := core .GetBlockHeaderByHash (snapshot , blockHash )
450456 if err != nil {
451457 return nil , nil , err
452458 }
453459
454- return core .NewDeprecatedStateHistory (core .NewState (txn ), header .Number ), noopStateCloser , nil
460+ stateReader := core .NewStateSnapshotReader (snapshot )
461+ return core .NewDeprecatedStateHistory (stateReader , header .Number ), snapshot .Close , nil
455462}
456463
457464// EventFilter returns an EventFilter object that is tied to a snapshot of the blockchain
@@ -480,25 +487,34 @@ func (b *Blockchain) EventFilter(
480487
481488// RevertHead reverts the head block
482489func (b * Blockchain ) RevertHead () error {
483- return b .database .Update (b .revertHead )
490+ txn , closer := b .database .NewSnapshotBatch ()
491+ defer closer ()
492+ if err := b .revertHead (txn ); err != nil {
493+ return err
494+ }
495+ if err := txn .Write (); err != nil {
496+ return err
497+ }
498+ return nil
484499}
485500
486501// todo(rdr): return `core.StateDiff` by value
487502func (b * Blockchain ) GetReverseStateDiff () (* core.StateDiff , error ) {
488503 var reverseStateDiff * core.StateDiff
489504
490- txn := b .database .NewIndexedBatch ()
491- blockNum , err := core .GetChainHeight (txn )
505+ snapshot := b .database .NewSnapshot ()
506+ defer snapshot .Close ()
507+ blockNum , err := core .GetChainHeight (snapshot )
492508 if err != nil {
493509 return nil , err
494510 }
495511
496- stateUpdate , err := core .GetStateUpdateByBlockNum (txn , blockNum )
512+ stateUpdate , err := core .GetStateUpdateByBlockNum (snapshot , blockNum )
497513 if err != nil {
498514 return nil , err
499515 }
500516
501- state := core .NewState ( txn )
517+ state := core .NewStateSnapshotReader ( snapshot )
502518 reverseStateDiff , err = state .GetReverseStateDiff (blockNum , stateUpdate .StateDiff )
503519 if err != nil {
504520 return nil , err
@@ -507,7 +523,7 @@ func (b *Blockchain) GetReverseStateDiff() (*core.StateDiff, error) {
507523 return reverseStateDiff , nil
508524}
509525
510- func (b * Blockchain ) revertHead (txn db.IndexedBatch ) error {
526+ func (b * Blockchain ) revertHead (txn db.SnapshotBatch ) error {
511527 blockNumber , err := core .GetChainHeight (txn )
512528 if err != nil {
513529 return err
@@ -579,8 +595,8 @@ func (b *Blockchain) Simulate(
579595 sign utils.BlockSignFunc ,
580596) (SimulateResult , error ) {
581597 // Simulate without commit
582- txn := b .database .NewIndexedBatch ()
583- defer txn . Reset ()
598+ txn , closer := b .database .NewSnapshotBatch ()
599+ defer closer ()
584600
585601 if err := b .updateStateRoots (txn , block , stateUpdate , newClasses ); err != nil {
586602 return SimulateResult {}, err
@@ -615,38 +631,41 @@ func (b *Blockchain) Finalise(
615631 newClasses map [felt.Felt ]core.ClassDefinition ,
616632 sign utils.BlockSignFunc ,
617633) error {
618- err := b .database .Update (func (txn db.IndexedBatch ) error {
619- if err := b .updateStateRoots (txn , block , stateUpdate , newClasses ); err != nil {
620- return err
621- }
622- commitments , err := b .updateBlockHash (block , stateUpdate )
623- if err != nil {
624- return err
625- }
626- if err := b .signBlock (block , stateUpdate , sign ); err != nil {
627- return err
628- }
629- if err := b .storeBlockData (txn , block , stateUpdate , commitments ); err != nil {
630- return err
631- }
632-
633- err = storeCasmClassHashesV2ForBlock (txn , block .ProtocolVersion , newClasses , stateUpdate )
634- if err != nil {
635- return err
636- }
634+ txn , closer := b .database .NewSnapshotBatch ()
635+ defer closer ()
636+ if err := b .updateStateRoots (txn , block , stateUpdate , newClasses ); err != nil {
637+ return err
638+ }
639+ commitments , err := b .updateBlockHash (block , stateUpdate )
640+ if err != nil {
641+ return err
642+ }
643+ if err := b .signBlock (block , stateUpdate , sign ); err != nil {
644+ return err
645+ }
646+ if err := b .storeBlockData (txn , block , stateUpdate , commitments ); err != nil {
647+ return err
648+ }
637649
638- return core .WriteChainHeight (txn , block .Number )
639- })
650+ err = storeCasmClassHashesV2ForBlock (txn , block .ProtocolVersion , newClasses , stateUpdate )
640651 if err != nil {
641652 return err
642653 }
643654
655+ if err := core .WriteChainHeight (txn , block .Number ); err != nil {
656+ return err
657+ }
658+
659+ if err := txn .Write (); err != nil {
660+ return err
661+ }
662+
644663 return b .runningFilter .Insert (block .EventsBloom , block .Number )
645664}
646665
647666// updateStateRoots computes and updates state roots in the block and state update
648667func (b * Blockchain ) updateStateRoots (
649- txn db.IndexedBatch ,
668+ txn db.SnapshotBatch ,
650669 block * core.Block ,
651670 stateUpdate * core.StateUpdate ,
652671 newClasses map [felt.Felt ]core.ClassDefinition ,
@@ -715,7 +734,7 @@ func (b *Blockchain) signBlock(
715734
716735// storeBlockData persists all block-related data to the database
717736func (b * Blockchain ) storeBlockData (
718- txn db.IndexedBatch ,
737+ txn db.SnapshotBatch ,
719738 block * core.Block ,
720739 stateUpdate * core.StateUpdate ,
721740 commitments * core.BlockCommitments ,
0 commit comments