@@ -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 ) {
@@ -236,48 +240,51 @@ func (b *Blockchain) Store(
236240 stateUpdate * core.StateUpdate ,
237241 newClasses map [felt.Felt ]core.ClassDefinition ,
238242) error {
239- err := b .database .Update (func (txn db.IndexedBatch ) error {
240- if err := verifyBlock (txn , block ); err != nil {
241- return err
242- }
243-
244- if err := core .NewState (txn ).Update (block .Number , stateUpdate , newClasses , false ); err != nil {
245- return err
246- }
247- if err := core .WriteBlockHeader (txn , block .Header ); err != nil {
248- return err
249- }
243+ txn , closer := b .database .NewSnapshotBatch ()
244+ defer closer ()
245+ if err := verifyBlock (txn , block ); err != nil {
246+ return err
247+ }
250248
251- for i , tx := range block .Transactions {
252- if err := core . WriteTxAndReceipt ( txn , block . Number , uint64 ( i ), tx ,
253- block . Receipts [ i ]); err != nil {
254- return err
255- }
256- }
249+ if err := core . NewState ( txn ). Update ( block .Number , stateUpdate , newClasses , false ); err != nil {
250+ return err
251+ }
252+ if err := core . WriteBlockHeader ( txn , block . Header ); err != nil {
253+ return err
254+ }
257255
258- if err := core .WriteStateUpdateByBlockNum (txn , block .Number , stateUpdate ); err != nil {
256+ for i , tx := range block .Transactions {
257+ if err := core .WriteTxAndReceipt (txn , block .Number , uint64 (i ), tx ,
258+ block .Receipts [i ]); err != nil {
259259 return err
260260 }
261+ }
261262
262- if err := core .WriteBlockCommitment (txn , block .Number , blockCommitments ); err != nil {
263- return err
264- }
263+ if err := core .WriteStateUpdateByBlockNum (txn , block .Number , stateUpdate ); err != nil {
264+ return err
265+ }
265266
266- if err := core .WriteL1HandlerMsgHashes (txn , block .Transactions ); err != nil {
267- return err
268- }
267+ if err := core .WriteBlockCommitment (txn , block .Number , blockCommitments ); err != nil {
268+ return err
269+ }
269270
270- err := storeCasmClassHashesV2ForBlock (txn , block .ProtocolVersion , newClasses , stateUpdate )
271- if err != nil {
272- return err
273- }
271+ if err := core .WriteL1HandlerMsgHashes (txn , block .Transactions ); err != nil {
272+ return err
273+ }
274274
275- return core .WriteChainHeight (txn , block .Number )
276- })
275+ err := storeCasmClassHashesV2ForBlock (txn , block .ProtocolVersion , newClasses , stateUpdate )
277276 if err != nil {
278277 return err
279278 }
280279
280+ if err := core .WriteChainHeight (txn , block .Number ); err != nil {
281+ return err
282+ }
283+
284+ if err := txn .Write (); err != nil {
285+ return err
286+ }
287+
281288 return b .runningFilter .Insert (
282289 block .EventsBloom ,
283290 block .Number ,
@@ -288,7 +295,7 @@ func (b *Blockchain) Store(
288295// For versions < 0.14.1, it computes hashes from class definitions.
289296// For versions >= 0.14.1, it uses pre-computed hashes from the state update.
290297func storeCasmClassHashesV2ForBlock (
291- txn db.IndexedBatch ,
298+ txn db.KeyValueWriter ,
292299 protocolVersion string ,
293300 newClasses map [felt.Felt ]core.ClassDefinition ,
294301 stateUpdate * core.StateUpdate ,
@@ -307,7 +314,7 @@ func storeCasmClassHashesV2ForBlock(
307314
308315// computeAndStoreCasmClassHashesV2 computes and stores CASM class hashes V2 from class definitions.
309316func computeAndStoreCasmClassHashesV2 (
310- txn db.IndexedBatch ,
317+ txn db.KeyValueWriter ,
311318 declaredClasses map [felt.Felt ]core.ClassDefinition ,
312319) error {
313320 for classHash , classDefinition := range declaredClasses {
@@ -328,7 +335,7 @@ func computeAndStoreCasmClassHashesV2(
328335
329336// storeCasmClassHashesV2 stores pre-computed CASM class hashes V2 from the state update.
330337func storeCasmClassHashesV2 (
331- txn db.IndexedBatch ,
338+ txn db.KeyValueWriter ,
332339 declaredV1Classes map [felt.Felt ]* felt.Felt ,
333340) error {
334341 for classHash , casmClassHashV2 := range declaredV1Classes {
@@ -397,33 +404,32 @@ func (b *Blockchain) SanityCheckNewHeight(block *core.Block, stateUpdate *core.S
397404
398405type StateCloser = func () error
399406
400- var noopStateCloser = func () error { return nil } // TODO: remove this once we refactor the state
401-
402407// HeadState returns a StateReader that provides a stable view to the latest state
403408func (b * Blockchain ) HeadState () (core.StateReader , StateCloser , error ) {
404409 b .listener .OnRead ("HeadState" )
405- txn := b .database .NewIndexedBatch ()
410+ snapshot := b .database .NewSnapshot ()
406411
407- _ , err := core .GetChainHeight (txn )
412+ _ , err := core .GetChainHeight (snapshot )
408413 if err != nil {
409414 return nil , nil , err
410415 }
411416
412- return core .NewState ( txn ), noopStateCloser , nil
417+ return core .NewStateSnapshotReader ( snapshot ), snapshot . Close , nil
413418}
414419
415420// StateAtBlockNumber returns a StateReader that provides a stable view to the state at the given
416421// block number
417422func (b * Blockchain ) StateAtBlockNumber (blockNumber uint64 ) (core.StateReader , StateCloser , error ) {
418423 b .listener .OnRead ("StateAtBlockNumber" )
419- txn := b .database .NewIndexedBatch ()
424+ snapshot := b .database .NewSnapshot ()
420425
421- _ , err := core .GetBlockHeaderByNumber (txn , blockNumber )
426+ _ , err := core .GetBlockHeaderByNumber (snapshot , blockNumber )
422427 if err != nil {
423428 return nil , nil , err
424429 }
425430
426- return core .NewDeprecatedStateHistory (core .NewState (txn ), blockNumber ), noopStateCloser , nil
431+ stateReader := core .NewStateSnapshotReader (snapshot )
432+ return core .NewDeprecatedStateHistory (stateReader , blockNumber ), snapshot .Close , nil
427433}
428434
429435// StateAtBlockHash returns a StateReader that provides a stable view to the state at the given
@@ -432,18 +438,19 @@ func (b *Blockchain) StateAtBlockHash(blockHash *felt.Felt) (core.StateReader, S
432438 b .listener .OnRead ("StateAtBlockHash" )
433439 if blockHash .IsZero () {
434440 memDB := memory .New ()
435- txn := memDB .NewIndexedBatch ()
436- emptyState := core .NewState ( txn )
437- return emptyState , noopStateCloser , nil
441+ snapshot := memDB .NewSnapshot ()
442+ emptyState := core .NewStateSnapshotReader ( snapshot )
443+ return emptyState , snapshot . Close , nil
438444 }
439445
440- txn := b .database .NewIndexedBatch ()
441- header , err := core .GetBlockHeaderByHash (txn , blockHash )
446+ snapshot := b .database .NewSnapshot ()
447+ header , err := core .GetBlockHeaderByHash (snapshot , blockHash )
442448 if err != nil {
443449 return nil , nil , err
444450 }
445451
446- return core .NewDeprecatedStateHistory (core .NewState (txn ), header .Number ), noopStateCloser , nil
452+ stateReader := core .NewStateSnapshotReader (snapshot )
453+ return core .NewDeprecatedStateHistory (stateReader , header .Number ), snapshot .Close , nil
447454}
448455
449456// EventFilter returns an EventFilter object that is tied to a snapshot of the blockchain
@@ -472,25 +479,34 @@ func (b *Blockchain) EventFilter(
472479
473480// RevertHead reverts the head block
474481func (b * Blockchain ) RevertHead () error {
475- return b .database .Update (b .revertHead )
482+ txn , closer := b .database .NewSnapshotBatch ()
483+ defer closer ()
484+ if err := b .revertHead (txn ); err != nil {
485+ return err
486+ }
487+ if err := txn .Write (); err != nil {
488+ return err
489+ }
490+ return nil
476491}
477492
478493// todo(rdr): return `core.StateDiff` by value
479494func (b * Blockchain ) GetReverseStateDiff () (* core.StateDiff , error ) {
480495 var reverseStateDiff * core.StateDiff
481496
482- txn := b .database .NewIndexedBatch ()
483- blockNum , err := core .GetChainHeight (txn )
497+ snapshot := b .database .NewSnapshot ()
498+ defer snapshot .Close ()
499+ blockNum , err := core .GetChainHeight (snapshot )
484500 if err != nil {
485501 return nil , err
486502 }
487503
488- stateUpdate , err := core .GetStateUpdateByBlockNum (txn , blockNum )
504+ stateUpdate , err := core .GetStateUpdateByBlockNum (snapshot , blockNum )
489505 if err != nil {
490506 return nil , err
491507 }
492508
493- state := core .NewState ( txn )
509+ state := core .NewStateSnapshotReader ( snapshot )
494510 reverseStateDiff , err = state .GetReverseStateDiff (blockNum , stateUpdate .StateDiff )
495511 if err != nil {
496512 return nil , err
@@ -499,7 +515,7 @@ func (b *Blockchain) GetReverseStateDiff() (*core.StateDiff, error) {
499515 return reverseStateDiff , nil
500516}
501517
502- func (b * Blockchain ) revertHead (txn db.IndexedBatch ) error {
518+ func (b * Blockchain ) revertHead (txn db.SnapshotBatch ) error {
503519 blockNumber , err := core .GetChainHeight (txn )
504520 if err != nil {
505521 return err
@@ -571,8 +587,8 @@ func (b *Blockchain) Simulate(
571587 sign utils.BlockSignFunc ,
572588) (SimulateResult , error ) {
573589 // Simulate without commit
574- txn := b .database .NewIndexedBatch ()
575- defer txn . Reset ()
590+ txn , closer := b .database .NewSnapshotBatch ()
591+ defer closer ()
576592
577593 if err := b .updateStateRoots (txn , block , stateUpdate , newClasses ); err != nil {
578594 return SimulateResult {}, err
@@ -607,38 +623,41 @@ func (b *Blockchain) Finalise(
607623 newClasses map [felt.Felt ]core.ClassDefinition ,
608624 sign utils.BlockSignFunc ,
609625) error {
610- err := b .database .Update (func (txn db.IndexedBatch ) error {
611- if err := b .updateStateRoots (txn , block , stateUpdate , newClasses ); err != nil {
612- return err
613- }
614- commitments , err := b .updateBlockHash (block , stateUpdate )
615- if err != nil {
616- return err
617- }
618- if err := b .signBlock (block , stateUpdate , sign ); err != nil {
619- return err
620- }
621- if err := b .storeBlockData (txn , block , stateUpdate , commitments ); err != nil {
622- return err
623- }
624-
625- err = storeCasmClassHashesV2ForBlock (txn , block .ProtocolVersion , newClasses , stateUpdate )
626- if err != nil {
627- return err
628- }
626+ txn , closer := b .database .NewSnapshotBatch ()
627+ defer closer ()
628+ if err := b .updateStateRoots (txn , block , stateUpdate , newClasses ); err != nil {
629+ return err
630+ }
631+ commitments , err := b .updateBlockHash (block , stateUpdate )
632+ if err != nil {
633+ return err
634+ }
635+ if err := b .signBlock (block , stateUpdate , sign ); err != nil {
636+ return err
637+ }
638+ if err := b .storeBlockData (txn , block , stateUpdate , commitments ); err != nil {
639+ return err
640+ }
629641
630- return core .WriteChainHeight (txn , block .Number )
631- })
642+ err = storeCasmClassHashesV2ForBlock (txn , block .ProtocolVersion , newClasses , stateUpdate )
632643 if err != nil {
633644 return err
634645 }
635646
647+ if err := core .WriteChainHeight (txn , block .Number ); err != nil {
648+ return err
649+ }
650+
651+ if err := txn .Write (); err != nil {
652+ return err
653+ }
654+
636655 return b .runningFilter .Insert (block .EventsBloom , block .Number )
637656}
638657
639658// updateStateRoots computes and updates state roots in the block and state update
640659func (b * Blockchain ) updateStateRoots (
641- txn db.IndexedBatch ,
660+ txn db.SnapshotBatch ,
642661 block * core.Block ,
643662 stateUpdate * core.StateUpdate ,
644663 newClasses map [felt.Felt ]core.ClassDefinition ,
@@ -707,7 +726,7 @@ func (b *Blockchain) signBlock(
707726
708727// storeBlockData persists all block-related data to the database
709728func (b * Blockchain ) storeBlockData (
710- txn db.IndexedBatch ,
729+ txn db.SnapshotBatch ,
711730 block * core.Block ,
712731 stateUpdate * core.StateUpdate ,
713732 commitments * core.BlockCommitments ,
0 commit comments