@@ -6,8 +6,10 @@ import (
66
77 "github.com/NethermindEth/juno/core"
88 "github.com/NethermindEth/juno/core/felt"
9+ "github.com/NethermindEth/juno/core/state"
10+ "github.com/NethermindEth/juno/core/state/statefactory"
11+ "github.com/NethermindEth/juno/core/trie2/triedb"
912 "github.com/NethermindEth/juno/db"
10- "github.com/NethermindEth/juno/db/memory"
1113 "github.com/NethermindEth/juno/feed"
1214 "github.com/NethermindEth/juno/utils"
1315 "github.com/ethereum/go-ethereum/common"
@@ -19,6 +21,7 @@ type L1HeadSubscription struct {
1921
2022//go:generate mockgen -destination=../mocks/mock_blockchain.go -package=mocks github.com/NethermindEth/juno/blockchain Reader
2123type Reader interface {
24+ StateProvider
2225 Height () (height uint64 , err error )
2326
2427 Head () (head * core.Block , err error )
@@ -51,10 +54,6 @@ type Reader interface {
5154 StateUpdateByHash (hash * felt.Felt ) (update * core.StateUpdate , err error )
5255 L1HandlerTxnHash (msgHash * common.Hash ) (l1HandlerTxnHash felt.Felt , err error )
5356
54- HeadState () (core.StateReader , StateCloser , error )
55- StateAtBlockHash (blockHash * felt.Felt ) (core.StateReader , StateCloser , error )
56- StateAtBlockNumber (blockNumber uint64 ) (core.StateReader , StateCloser , error )
57-
5857 BlockCommitmentsByNumber (blockNumber uint64 ) (* core.BlockCommitments , error )
5958
6059 EventFilter (
@@ -66,6 +65,12 @@ type Reader interface {
6665 Network () * utils.Network
6766}
6867
68+ type StateProvider interface {
69+ HeadState () (core.StateReader , StateCloser , error )
70+ StateAtBlockHash (blockHash * felt.Felt ) (core.StateReader , StateCloser , error )
71+ StateAtBlockNumber (blockNumber uint64 ) (core.StateReader , StateCloser , error )
72+ }
73+
6974var ErrParentDoesNotMatchHead = errors .New ("block's parent hash does not match head block hash" )
7075
7176var _ Reader = (* Blockchain )(nil )
@@ -74,14 +79,24 @@ var _ Reader = (*Blockchain)(nil)
7479type Blockchain struct {
7580 network * utils.Network
7681 database db.KeyValueStore
82+ stateDB * state.StateDB
7783 listener EventListener
7884 l1HeadFeed * feed.Feed [* core.L1Head ]
7985 cachedFilters * AggregatedBloomFilterCache
8086 runningFilter * core.RunningEventFilter
8187 transactionLayout core.TransactionLayout
88+ StateFactory * statefactory.StateFactory
8289}
8390
84- func New (database db.KeyValueStore , network * utils.Network ) * Blockchain {
91+ func New (database db.KeyValueStore , network * utils.Network , stateVersion bool ) * Blockchain {
92+ trieDB , err := triedb .New (database , nil ) // TODO: handle hashdb and pathdb
93+ if err != nil {
94+ panic (err )
95+ }
96+ stateDB := state .NewStateDB (database , trieDB )
97+
98+ stateFactory := statefactory .NewStateFactory (stateVersion , trieDB , stateDB )
99+
85100 cachedFilters := NewAggregatedBloomCache (AggregatedBloomFilterCacheSize )
86101 fallback := func (key EventFiltersCacheKey ) (core.AggregatedBloomFilter , error ) {
87102 return core .GetAggregatedBloomFilter (database , key .fromBlock , key .toBlock )
@@ -92,12 +107,14 @@ func New(database db.KeyValueStore, network *utils.Network) *Blockchain {
92107
93108 return & Blockchain {
94109 database : database ,
110+ stateDB : stateDB ,
95111 network : network ,
96112 listener : & SelectiveListener {},
97113 l1HeadFeed : feed .New [* core.L1Head ](),
98114 cachedFilters : & cachedFilters ,
99115 runningFilter : runningFilter ,
100116 transactionLayout : core .TransactionLayoutPerTx , // default to per-tx for backward compatibility
117+ StateFactory : stateFactory ,
101118 }
102119}
103120
@@ -295,8 +312,7 @@ func (b *Blockchain) SubscribeL1Head() L1HeadSubscription {
295312
296313func (b * Blockchain ) L1Head () (core.L1Head , error ) {
297314 b .listener .OnRead ("L1Head" )
298- l1Head , err := core .GetL1Head (b .database )
299- return l1Head , err
315+ return core .GetL1Head (b .database )
300316}
301317
302318func (b * Blockchain ) SetL1Head (update * core.L1Head ) error {
@@ -310,6 +326,21 @@ func (b *Blockchain) Store(
310326 blockCommitments * core.BlockCommitments ,
311327 stateUpdate * core.StateUpdate ,
312328 newClasses map [felt.Felt ]core.ClassDefinition ,
329+ ) error {
330+ // old state
331+ // TODO(maksymmalick): remove this once we have a new state implementation
332+ if ! b .StateFactory .UseNewState () {
333+ return b .deprecatedStore (block , blockCommitments , stateUpdate , newClasses )
334+ }
335+
336+ return b .store (block , blockCommitments , stateUpdate , newClasses )
337+ }
338+
339+ func (b * Blockchain ) deprecatedStore (
340+ block * core.Block ,
341+ blockCommitments * core.BlockCommitments ,
342+ stateUpdate * core.StateUpdate ,
343+ newClasses map [felt.Felt ]core.ClassDefinition ,
313344) error {
314345 err := b .database .Update (func (txn db.IndexedBatch ) error {
315346 if err := verifyBlock (txn , block ); err != nil {
@@ -348,6 +379,7 @@ func (b *Blockchain) Store(
348379 }
349380
350381 err = storeCasmHashMetadata (
382+ b .database ,
351383 txn ,
352384 block .Number ,
353385 block .ProtocolVersion ,
@@ -432,7 +464,8 @@ func (b *Blockchain) store(
432464// storeCasmHashMetadata stores CASM hash metadata for declared and migrated classes.
433465// See [core.ClassCasmHashMetadata]
434466func storeCasmHashMetadata (
435- txn db.IndexedBatch ,
467+ reader db.KeyValueReader ,
468+ writer db.KeyValueWriter ,
436469 blockNumber uint64 ,
437470 protocolVersion string ,
438471 stateUpdate * core.StateUpdate ,
@@ -446,16 +479,17 @@ func storeCasmHashMetadata(
446479 isV2Protocol := ver .GreaterThanEqual (core .Ver0_14_1 )
447480
448481 if isV2Protocol {
449- return storeCasmHashMetadataV2 (txn , blockNumber , stateUpdate )
482+ return storeCasmHashMetadataV2 (reader , writer , blockNumber , stateUpdate )
450483 }
451484
452- return storeCasmHashMetadataV1 (txn , blockNumber , stateUpdate , newClasses )
485+ return storeCasmHashMetadataV1 (writer , blockNumber , stateUpdate , newClasses )
453486}
454487
455488// storeCasmHashMetadataV2 stores metadata for classes declared with casm hash v2 or
456489// migrated from v1. casm hash v2 is after protocol version >= 0.14.1.
457490func storeCasmHashMetadataV2 (
458- txn db.IndexedBatch ,
491+ reader db.KeyValueReader ,
492+ writer db.KeyValueWriter ,
459493 blockNumber uint64 ,
460494 stateUpdate * core.StateUpdate ,
461495) error {
@@ -465,7 +499,7 @@ func storeCasmHashMetadataV2(
465499 (* felt .CasmClassHash )(casmHash ),
466500 )
467501 err := core .WriteClassCasmHashMetadata (
468- txn ,
502+ writer ,
469503 (* felt .SierraClassHash )(& sierraClassHash ),
470504 & metadata ,
471505 )
@@ -475,7 +509,7 @@ func storeCasmHashMetadataV2(
475509 }
476510
477511 for sierraClassHash := range stateUpdate .StateDiff .MigratedClasses {
478- metadata , err := core .GetClassCasmHashMetadata (txn , & sierraClassHash )
512+ metadata , err := core .GetClassCasmHashMetadata (reader , & sierraClassHash )
479513 if err != nil {
480514 return fmt .Errorf ("cannot migrate class %s: metadata not found" ,
481515 sierraClassHash .String (),
@@ -490,7 +524,7 @@ func storeCasmHashMetadataV2(
490524 )
491525 }
492526
493- err = core .WriteClassCasmHashMetadata (txn , & sierraClassHash , & metadata )
527+ err = core .WriteClassCasmHashMetadata (writer , & sierraClassHash , & metadata )
494528 if err != nil {
495529 return err
496530 }
@@ -501,7 +535,7 @@ func storeCasmHashMetadataV2(
501535// storeDeclaredV1Classes stores metadata for classes declared with V1 hash (protocol < 0.14.1).
502536// It computes the V2 hash from the class definition.
503537func storeCasmHashMetadataV1 (
504- txn db.IndexedBatch ,
538+ writer db.KeyValueWriter ,
505539 blockNumber uint64 ,
506540 stateUpdate * core.StateUpdate ,
507541 newClasses map [felt.Felt ]core.ClassDefinition ,
@@ -530,7 +564,7 @@ func storeCasmHashMetadataV1(
530564
531565 metadata := core .NewCasmHashMetadataDeclaredV1 (blockNumber , casmHashV1 , & casmHashV2 )
532566 err := core .WriteClassCasmHashMetadata (
533- txn ,
567+ writer ,
534568 (* felt .SierraClassHash )(& sierraClassHash ),
535569 & metadata ,
536570 )
@@ -604,7 +638,7 @@ func (b *Blockchain) HeadState() (core.CommonStateReader, StateCloser, error) {
604638 b .listener .OnRead ("HeadState" )
605639 txn := b .database .NewIndexedBatch ()
606640
607- _ , err := core .GetChainHeight (txn )
641+ height , err := core .GetChainHeight (txn )
608642 if err != nil {
609643 return nil , nil , err
610644 }
@@ -633,7 +667,25 @@ func (b *Blockchain) StateAtBlockNumber(
633667 return nil , nil , err
634668 }
635669
636- return core .NewDeprecatedStateHistory (core .NewState (txn ), blockNumber ), noopStateCloser , nil
670+ if ! b .StateFactory .UseNewState () {
671+ return core .NewDeprecatedStateHistory (core .NewState (txn ), blockNumber ), noopStateCloser , nil
672+ }
673+
674+ height , err := core .GetChainHeight (txn )
675+ if err != nil {
676+ return nil , nil , err
677+ }
678+
679+ header , err := core .GetBlockHeaderByNumber (txn , height )
680+ if err != nil {
681+ return nil , nil , err
682+ }
683+
684+ history , err := state .NewStateHistory (blockNumber , header .GlobalStateRoot , b .stateDB )
685+ if err != nil {
686+ return nil , nil , err
687+ }
688+ return & history , noopStateCloser , nil
637689}
638690
639691// StateAtBlockHash returns a StateReader that provides
@@ -643,19 +695,34 @@ func (b *Blockchain) StateAtBlockHash(
643695) (core.StateReader , StateCloser , error ) {
644696 b .listener .OnRead ("StateAtBlockHash" )
645697 if blockHash .IsZero () {
646- memDB := memory .New ()
647- txn := memDB .NewIndexedBatch ()
648- emptyState := core .NewState (txn )
649- return emptyState , noopStateCloser , nil
698+ emptyState , err := b .StateFactory .EmptyState ()
699+ return emptyState , noopStateCloser , err
650700 }
651701
652702 txn := b .database .NewIndexedBatch ()
653703 header , err := core .GetBlockHeaderByHash (txn , blockHash )
654704 if err != nil {
655705 return nil , nil , err
656706 }
707+ if ! b .StateFactory .UseNewState () {
708+ return core .NewDeprecatedStateHistory (core .NewState (txn ), header .Number ), noopStateCloser , nil
709+ }
710+
711+ height , err := core .GetChainHeight (txn )
712+ if err != nil {
713+ return nil , nil , err
714+ }
657715
658- return core .NewDeprecatedStateHistory (core .NewState (txn ), header .Number ), noopStateCloser , nil
716+ headHeader , err := core .GetBlockHeaderByNumber (txn , height )
717+ if err != nil {
718+ return nil , nil , err
719+ }
720+
721+ history , err := state .NewStateHistory (header .Number , headHeader .GlobalStateRoot , b .stateDB )
722+ if err != nil {
723+ return nil , nil , err
724+ }
725+ return & history , noopStateCloser , nil
659726}
660727
661728// EventFilter returns an EventFilter object that is tied to a snapshot of the blockchain
@@ -685,10 +752,22 @@ func (b *Blockchain) EventFilter(
685752
686753// RevertHead reverts the head block
687754func (b * Blockchain ) RevertHead () error {
688- return b .database .Update (b .revertHead )
755+ if ! b .StateFactory .UseNewState () {
756+ return b .database .Update (b .deprecatedRevertHead )
757+ }
758+ return b .database .Write (b .revertHead )
689759}
690760
691761func (b * Blockchain ) GetReverseStateDiff () (core.StateDiff , error ) {
762+ if ! b .StateFactory .UseNewState () {
763+ return b .deprecatedGetReverseStateDiff ()
764+ }
765+
766+ return b .getReverseStateDiff ()
767+ }
768+
769+ // TODO(maksymmalick): remove this once we have a new state integrated
770+ func (b * Blockchain ) deprecatedGetReverseStateDiff () (core.StateDiff , error ) {
692771 txn := b .database .NewIndexedBatch ()
693772 blockNum , err := core .GetChainHeight (txn )
694773 if err != nil {
@@ -753,7 +832,7 @@ func (b *Blockchain) revertHead(txn db.IndexedBatch) error {
753832 }
754833 }
755834
756- if err := b .transactionLayout .DeleteTxsAndReceipts (txn , blockNumber ); err != nil {
835+ if err := b .transactionLayout .DeleteTxsAndReceipts (b . database , txn , blockNumber ); err != nil {
757836 return err
758837 }
759838
@@ -979,6 +1058,7 @@ func (b *Blockchain) updateStateRoots(
9791058 block * core .Block ,
9801059 stateUpdate * core .StateUpdate ,
9811060 newClasses map [felt.Felt ]core.ClassDefinition ,
1061+ flushChanges bool ,
9821062) error {
9831063 var height uint64
9841064 var err error
@@ -1011,7 +1091,7 @@ func (b *Blockchain) updateStateRoots(
10111091 stateUpdate .OldRoot = & oldStateRoot
10121092
10131093 // Apply state update
1014- if err = state .Update (block .Number , stateUpdate , newClasses , true ); err != nil {
1094+ if err = state .Update (block .Number , stateUpdate , newClasses , true , flushChanges ); err != nil {
10151095 return err
10161096 }
10171097
@@ -1065,7 +1145,7 @@ func (b *Blockchain) signBlock(
10651145
10661146// storeBlockData persists all block-related data to the database
10671147func (b * Blockchain ) storeBlockData (
1068- txn db .IndexedBatch ,
1148+ txn db .KeyValueWriter ,
10691149 block * core .Block ,
10701150 stateUpdate * core .StateUpdate ,
10711151 commitments * core .BlockCommitments ,
0 commit comments