diff --git a/ibc/store/provable_store_test.go b/ibc/store/provable_store_test.go index f5739e359..10fdaf3c0 100644 --- a/ibc/store/provable_store_test.go +++ b/ibc/store/provable_store_test.go @@ -465,7 +465,7 @@ func newTreeStoreMock(t *testing.T, ctrl := gomock.NewController(t) treeStoreMock := mockModules.NewMockTreeStoreModule(ctrl) - treeStoreMock.EXPECT().GetModuleName().Return(modules.TreeStoreModuleName).AnyTimes() + treeStoreMock.EXPECT().GetModuleName().Return(modules.TreeStoreSubmoduleName).AnyTimes() treeStoreMock.EXPECT().SetBus(gomock.Any()).Return().AnyTimes() treeStoreMock.EXPECT().GetBus().Return(bus).AnyTimes() diff --git a/persistence/module.go b/persistence/module.go index dec15112b..0d6acd17f 100644 --- a/persistence/module.go +++ b/persistence/module.go @@ -41,10 +41,6 @@ type persistenceModule struct { // IMPORTANT: It doubles as the data store for the transaction tree in state tree set. txIndexer indexer.TxIndexer - // stateTrees manages all of the merkle trees maintained by the - // persistence module that roll up into the state commitment. - stateTrees modules.TreeStoreModule - // Only one write context is allowed at a time writeContext *PostgresContext @@ -103,21 +99,22 @@ func (*persistenceModule) Create(bus modules.Bus, options ...modules.ModuleOptio return nil, err } - treeModule, err := trees.Create( + _, err = trees.Create( bus, trees.WithTreeStoreDirectory(persistenceCfg.TreesStoreDir), trees.WithLogger(m.logger)) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to create TreeStoreModule: %w", err) } m.config = persistenceCfg m.genesisState = genesisState m.networkId = runtimeMgr.GetConfig().NetworkId + // TECHDEBT: fetch blockstore from bus once it's a proper submodule m.blockStore = blockStore + // TECHDEBT: fetch txIndexer from bus m.txIndexer = txIndexer - m.stateTrees = treeModule // TECHDEBT: reconsider if this is the best place to call `populateGenesisState`. Note that // this forces the genesis state to be reloaded on every node startup until state @@ -180,7 +177,7 @@ func (m *persistenceModule) NewRWContext(height int64) (modules.PersistenceRWCon stateHash: "", blockStore: m.blockStore, txIndexer: m.txIndexer, - stateTrees: m.stateTrees, + stateTrees: m.GetBus().GetTreeStore(), networkId: m.networkId, } @@ -212,7 +209,7 @@ func (m *persistenceModule) NewReadContext(height int64) (modules.PersistenceRea stateHash: "", blockStore: m.blockStore, txIndexer: m.txIndexer, - stateTrees: m.stateTrees, + stateTrees: m.GetBus().GetTreeStore(), networkId: m.networkId, }, nil } @@ -238,10 +235,6 @@ func (m *persistenceModule) GetTxIndexer() indexer.TxIndexer { return m.txIndexer } -func (m *persistenceModule) GetTreeStore() modules.TreeStoreModule { - return m.stateTrees -} - func (m *persistenceModule) GetNetworkID() string { return m.networkId } diff --git a/persistence/sql/sql.go b/persistence/sql/sql.go index 80a1c8320..9e99189bb 100644 --- a/persistence/sql/sql.go +++ b/persistence/sql/sql.go @@ -6,7 +6,6 @@ import ( "fmt" "github.com/jackc/pgx/v5" - "github.com/pokt-network/pocket/persistence/indexer" ptypes "github.com/pokt-network/pocket/persistence/types" coreTypes "github.com/pokt-network/pocket/shared/core/types" ) @@ -91,16 +90,6 @@ func GetAccountsUpdated( return accounts, nil } -// GetTransactions takes a transaction indexer and returns the transactions for the current height -func GetTransactions(txi indexer.TxIndexer, height uint64) ([]*coreTypes.IndexedTransaction, error) { - // TECHDEBT(#813): Avoid this cast to int64 - indexedTxs, err := txi.GetByHeight(int64(height), false) - if err != nil { - return nil, fmt.Errorf("failed to get transactions by height: %w", err) - } - return indexedTxs, nil -} - // GetPools returns the pools updated at the given height func GetPools(pgtx pgx.Tx, height uint64) ([]*coreTypes.Account, error) { pools, err := GetAccountsUpdated(pgtx, ptypes.Pool, height) diff --git a/persistence/trees/module.go b/persistence/trees/module.go index 942ab0423..7da8bf20f 100644 --- a/persistence/trees/module.go +++ b/persistence/trees/module.go @@ -8,6 +8,8 @@ import ( "github.com/pokt-network/smt" ) +var _ modules.TreeStoreModule = &treeStore{} + func (*treeStore) Create(bus modules.Bus, options ...modules.TreeStoreOption) (modules.TreeStoreModule, error) { m := &treeStore{} @@ -41,12 +43,15 @@ func WithLogger(logger *modules.Logger) modules.TreeStoreOption { // saves its data. func WithTreeStoreDirectory(path string) modules.TreeStoreOption { return func(m modules.TreeStoreModule) { - if mod, ok := m.(*treeStore); ok { + mod, ok := m.(*treeStore) + if ok { mod.treeStoreDir = path } } } +func (t *treeStore) GetModuleName() string { return modules.TreeStoreSubmoduleName } + func (t *treeStore) setupTrees() error { if t.treeStoreDir == ":memory:" { return t.setupInMemory() diff --git a/persistence/trees/module_test.go b/persistence/trees/module_test.go new file mode 100644 index 000000000..7c7bc660c --- /dev/null +++ b/persistence/trees/module_test.go @@ -0,0 +1,176 @@ +package trees_test + +import ( + "fmt" + "testing" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/pokt-network/pocket/internal/testutil" + "github.com/pokt-network/pocket/p2p/providers/peerstore_provider" + "github.com/pokt-network/pocket/persistence/trees" + "github.com/pokt-network/pocket/runtime" + "github.com/pokt-network/pocket/runtime/genesis" + "github.com/pokt-network/pocket/runtime/test_artifacts" + coreTypes "github.com/pokt-network/pocket/shared/core/types" + cryptoPocket "github.com/pokt-network/pocket/shared/crypto" + "github.com/pokt-network/pocket/shared/modules" + mockModules "github.com/pokt-network/pocket/shared/modules/mocks" +) + +const ( + serviceURLFormat = "node%d.consensus:42069" +) + +func TestTreeStore_Create(t *testing.T) { + ctrl := gomock.NewController(t) + mockRuntimeMgr := mockModules.NewMockRuntimeMgr(ctrl) + mockBus := createMockBus(t, mockRuntimeMgr) + genesisStateMock := createMockGenesisState(nil) + persistenceMock := preparePersistenceMock(t, mockBus, genesisStateMock) + + mockBus.EXPECT(). + GetPersistenceModule(). + Return(persistenceMock). + AnyTimes() + persistenceMock.EXPECT(). + GetBus(). + AnyTimes(). + Return(mockBus) + persistenceMock.EXPECT(). + NewRWContext(int64(0)). + AnyTimes() + persistenceMock.EXPECT(). + GetTxIndexer(). + AnyTimes() + + treemod, err := trees.Create(mockBus, trees.WithTreeStoreDirectory(":memory:")) + assert.NoError(t, err) + + got := treemod.GetBus() + assert.Equal(t, got, mockBus) + + // root hash should be empty for empty tree + root, ns := treemod.GetTree(trees.TransactionsTreeName) + require.Equal(t, root, make([]byte, 32)) + + // nodestore should have no values in it + keys, vals, err := ns.GetAll(nil, false) + require.NoError(t, err) + require.Empty(t, keys, vals) +} + +func TestTreeStore_DebugClearAll(t *testing.T) { + // TODO: Write test case for the DebugClearAll method + t.Skip("TODO: Write test case for DebugClearAll method") +} + +// createMockGenesisState configures and returns a mocked GenesisState +func createMockGenesisState(valKeys []cryptoPocket.PrivateKey) *genesis.GenesisState { + genesisState := new(genesis.GenesisState) + validators := make([]*coreTypes.Actor, len(valKeys)) + for i, valKey := range valKeys { + addr := valKey.Address().String() + mockActor := &coreTypes.Actor{ + ActorType: coreTypes.ActorType_ACTOR_TYPE_VAL, + Address: addr, + PublicKey: valKey.PublicKey().String(), + ServiceUrl: validatorId(i + 1), + StakedAmount: test_artifacts.DefaultStakeAmountString, + PausedHeight: int64(0), + UnstakingHeight: int64(0), + Output: addr, + } + validators[i] = mockActor + } + genesisState.Validators = validators + + return genesisState +} + +// Persistence mock - only needed for validatorMap access +func preparePersistenceMock(t *testing.T, busMock *mockModules.MockBus, genesisState *genesis.GenesisState) *mockModules.MockPersistenceModule { + ctrl := gomock.NewController(t) + + persistenceModuleMock := mockModules.NewMockPersistenceModule(ctrl) + readCtxMock := mockModules.NewMockPersistenceReadContext(ctrl) + + readCtxMock.EXPECT(). + GetAllValidators(gomock.Any()). + Return(genesisState.GetValidators(), nil).AnyTimes() + readCtxMock.EXPECT(). + GetAllStakedActors(gomock.Any()). + DoAndReturn(func(height int64) ([]*coreTypes.Actor, error) { + return testutil.Concatenate[*coreTypes.Actor]( + genesisState.GetValidators(), + genesisState.GetServicers(), + genesisState.GetFishermen(), + genesisState.GetApplications(), + ), nil + }). + AnyTimes() + persistenceModuleMock.EXPECT(). + NewReadContext(gomock.Any()). + Return(readCtxMock, nil). + AnyTimes() + readCtxMock.EXPECT(). + Release(). + AnyTimes() + persistenceModuleMock.EXPECT(). + GetBus(). + Return(busMock). + AnyTimes() + persistenceModuleMock.EXPECT(). + SetBus(busMock). + AnyTimes() + persistenceModuleMock.EXPECT(). + GetModuleName(). + Return(modules.PersistenceModuleName). + AnyTimes() + busMock. + RegisterModule(persistenceModuleMock) + + return persistenceModuleMock +} + +func validatorId(i int) string { + return fmt.Sprintf(serviceURLFormat, i) +} + +// createMockBus returns a mock bus with stubbed out functions for bus registration +func createMockBus(t *testing.T, runtimeMgr modules.RuntimeMgr) *mockModules.MockBus { + t.Helper() + ctrl := gomock.NewController(t) + mockBus := mockModules.NewMockBus(ctrl) + mockModulesRegistry := mockModules.NewMockModulesRegistry(ctrl) + + mockBus.EXPECT(). + GetRuntimeMgr(). + Return(runtimeMgr). + AnyTimes() + mockBus.EXPECT(). + RegisterModule(gomock.Any()). + DoAndReturn(func(m modules.Submodule) { + m.SetBus(mockBus) + }). + AnyTimes() + mockModulesRegistry.EXPECT(). + GetModule(peerstore_provider.PeerstoreProviderSubmoduleName). + Return(nil, runtime.ErrModuleNotRegistered(peerstore_provider.PeerstoreProviderSubmoduleName)). + AnyTimes() + mockModulesRegistry.EXPECT(). + GetModule(modules.CurrentHeightProviderSubmoduleName). + Return(nil, runtime.ErrModuleNotRegistered(modules.CurrentHeightProviderSubmoduleName)). + AnyTimes() + mockBus.EXPECT(). + GetModulesRegistry(). + Return(mockModulesRegistry). + AnyTimes() + mockBus.EXPECT(). + PublishEventToBus(gomock.Any()). + AnyTimes() + + return mockBus +} diff --git a/persistence/trees/trees.go b/persistence/trees/trees.go index 627b11229..0ec61b79e 100644 --- a/persistence/trees/trees.go +++ b/persistence/trees/trees.go @@ -74,23 +74,25 @@ type stateTree struct { var _ modules.TreeStoreModule = &treeStore{} -// treeStore stores a set of merkle trees that -// it manages. It fulfills the modules.TreeStore interface. -// * It is responsible for atomic commit or rollback behavior -// of the underlying trees by utilizing the lazy loading -// functionality provided by the underlying smt library. +// treeStore stores a set of merkle trees that it manages. +// It fulfills the modules.treeStore interface +// * It is responsible for atomic commit or rollback behavior of the underlying +// trees by utilizing the lazy loading functionality of the smt library. +// TECHDEBT(#880): treeStore is exported for testing purposes to avoid import cycle errors. +// Make it private and export a custom struct with a test build tag when necessary. type treeStore struct { base_modules.IntegrableModule - logger *modules.Logger + logger *modules.Logger + treeStoreDir string rootTree *stateTree merkleTrees map[string]*stateTree } -// GetTree returns the name, root hash, and nodeStore for the matching tree tree -// stored in the TreeStore. This enables the caller to import the smt and not -// change the one stored +// GetTree returns the root hash and nodeStore for the matching tree stored in the TreeStore. +// This enables the caller to import the SMT without changing the one stored unless they call +// `Commit()` to write to the nodestore. func (t *treeStore) GetTree(name string) ([]byte, kvstore.KVStore) { if name == RootTreeName { return t.rootTree.tree.Root(), t.rootTree.nodeStore @@ -114,9 +116,13 @@ func (t *treeStore) GetTreeHashes() map[string]string { // Update takes a transaction and a height and updates // all of the trees in the treeStore for that height. func (t *treeStore) Update(pgtx pgx.Tx, height uint64) (string, error) { - txi := t.GetBus().GetPersistenceModule().GetTxIndexer() t.logger.Info().Msgf("🌴 updating state trees at height %d", height) - return t.updateMerkleTrees(pgtx, txi, height) + txi := t.GetBus().GetPersistenceModule().GetTxIndexer() + stateHash, err := t.updateMerkleTrees(pgtx, txi, height) + if err != nil { + return "", fmt.Errorf("failed to update merkle trees: %w", err) + } + return stateHash, nil } // DebugClearAll is used by the debug cli to completely reset all merkle trees. @@ -137,13 +143,10 @@ func (t *treeStore) DebugClearAll() error { return nil } -// GetModuleName implements the respective `TreeStoreModule` interface method. -func (t *treeStore) GetModuleName() string { - return modules.TreeStoreModuleName -} - // updateMerkleTrees updates all of the merkle trees in order defined by `numMerkleTrees` -// * it returns the new state hash capturing the state of all the trees or an error if one occurred +// * It returns the new state hash capturing the state of all the trees or an error if one occurred. +// * This function does not commit state to disk. The caller must manually invoke `Commit` to persist +// changes to disk. func (t *treeStore) updateMerkleTrees(pgtx pgx.Tx, txi indexer.TxIndexer, height uint64) (string, error) { for treeName := range t.merkleTrees { switch treeName { @@ -183,7 +186,7 @@ func (t *treeStore) updateMerkleTrees(pgtx pgx.Tx, txi indexer.TxIndexer, height // Data Merkle Trees case TransactionsTreeName: - indexedTxs, err := sql.GetTransactions(txi, height) + indexedTxs, err := getTransactions(txi, height) if err != nil { return "", fmt.Errorf("failed to get transactions: %w", err) } @@ -220,24 +223,34 @@ func (t *treeStore) updateMerkleTrees(pgtx pgx.Tx, txi indexer.TxIndexer, height } } - if err := t.commit(); err != nil { + if err := t.Commit(); err != nil { return "", fmt.Errorf("failed to commit: %w", err) } return t.getStateHash(), nil } -func (t *treeStore) commit() error { - for treeName, stateTree := range t.merkleTrees { - if err := stateTree.tree.Commit(); err != nil { - return fmt.Errorf("failed to commit %s: %w", treeName, err) +// Commit commits changes in the sub-trees to the root tree and then commits updates for each sub-tree. +func (t *treeStore) Commit() error { + if err := t.rootTree.tree.Commit(); err != nil { + t.logger.Err(err).Msg("TECHDEBT: failed to commit root tree: changes to sub-trees will not be committed - this should be investigated") + return fmt.Errorf("failed to commit root tree: %w", err) + } + + for name, treeStore := range t.merkleTrees { + if err := treeStore.tree.Commit(); err != nil { + t.logger.Err(err).Msgf("TECHDEBT: failed to commit to %s tree: changes will not be saved - this should be investigated", name) + return fmt.Errorf("failed to commit %s: %w", name, err) } } + return nil } func (t *treeStore) getStateHash() string { for _, stateTree := range t.merkleTrees { - if err := t.rootTree.tree.Update([]byte(stateTree.name), stateTree.tree.Root()); err != nil { + key := []byte(stateTree.name) + val := stateTree.tree.Root() + if err := t.rootTree.tree.Update(key, val); err != nil { log.Fatalf("failed to update root tree with %s tree's hash: %v", stateTree.name, err) } } @@ -384,3 +397,13 @@ func (t *treeStore) updateIBCTree(keys, values [][]byte) error { } return nil } + +// getTransactions takes a transaction indexer and returns the transactions for the current height +func getTransactions(txi indexer.TxIndexer, height uint64) ([]*coreTypes.IndexedTransaction, error) { + // TECHDEBT(#813): Avoid this cast to int64 + indexedTxs, err := txi.GetByHeight(int64(height), false) + if err != nil { + return nil, fmt.Errorf("failed to get transactions by height: %w", err) + } + return indexedTxs, nil +} diff --git a/runtime/bus.go b/runtime/bus.go index 2b607ac8e..9d7a6e05f 100644 --- a/runtime/bus.go +++ b/runtime/bus.go @@ -71,6 +71,10 @@ func (m *bus) GetPersistenceModule() modules.PersistenceModule { return getModuleFromRegistry[modules.PersistenceModule](m, modules.PersistenceModuleName) } +func (m *bus) GetTreeStoreModule() modules.TreeStoreModule { + return getModuleFromRegistry[modules.TreeStoreModule](m, modules.TreeStoreSubmoduleName) +} + func (m *bus) GetP2PModule() modules.P2PModule { return getModuleFromRegistry[modules.P2PModule](m, modules.P2PModuleName) } @@ -124,7 +128,7 @@ func (m *bus) GetIBCModule() modules.IBCModule { } func (m *bus) GetTreeStore() modules.TreeStoreModule { - return getModuleFromRegistry[modules.TreeStoreModule](m, modules.TreeStoreModuleName) + return getModuleFromRegistry[modules.TreeStoreModule](m, modules.TreeStoreSubmoduleName) } func (m *bus) GetIBCHost() modules.IBCHostSubmodule { diff --git a/shared/modules/doc/README.md b/shared/modules/doc/README.md index 28a2c249b..201856453 100644 --- a/shared/modules/doc/README.md +++ b/shared/modules/doc/README.md @@ -6,32 +6,34 @@ This document outlines how we structured the code by splitting it into modules, - [tl;dr Just show me an example](#tldr-just-show-me-an-example) - [Definitions](#definitions) - - [Requirement Level Keywords](#requirement-level-keywords) - - [Module](#module) - - [Module mock](#module-mock) - - [Shared module interfaces](#shared-module-interfaces) - - [Base module](#base-module) - - [Submodule](#submodule) - - [Shared submodule](#shared-submodule) - - [Class Diagram Legend](#class-diagram-legend) - - [Module, Submodule \& Shared Interfaces](#module-submodule--shared-interfaces) - - [Factory interfaces](#factory-interfaces) + - [Requirement Level Keywords](#requirement-level-keywords) + - [Module](#module) + - [Module mock](#module-mock) + - [Shared module interfaces](#shared-module-interfaces) + - [Base module](#base-module) + - [Submodule](#submodule) + - [Shared submodule](#shared-submodule) + - [Class Diagram Legend](#class-diagram-legend) + - [Module, Submodule \& Shared Interfaces](#module-submodule--shared-interfaces) + - [Factory interfaces](#factory-interfaces) - [Code Organization](#code-organization) -- [(Sub)Modules in detail](#submodules-in-detail) - [Shared (sub)module interfaces](#shared-submodule-interfaces) - [Construction parameters \& non-(sub)module dependencies](#construction-parameters--non-submodule-dependencies) - - [Module creation](#module-creation) - - [Module configs \& options](#module-configs--options) - - [Submodule creation](#submodule-creation) - - [Submodule configs \& options](#submodule-configs--options) - - [Configs](#configs) - - [Options](#options) - - [Comprehensive Submodule Example:](#comprehensive-submodule-example) - - [Interacting \& Registering with the `bus`](#interacting--registering-with-the-bus) - - [Modules Registry](#modules-registry) - - [Modules Registry Example](#modules-registry-example) - - [Start the module](#start-the-module) - - [Add a logger to the module](#add-a-logger-to-the-module) - - [Get the module `bus`](#get-the-module-bus) - - [Stop the module](#stop-the-module) +- [(Sub)Modules in detail](#submodules-in-detail) + - [Shared (sub)module interfaces](#shared-submodule-interfaces) + - [Construction parameters \& non-(sub)module dependencies](#construction-parameters--non-submodule-dependencies) + - [Module creation](#module-creation) + - [Module configs \& options](#module-configs--options) + - [Submodule creation](#submodule-creation) + - [Submodule configs \& options](#submodule-configs--options) + - [Configs](#configs) + - [Options](#options) + - [Comprehensive Submodule Example:](#comprehensive-submodule-example) + - [Interacting \& Registering with the `bus`](#interacting--registering-with-the-bus) + - [Modules Registry](#modules-registry) + - [Modules Registry Example](#modules-registry-example) + - [Start the module](#start-the-module) + - [Add a logger to the module](#add-a-logger-to-the-module) + - [Get the module `bus`](#get-the-module-bus) + - [Stop the module](#stop-the-module) ## tl;dr Just show me an example @@ -420,8 +422,8 @@ What the `bus` does is setting its reference to the module instance and delegati ```golang func (m *bus) RegisterModule(module modules.Module) { - module.SetBus(m) - m.modulesRegistry.RegisterModule(module) + module.SetBus(m) + m.modulesRegistry.RegisterModule(module) } ``` @@ -432,7 +434,40 @@ This is quite **important** because it unlocks a powerful concept **Dependency I This enables the developer to define different implementations of a module and to register the one that is needed at runtime. This is because we can only have one module registered with a unique name and also because, by convention, we keep module names defined as constants. This is useful not only for prototyping but also for different use cases such as the `p1` CLI and the `pocket` binary where different implementations of the same module are necessary due to the fact that the `p1` CLI doesn't have a persistence module but still needs to know what's going on in the network. -Submodules can be registered the same way full Modules can be, by passing the Submodule to the RegisterModule function. Submodules should typically be registered to the bus for dependency injection reasons. +**Registration**: Submodules can be registered the same way full Modules by passing the Submodule to the `RegisterModule` function. Submodules should typically be registered to the bus for dependency injection reasons. Registration should occur _after_ processing the module's options. + +```go +func (*treeStore) Create(bus modules.Bus, options ...modules.TreeStoreOption) (modules.TreeStoreModule, error) { + m := &treeStore{} + + for _, option := range options { + option(m) + } + + bus.RegisterModule(m) + // ... +} +``` + +**IMPORTANT**: Modules and Submodules are all responsible for registering themselves with the Bus. This pattern emerged organically during development and is now considered best practice. + +**Module Access**: Full Modules should not maintain pointer references to other full Modules. Instead, they should call the Bus to get a new module reference whenever needed. + +Submodule interfaces are typically defined in the `shared/modules` package with the rest of the module interfaces in a file named `XXX_submodule.go`, where XXX denotes the name of the Submodule. That same file SHOULD contain the factory function definition for a Submodule where the `Submodule` interface type MUST be embedded. Factory function definitions SHOULD NOT be exported. + +For example, in the TreeStore code below, the `treeStoreFactory` is defined and then embedded in the `TreeStoreModule`, which also embeds the Submodule interface. Typically these factory functions should be kept private at the package level. + +```go +type treeStoreFactory = FactoryWithOptions[TreeStoreModule, TreeStoreOption] + +// TreeStoreModules defines the interface for atomic updates and rollbacks to the internal +// merkle trees that compose the state hash of pocket. +type TreeStoreModule interface { + Submodule + treeStoreFactory + // ... +} +``` ##### Modules Registry Example diff --git a/shared/modules/persistence_module.go b/shared/modules/persistence_module.go index c9c5519d6..b510d835b 100644 --- a/shared/modules/persistence_module.go +++ b/shared/modules/persistence_module.go @@ -35,9 +35,6 @@ type PersistenceModule interface { GetTxIndexer() indexer.TxIndexer TransactionExists(transactionHash string) (bool, error) - // TreeStore operations - GetTreeStore() TreeStoreModule - // Debugging / development only HandleDebugMessage(*messaging.DebugMessage) error diff --git a/shared/modules/treestore_module.go b/shared/modules/treestore_module.go index 661a3104b..117026f05 100644 --- a/shared/modules/treestore_module.go +++ b/shared/modules/treestore_module.go @@ -8,17 +8,18 @@ import ( //go:generate mockgen -destination=./mocks/treestore_module_mock.go github.com/pokt-network/pocket/shared/modules TreeStoreModule const ( - TreeStoreModuleName = "tree_store" + TreeStoreSubmoduleName = "tree_store" ) type TreeStoreOption func(TreeStoreModule) -type TreeStoreFactory = FactoryWithOptions[TreeStoreModule, TreeStoreOption] +type treeStoreFactory = FactoryWithOptions[TreeStoreModule, TreeStoreOption] // TreeStoreModules defines the interface for atomic updates and rollbacks to the internal // merkle trees that compose the state hash of pocket. type TreeStoreModule interface { Submodule + treeStoreFactory // Update returns the new state hash for a given height. // * Height is passed through to the Update function and is used to query the TxIndexer for transactions