diff --git a/config/config.go b/config/config.go index f9f84d197d2..d023a4fd522 100644 --- a/config/config.go +++ b/config/config.go @@ -308,13 +308,14 @@ type FacadeConfig struct { // StateTriesConfig will hold information about state tries type StateTriesConfig struct { - SnapshotsEnabled bool - AccountsStatePruningEnabled bool - PeerStatePruningEnabled bool - CollectStateChangesEnabled bool - MaxStateTrieLevelInMemory uint - MaxPeerTrieLevelInMemory uint - StateStatisticsEnabled bool + SnapshotsEnabled bool + AccountsStatePruningEnabled bool + PeerStatePruningEnabled bool + CollectStateChangesEnabled bool + CollectStateChangesWithReadEnabled bool + MaxStateTrieLevelInMemory uint + MaxPeerTrieLevelInMemory uint + StateStatisticsEnabled bool } // TrieStorageManagerConfig will hold config information about trie storage manager diff --git a/epochStart/bootstrap/disabled/disabledAccountsAdapter.go b/epochStart/bootstrap/disabled/disabledAccountsAdapter.go index be951395f8c..56c50ea8daf 100644 --- a/epochStart/bootstrap/disabled/disabledAccountsAdapter.go +++ b/epochStart/bootstrap/disabled/disabledAccountsAdapter.go @@ -3,6 +3,7 @@ package disabled import ( "context" + "github.com/multiversx/mx-chain-core-go/data/transaction" "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/state" vmcommon "github.com/multiversx/mx-chain-vm-common-go" @@ -129,12 +130,7 @@ func (a *accountsAdapter) GetStackDebugFirstEntry() []byte { } // SetTxHashForLatestStateChanges - -func (a *accountsAdapter) SetTxHashForLatestStateChanges(_ []byte) { -} - -// ResetStateChangesCollector - -func (a *accountsAdapter) ResetStateChangesCollector() []state.StateChangesForTx { - return nil +func (a *accountsAdapter) SetTxHashForLatestStateChanges(_ []byte, _ *transaction.Transaction) { } // Close - diff --git a/epochStart/metachain/baseRewards_test.go b/epochStart/metachain/baseRewards_test.go index 50aeb42e7ad..87ccb625643 100644 --- a/epochStart/metachain/baseRewards_test.go +++ b/epochStart/metachain/baseRewards_test.go @@ -20,6 +20,7 @@ import ( "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/sharding" "github.com/multiversx/mx-chain-go/state/factory" + "github.com/multiversx/mx-chain-go/state/stateChanges" "github.com/multiversx/mx-chain-go/testscommon" txExecOrderStub "github.com/multiversx/mx-chain-go/testscommon/common" dataRetrieverMock "github.com/multiversx/mx-chain-go/testscommon/dataRetriever" @@ -1177,9 +1178,10 @@ func getBaseRewardsArguments() BaseRewardsCreatorArgs { trieFactoryManager, _ := trie.CreateTrieStorageManager(storageManagerArgs, storage.GetStorageManagerOptions()) argsAccCreator := factory.ArgsAccountCreator{ - Hasher: hasher, - Marshaller: marshalizer, - EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + Hasher: hasher, + Marshaller: marshalizer, + EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + StateChangesCollector: stateChanges.NewStateChangesCollector(), } accCreator, _ := factory.NewAccountCreator(argsAccCreator) enableEpochsHandler := &enableEpochsHandlerMock.EnableEpochsHandlerStub{} diff --git a/epochStart/metachain/systemSCs_test.go b/epochStart/metachain/systemSCs_test.go index fd907b5b868..8d410aeb017 100644 --- a/epochStart/metachain/systemSCs_test.go +++ b/epochStart/metachain/systemSCs_test.go @@ -779,9 +779,10 @@ func createFullArgumentsForSystemSCProcessing(enableEpochsConfig config.EnableEp trieFactoryManager, _ := trie.CreateTrieStorageManager(storageManagerArgs, storageMock.GetStorageManagerOptions()) argsAccCreator := factory.ArgsAccountCreator{ - Hasher: hasher, - Marshaller: marshalizer, - EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + Hasher: hasher, + Marshaller: marshalizer, + EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + StateChangesCollector: disabledState.NewDisabledStateChangesCollector(), } accCreator, _ := factory.NewAccountCreator(argsAccCreator) peerAccCreator := factory.NewPeerAccountCreator() diff --git a/factory/api/apiResolverFactory.go b/factory/api/apiResolverFactory.go index dca46b8a171..05a3bc64e18 100644 --- a/factory/api/apiResolverFactory.go +++ b/factory/api/apiResolverFactory.go @@ -548,9 +548,10 @@ func createShardVmContainerFactory(args scQueryElementArgs, argsHook hooks.ArgBl func createNewAccountsAdapterApi(args scQueryElementArgs, chainHandler data.ChainHandler) (state.AccountsAdapterAPI, common.StorageManager, error) { argsAccCreator := factoryState.ArgsAccountCreator{ - Hasher: args.coreComponents.Hasher(), - Marshaller: args.coreComponents.InternalMarshalizer(), - EnableEpochsHandler: args.coreComponents.EnableEpochsHandler(), + Hasher: args.coreComponents.Hasher(), + Marshaller: args.coreComponents.InternalMarshalizer(), + EnableEpochsHandler: args.coreComponents.EnableEpochsHandler(), + StateChangesCollector: args.stateComponents.StateChangesCollector(), } accountFactory, err := factoryState.NewAccountCreator(argsAccCreator) if err != nil { diff --git a/factory/api/apiResolverFactory_test.go b/factory/api/apiResolverFactory_test.go index 6f0d1026304..57659db37c1 100644 --- a/factory/api/apiResolverFactory_test.go +++ b/factory/api/apiResolverFactory_test.go @@ -19,6 +19,7 @@ import ( "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/process/sync/disabled" "github.com/multiversx/mx-chain-go/state" + stateDisabled "github.com/multiversx/mx-chain-go/state/disabled" "github.com/multiversx/mx-chain-go/testscommon" componentsMock "github.com/multiversx/mx-chain-go/testscommon/components" "github.com/multiversx/mx-chain-go/testscommon/dataRetriever" @@ -344,6 +345,9 @@ func createMockSCQueryElementArgs() api.SCQueryElementArgs { PeerAccountsCalled: func() state.AccountsAdapter { return &stateMocks.AccountsStub{} }, + StateChangesCollectorCalled: func() state.StateChangesCollector { + return stateDisabled.NewDisabledStateChangesCollector() + }, }, StatusCoreComponents: &factory.StatusCoreComponentsStub{ AppStatusHandlerCalled: func() core.AppStatusHandler { diff --git a/factory/interface.go b/factory/interface.go index ec92f478992..0b2a6594a02 100644 --- a/factory/interface.go +++ b/factory/interface.go @@ -336,6 +336,7 @@ type StateComponentsHolder interface { TriesContainer() common.TriesHolder TrieStorageManagers() map[string]common.StorageManager MissingTrieNodesNotifier() common.MissingTrieNodesNotifier + StateChangesCollector() state.StateChangesCollector Close() error IsInterfaceNil() bool } diff --git a/factory/mock/stateComponentsHolderStub.go b/factory/mock/stateComponentsHolderStub.go index c851fdc6dac..1775ad915f0 100644 --- a/factory/mock/stateComponentsHolderStub.go +++ b/factory/mock/stateComponentsHolderStub.go @@ -14,6 +14,7 @@ type StateComponentsHolderStub struct { TriesContainerCalled func() common.TriesHolder TrieStorageManagersCalled func() map[string]common.StorageManager MissingTrieNodesNotifierCalled func() common.MissingTrieNodesNotifier + StateChangesCollectorCalled func() state.StateChangesCollector } // PeerAccounts - @@ -79,6 +80,15 @@ func (s *StateComponentsHolderStub) MissingTrieNodesNotifier() common.MissingTri return nil } +// StateChangesCollector - +func (s *StateComponentsHolderStub) StateChangesCollector() state.StateChangesCollector { + if s.StateChangesCollectorCalled != nil { + return s.StateChangesCollectorCalled() + } + + return nil +} + // Close - func (s *StateComponentsHolderStub) Close() error { return nil diff --git a/factory/processing/blockProcessorCreator.go b/factory/processing/blockProcessorCreator.go index c48a777f01c..9dca0dd515a 100644 --- a/factory/processing/blockProcessorCreator.go +++ b/factory/processing/blockProcessorCreator.go @@ -6,6 +6,10 @@ import ( "github.com/multiversx/mx-chain-core-go/core" dataBlock "github.com/multiversx/mx-chain-core-go/data/block" + logger "github.com/multiversx/mx-chain-logger-go" + vmcommon "github.com/multiversx/mx-chain-vm-common-go" + "github.com/multiversx/mx-chain-vm-common-go/parsers" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/config" "github.com/multiversx/mx-chain-go/dataRetriever" @@ -43,9 +47,6 @@ import ( "github.com/multiversx/mx-chain-go/state/syncer" "github.com/multiversx/mx-chain-go/storage/txcache" "github.com/multiversx/mx-chain-go/vm" - logger "github.com/multiversx/mx-chain-logger-go" - vmcommon "github.com/multiversx/mx-chain-vm-common-go" - "github.com/multiversx/mx-chain-vm-common-go/parsers" ) type blockProcessorAndVmFactories struct { @@ -454,6 +455,7 @@ func (pcf *processComponentsFactory) newShardBlockProcessor( BlockProcessingCutoffHandler: blockProcessingCutoffHandler, ManagedPeersHolder: pcf.crypto.ManagedPeersHolder(), SentSignaturesTracker: sentSignaturesTracker, + StateChangesCollector: pcf.state.StateChangesCollector(), } arguments := block.ArgShardProcessor{ ArgBaseProcessor: argumentsBaseProcessor, @@ -898,6 +900,7 @@ func (pcf *processComponentsFactory) newMetaBlockProcessor( BlockProcessingCutoffHandler: blockProcessingCutoffhandler, ManagedPeersHolder: pcf.crypto.ManagedPeersHolder(), SentSignaturesTracker: sentSignaturesTracker, + StateChangesCollector: pcf.state.StateChangesCollector(), } esdtOwnerAddress, err := pcf.coreData.AddressPubKeyConverter().Decode(pcf.systemSCConfig.ESDTSystemSCConfig.OwnerAddress) @@ -1057,6 +1060,7 @@ func (pcf *processComponentsFactory) createOutportDataProvider( MbsStorer: mbsStorer, EnableEpochsHandler: pcf.coreData.EnableEpochsHandler(), ExecutionOrderGetter: pcf.txExecutionOrderHandler, + StateChangesCollector: pcf.state.StateChangesCollector(), }) } diff --git a/factory/processing/blockProcessorCreator_test.go b/factory/processing/blockProcessorCreator_test.go index 0dcdc7128e2..cc8ef9f8ddf 100644 --- a/factory/processing/blockProcessorCreator_test.go +++ b/factory/processing/blockProcessorCreator_test.go @@ -17,6 +17,7 @@ import ( "github.com/multiversx/mx-chain-go/state/accounts" disabledState "github.com/multiversx/mx-chain-go/state/disabled" factoryState "github.com/multiversx/mx-chain-go/state/factory" + "github.com/multiversx/mx-chain-go/state/stateChanges" "github.com/multiversx/mx-chain-go/state/storagePruningManager/disabled" "github.com/multiversx/mx-chain-go/testscommon" componentsMock "github.com/multiversx/mx-chain-go/testscommon/components" @@ -103,9 +104,10 @@ func Test_newBlockProcessorCreatorForMeta(t *testing.T) { trieStorageManagers[dataRetriever.PeerAccountsUnit.String()] = storageManagerPeer argsAccCreator := factoryState.ArgsAccountCreator{ - Hasher: coreComponents.Hasher(), - Marshaller: coreComponents.InternalMarshalizer(), - EnableEpochsHandler: coreComponents.EnableEpochsHandler(), + Hasher: coreComponents.Hasher(), + Marshaller: coreComponents.InternalMarshalizer(), + EnableEpochsHandler: coreComponents.EnableEpochsHandler(), + StateChangesCollector: stateChanges.NewStateChangesCollector(), } accCreator, _ := factoryState.NewAccountCreator(argsAccCreator) diff --git a/factory/processing/processComponents.go b/factory/processing/processComponents.go index 6f711a502ae..76c849abc6e 100644 --- a/factory/processing/processComponents.go +++ b/factory/processing/processComponents.go @@ -1687,7 +1687,7 @@ func (pcf *processComponentsFactory) newShardInterceptorContainerFactory( shardInterceptorsContainerFactoryArgs := interceptorscontainer.CommonInterceptorsContainerFactoryArgs{ CoreComponents: pcf.coreData, CryptoComponents: pcf.crypto, - Accounts: pcf.state.AccountsAdapter(), + Accounts: pcf.state.AccountsAdapterAPI(), ShardCoordinator: pcf.bootstrapComponents.ShardCoordinator(), NodesCoordinator: pcf.nodesCoordinator, MainMessenger: pcf.network.NetworkMessenger(), @@ -1748,7 +1748,7 @@ func (pcf *processComponentsFactory) newMetaInterceptorContainerFactory( FullArchiveMessenger: pcf.network.FullArchiveNetworkMessenger(), Store: pcf.data.StorageService(), DataPool: pcf.data.Datapool(), - Accounts: pcf.state.AccountsAdapter(), + Accounts: pcf.state.AccountsAdapterAPI(), MaxTxNonceDeltaAllowed: common.MaxTxNonceDeltaAllowed, TxFeeHandler: pcf.coreData.EconomicsData(), BlockBlackList: headerBlackList, diff --git a/factory/state/stateComponents.go b/factory/state/stateComponents.go index 33ca9488dd2..dce52d14547 100644 --- a/factory/state/stateComponents.go +++ b/factory/state/stateComponents.go @@ -2,6 +2,7 @@ package state import ( "fmt" + "github.com/multiversx/mx-chain-core-go/core/check" chainData "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-go/common" @@ -14,10 +15,12 @@ import ( factoryState "github.com/multiversx/mx-chain-go/state/factory" "github.com/multiversx/mx-chain-go/state/iteratorChannelsProvider" "github.com/multiversx/mx-chain-go/state/lastSnapshotMarker" + "github.com/multiversx/mx-chain-go/state/stateChanges" "github.com/multiversx/mx-chain-go/state/stateMetrics" "github.com/multiversx/mx-chain-go/state/storagePruningManager" "github.com/multiversx/mx-chain-go/state/storagePruningManager/evictionWaitingList" "github.com/multiversx/mx-chain-go/state/syncer" + storageFactory "github.com/multiversx/mx-chain-go/storage/factory" trieFactory "github.com/multiversx/mx-chain-go/trie/factory" ) @@ -53,6 +56,7 @@ type stateComponents struct { triesContainer common.TriesHolder trieStorageManagers map[string]common.StorageManager missingTrieNodesNotifier common.MissingTrieNodesNotifier + stateChangesCollector state.StateChangesCollector } // NewStateComponentsFactory will return a new instance of stateComponentsFactory @@ -90,7 +94,12 @@ func (scf *stateComponentsFactory) Create() (*stateComponents, error) { return nil, err } - accountsAdapter, accountsAdapterAPI, accountsRepository, err := scf.createAccountsAdapters(triesContainer) + stateChangesCollector, err := scf.createStateChangesCollector() + if err != nil { + return nil, err + } + + accountsAdapter, accountsAdapterAPI, accountsRepository, err := scf.createAccountsAdapters(triesContainer, stateChangesCollector) if err != nil { return nil, err } @@ -108,9 +117,41 @@ func (scf *stateComponentsFactory) Create() (*stateComponents, error) { triesContainer: triesContainer, trieStorageManagers: trieStorageManagers, missingTrieNodesNotifier: syncer.NewMissingTrieNodesNotifier(), + stateChangesCollector: stateChangesCollector, }, nil } +func (scf *stateComponentsFactory) createStateChangesCollector() (state.StateChangesCollector, error) { + if !scf.config.StateTriesConfig.CollectStateChangesEnabled { + return disabled.NewDisabledStateChangesCollector(), nil + } + + if !scf.config.StateTriesConfig.CollectStateChangesWithReadEnabled { + return stateChanges.NewStateChangesCollector(), nil + } + + // TODO: move to toml config file + dbConfig := config.DBConfig{ + FilePath: "stateChanges", + Type: "LvlDBSerial", + BatchDelaySeconds: 2, + MaxBatchSize: 100, + MaxOpenFiles: 10, + } + + persisterFactory, err := storageFactory.NewPersisterFactory(dbConfig) + if err != nil { + return nil, err + } + + db, err := persisterFactory.CreateWithRetries(dbConfig.FilePath) + if err != nil { + return nil, fmt.Errorf("%w while creating the db for the trie nodes", err) + } + + return stateChanges.NewDataAnalysisStateChangesCollector(db) +} + func (scf *stateComponentsFactory) createSnapshotManager( accountFactory state.AccountFactory, stateMetrics state.StateMetrics, @@ -135,11 +176,12 @@ func (scf *stateComponentsFactory) createSnapshotManager( return state.NewSnapshotsManager(argsSnapshotsManager) } -func (scf *stateComponentsFactory) createAccountsAdapters(triesContainer common.TriesHolder) (state.AccountsAdapter, state.AccountsAdapter, state.AccountsRepository, error) { +func (scf *stateComponentsFactory) createAccountsAdapters(triesContainer common.TriesHolder, stateChangesCollector state.StateChangesCollector) (state.AccountsAdapter, state.AccountsAdapter, state.AccountsRepository, error) { argsAccCreator := factoryState.ArgsAccountCreator{ - Hasher: scf.core.Hasher(), - Marshaller: scf.core.InternalMarshalizer(), - EnableEpochsHandler: scf.core.EnableEpochsHandler(), + Hasher: scf.core.Hasher(), + Marshaller: scf.core.InternalMarshalizer(), + EnableEpochsHandler: scf.core.EnableEpochsHandler(), + StateChangesCollector: stateChangesCollector, } accountFactory, err := factoryState.NewAccountCreator(argsAccCreator) if err != nil { @@ -152,11 +194,6 @@ func (scf *stateComponentsFactory) createAccountsAdapters(triesContainer common. return nil, nil, nil, err } - stateChangesCollector := disabled.NewDisabledStateChangesCollector() - if scf.config.StateTriesConfig.CollectStateChangesEnabled { - stateChangesCollector = state.NewStateChangesCollector() - } - argStateMetrics := stateMetrics.ArgsStateMetrics{ SnapshotInProgressKey: common.MetricAccountsSnapshotInProgress, LastSnapshotDurationKey: common.MetricLastAccountsSnapshotDurationSec, @@ -173,14 +210,14 @@ func (scf *stateComponentsFactory) createAccountsAdapters(triesContainer common. } argsProcessingAccountsDB := state.ArgsAccountsDB{ - Trie: merkleTrie, - Hasher: scf.core.Hasher(), - Marshaller: scf.core.InternalMarshalizer(), - AccountFactory: accountFactory, - StoragePruningManager: storagePruning, - AddressConverter: scf.core.AddressPubKeyConverter(), - SnapshotsManager: snapshotsManager, - StateChangesCollector: stateChangesCollector, + Trie: merkleTrie, + Hasher: scf.core.Hasher(), + Marshaller: scf.core.InternalMarshalizer(), + AccountFactory: accountFactory, + StoragePruningManager: storagePruning, + AddressConverter: scf.core.AddressPubKeyConverter(), + SnapshotsManager: snapshotsManager, + StateChangesCollector: stateChangesCollector, } accountsAdapter, err := state.NewAccountsDB(argsProcessingAccountsDB) if err != nil { @@ -235,11 +272,6 @@ func (scf *stateComponentsFactory) createPeerAdapter(triesContainer common.Tries return nil, err } - stateChangesCollector := disabled.NewDisabledStateChangesCollector() - if scf.config.StateTriesConfig.CollectStateChangesEnabled { - stateChangesCollector = state.NewStateChangesCollector() - } - argStateMetrics := stateMetrics.ArgsStateMetrics{ SnapshotInProgressKey: common.MetricPeersSnapshotInProgress, LastSnapshotDurationKey: common.MetricLastPeersSnapshotDurationSec, @@ -255,15 +287,20 @@ func (scf *stateComponentsFactory) createPeerAdapter(triesContainer common.Tries return nil, err } + stateChangesCollector, err := scf.createStateChangesCollector() + if err != nil { + return nil, err + } + argsProcessingPeerAccountsDB := state.ArgsAccountsDB{ - Trie: merkleTrie, - Hasher: scf.core.Hasher(), - Marshaller: scf.core.InternalMarshalizer(), - AccountFactory: accountFactory, - StoragePruningManager: storagePruning, - AddressConverter: scf.core.AddressPubKeyConverter(), - SnapshotsManager: snapshotManager, - StateChangesCollector: stateChangesCollector, + Trie: merkleTrie, + Hasher: scf.core.Hasher(), + Marshaller: scf.core.InternalMarshalizer(), + AccountFactory: accountFactory, + StoragePruningManager: storagePruning, + AddressConverter: scf.core.AddressPubKeyConverter(), + SnapshotsManager: snapshotManager, + StateChangesCollector: stateChangesCollector, } peerAdapter, err := state.NewPeerAccountsDB(argsProcessingPeerAccountsDB) if err != nil { diff --git a/factory/state/stateComponentsHandler.go b/factory/state/stateComponentsHandler.go index 78271a28ffe..b9ba0250d7d 100644 --- a/factory/state/stateComponentsHandler.go +++ b/factory/state/stateComponentsHandler.go @@ -214,6 +214,17 @@ func (msc *managedStateComponents) MissingTrieNodesNotifier() common.MissingTrie return msc.stateComponents.missingTrieNodesNotifier } +func (msc *managedStateComponents) StateChangesCollector() state.StateChangesCollector { + msc.mutStateComponents.RLock() + defer msc.mutStateComponents.RUnlock() + + if msc.stateComponents == nil { + return nil + } + + return msc.stateComponents.stateChangesCollector +} + // IsInterfaceNil returns true if the interface is nil func (msc *managedStateComponents) IsInterfaceNil() bool { return msc == nil diff --git a/factory/status/statusComponents.go b/factory/status/statusComponents.go index b8c5cf29163..73ecb5e2777 100644 --- a/factory/status/statusComponents.go +++ b/factory/status/statusComponents.go @@ -9,6 +9,8 @@ import ( outportCore "github.com/multiversx/mx-chain-core-go/data/outport" factoryMarshalizer "github.com/multiversx/mx-chain-core-go/marshal/factory" indexerFactory "github.com/multiversx/mx-chain-es-indexer-go/process/factory" + logger "github.com/multiversx/mx-chain-logger-go" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/common/statistics" swVersionFactory "github.com/multiversx/mx-chain-go/common/statistics/softwareVersion/factory" @@ -23,7 +25,6 @@ import ( "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/sharding" "github.com/multiversx/mx-chain-go/sharding/nodesCoordinator" - logger "github.com/multiversx/mx-chain-logger-go" ) type statusComponents struct { diff --git a/genesis/mock/userAccountMock.go b/genesis/mock/userAccountMock.go index 10362edba89..28ef9e7c966 100644 --- a/genesis/mock/userAccountMock.go +++ b/genesis/mock/userAccountMock.go @@ -6,8 +6,9 @@ import ( "math/big" "github.com/multiversx/mx-chain-core-go/core" + "github.com/multiversx/mx-chain-core-go/data/stateChange" + "github.com/multiversx/mx-chain-go/common" - "github.com/multiversx/mx-chain-go/state" ) // ErrNegativeValue - @@ -148,7 +149,7 @@ func (uam *UserAccountMock) GetUserName() []byte { } // SaveDirtyData - -func (uam *UserAccountMock) SaveDirtyData(_ common.Trie) ([]state.DataTrieChange, []core.TrieData, error) { +func (uam *UserAccountMock) SaveDirtyData(_ common.Trie) ([]*stateChange.DataTrieChange, []core.TrieData, error) { return nil, nil, nil } diff --git a/genesis/process/genesisBlockCreator.go b/genesis/process/genesisBlockCreator.go index 3f5e559888f..b59c9b26462 100644 --- a/genesis/process/genesisBlockCreator.go +++ b/genesis/process/genesisBlockCreator.go @@ -24,6 +24,7 @@ import ( "github.com/multiversx/mx-chain-go/process/smartContract/hooks" "github.com/multiversx/mx-chain-go/process/smartContract/hooks/counters" "github.com/multiversx/mx-chain-go/sharding" + disabledState "github.com/multiversx/mx-chain-go/state/disabled" factoryState "github.com/multiversx/mx-chain-go/state/factory" "github.com/multiversx/mx-chain-go/state/syncer" "github.com/multiversx/mx-chain-go/statusHandler" @@ -493,9 +494,10 @@ func (gbc *genesisBlockCreator) getNewArgForShard(shardID uint32) (ArgsGenesisBl } argsAccCreator := factoryState.ArgsAccountCreator{ - Hasher: newArgument.Core.Hasher(), - Marshaller: newArgument.Core.InternalMarshalizer(), - EnableEpochsHandler: newArgument.Core.EnableEpochsHandler(), + Hasher: newArgument.Core.Hasher(), + Marshaller: newArgument.Core.InternalMarshalizer(), + EnableEpochsHandler: newArgument.Core.EnableEpochsHandler(), + StateChangesCollector: disabledState.NewDisabledStateChangesCollector(), } accCreator, err := factoryState.NewAccountCreator(argsAccCreator) if err != nil { diff --git a/genesis/process/genesisBlockCreator_test.go b/genesis/process/genesisBlockCreator_test.go index a681a0e271c..13ca44fc785 100644 --- a/genesis/process/genesisBlockCreator_test.go +++ b/genesis/process/genesisBlockCreator_test.go @@ -200,9 +200,10 @@ func createMockArgument( } argsAccCreator := factoryState.ArgsAccountCreator{ - Hasher: &hashingMocks.HasherMock{}, - Marshaller: &mock.MarshalizerMock{}, - EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + Hasher: &hashingMocks.HasherMock{}, + Marshaller: &mock.MarshalizerMock{}, + EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + StateChangesCollector: &stateMock.StateChangesCollectorStub{}, } accCreator, err := factoryState.NewAccountCreator(argsAccCreator) require.Nil(t, err) diff --git a/genesis/process/memoryComponents.go b/genesis/process/memoryComponents.go index 2db8a0bd1ba..23bd7d3850c 100644 --- a/genesis/process/memoryComponents.go +++ b/genesis/process/memoryComponents.go @@ -34,7 +34,7 @@ func createAccountAdapter( StoragePruningManager: disabled.NewDisabledStoragePruningManager(), AddressConverter: addressConverter, SnapshotsManager: disabledState.NewDisabledSnapshotsManager(), - StateChangesCollector: state.NewStateChangesCollector(), + StateChangesCollector: disabledState.NewDisabledStateChangesCollector(), } adb, err := state.NewAccountsDB(args) diff --git a/go.mod b/go.mod index 49f55d1e0b4..d879c1cf45b 100644 --- a/go.mod +++ b/go.mod @@ -15,12 +15,12 @@ require ( github.com/klauspost/cpuid/v2 v2.2.5 github.com/mitchellh/mapstructure v1.5.0 github.com/multiversx/mx-chain-communication-go v1.1.0 - github.com/multiversx/mx-chain-core-go v1.2.21 + github.com/multiversx/mx-chain-core-go v1.2.23-0.20240918093335-b9e28fbed67c github.com/multiversx/mx-chain-crypto-go v1.2.12 github.com/multiversx/mx-chain-es-indexer-go v1.7.5-0.20240807095116-4f2f595e52d9 github.com/multiversx/mx-chain-logger-go v1.0.15 github.com/multiversx/mx-chain-scenario-go v1.4.4 - github.com/multiversx/mx-chain-storage-go v1.0.16 + github.com/multiversx/mx-chain-storage-go v1.0.17-0.20240909105906-39ad1daf2a4c github.com/multiversx/mx-chain-vm-common-go v1.5.14-0.20240812082318-afa839968da3 github.com/multiversx/mx-chain-vm-go v1.5.32-0.20240812082514-1f3c25b3171e github.com/multiversx/mx-chain-vm-v1_2-go v1.2.68 diff --git a/go.sum b/go.sum index 00b1197adc8..3a6a35eb248 100644 --- a/go.sum +++ b/go.sum @@ -387,8 +387,8 @@ github.com/multiversx/concurrent-map v0.1.4 h1:hdnbM8VE4b0KYJaGY5yJS2aNIW9TFFsUY github.com/multiversx/concurrent-map v0.1.4/go.mod h1:8cWFRJDOrWHOTNSqgYCUvwT7c7eFQ4U2vKMOp4A/9+o= github.com/multiversx/mx-chain-communication-go v1.1.0 h1:J7bX6HoN3HiHY7cUeEjG8AJWgQDDPcY+OPDOsSUOkRE= github.com/multiversx/mx-chain-communication-go v1.1.0/go.mod h1:WK6bP4pGEHGDDna/AYRIMtl6G9OA0NByI1Lw8PmOnRM= -github.com/multiversx/mx-chain-core-go v1.2.21 h1:+XVKznPTlUU5EFS1A8chtS8fStW60upRIyF4Pgml19I= -github.com/multiversx/mx-chain-core-go v1.2.21/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE= +github.com/multiversx/mx-chain-core-go v1.2.23-0.20240918093335-b9e28fbed67c h1:wPqkaTaiSnMXXGmnqJNtn+xMZUoJEAw16QgtrlUGSgk= +github.com/multiversx/mx-chain-core-go v1.2.23-0.20240918093335-b9e28fbed67c/go.mod h1:B5zU4MFyJezmEzCsAHE9YNULmGCm2zbPHvl9hazNxmE= github.com/multiversx/mx-chain-crypto-go v1.2.12 h1:zWip7rpUS4CGthJxfKn5MZfMfYPjVjIiCID6uX5BSOk= github.com/multiversx/mx-chain-crypto-go v1.2.12/go.mod h1:HzcPpCm1zanNct/6h2rIh+MFrlXbjA5C8+uMyXj3LI4= github.com/multiversx/mx-chain-es-indexer-go v1.7.5-0.20240807095116-4f2f595e52d9 h1:VJOigTM9JbjFdy9ICVhsDfM9YQkFqMigAaQCHaM0iwY= @@ -397,8 +397,8 @@ github.com/multiversx/mx-chain-logger-go v1.0.15 h1:HlNdK8etyJyL9NQ+6mIXyKPEBo+w github.com/multiversx/mx-chain-logger-go v1.0.15/go.mod h1:t3PRKaWB1M+i6gUfD27KXgzLJJC+mAQiN+FLlL1yoGQ= github.com/multiversx/mx-chain-scenario-go v1.4.4 h1:DVE2V+FPeyD/yWoC+KEfPK3jsFzHeruelESfpTlf460= github.com/multiversx/mx-chain-scenario-go v1.4.4/go.mod h1:kI+TWR3oIEgUkbwkHCPo2CQ3VjIge+ezGTibiSGwMxo= -github.com/multiversx/mx-chain-storage-go v1.0.16 h1:l2lJq+EAN3YwLbjJrnoKfFd1/1Xmo9DcAUECND2obLs= -github.com/multiversx/mx-chain-storage-go v1.0.16/go.mod h1:uM/z7YyqTOD3wgyH8TfapyEl5sb+7x/Jaxne4cfG4HI= +github.com/multiversx/mx-chain-storage-go v1.0.17-0.20240909105906-39ad1daf2a4c h1:1Wmh5iblKtE6S5NBdyPcHcKmiR3C1oF+MNRBVOrmAcc= +github.com/multiversx/mx-chain-storage-go v1.0.17-0.20240909105906-39ad1daf2a4c/go.mod h1:2VWMriwcI0s7kTnKHqJxFQnb0aMswc5KTbHp8MKw3Uk= github.com/multiversx/mx-chain-vm-common-go v1.5.14-0.20240812082318-afa839968da3 h1:RlHKl5enbGrleB0Aea9TinZLLymS4WvG0/xAt/iRb6E= github.com/multiversx/mx-chain-vm-common-go v1.5.14-0.20240812082318-afa839968da3/go.mod h1:OSvFbzdWThfRbLZbUsEr7bikBSaLrPJQ2iUm9jw9nXQ= github.com/multiversx/mx-chain-vm-go v1.5.32-0.20240812082514-1f3c25b3171e h1:BkZtPUAQ9JlATkENydCLxPZ819hjop6laZtmC7Wzqec= diff --git a/integrationTests/state/stateTrie/stateTrie_test.go b/integrationTests/state/stateTrie/stateTrie_test.go index 89525d46daf..7110d09613d 100644 --- a/integrationTests/state/stateTrie/stateTrie_test.go +++ b/integrationTests/state/stateTrie/stateTrie_test.go @@ -1059,9 +1059,10 @@ func createAccounts( tr, _ := trie.NewTrie(trieStorage, integrationTests.TestMarshalizer, integrationTests.TestHasher, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, maxTrieLevelInMemory) spm, _ := storagePruningManager.NewStoragePruningManager(ewl, 10) argsAccCreator := factory.ArgsAccountCreator{ - Hasher: integrationTests.TestHasher, - Marshaller: integrationTests.TestMarshalizer, - EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + Hasher: integrationTests.TestHasher, + Marshaller: integrationTests.TestMarshalizer, + EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + StateChangesCollector: &stateMock.StateChangesCollectorStub{}, } accCreator, _ := factory.NewAccountCreator(argsAccCreator) snapshotsManager, _ := state.NewSnapshotsManager(state.ArgsNewSnapshotsManager{ @@ -1083,7 +1084,7 @@ func createAccounts( StoragePruningManager: spm, AddressConverter: &testscommon.PubkeyConverterMock{}, SnapshotsManager: snapshotsManager, - StateChangesCollector: state.NewStateChangesCollector(), + StateChangesCollector: &stateMock.StateChangesCollectorStub{}, } adb, _ := state.NewAccountsDB(argsAccountsDB) @@ -2732,9 +2733,10 @@ func createAccountsDBTestSetup() *state.AccountsDB { tr, _ := trie.NewTrie(trieStorage, integrationTests.TestMarshalizer, integrationTests.TestHasher, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, maxTrieLevelInMemory) spm, _ := storagePruningManager.NewStoragePruningManager(ewl, 10) argsAccCreator := factory.ArgsAccountCreator{ - Hasher: integrationTests.TestHasher, - Marshaller: integrationTests.TestMarshalizer, - EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + Hasher: integrationTests.TestHasher, + Marshaller: integrationTests.TestMarshalizer, + EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + StateChangesCollector: &stateMock.StateChangesCollectorStub{}, } accCreator, _ := factory.NewAccountCreator(argsAccCreator) @@ -2758,7 +2760,7 @@ func createAccountsDBTestSetup() *state.AccountsDB { StoragePruningManager: spm, AddressConverter: &testscommon.PubkeyConverterMock{}, SnapshotsManager: snapshotsManager, - StateChangesCollector: state.NewStateChangesCollector(), + StateChangesCollector: &stateMock.StateChangesCollectorStub{}, } adb, _ := state.NewAccountsDB(argsAccountsDB) diff --git a/integrationTests/testInitializer.go b/integrationTests/testInitializer.go index 644066487cd..99c578b95e6 100644 --- a/integrationTests/testInitializer.go +++ b/integrationTests/testInitializer.go @@ -49,6 +49,7 @@ import ( "github.com/multiversx/mx-chain-go/sharding/nodesCoordinator" "github.com/multiversx/mx-chain-go/state" "github.com/multiversx/mx-chain-go/state/accounts" + "github.com/multiversx/mx-chain-go/state/disabled" "github.com/multiversx/mx-chain-go/state/factory" "github.com/multiversx/mx-chain-go/state/iteratorChannelsProvider" "github.com/multiversx/mx-chain-go/state/lastSnapshotMarker" @@ -487,7 +488,7 @@ func CreateAccountsDBWithEnableEpochsHandler( StoragePruningManager: spm, AddressConverter: &testscommon.PubkeyConverterMock{}, SnapshotsManager: snapshotsManager, - StateChangesCollector: state.NewStateChangesCollector(), + StateChangesCollector: disabled.NewDisabledStateChangesCollector(), } adb, _ := state.NewAccountsDB(args) @@ -498,9 +499,10 @@ func getAccountFactory(accountType Type, enableEpochsHandler common.EnableEpochs switch accountType { case UserAccount: argsAccCreator := factory.ArgsAccountCreator{ - Hasher: TestHasher, - Marshaller: TestMarshalizer, - EnableEpochsHandler: enableEpochsHandler, + Hasher: TestHasher, + Marshaller: TestMarshalizer, + EnableEpochsHandler: enableEpochsHandler, + StateChangesCollector: disabled.NewDisabledStateChangesCollector(), } return factory.NewAccountCreator(argsAccCreator) case ValidatorAccount: @@ -972,7 +974,7 @@ func GenerateAddressJournalAccountAccountsDB() ([]byte, state.UserAccountHandler adb, _ := CreateAccountsDB(UserAccount, trieStorage) dtlp, _ := parsers.NewDataTrieLeafParser(adr, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}) - dtt, _ := trackableDataTrie.NewTrackableDataTrie(adr, &testscommon.HasherStub{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}) + dtt, _ := trackableDataTrie.NewTrackableDataTrie(adr, &testscommon.HasherStub{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, disabled.NewDisabledStateChangesCollector()) account, _ := accounts.NewUserAccount(adr, dtt, dtlp) diff --git a/integrationTests/testProcessorNode.go b/integrationTests/testProcessorNode.go index cf76e1582d0..bed1bef8177 100644 --- a/integrationTests/testProcessorNode.go +++ b/integrationTests/testProcessorNode.go @@ -2234,6 +2234,7 @@ func (tpn *TestProcessorNode) initBlockProcessor() { BlockProcessingCutoffHandler: &testscommon.BlockProcessingCutoffStub{}, ManagedPeersHolder: &testscommon.ManagedPeersHolderStub{}, SentSignaturesTracker: &testscommon.SentSignatureTrackerStub{}, + StateChangesCollector: &stateMock.StateChangesCollectorStub{}, } if check.IfNil(tpn.EpochStartNotifier) { diff --git a/integrationTests/testSyncNode.go b/integrationTests/testSyncNode.go index b28d5e3f953..80329c3eb6b 100644 --- a/integrationTests/testSyncNode.go +++ b/integrationTests/testSyncNode.go @@ -15,6 +15,7 @@ import ( "github.com/multiversx/mx-chain-go/process/block/bootstrapStorage" "github.com/multiversx/mx-chain-go/process/sync" "github.com/multiversx/mx-chain-go/state" + stateDisabled "github.com/multiversx/mx-chain-go/state/disabled" "github.com/multiversx/mx-chain-go/testscommon" "github.com/multiversx/mx-chain-go/testscommon/dblookupext" "github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock" @@ -105,6 +106,7 @@ func (tpn *TestProcessorNode) initBlockProcessorWithSync() { BlockProcessingCutoffHandler: &testscommon.BlockProcessingCutoffStub{}, ManagedPeersHolder: &testscommon.ManagedPeersHolderStub{}, SentSignaturesTracker: &testscommon.SentSignatureTrackerStub{}, + StateChangesCollector: stateDisabled.NewDisabledStateChangesCollector(), } if tpn.ShardCoordinator.SelfId() == core.MetachainShardId { diff --git a/integrationTests/vm/staking/componentsHolderCreator.go b/integrationTests/vm/staking/componentsHolderCreator.go index 251e7eec511..8be321e03e3 100644 --- a/integrationTests/vm/staking/componentsHolderCreator.go +++ b/integrationTests/vm/staking/componentsHolderCreator.go @@ -158,9 +158,10 @@ func createStateComponents(coreComponents factory.CoreComponentsHolder) factory. trieFactoryManager, _ := trie.NewTrieStorageManagerWithoutPruning(tsm) argsAccCreator := stateFactory.ArgsAccountCreator{ - Hasher: coreComponents.Hasher(), - Marshaller: coreComponents.InternalMarshalizer(), - EnableEpochsHandler: coreComponents.EnableEpochsHandler(), + Hasher: coreComponents.Hasher(), + Marshaller: coreComponents.InternalMarshalizer(), + EnableEpochsHandler: coreComponents.EnableEpochsHandler(), + StateChangesCollector: disabledState.NewDisabledStateChangesCollector(), } accCreator, _ := stateFactory.NewAccountCreator(argsAccCreator) diff --git a/integrationTests/vm/staking/metaBlockProcessorCreator.go b/integrationTests/vm/staking/metaBlockProcessorCreator.go index 759458cf30e..ab96a156e9e 100644 --- a/integrationTests/vm/staking/metaBlockProcessorCreator.go +++ b/integrationTests/vm/staking/metaBlockProcessorCreator.go @@ -22,6 +22,7 @@ import ( "github.com/multiversx/mx-chain-go/sharding" "github.com/multiversx/mx-chain-go/sharding/nodesCoordinator" "github.com/multiversx/mx-chain-go/state" + "github.com/multiversx/mx-chain-go/state/disabled" "github.com/multiversx/mx-chain-go/testscommon" "github.com/multiversx/mx-chain-go/testscommon/dblookupext" factory2 "github.com/multiversx/mx-chain-go/testscommon/factory" @@ -104,6 +105,7 @@ func createMetaBlockProcessor( ManagedPeersHolder: &testscommon.ManagedPeersHolderStub{}, BlockProcessingCutoffHandler: &testscommon.BlockProcessingCutoffStub{}, SentSignaturesTracker: &testscommon.SentSignatureTrackerStub{}, + StateChangesCollector: disabled.NewDisabledStateChangesCollector(), }, SCToProtocol: stakingToPeer, PendingMiniBlocksHandler: &mock.PendingMiniBlocksHandlerStub{}, diff --git a/integrationTests/vm/wasm/wasmvm/mockContracts.go b/integrationTests/vm/wasm/wasmvm/mockContracts.go index 4e1b2b2b2c2..d8eeccdbd25 100644 --- a/integrationTests/vm/wasm/wasmvm/mockContracts.go +++ b/integrationTests/vm/wasm/wasmvm/mockContracts.go @@ -13,6 +13,7 @@ import ( "github.com/multiversx/mx-chain-go/process/factory" "github.com/multiversx/mx-chain-go/state" stateFactory "github.com/multiversx/mx-chain-go/state/factory" + "github.com/multiversx/mx-chain-go/state/stateChanges" "github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock" "github.com/multiversx/mx-chain-go/testscommon/hashingMocks" "github.com/multiversx/mx-chain-go/testscommon/marshallerMock" @@ -106,9 +107,10 @@ func GetAddressForNewAccountOnWalletAndNodeWithVM( address := net.NewAddressWithVM(wallet, vmType) argsAccCreation := stateFactory.ArgsAccountCreator{ - Hasher: &hashingMocks.HasherMock{}, - Marshaller: &marshallerMock.MarshalizerMock{}, - EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + Hasher: &hashingMocks.HasherMock{}, + Marshaller: &marshallerMock.MarshalizerMock{}, + EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + StateChangesCollector: stateChanges.NewStateChangesCollector(), } accountFactory, _ := stateFactory.NewAccountCreator(argsAccCreation) diff --git a/node/chainSimulator/components/stateComponents.go b/node/chainSimulator/components/stateComponents.go index b3fddf55f40..dddac1d31a1 100644 --- a/node/chainSimulator/components/stateComponents.go +++ b/node/chainSimulator/components/stateComponents.go @@ -10,6 +10,7 @@ import ( "github.com/multiversx/mx-chain-go/factory" factoryState "github.com/multiversx/mx-chain-go/factory/state" "github.com/multiversx/mx-chain-go/state" + "github.com/multiversx/mx-chain-go/state/disabled" ) // ArgsStateComponents will hold the components needed for state components @@ -109,6 +110,10 @@ func (s *stateComponentsHolder) MissingTrieNodesNotifier() common.MissingTrieNod return s.missingTrieNodesNotifier } +func (s *stateComponentsHolder) StateChangesCollector() state.StateChangesCollector { + return disabled.NewDisabledStateChangesCollector() +} + // Close will close the state components func (s *stateComponentsHolder) Close() error { return s.stateComponentsCloser.Close() diff --git a/node/node_test.go b/node/node_test.go index b584dc2370b..f82631fba71 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -45,6 +45,7 @@ import ( "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/state" "github.com/multiversx/mx-chain-go/state/accounts" + "github.com/multiversx/mx-chain-go/state/disabled" "github.com/multiversx/mx-chain-go/state/parsers" "github.com/multiversx/mx-chain-go/state/trackableDataTrie" "github.com/multiversx/mx-chain-go/storage" @@ -101,7 +102,7 @@ func createMockPubkeyConverter() *testscommon.PubkeyConverterMock { func createAcc(address []byte) state.UserAccountHandler { dtlp, _ := parsers.NewDataTrieLeafParser(address, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}) - dtt, _ := trackableDataTrie.NewTrackableDataTrie(address, &testscommon.HasherStub{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}) + dtt, _ := trackableDataTrie.NewTrackableDataTrie(address, &testscommon.HasherStub{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, disabled.NewDisabledStateChangesCollector()) acc, _ := accounts.NewUserAccount(address, dtt, dtlp) return acc diff --git a/outport/disabled/disabledOutport.go b/outport/disabled/disabledOutport.go index 97be7894c9b..24a53eaca18 100644 --- a/outport/disabled/disabledOutport.go +++ b/outport/disabled/disabledOutport.go @@ -2,6 +2,7 @@ package disabled import ( outportcore "github.com/multiversx/mx-chain-core-go/data/outport" + "github.com/multiversx/mx-chain-go/outport" ) diff --git a/outport/factory/hostDriverFactory.go b/outport/factory/hostDriverFactory.go index 42dfdeadcf7..efcf6b6c159 100644 --- a/outport/factory/hostDriverFactory.go +++ b/outport/factory/hostDriverFactory.go @@ -4,10 +4,12 @@ import ( "github.com/multiversx/mx-chain-communication-go/websocket/data" "github.com/multiversx/mx-chain-communication-go/websocket/factory" "github.com/multiversx/mx-chain-core-go/marshal" + + logger "github.com/multiversx/mx-chain-logger-go" + "github.com/multiversx/mx-chain-go/config" "github.com/multiversx/mx-chain-go/outport" "github.com/multiversx/mx-chain-go/outport/host" - logger "github.com/multiversx/mx-chain-logger-go" ) type ArgsHostDriverFactory struct { diff --git a/outport/factory/outportFactory.go b/outport/factory/outportFactory.go index e7259bfc69f..a137175053e 100644 --- a/outport/factory/outportFactory.go +++ b/outport/factory/outportFactory.go @@ -6,6 +6,7 @@ import ( outportcore "github.com/multiversx/mx-chain-core-go/data/outport" indexerFactory "github.com/multiversx/mx-chain-es-indexer-go/process/factory" + "github.com/multiversx/mx-chain-go/outport" ) diff --git a/outport/interface.go b/outport/interface.go index 768920a7709..70a3673cd0c 100644 --- a/outport/interface.go +++ b/outport/interface.go @@ -3,6 +3,7 @@ package outport import ( outportcore "github.com/multiversx/mx-chain-core-go/data/outport" "github.com/multiversx/mx-chain-core-go/marshal" + "github.com/multiversx/mx-chain-go/outport/process" ) diff --git a/outport/mock/driverStub.go b/outport/mock/driverStub.go index e142eb9f5aa..144e09a0ab6 100644 --- a/outport/mock/driverStub.go +++ b/outport/mock/driverStub.go @@ -3,6 +3,7 @@ package mock import ( outportcore "github.com/multiversx/mx-chain-core-go/data/outport" "github.com/multiversx/mx-chain-core-go/marshal" + "github.com/multiversx/mx-chain-go/testscommon/marshallerMock" ) diff --git a/outport/process/factory/outportDataProviderFactory.go b/outport/process/factory/outportDataProviderFactory.go index 5bb2c698136..18941caf279 100644 --- a/outport/process/factory/outportDataProviderFactory.go +++ b/outport/process/factory/outportDataProviderFactory.go @@ -4,6 +4,8 @@ import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/marshal" + vmcommon "github.com/multiversx/mx-chain-vm-common-go" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/outport" "github.com/multiversx/mx-chain-go/outport/process" @@ -16,7 +18,6 @@ import ( "github.com/multiversx/mx-chain-go/sharding/nodesCoordinator" "github.com/multiversx/mx-chain-go/state" "github.com/multiversx/mx-chain-go/storage" - vmcommon "github.com/multiversx/mx-chain-vm-common-go" ) // ArgOutportDataProviderFactory holds the arguments needed for creating a new instance of outport.DataProviderOutport @@ -37,6 +38,7 @@ type ArgOutportDataProviderFactory struct { MbsStorer storage.Storer EnableEpochsHandler common.EnableEpochsHandler ExecutionOrderGetter common.ExecutionOrderGetter + StateChangesCollector state.StateChangesCollector } // CreateOutportDataProvider will create a new instance of outport.DataProviderOutport @@ -85,5 +87,6 @@ func CreateOutportDataProvider(arg ArgOutportDataProviderFactory) (outport.DataP ExecutionOrderHandler: arg.ExecutionOrderGetter, Hasher: arg.Hasher, Marshaller: arg.Marshaller, + StateChangesCollector: arg.StateChangesCollector, }) } diff --git a/outport/process/outportDataProvider.go b/outport/process/outportDataProvider.go index aec1f15df8b..0528dd6b06d 100644 --- a/outport/process/outportDataProvider.go +++ b/outport/process/outportDataProvider.go @@ -16,12 +16,14 @@ import ( "github.com/multiversx/mx-chain-core-go/data/transaction" "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/marshal" + logger "github.com/multiversx/mx-chain-logger-go" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/outport/process/alteredaccounts/shared" "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/sharding" "github.com/multiversx/mx-chain-go/sharding/nodesCoordinator" - logger "github.com/multiversx/mx-chain-logger-go" + "github.com/multiversx/mx-chain-go/state" ) var log = logger.GetOrCreate("outport/process/outportDataProvider") @@ -39,6 +41,7 @@ type ArgOutportDataProvider struct { Marshaller marshal.Marshalizer Hasher hashing.Hasher ExecutionOrderHandler common.ExecutionOrderGetter + StateChangesCollector state.StateChangesCollector } // ArgPrepareOutportSaveBlockData holds the arguments needed for prepare outport save block data @@ -67,6 +70,7 @@ type outportDataProvider struct { executionOrderHandler common.ExecutionOrderGetter marshaller marshal.Marshalizer hasher hashing.Hasher + stateChangesCollector state.StateChangesCollector } // NewOutportDataProvider will create a new instance of outportDataProvider @@ -83,6 +87,7 @@ func NewOutportDataProvider(arg ArgOutportDataProvider) (*outportDataProvider, e executionOrderHandler: arg.ExecutionOrderHandler, marshaller: arg.Marshaller, hasher: arg.Hasher, + stateChangesCollector: arg.StateChangesCollector, }, nil } @@ -134,6 +139,8 @@ func (odp *outportDataProvider) PrepareOutportSaveBlockData(arg ArgPrepareOutpor return nil, err } + stateChanges := odp.stateChangesCollector.GetStateChangesForTxs() + return &outportcore.OutportBlockWithHeaderAndBody{ OutportBlock: &outportcore.OutportBlock{ ShardID: odp.shardID, @@ -145,6 +152,7 @@ func (odp *outportDataProvider) PrepareOutportSaveBlockData(arg ArgPrepareOutpor GasPenalized: odp.gasConsumedProvider.TotalGasPenalized(), MaxGasPerBlock: odp.economicsData.MaxGasLimitPerBlock(odp.shardID), }, + StateChanges: stateChanges, AlteredAccounts: alteredAccounts, NotarizedHeadersHashes: arg.NotarizedHeadersHashes, NumberOfShards: odp.numOfShards, diff --git a/outport/process/outportDataProvider_test.go b/outport/process/outportDataProvider_test.go index ef1422d230a..43c2fc6b57b 100644 --- a/outport/process/outportDataProvider_test.go +++ b/outport/process/outportDataProvider_test.go @@ -12,6 +12,8 @@ import ( "github.com/multiversx/mx-chain-core-go/data/rewardTx" "github.com/multiversx/mx-chain-core-go/data/smartContractResult" "github.com/multiversx/mx-chain-core-go/data/transaction" + "github.com/stretchr/testify/require" + "github.com/multiversx/mx-chain-go/outport/mock" "github.com/multiversx/mx-chain-go/outport/process/transactionsfee" "github.com/multiversx/mx-chain-go/testscommon" @@ -21,7 +23,7 @@ import ( "github.com/multiversx/mx-chain-go/testscommon/hashingMocks" "github.com/multiversx/mx-chain-go/testscommon/marshallerMock" "github.com/multiversx/mx-chain-go/testscommon/shardingMocks" - "github.com/stretchr/testify/require" + "github.com/multiversx/mx-chain-go/testscommon/state" ) func createArgOutportDataProvider() ArgOutportDataProvider { @@ -45,6 +47,7 @@ func createArgOutportDataProvider() ArgOutportDataProvider { ExecutionOrderHandler: &commonMocks.TxExecutionOrderHandlerStub{}, Marshaller: &marshallerMock.MarshalizerMock{}, Hasher: &hashingMocks.HasherMock{}, + StateChangesCollector: &state.StateChangesCollectorStub{}, } } diff --git a/p2p/disabled/networkMessenger.go b/p2p/disabled/networkMessenger.go index 4f854d976bc..f76228462f9 100644 --- a/p2p/disabled/networkMessenger.go +++ b/p2p/disabled/networkMessenger.go @@ -4,6 +4,7 @@ import ( "time" "github.com/multiversx/mx-chain-core-go/core" + "github.com/multiversx/mx-chain-go/p2p" ) diff --git a/process/block/argProcessor.go b/process/block/argProcessor.go index df929214829..f5906980469 100644 --- a/process/block/argProcessor.go +++ b/process/block/argProcessor.go @@ -94,6 +94,7 @@ type ArgBaseProcessor struct { BlockProcessingCutoffHandler cutoff.BlockProcessingCutoffHandler ManagedPeersHolder common.ManagedPeersHolder SentSignaturesTracker process.SentSignaturesTracker + StateChangesCollector state.StateChangesCollector } // ArgShardProcessor holds all dependencies required by the process data factory in order to create diff --git a/process/block/baseProcess.go b/process/block/baseProcess.go index 0e3c573b23d..79475b7f624 100644 --- a/process/block/baseProcess.go +++ b/process/block/baseProcess.go @@ -102,17 +102,18 @@ type baseProcessor struct { blockProcessor blockProcessor txCounter *transactionCounter - outportHandler outport.OutportHandler - outportDataProvider outport.DataProviderOutport - historyRepo dblookupext.HistoryRepository - epochNotifier process.EpochNotifier - enableEpochsHandler common.EnableEpochsHandler - roundNotifier process.RoundNotifier - enableRoundsHandler process.EnableRoundsHandler - vmContainerFactory process.VirtualMachinesContainerFactory - vmContainer process.VirtualMachinesContainer - gasConsumedProvider gasConsumedProvider - economicsData process.EconomicsDataHandler + outportHandler outport.OutportHandler + outportDataProvider outport.DataProviderOutport + historyRepo dblookupext.HistoryRepository + epochNotifier process.EpochNotifier + enableEpochsHandler common.EnableEpochsHandler + roundNotifier process.RoundNotifier + enableRoundsHandler process.EnableRoundsHandler + vmContainerFactory process.VirtualMachinesContainerFactory + vmContainer process.VirtualMachinesContainer + gasConsumedProvider gasConsumedProvider + economicsData process.EconomicsDataHandler + stateChangesCollector state.StateChangesCollector processDataTriesOnCommitEpoch bool lastRestartNonce uint64 @@ -1773,9 +1774,10 @@ func (bp *baseProcessor) commitTrieEpochRootHashIfNeeded(metaBlock *block.MetaBl totalSizeCodeLeaves := 0 argsAccCreator := factory.ArgsAccountCreator{ - Hasher: bp.hasher, - Marshaller: bp.marshalizer, - EnableEpochsHandler: bp.enableEpochsHandler, + Hasher: bp.hasher, + Marshaller: bp.marshalizer, + EnableEpochsHandler: bp.enableEpochsHandler, + StateChangesCollector: bp.stateChangesCollector, } accountCreator, err := factory.NewAccountCreator(argsAccCreator) if err != nil { diff --git a/process/block/baseProcess_test.go b/process/block/baseProcess_test.go index f88d7e8d667..2e667d976cb 100644 --- a/process/block/baseProcess_test.go +++ b/process/block/baseProcess_test.go @@ -36,6 +36,7 @@ import ( "github.com/multiversx/mx-chain-go/process/mock" "github.com/multiversx/mx-chain-go/sharding/nodesCoordinator" "github.com/multiversx/mx-chain-go/state" + "github.com/multiversx/mx-chain-go/state/disabled" "github.com/multiversx/mx-chain-go/storage" "github.com/multiversx/mx-chain-go/storage/database" "github.com/multiversx/mx-chain-go/storage/storageunit" @@ -128,6 +129,7 @@ func createArgBaseProcessor( BlockProcessingCutoffHandler: &testscommon.BlockProcessingCutoffStub{}, ManagedPeersHolder: &testscommon.ManagedPeersHolderStub{}, SentSignaturesTracker: &testscommon.SentSignatureTrackerStub{}, + StateChangesCollector: disabled.NewDisabledStateChangesCollector(), } } diff --git a/process/block/metablock.go b/process/block/metablock.go index fb53f1207d7..2343f17e78d 100644 --- a/process/block/metablock.go +++ b/process/block/metablock.go @@ -13,6 +13,8 @@ import ( "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/data/block" "github.com/multiversx/mx-chain-core-go/data/headerVersionData" + logger "github.com/multiversx/mx-chain-logger-go" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/common/holders" "github.com/multiversx/mx-chain-go/dataRetriever" @@ -22,7 +24,6 @@ import ( "github.com/multiversx/mx-chain-go/process/block/helpers" "github.com/multiversx/mx-chain-go/process/block/processedMb" "github.com/multiversx/mx-chain-go/state" - logger "github.com/multiversx/mx-chain-logger-go" ) const firstHeaderNonce = uint64(1) @@ -138,6 +139,7 @@ func NewMetaProcessor(arguments ArgMetaProcessor) (*metaProcessor, error) { blockProcessingCutoffHandler: arguments.BlockProcessingCutoffHandler, managedPeersHolder: arguments.ManagedPeersHolder, sentSignaturesTracker: arguments.SentSignaturesTracker, + stateChangesCollector: arguments.StateChangesCollector, extraDelayRequestBlockInfo: time.Duration(arguments.Config.EpochStartConfig.ExtraDelayForRequestBlockInfoInMilliseconds) * time.Millisecond, } @@ -634,6 +636,7 @@ func (mp *metaProcessor) indexBlock( HighestFinalBlockNonce: mp.forkDetector.GetHighestFinalBlockNonce(), HighestFinalBlockHash: mp.forkDetector.GetHighestFinalBlockHash(), }) + if err != nil { log.Error("metaProcessor.indexBlock cannot prepare argSaveBlock", "error", err.Error(), "hash", headerHash, "nonce", metaBlock.GetNonce(), "round", metaBlock.GetRound()) @@ -1304,6 +1307,7 @@ func (mp *metaProcessor) CommitBlock( // TODO: Should be sent also validatorInfoTxs alongside rewardsTxs -> mp.validatorInfoCreator.GetValidatorInfoTxs(body) ? mp.indexBlock(header, headerHash, body, lastMetaBlock, notarizedHeadersHashes, rewardsTxs) + mp.stateChangesCollector.Reset() mp.recordBlockInHistory(headerHash, headerHandler, bodyHandler) highestFinalBlockNonce := mp.forkDetector.GetHighestFinalBlockNonce() diff --git a/process/block/metablock_test.go b/process/block/metablock_test.go index c78f2c5b039..a5665e7d8cb 100644 --- a/process/block/metablock_test.go +++ b/process/block/metablock_test.go @@ -13,6 +13,9 @@ import ( "github.com/multiversx/mx-chain-core-go/core/atomic" "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/data/block" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/dataRetriever" "github.com/multiversx/mx-chain-go/dataRetriever/blockchain" @@ -36,8 +39,6 @@ import ( stateMock "github.com/multiversx/mx-chain-go/testscommon/state" statusHandlerMock "github.com/multiversx/mx-chain-go/testscommon/statusHandler" storageStubs "github.com/multiversx/mx-chain-go/testscommon/storage" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func createMockComponentHolders() ( @@ -919,6 +920,7 @@ func TestMetaProcessor_CommitBlockStorageFailsForHeaderShouldNotReturnError(t *t return &block.Header{}, []byte("hash"), nil } arguments.BlockTracker = blockTrackerMock + arguments.StateChangesCollector = &stateMock.StateChangesCollectorStub{} mp, _ := blproc.NewMetaProcessor(arguments) processHandler := arguments.CoreComponents.ProcessStatusHandler() @@ -1050,6 +1052,7 @@ func TestMetaProcessor_CommitBlockOkValsShouldWork(t *testing.T) { resetCountersForManagedBlockSignerCalled = true }, } + arguments.StateChangesCollector = &stateMock.StateChangesCollectorStub{} mp, _ := blproc.NewMetaProcessor(arguments) diff --git a/process/block/shardblock.go b/process/block/shardblock.go index a73b4e0be6d..b0683947a09 100644 --- a/process/block/shardblock.go +++ b/process/block/shardblock.go @@ -11,6 +11,8 @@ import ( "github.com/multiversx/mx-chain-core-go/data" "github.com/multiversx/mx-chain-core-go/data/block" "github.com/multiversx/mx-chain-core-go/data/headerVersionData" + logger "github.com/multiversx/mx-chain-logger-go" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/common/holders" "github.com/multiversx/mx-chain-go/dataRetriever" @@ -20,7 +22,6 @@ import ( "github.com/multiversx/mx-chain-go/process/block/helpers" "github.com/multiversx/mx-chain-go/process/block/processedMb" "github.com/multiversx/mx-chain-go/state" - logger "github.com/multiversx/mx-chain-logger-go" ) var _ process.BlockProcessor = (*shardProcessor)(nil) @@ -123,6 +124,7 @@ func NewShardProcessor(arguments ArgShardProcessor) (*shardProcessor, error) { blockProcessingCutoffHandler: arguments.BlockProcessingCutoffHandler, managedPeersHolder: arguments.ManagedPeersHolder, sentSignaturesTracker: arguments.SentSignaturesTracker, + stateChangesCollector: arguments.StateChangesCollector, extraDelayRequestBlockInfo: time.Duration(arguments.Config.EpochStartConfig.ExtraDelayForRequestBlockInfoInMilliseconds) * time.Millisecond, } @@ -1040,6 +1042,7 @@ func (sp *shardProcessor) CommitBlock( sp.blockChain.SetCurrentBlockHeaderHash(headerHash) sp.indexBlockIfNeeded(bodyHandler, headerHash, headerHandler, lastBlockHeader) + sp.stateChangesCollector.Reset() sp.recordBlockInHistory(headerHash, headerHandler, bodyHandler) lastCrossNotarizedHeader, _, err := sp.blockTracker.GetLastCrossNotarizedHeader(core.MetachainShardId) diff --git a/process/rewardTransaction/process_test.go b/process/rewardTransaction/process_test.go index c75fa1a1cdc..13b546213ab 100644 --- a/process/rewardTransaction/process_test.go +++ b/process/rewardTransaction/process_test.go @@ -260,7 +260,13 @@ func TestRewardTxProcessor_ProcessRewardTransactionToASmartContractShouldWork(t address := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6} - dtt, _ := trackableDataTrie.NewTrackableDataTrie(address, &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, enableEpochsHandlerMock.NewEnableEpochsHandlerStub()) + dtt, _ := trackableDataTrie.NewTrackableDataTrie( + address, + &hashingMocks.HasherMock{}, + &marshallerMock.MarshalizerMock{}, + enableEpochsHandlerMock.NewEnableEpochsHandlerStub(), + &stateMock.StateChangesCollectorStub{}, + ) userAccount, _ := accounts.NewUserAccount(address, dtt, &trie.TrieLeafParserStub{}) accountsDb := &stateMock.AccountsStub{ LoadAccountCalled: func(address []byte) (vmcommon.AccountHandler, error) { diff --git a/process/scToProtocol/stakingToPeer_test.go b/process/scToProtocol/stakingToPeer_test.go index a6f0d80bc1b..fdc97c84908 100644 --- a/process/scToProtocol/stakingToPeer_test.go +++ b/process/scToProtocol/stakingToPeer_test.go @@ -61,7 +61,13 @@ func createBlockBody() *block.Body { } func createStakingScAccount() state.UserAccountHandler { - dtt, _ := trackableDataTrie.NewTrackableDataTrie(vm.StakingSCAddress, &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, enableEpochsHandlerMock.NewEnableEpochsHandlerStub()) + dtt, _ := trackableDataTrie.NewTrackableDataTrie( + vm.StakingSCAddress, + &hashingMocks.HasherMock{}, + &marshallerMock.MarshalizerMock{}, + enableEpochsHandlerMock.NewEnableEpochsHandlerStub(), + &stateMock.StateChangesCollectorStub{}, + ) userAcc, _ := accounts.NewUserAccount(vm.StakingSCAddress, dtt, &trie.TrieLeafParserStub{}) return userAcc diff --git a/process/smartContract/hooks/blockChainHook.go b/process/smartContract/hooks/blockChainHook.go index 6e590484992..358f122a77c 100644 --- a/process/smartContract/hooks/blockChainHook.go +++ b/process/smartContract/hooks/blockChainHook.go @@ -273,6 +273,7 @@ func (bh *BlockChainHookImpl) GetStorageData(accountAddress []byte, index []byte } value, trieDepth, err := userAcc.AccountDataHandler().RetrieveValue(index) + messages := []interface{}{ "address", accountAddress, "rootHash", userAcc.GetRootHash(), diff --git a/process/smartContract/processorV2/process_test.go b/process/smartContract/processorV2/process_test.go index 8722991d0a7..0a1bbdd77e1 100644 --- a/process/smartContract/processorV2/process_test.go +++ b/process/smartContract/processorV2/process_test.go @@ -63,9 +63,10 @@ func createMockPubkeyConverter() *testscommon.PubkeyConverterMock { func createAccount(address []byte) state.UserAccountHandler { argsAccCreation := stateFactory.ArgsAccountCreator{ - Hasher: &hashingMocks.HasherMock{}, - Marshaller: &marshallerMock.MarshalizerMock{}, - EnableEpochsHandler: enableEpochsHandlerMock.NewEnableEpochsHandlerStub(), + Hasher: &hashingMocks.HasherMock{}, + Marshaller: &marshallerMock.MarshalizerMock{}, + EnableEpochsHandler: enableEpochsHandlerMock.NewEnableEpochsHandlerStub(), + StateChangesCollector: &stateMock.StateChangesCollectorStub{}, } accountFactory, _ := stateFactory.NewAccountCreator(argsAccCreation) account, _ := accountFactory.CreateAccount(address) diff --git a/process/sync/trieIterators/tokensSuppliesProcessor_test.go b/process/sync/trieIterators/tokensSuppliesProcessor_test.go index 9778ad72459..d791e28fe66 100644 --- a/process/sync/trieIterators/tokensSuppliesProcessor_test.go +++ b/process/sync/trieIterators/tokensSuppliesProcessor_test.go @@ -14,6 +14,7 @@ import ( coreEsdt "github.com/multiversx/mx-chain-go/dblookupext/esdtSupply" "github.com/multiversx/mx-chain-go/state/accounts" "github.com/multiversx/mx-chain-go/state/parsers" + "github.com/multiversx/mx-chain-go/state/stateChanges" "github.com/multiversx/mx-chain-go/state/trackableDataTrie" chainStorage "github.com/multiversx/mx-chain-go/storage" "github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock" @@ -196,7 +197,13 @@ func TestTokensSuppliesProcessor_HandleTrieAccountIteration(t *testing.T) { args := getTokensSuppliesProcessorArgs() tsp, _ := NewTokensSuppliesProcessor(args) - dtt, _ := trackableDataTrie.NewTrackableDataTrie([]byte("addr"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}) + dtt, _ := trackableDataTrie.NewTrackableDataTrie( + []byte("addr"), + &hashingMocks.HasherMock{}, + &marshallerMock.MarshalizerMock{}, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + stateChanges.NewStateChangesCollector(), + ) dtlp, _ := parsers.NewDataTrieLeafParser([]byte("addr"), &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}) userAcc, _ := accounts.NewUserAccount([]byte("addr"), dtt, dtlp) userAcc.SetRootHash([]byte("rootHash")) diff --git a/process/transaction/metaProcess.go b/process/transaction/metaProcess.go index 0c9c17b6a69..3bac9c466a7 100644 --- a/process/transaction/metaProcess.go +++ b/process/transaction/metaProcess.go @@ -123,7 +123,10 @@ func (txProc *metaTxProcessor) ProcessTransaction(tx *transaction.Transaction) ( txProc.pubkeyConv, ) - defer txProc.accounts.SetTxHashForLatestStateChanges(txHash) + defer func() { + txProc.accounts.SetTxHashForLatestStateChanges(txHash, tx) + log.Debug("SetTxHashForLatestStateChanges", "txHash", txHash) + }() err = txProc.checkTxValues(tx, acntSnd, acntDst, false) if err != nil { diff --git a/process/transaction/shardProcess.go b/process/transaction/shardProcess.go index d8ae87fe195..9014f05949b 100644 --- a/process/transaction/shardProcess.go +++ b/process/transaction/shardProcess.go @@ -15,6 +15,7 @@ import ( "github.com/multiversx/mx-chain-core-go/data/vm" "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/marshal" + logger "github.com/multiversx/mx-chain-logger-go" vmcommon "github.com/multiversx/mx-chain-vm-common-go" @@ -210,7 +211,10 @@ func (txProc *txProcessor) ProcessTransaction(tx *transaction.Transaction) (vmco ) // TODO refactor to set the tx hash for the following state changes before the processing occurs - defer txProc.accounts.SetTxHashForLatestStateChanges(txHash) + defer func() { + txProc.accounts.SetTxHashForLatestStateChanges(txHash, tx) + log.Debug("SetTxHashForLatestStateChanges", "txHash", txHash) + }() txType, dstShardTxType := txProc.txTypeHandler.ComputeTransactionType(tx) err = txProc.checkTxValues(tx, acntSnd, acntDst, false) diff --git a/process/transactionEvaluator/simulationAccountsDB.go b/process/transactionEvaluator/simulationAccountsDB.go index c26fce2bc55..85d8c05fa41 100644 --- a/process/transactionEvaluator/simulationAccountsDB.go +++ b/process/transactionEvaluator/simulationAccountsDB.go @@ -5,6 +5,7 @@ import ( "sync" "github.com/multiversx/mx-chain-core-go/core/check" + "github.com/multiversx/mx-chain-core-go/data/transaction" "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/state" vmcommon "github.com/multiversx/mx-chain-vm-common-go" @@ -168,13 +169,8 @@ func (r *simulationAccountsDB) GetStackDebugFirstEntry() []byte { } // SetTxHashForLatestStateChanges - -func (r *simulationAccountsDB) SetTxHashForLatestStateChanges(txHash []byte) { - r.originalAccounts.SetTxHashForLatestStateChanges(txHash) -} - -// ResetStateChangesCollector - -func (r *simulationAccountsDB) ResetStateChangesCollector() []state.StateChangesForTx { - return nil +func (r *simulationAccountsDB) SetTxHashForLatestStateChanges(txHash []byte, tx *transaction.Transaction) { + r.originalAccounts.SetTxHashForLatestStateChanges(txHash, tx) } // Close will handle the closing of the underlying components diff --git a/state/accountsDB.go b/state/accountsDB.go index 3809a1b3442..52cb1b87b51 100644 --- a/state/accountsDB.go +++ b/state/accountsDB.go @@ -13,16 +13,19 @@ import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/core/check" + "github.com/multiversx/mx-chain-core-go/data/stateChange" + "github.com/multiversx/mx-chain-core-go/data/transaction" "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/marshal" + logger "github.com/multiversx/mx-chain-logger-go" + vmcommon "github.com/multiversx/mx-chain-vm-common-go" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/common/errChan" "github.com/multiversx/mx-chain-go/common/holders" "github.com/multiversx/mx-chain-go/state/parsers" "github.com/multiversx/mx-chain-go/trie/keyBuilder" "github.com/multiversx/mx-chain-go/trie/statistics" - logger "github.com/multiversx/mx-chain-logger-go" - vmcommon "github.com/multiversx/mx-chain-vm-common-go" ) const ( @@ -207,6 +210,15 @@ func (adb *AccountsDB) GetCode(codeHash []byte) []byte { return nil } + stateChange := &stateChange.StateChange{ + Type: "read", + MainTrieKey: codeHash, + MainTrieVal: val, + Operation: "getCode", + DataTrieChanges: nil, + } + adb.stateChangesCollector.AddStateChange(stateChange) + err = adb.marshaller.Unmarshal(&codeEntry, val) if err != nil { return nil @@ -273,17 +285,20 @@ func (adb *AccountsDB) SaveAccount(account vmcommon.AccountHandler) error { return err } - stateChange := StateChangeDTO{ + stateChange := &stateChange.StateChange{ + Type: "write", MainTrieKey: account.AddressBytes(), MainTrieVal: marshalledAccount, DataTrieChanges: newDataTrieValues, + Operation: "saveAccount", } - adb.stateChangesCollector.AddStateChange(stateChange) + + adb.stateChangesCollector.AddSaveAccountStateChange(oldAccount, account, stateChange) return nil } -func (adb *AccountsDB) saveCodeAndDataTrie(oldAcc, newAcc vmcommon.AccountHandler) ([]DataTrieChange, error) { +func (adb *AccountsDB) saveCodeAndDataTrie(oldAcc, newAcc vmcommon.AccountHandler) ([]*stateChange.DataTrieChange, error) { baseNewAcc, newAccOk := newAcc.(baseAccountHandler) baseOldAccount, _ := oldAcc.(baseAccountHandler) @@ -357,6 +372,15 @@ func (adb *AccountsDB) updateOldCodeEntry(oldCodeHash []byte) (*CodeEntry, error return nil, nil } + sc := &stateChange.StateChange{ + Type: "read", + MainTrieKey: oldCodeHash, + MainTrieVal: nil, + Operation: "getCode", + DataTrieChanges: nil, + } + adb.stateChangesCollector.AddStateChange(sc) + unmodifiedOldCodeEntry := &CodeEntry{ Code: oldCodeEntry.Code, NumReferences: oldCodeEntry.NumReferences, @@ -368,12 +392,14 @@ func (adb *AccountsDB) updateOldCodeEntry(oldCodeHash []byte) (*CodeEntry, error return nil, err } - stateChange := StateChangeDTO{ + sc1 := &stateChange.StateChange{ + Type: "write", MainTrieKey: oldCodeHash, MainTrieVal: nil, + Operation: "writeCode", DataTrieChanges: nil, } - adb.stateChangesCollector.AddStateChange(stateChange) + adb.stateChangesCollector.AddStateChange(sc1) return unmodifiedOldCodeEntry, nil } @@ -384,13 +410,14 @@ func (adb *AccountsDB) updateOldCodeEntry(oldCodeHash []byte) (*CodeEntry, error return nil, err } - // TODO refactor this after remove code leaf is merged - stateChange := StateChangeDTO{ + sc = &stateChange.StateChange{ + Type: "write", MainTrieKey: oldCodeHash, MainTrieVal: codeEntryBytes, + Operation: "writeCode", DataTrieChanges: nil, } - adb.stateChangesCollector.AddStateChange(stateChange) + adb.stateChangesCollector.AddStateChange(sc) return unmodifiedOldCodeEntry, nil } @@ -417,12 +444,14 @@ func (adb *AccountsDB) updateNewCodeEntry(newCodeHash []byte, newCode []byte) er return err } - stateChange := StateChangeDTO{ + sc := &stateChange.StateChange{ + Type: "write", MainTrieKey: newCodeHash, MainTrieVal: codeEntryBytes, + Operation: "writeCode", DataTrieChanges: nil, } - adb.stateChangesCollector.AddStateChange(stateChange) + adb.stateChangesCollector.AddStateChange(sc) return nil } @@ -489,7 +518,7 @@ func (adb *AccountsDB) loadDataTrieConcurrentSafe(accountHandler baseAccountHand // SaveDataTrie is used to save the data trie (not committing it) and to recompute the new Root value // If data is not dirtied, method will not create its JournalEntries to keep track of data modification -func (adb *AccountsDB) saveDataTrie(accountHandler baseAccountHandler) ([]DataTrieChange, error) { +func (adb *AccountsDB) saveDataTrie(accountHandler baseAccountHandler) ([]*stateChange.DataTrieChange, error) { newValues, oldValues, err := accountHandler.SaveDirtyData(adb.mainTrie) if err != nil { return nil, err @@ -509,6 +538,7 @@ func (adb *AccountsDB) saveDataTrie(accountHandler baseAccountHandler) ([]DataTr return nil, err } accountHandler.SetRootHash(rootHash) + log.Trace("saveDataTrie: rootHash changed", "address", accountHandler.AddressBytes()) if check.IfNil(adb.dataTries.Get(accountHandler.AddressBytes())) { trie, ok := accountHandler.DataTrie().(common.Trie) @@ -623,6 +653,14 @@ func (adb *AccountsDB) removeDataTrie(baseAcc baseAccountHandler) error { } adb.journalize(entry) + sc := &stateChange.StateChange{ + Type: "write", + MainTrieKey: baseAcc.AddressBytes(), + Operation: "removeDataTrie", + DataTrieChanges: nil, + } + adb.stateChangesCollector.AddStateChange(sc) + return nil } @@ -681,6 +719,15 @@ func (adb *AccountsDB) getAccount(address []byte, mainTrie common.Trie) (vmcommo return nil, nil } + stateChange := &stateChange.StateChange{ + Type: "read", + MainTrieKey: address, + MainTrieVal: val, + Operation: "getAccount", + DataTrieChanges: nil, + } + adb.stateChangesCollector.AddStateChange(stateChange) + acnt, err := adb.accountFactory.CreateAccount(address) if err != nil { return nil, err @@ -813,6 +860,11 @@ func (adb *AccountsDB) RevertToSnapshot(snapshot int) error { adb.entries = adb.entries[:snapshot] + err := adb.stateChangesCollector.RevertToIndex(snapshot) + if err != nil { + return err + } + return nil } @@ -869,10 +921,10 @@ func (adb *AccountsDB) commit() ([]byte, error) { log.Trace("accountsDB.Commit started") adb.entries = make([]JournalEntry, 0) - stateChanges := adb.stateChangesCollector.GetStateChanges() - if len(stateChanges) != 0 { - log.Warn("state changes collector is not empty", "state changes", stateChanges) - adb.stateChangesCollector.Reset() + // TODO: evaluate moving this to procesing on CommitBlock + err := adb.stateChangesCollector.Publish() + if err != nil { + return nil, err } oldHashes := make(common.ModifiedHashes) @@ -890,7 +942,7 @@ func (adb *AccountsDB) commit() ([]byte, error) { oldRoot := adb.mainTrie.GetOldRoot() // Step 2. commit main trie - err := adb.commitTrie(adb.mainTrie, oldHashes, newHashes) + err = adb.commitTrie(adb.mainTrie, oldHashes, newHashes) if err != nil { return nil, err } @@ -989,6 +1041,8 @@ func (adb *AccountsDB) recreateTrie(options common.RootHashHolder) error { adb.obsoleteDataTrieHashes = make(map[string][][]byte) adb.dataTries.Reset() adb.entries = make([]JournalEntry, 0) + + adb.stateChangesCollector.Reset() newTrie, err := adb.mainTrie.Recreate(options) if err != nil { return err @@ -1104,6 +1158,8 @@ func (adb *AccountsDB) journalize(entry JournalEntry) { "entry type", fmt.Sprintf("%T", entry), ) + _ = adb.stateChangesCollector.SetIndexToLastStateChange(len(adb.entries)) + if len(adb.entries) == 1 { adb.stackDebug = debug.Stack() } @@ -1251,15 +1307,8 @@ func collectStats( } // SetTxHashForLatestStateChanges will return the state changes since the last call of this method -func (adb *AccountsDB) SetTxHashForLatestStateChanges(txHash []byte) { - adb.stateChangesCollector.AddTxHashToCollectedStateChanges(txHash) -} - -func (adb *AccountsDB) ResetStateChangesCollector() []StateChangesForTx { - stateChanges := adb.stateChangesCollector.GetStateChanges() - adb.stateChangesCollector.Reset() - - return stateChanges +func (adb *AccountsDB) SetTxHashForLatestStateChanges(txHash []byte, tx *transaction.Transaction) { + adb.stateChangesCollector.AddTxHashToCollectedStateChanges(txHash, tx) } // IsSnapshotInProgress returns true if there is a snapshot in progress diff --git a/state/accountsDBApi.go b/state/accountsDBApi.go index 93af05a8a12..ef2f7e26e9f 100644 --- a/state/accountsDBApi.go +++ b/state/accountsDBApi.go @@ -6,9 +6,11 @@ import ( "sync" "github.com/multiversx/mx-chain-core-go/core/check" + "github.com/multiversx/mx-chain-core-go/data/transaction" + vmcommon "github.com/multiversx/mx-chain-vm-common-go" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/common/holders" - vmcommon "github.com/multiversx/mx-chain-vm-common-go" ) type accountsDBApi struct { @@ -233,13 +235,8 @@ func (accountsDB *accountsDBApi) GetStackDebugFirstEntry() []byte { } // SetTxHashForLatestStateChanges will call the inner accountsAdapter method -func (accountsDB *accountsDBApi) SetTxHashForLatestStateChanges(txHash []byte) { - accountsDB.innerAccountsAdapter.SetTxHashForLatestStateChanges(txHash) -} - -// ResetStateChangesCollector returns nil -func (accountsDB *accountsDBApi) ResetStateChangesCollector() []StateChangesForTx { - return accountsDB.innerAccountsAdapter.ResetStateChangesCollector() +func (accountsDB *accountsDBApi) SetTxHashForLatestStateChanges(txHash []byte, tx *transaction.Transaction) { + accountsDB.innerAccountsAdapter.SetTxHashForLatestStateChanges(txHash, tx) } // Close will handle the closing of the underlying components diff --git a/state/accountsDBApiWithHistory.go b/state/accountsDBApiWithHistory.go index e16a738a0fd..c0fd5213e56 100644 --- a/state/accountsDBApiWithHistory.go +++ b/state/accountsDBApiWithHistory.go @@ -6,9 +6,11 @@ import ( "sync" "github.com/multiversx/mx-chain-core-go/core/check" + "github.com/multiversx/mx-chain-core-go/data/transaction" + vmcommon "github.com/multiversx/mx-chain-vm-common-go" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/common/holders" - vmcommon "github.com/multiversx/mx-chain-vm-common-go" ) type accountsDBApiWithHistory struct { @@ -136,12 +138,7 @@ func (accountsDB *accountsDBApiWithHistory) GetStackDebugFirstEntry() []byte { } // SetTxHashForLatestStateChanges returns nil -func (accountsDB *accountsDBApiWithHistory) SetTxHashForLatestStateChanges(_ []byte) { -} - -// ResetStateChangesCollector returns nil -func (accountsDB *accountsDBApiWithHistory) ResetStateChangesCollector() []StateChangesForTx { - return nil +func (accountsDB *accountsDBApiWithHistory) SetTxHashForLatestStateChanges(_ []byte, _ *transaction.Transaction) { } // Close will handle the closing of the underlying components diff --git a/state/accountsDB_test.go b/state/accountsDB_test.go index 2b99f566e63..b316899cb97 100644 --- a/state/accountsDB_test.go +++ b/state/accountsDB_test.go @@ -16,7 +16,14 @@ import ( "github.com/multiversx/mx-chain-core-go/core/atomic" "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/core/keyValStorage" + data "github.com/multiversx/mx-chain-core-go/data/stateChange" + "github.com/multiversx/mx-chain-core-go/data/transaction" "github.com/multiversx/mx-chain-core-go/marshal" + vmcommon "github.com/multiversx/mx-chain-vm-common-go" + "github.com/multiversx/mx-chain-vm-common-go/dataTrieMigrator" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/common/errChan" "github.com/multiversx/mx-chain-go/common/holders" @@ -30,6 +37,7 @@ import ( "github.com/multiversx/mx-chain-go/state/iteratorChannelsProvider" "github.com/multiversx/mx-chain-go/state/lastSnapshotMarker" "github.com/multiversx/mx-chain-go/state/parsers" + "github.com/multiversx/mx-chain-go/state/stateChanges" "github.com/multiversx/mx-chain-go/state/storagePruningManager" "github.com/multiversx/mx-chain-go/state/storagePruningManager/disabled" "github.com/multiversx/mx-chain-go/state/storagePruningManager/evictionWaitingList" @@ -42,10 +50,6 @@ import ( "github.com/multiversx/mx-chain-go/testscommon/storageManager" trieMock "github.com/multiversx/mx-chain-go/testscommon/trie" "github.com/multiversx/mx-chain-go/trie" - vmcommon "github.com/multiversx/mx-chain-vm-common-go" - "github.com/multiversx/mx-chain-vm-common-go/dataTrieMigrator" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) const trieDbOperationDelay = time.Second @@ -81,7 +85,7 @@ func createMockAccountsDBArgs() state.ArgsAccountsDB { StoragePruningManager: disabled.NewDisabledStoragePruningManager(), AddressConverter: &testscommon.PubkeyConverterMock{}, SnapshotsManager: snapshotsManager, - StateChangesCollector: state.NewStateChangesCollector(), + StateChangesCollector: &stateMock.StateChangesCollectorStub{}, } } @@ -149,9 +153,10 @@ func getDefaultStateComponents( ewl, _ := evictionWaitingList.NewMemoryEvictionWaitingList(ewlArgs) spm, _ := storagePruningManager.NewStoragePruningManager(ewl, generalCfg.PruningBufferLen) argsAccCreator := factory.ArgsAccountCreator{ - Hasher: hasher, - Marshaller: marshaller, - EnableEpochsHandler: enableEpochsHandler, + Hasher: hasher, + Marshaller: marshaller, + EnableEpochsHandler: enableEpochsHandler, + StateChangesCollector: &stateMock.StateChangesCollectorStub{}, } accCreator, _ := factory.NewAccountCreator(argsAccCreator) @@ -175,7 +180,7 @@ func getDefaultStateComponents( StoragePruningManager: spm, AddressConverter: &testscommon.PubkeyConverterMock{}, SnapshotsManager: snapshotsManager, - StateChangesCollector: state.NewStateChangesCollector(), + StateChangesCollector: stateChanges.NewStateChangesCollector(), } adb, _ := state.NewAccountsDB(argsAccountsDB) @@ -371,8 +376,8 @@ func TestAccountsDB_SaveAccountSavesCodeAndDataTrieForUserAccount(t *testing.T) }) dtt := &trieMock.DataTrieTrackerStub{ - SaveDirtyDataCalled: func(_ common.Trie) ([]state.DataTrieChange, []core.TrieData, error) { - var stateChanges []state.DataTrieChange + SaveDirtyDataCalled: func(_ common.Trie) ([]*data.DataTrieChange, []core.TrieData, error) { + var stateChanges []*data.DataTrieChange oldVal := []core.TrieData{ { Key: []byte("key"), @@ -432,6 +437,7 @@ func TestAccountsDB_SaveAccountCollectsAllStateChanges(t *testing.T) { return autoBalanceFlagEnabled }, } + _, adb := getDefaultStateComponentsWithCustomEnableEpochs(enableEpochs) address := generateRandomByteArray(32) @@ -456,16 +462,19 @@ func stepCreateAccountWithDataTrieAndCode( _ = userAcc.SaveKeyValue(key1, []byte("value")) _ = userAcc.SaveKeyValue(key2, []byte("value")) _ = adb.SaveAccount(userAcc) - adb.SetTxHashForLatestStateChanges([]byte("accountCreationTxHash")) + + txHash := []byte("accountCreationTxHash") + + adb.SetTxHashForLatestStateChanges(txHash, &transaction.Transaction{}) serializedAcc, _ := marshaller.Marshal(userAcc) codeHash := userAcc.GetCodeHash() stateChangesForTx := adb.ResetStateChangesCollector() assert.Equal(t, 1, len(stateChangesForTx)) - stateChanges := stateChangesForTx[0].StateChanges + stateChanges := stateChangesForTx[string(txHash)].StateChanges assert.Equal(t, 2, len(stateChanges)) - assert.Equal(t, []byte("accountCreationTxHash"), stateChangesForTx[0].TxHash) + assert.Equal(t, txHash, stateChangesForTx[string(txHash)].StateChanges[0].GetTxHash()) codeStateChange := stateChanges[0] assert.Equal(t, codeHash, codeStateChange.MainTrieKey) @@ -505,14 +514,17 @@ func stepMigrateDataTrieValAndChangeCode( userAcc.SetCode(code) _ = userAcc.SaveKeyValue([]byte("key1"), []byte("value1")) _ = adb.SaveAccount(userAcc) - adb.SetTxHashForLatestStateChanges([]byte("accountUpdateTxHash")) + + txHash := []byte("accountCreationTxHash") + + adb.SetTxHashForLatestStateChanges(txHash, &transaction.Transaction{}) stateChangesForTx := adb.ResetStateChangesCollector() assert.Equal(t, 1, len(stateChangesForTx)) - assert.Equal(t, 3, len(stateChangesForTx[0].StateChanges)) - assert.Equal(t, []byte("accountUpdateTxHash"), stateChangesForTx[0].TxHash) + assert.Equal(t, 3, len(stateChangesForTx[string(txHash)].StateChanges)) + assert.Equal(t, txHash, stateChangesForTx[string(txHash)].StateChanges[0].GetTxHash()) - stateChanges := stateChangesForTx[0].StateChanges + stateChanges := stateChangesForTx[string(txHash)].StateChanges oldCodeEntryChange := stateChanges[0] assert.Equal(t, oldCodeHash, oldCodeEntryChange.MainTrieKey) assert.Equal(t, []byte(nil), oldCodeEntryChange.MainTrieVal) @@ -1919,9 +1931,10 @@ func TestAccountsDB_MainTrieAutomaticallyMarksCodeUpdatesForEviction(t *testing. argsAccountsDB.Hasher = hasher argsAccountsDB.Marshaller = marshaller argsAccCreator := factory.ArgsAccountCreator{ - Hasher: hasher, - Marshaller: marshaller, - EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + Hasher: hasher, + Marshaller: marshaller, + EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + StateChangesCollector: &stateMock.StateChangesCollectorStub{}, } argsAccountsDB.AccountFactory, _ = factory.NewAccountCreator(argsAccCreator) argsAccountsDB.StoragePruningManager = spm @@ -2000,9 +2013,10 @@ func TestAccountsDB_RemoveAccountMarksObsoleteHashesForEviction(t *testing.T) { argsAccountsDB.Hasher = hasher argsAccountsDB.Marshaller = marshaller argsAccCreator := factory.ArgsAccountCreator{ - Hasher: hasher, - Marshaller: marshaller, - EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + Hasher: hasher, + Marshaller: marshaller, + EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + StateChangesCollector: &stateMock.StateChangesCollectorStub{}, } argsAccountsDB.AccountFactory, _ = factory.NewAccountCreator(argsAccCreator) argsAccountsDB.StoragePruningManager = spm @@ -2202,9 +2216,10 @@ func TestAccountsDB_GetCode(t *testing.T) { argsAccountsDB.Hasher = hasher argsAccountsDB.Marshaller = marshaller argsAccCreator := factory.ArgsAccountCreator{ - Hasher: hasher, - Marshaller: marshaller, - EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + Hasher: hasher, + Marshaller: marshaller, + EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + StateChangesCollector: &stateMock.StateChangesCollectorStub{}, } argsAccountsDB.AccountFactory, _ = factory.NewAccountCreator(argsAccCreator) argsAccountsDB.StoragePruningManager = spm @@ -2369,9 +2384,10 @@ func TestAccountsDB_Close(t *testing.T) { argsAccountsDB.Hasher = hasher argsAccountsDB.Marshaller = marshaller argsAccCreator := factory.ArgsAccountCreator{ - Hasher: hasher, - Marshaller: marshaller, - EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + Hasher: hasher, + Marshaller: marshaller, + EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + StateChangesCollector: &stateMock.StateChangesCollectorStub{}, } argsAccountsDB.AccountFactory, _ = factory.NewAccountCreator(argsAccCreator) argsAccountsDB.StoragePruningManager = spm @@ -2657,9 +2673,10 @@ func BenchmarkAccountsDb_GetCodeEntry(b *testing.B) { argsAccountsDB.Hasher = hasher argsAccountsDB.Marshaller = marshaller argsAccCreator := factory.ArgsAccountCreator{ - Hasher: hasher, - Marshaller: marshaller, - EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + Hasher: hasher, + Marshaller: marshaller, + EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + StateChangesCollector: &stateMock.StateChangesCollectorStub{}, } argsAccountsDB.AccountFactory, _ = factory.NewAccountCreator(argsAccCreator) argsAccountsDB.StoragePruningManager = spm @@ -2929,6 +2946,8 @@ func TestAccountsDb_Concurrent(t *testing.T) { numAccounts := 100000 accountsAddresses := generateAccounts(t, numAccounts, adb) + + adb.SetTxHashForLatestStateChanges([]byte("txHash"), &transaction.Transaction{}) rootHash, _ := adb.Commit() testAccountMethodsConcurrency(t, adb, accountsAddresses, rootHash) @@ -2977,9 +2996,10 @@ func TestAccountsDB_RevertTxWhichMigratesDataRemovesMigratedData(t *testing.T) { argsAccountsDB.Hasher = hasher argsAccountsDB.Marshaller = marshaller argsAccCreator := factory.ArgsAccountCreator{ - Hasher: hasher, - Marshaller: marshaller, - EnableEpochsHandler: enableEpochsHandler, + Hasher: hasher, + Marshaller: marshaller, + EnableEpochsHandler: enableEpochsHandler, + StateChangesCollector: &stateMock.StateChangesCollectorStub{}, } argsAccountsDB.AccountFactory, _ = factory.NewAccountCreator(argsAccCreator) argsAccountsDB.StoragePruningManager = spm diff --git a/state/disabled/disabledStateChangesCollector.go b/state/disabled/disabledStateChangesCollector.go index a4f5c15c069..297d89ce5dd 100644 --- a/state/disabled/disabledStateChangesCollector.go +++ b/state/disabled/disabledStateChangesCollector.go @@ -1,6 +1,10 @@ package disabled import ( + "github.com/multiversx/mx-chain-core-go/data/stateChange" + "github.com/multiversx/mx-chain-core-go/data/transaction" + vmcommon "github.com/multiversx/mx-chain-vm-common-go" + "github.com/multiversx/mx-chain-go/state" ) @@ -13,13 +17,12 @@ func NewDisabledStateChangesCollector() state.StateChangesCollector { return &disabledStateChangesCollector{} } -// AddStateChange does nothing -func (d *disabledStateChangesCollector) AddStateChange(_ state.StateChangeDTO) { +// AddSaveAccountStateChange - +func (d *disabledStateChangesCollector) AddSaveAccountStateChange(oldAccount, account vmcommon.AccountHandler, stateChange state.StateChange) { } -// GetStateChanges returns an empty slice -func (d *disabledStateChangesCollector) GetStateChanges() []state.StateChangesForTx { - return make([]state.StateChangesForTx, 0) +// AddStateChange does nothing +func (d *disabledStateChangesCollector) AddStateChange(_ state.StateChange) { } // Reset does nothing @@ -27,7 +30,27 @@ func (d *disabledStateChangesCollector) Reset() { } // AddTxHashToCollectedStateChanges does nothing -func (d *disabledStateChangesCollector) AddTxHashToCollectedStateChanges(_ []byte) { +func (d *disabledStateChangesCollector) AddTxHashToCollectedStateChanges(_ []byte, _ *transaction.Transaction) { +} + +// SetIndexToLastStateChange - +func (d *disabledStateChangesCollector) SetIndexToLastStateChange(index int) error { + return nil +} + +// RevertToIndex - +func (d *disabledStateChangesCollector) RevertToIndex(index int) error { + return nil +} + +// Publish returns nil +func (d *disabledStateChangesCollector) Publish() error { + return nil +} + +// GetStateChangesForTxs - +func (d *disabledStateChangesCollector) GetStateChangesForTxs() map[string]*stateChange.StateChanges { + return nil } // IsInterfaceNil returns true if there is no value under the interface diff --git a/state/errors.go b/state/errors.go index 8da20ed523d..c057562b4a6 100644 --- a/state/errors.go +++ b/state/errors.go @@ -168,3 +168,6 @@ var ErrValidatorNotFound = errors.New("validator not found") // ErrNilStateChangesCollector signals that a nil state changes collector has been given var ErrNilStateChangesCollector = errors.New("nil state changes collector") + +// ErrStateChangesIndexOutOfBounds signals that the state changes index is out of bounds +var ErrStateChangesIndexOutOfBounds = errors.New("state changes index out of bounds") diff --git a/state/export_test.go b/state/export_test.go index 4398d616dd3..8353abd92d4 100644 --- a/state/export_test.go +++ b/state/export_test.go @@ -1,6 +1,7 @@ package state import ( + data "github.com/multiversx/mx-chain-core-go/data/stateChange" "github.com/multiversx/mx-chain-core-go/marshal" "github.com/multiversx/mx-chain-go/common" vmcommon "github.com/multiversx/mx-chain-vm-common-go" @@ -26,6 +27,15 @@ func (adb *AccountsDB) GetObsoleteHashes() map[string][][]byte { return adb.obsoleteDataTrieHashes } +// ResetStateChangesCollector - +func (adb *AccountsDB) ResetStateChangesCollector() map[string]*data.StateChanges { + stateChanges := adb.stateChangesCollector.GetStateChangesForTxs() + + adb.stateChangesCollector.Reset() + + return stateChanges +} + // GetCode - func GetCode(account baseAccountHandler) []byte { return account.GetCodeHash() diff --git a/state/factory/accountCreator.go b/state/factory/accountCreator.go index c117a3dfe25..99a16e1b298 100644 --- a/state/factory/accountCreator.go +++ b/state/factory/accountCreator.go @@ -15,16 +15,18 @@ import ( // ArgsAccountCreator holds the arguments needed to create a new account creator type ArgsAccountCreator struct { - Hasher hashing.Hasher - Marshaller marshal.Marshalizer - EnableEpochsHandler common.EnableEpochsHandler + Hasher hashing.Hasher + Marshaller marshal.Marshalizer + EnableEpochsHandler common.EnableEpochsHandler + StateChangesCollector state.StateChangesCollector } // AccountCreator has method to create a new account type accountCreator struct { - hasher hashing.Hasher - marshaller marshal.Marshalizer - enableEpochsHandler common.EnableEpochsHandler + hasher hashing.Hasher + marshaller marshal.Marshalizer + enableEpochsHandler common.EnableEpochsHandler + stateChangesCollector state.StateChangesCollector } // NewAccountCreator creates a new instance of AccountCreator @@ -38,17 +40,21 @@ func NewAccountCreator(args ArgsAccountCreator) (state.AccountFactory, error) { if check.IfNil(args.EnableEpochsHandler) { return nil, errors.ErrNilEnableEpochsHandler } + if check.IfNil(args.StateChangesCollector) { + return nil, state.ErrNilStateChangesCollector + } return &accountCreator{ - hasher: args.Hasher, - marshaller: args.Marshaller, - enableEpochsHandler: args.EnableEpochsHandler, + hasher: args.Hasher, + marshaller: args.Marshaller, + enableEpochsHandler: args.EnableEpochsHandler, + stateChangesCollector: args.StateChangesCollector, }, nil } // CreateAccount calls the new Account creator and returns the result func (ac *accountCreator) CreateAccount(address []byte) (vmcommon.AccountHandler, error) { - tdt, err := trackableDataTrie.NewTrackableDataTrie(address, ac.hasher, ac.marshaller, ac.enableEpochsHandler) + tdt, err := trackableDataTrie.NewTrackableDataTrie(address, ac.hasher, ac.marshaller, ac.enableEpochsHandler, ac.stateChangesCollector) if err != nil { return nil, err } diff --git a/state/factory/accountCreator_test.go b/state/factory/accountCreator_test.go index e5cba461d28..11490deae17 100644 --- a/state/factory/accountCreator_test.go +++ b/state/factory/accountCreator_test.go @@ -7,6 +7,7 @@ import ( "github.com/multiversx/mx-chain-go/errors" "github.com/multiversx/mx-chain-go/state" "github.com/multiversx/mx-chain-go/state/factory" + "github.com/multiversx/mx-chain-go/state/stateChanges" "github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock" "github.com/multiversx/mx-chain-go/testscommon/hashingMocks" "github.com/multiversx/mx-chain-go/testscommon/marshallerMock" @@ -15,9 +16,10 @@ import ( func getDefaultArgs() factory.ArgsAccountCreator { return factory.ArgsAccountCreator{ - Hasher: &hashingMocks.HasherMock{}, - Marshaller: &marshallerMock.MarshalizerMock{}, - EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + Hasher: &hashingMocks.HasherMock{}, + Marshaller: &marshallerMock.MarshalizerMock{}, + EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + StateChangesCollector: stateChanges.NewStateChangesCollector(), } } diff --git a/state/factory/accountsAdapterAPICreator_test.go b/state/factory/accountsAdapterAPICreator_test.go index d1df498d6bc..fd524231e5d 100644 --- a/state/factory/accountsAdapterAPICreator_test.go +++ b/state/factory/accountsAdapterAPICreator_test.go @@ -7,6 +7,7 @@ import ( "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/state" + "github.com/multiversx/mx-chain-go/state/stateChanges" "github.com/multiversx/mx-chain-go/testscommon" "github.com/multiversx/mx-chain-go/testscommon/marshallerMock" mockState "github.com/multiversx/mx-chain-go/testscommon/state" @@ -28,7 +29,7 @@ func createMockAccountsArgs() state.ArgsAccountsDB { StoragePruningManager: &mockState.StoragePruningManagerStub{}, AddressConverter: &testscommon.PubkeyConverterMock{}, SnapshotsManager: &mockState.SnapshotsManagerStub{}, - StateChangesCollector: state.NewStateChangesCollector(), + StateChangesCollector: stateChanges.NewStateChangesCollector(), } } diff --git a/state/interface.go b/state/interface.go index 7d8ff9ac8d0..73ac6c9d50a 100644 --- a/state/interface.go +++ b/state/interface.go @@ -6,6 +6,8 @@ import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/data/api" + data "github.com/multiversx/mx-chain-core-go/data/stateChange" + "github.com/multiversx/mx-chain-core-go/data/transaction" vmcommon "github.com/multiversx/mx-chain-vm-common-go" "github.com/multiversx/mx-chain-go/common" @@ -90,8 +92,7 @@ type AccountsAdapter interface { GetStackDebugFirstEntry() []byte SetSyncer(syncer AccountsDBSyncer) error StartSnapshotIfNeeded() error - SetTxHashForLatestStateChanges(txHash []byte) - ResetStateChangesCollector() []StateChangesForTx + SetTxHashForLatestStateChanges(txHash []byte, tx *transaction.Transaction) Close() error IsInterfaceNil() bool } @@ -161,7 +162,7 @@ type baseAccountHandler interface { GetRootHash() []byte SetDataTrie(trie common.Trie) DataTrie() common.DataTrieHandler - SaveDirtyData(trie common.Trie) ([]DataTrieChange, []core.TrieData, error) + SaveDirtyData(trie common.Trie) ([]*data.DataTrieChange, []core.TrieData, error) IsInterfaceNil() bool } @@ -259,7 +260,7 @@ type DataTrieTracker interface { SaveKeyValue(key []byte, value []byte) error SetDataTrie(tr common.Trie) DataTrie() common.DataTrieHandler - SaveDirtyData(common.Trie) ([]DataTrieChange, []core.TrieData, error) + SaveDirtyData(common.Trie) ([]*data.DataTrieChange, []core.TrieData, error) MigrateDataTrieLeaves(args vmcommon.ArgsMigrateDataTrieLeaves) error IsInterfaceNil() bool } @@ -358,9 +359,27 @@ type ValidatorInfoHandler interface { // StateChangesCollector defines the methods needed for an StateChangesCollector implementation type StateChangesCollector interface { - AddStateChange(stateChange StateChangeDTO) - GetStateChanges() []StateChangesForTx + AddStateChange(stateChange StateChange) + AddSaveAccountStateChange(oldAccount, account vmcommon.AccountHandler, stateChange StateChange) Reset() - AddTxHashToCollectedStateChanges(txHash []byte) + AddTxHashToCollectedStateChanges(txHash []byte, tx *transaction.Transaction) + SetIndexToLastStateChange(index int) error + RevertToIndex(index int) error + Publish() error IsInterfaceNil() bool + GetStateChangesForTxs() map[string]*data.StateChanges +} + +// StateChange defines the behaviour of a state change holder +type StateChange interface { + GetType() string + GetIndex() int32 + GetTxHash() []byte + GetMainTrieKey() []byte + GetMainTrieVal() []byte + GetOperation() string + GetDataTrieChanges() []*data.DataTrieChange + + SetTxHash(txHash []byte) + SetIndex(index int32) } diff --git a/state/stateChanges/dataAnalysisCollector.go b/state/stateChanges/dataAnalysisCollector.go new file mode 100644 index 00000000000..481eb8e9fc6 --- /dev/null +++ b/state/stateChanges/dataAnalysisCollector.go @@ -0,0 +1,191 @@ +package stateChanges + +import ( + "bytes" + "encoding/json" + "fmt" + "math/big" + + "github.com/multiversx/mx-chain-core-go/core/check" + "github.com/multiversx/mx-chain-core-go/data/transaction" + vmcommon "github.com/multiversx/mx-chain-vm-common-go" + + "github.com/multiversx/mx-chain-go/state" + "github.com/multiversx/mx-chain-go/storage" +) + +type dataAnalysisStateChangeDTO struct { + state.StateChange + Operation string `json:"operation"` + Nonce bool `json:"nonceChanged"` + Balance bool `json:"balanceChanged"` + CodeHash bool `json:"codeHashChanged"` + RootHash bool `json:"rootHashChanged"` + DeveloperReward bool `json:"developerRewardChanged"` + OwnerAddress bool `json:"ownerAddressChanged"` + UserName bool `json:"userNameChanged"` + CodeMetadata bool `json:"codeMetadataChanged"` +} + +type dataAnalysisStateChangesForTx struct { + StateChangesForTx + Tx *transaction.Transaction `json:"tx"` +} + +type userAccountHandler interface { + GetCodeMetadata() []byte + GetCodeHash() []byte + GetRootHash() []byte + GetBalance() *big.Int + GetDeveloperReward() *big.Int + GetOwnerAddress() []byte + GetUserName() []byte + vmcommon.AccountHandler +} + +type dataAnalysisCollector struct { + *stateChangesCollector + + cachedTxs map[string]*transaction.Transaction + storer storage.Persister +} + +// NewDataAnalysisStateChangesCollector will create a new instance of data analysis collector +func NewDataAnalysisStateChangesCollector(storer storage.Persister) (*dataAnalysisCollector, error) { + if check.IfNil(storer) { + return nil, storage.ErrNilPersister + } + + return &dataAnalysisCollector{ + stateChangesCollector: NewStateChangesCollector(), + cachedTxs: make(map[string]*transaction.Transaction), + storer: storer, + }, nil +} + +// AddSaveAccountStateChange adds a new state change for the save account operation +func (scc *dataAnalysisCollector) AddSaveAccountStateChange(oldAccount, account vmcommon.AccountHandler, stateChange state.StateChange) { + dataAnalysisStateChange := &dataAnalysisStateChangeDTO{ + StateChange: stateChange, + } + + checkAccountChanges(oldAccount, account, dataAnalysisStateChange) + + scc.AddStateChange(dataAnalysisStateChange) +} + +func checkAccountChanges(oldAcc, newAcc vmcommon.AccountHandler, stateChange *dataAnalysisStateChangeDTO) { + baseNewAcc, newAccOk := newAcc.(userAccountHandler) + if !newAccOk { + return + } + baseOldAccount, oldAccOk := oldAcc.(userAccountHandler) + if !oldAccOk { + return + } + + if baseNewAcc.GetNonce() != baseOldAccount.GetNonce() { + stateChange.Nonce = true + } + + if baseNewAcc.GetBalance().Uint64() != baseOldAccount.GetBalance().Uint64() { + stateChange.Balance = true + } + + if !bytes.Equal(baseNewAcc.GetCodeHash(), baseOldAccount.GetCodeHash()) { + stateChange.CodeHash = true + } + + if !bytes.Equal(baseNewAcc.GetRootHash(), baseOldAccount.GetRootHash()) { + stateChange.RootHash = true + } + + if !bytes.Equal(baseNewAcc.GetDeveloperReward().Bytes(), baseOldAccount.GetDeveloperReward().Bytes()) { + stateChange.DeveloperReward = true + } + + if !bytes.Equal(baseNewAcc.GetOwnerAddress(), baseOldAccount.GetOwnerAddress()) { + stateChange.OwnerAddress = true + } + + if !bytes.Equal(baseNewAcc.GetUserName(), baseOldAccount.GetUserName()) { + stateChange.UserName = true + } + + if !bytes.Equal(baseNewAcc.GetCodeMetadata(), baseOldAccount.GetCodeMetadata()) { + stateChange.CodeMetadata = true + } +} + +// AddStateChange adds a new state change to the collector +func (scc *dataAnalysisCollector) AddStateChange(stateChange state.StateChange) { + scc.stateChangesMut.Lock() + defer scc.stateChangesMut.Unlock() + + scc.stateChanges = append(scc.stateChanges, stateChange) +} + +func (scc *dataAnalysisCollector) getDataAnalysisStateChangesForTxs() ([]dataAnalysisStateChangesForTx, error) { + stateChangesForTxs, err := scc.getStateChangesForTxs() + if err != nil { + return nil, err + } + + dataAnalysisStateChangesForTxs := make([]dataAnalysisStateChangesForTx, 0) + + for _, stateChangeForTx := range stateChangesForTxs { + cachedTx, txOk := scc.cachedTxs[string(stateChangeForTx.TxHash)] + if !txOk { + return nil, fmt.Errorf("did not find tx in cache") + } + + stateChangesForTx := dataAnalysisStateChangesForTx{ + StateChangesForTx: stateChangeForTx, + Tx: cachedTx, + } + dataAnalysisStateChangesForTxs = append(dataAnalysisStateChangesForTxs, stateChangesForTx) + } + + return dataAnalysisStateChangesForTxs, nil +} + +func (scc *dataAnalysisCollector) AddTxHashToCollectedStateChanges(txHash []byte, tx *transaction.Transaction) { + scc.cachedTxs[string(txHash)] = tx + scc.addTxHashToCollectedStateChanges(txHash) +} + +// Reset resets the state changes collector +func (scc *dataAnalysisCollector) Reset() { + scc.stateChangesMut.Lock() + defer scc.stateChangesMut.Unlock() + + scc.resetStateChangesUnprotected() + scc.cachedTxs = make(map[string]*transaction.Transaction) +} + +// Publish will export state changes +func (scc *dataAnalysisCollector) Publish() error { + stateChangesForTx, err := scc.getDataAnalysisStateChangesForTxs() + if err != nil { + return err + } + + for _, stateChange := range stateChangesForTx { + marshalledData, err := json.Marshal(stateChange) + if err != nil { + return err + } + + err = scc.storer.Put(stateChange.TxHash, marshalledData) + if err != nil { + return err + } + } + + return nil +} + +// IsInterfaceNil returns true if there is no value under the interface +func (scc *dataAnalysisCollector) IsInterfaceNil() bool { + return scc == nil +} diff --git a/state/stateChanges/dataAnalysisCollector_test.go b/state/stateChanges/dataAnalysisCollector_test.go new file mode 100644 index 00000000000..1d33d0e79d4 --- /dev/null +++ b/state/stateChanges/dataAnalysisCollector_test.go @@ -0,0 +1,206 @@ +package stateChanges + +import ( + "math/big" + "testing" + + data "github.com/multiversx/mx-chain-core-go/data/stateChange" + "github.com/multiversx/mx-chain-core-go/data/transaction" + "github.com/multiversx/mx-chain-go/storage" + "github.com/multiversx/mx-chain-go/storage/mock" + "github.com/multiversx/mx-chain-go/testscommon/state" + "github.com/stretchr/testify/require" +) + +func TestNewDataAnalysisCollector(t *testing.T) { + t.Parallel() + + t.Run("nil storer", func(t *testing.T) { + t.Parallel() + + dsc, err := NewDataAnalysisStateChangesCollector(nil) + require.Nil(t, dsc) + require.Equal(t, storage.ErrNilPersister, err) + }) + + t.Run("should work", func(t *testing.T) { + t.Parallel() + + dsc, err := NewDataAnalysisStateChangesCollector(&mock.PersisterStub{}) + require.Nil(t, err) + require.False(t, dsc.IsInterfaceNil()) + }) +} + +func TestDataAnalysisStateChangesCollector_AddStateChange(t *testing.T) { + t.Parallel() + + dsc, err := NewDataAnalysisStateChangesCollector(&mock.PersisterStub{}) + require.Nil(t, err) + + require.Equal(t, 0, len(dsc.stateChanges)) + + dsc.AddStateChange(&data.StateChange{ + Type: "write", + }) + dsc.AddStateChange(&data.StateChange{ + Type: "read", + }) + dsc.AddStateChange(&data.StateChange{ + Type: "write", + }) + + require.Equal(t, 3, len(dsc.stateChanges)) +} + +func TestDataAnalysisStateChangesCollector_AddSaveAccountStateChange(t *testing.T) { + t.Parallel() + + t.Run("nil old account should return early", func(t *testing.T) { + t.Parallel() + + dsc, err := NewDataAnalysisStateChangesCollector(&mock.PersisterStub{}) + require.Nil(t, err) + + dsc.AddSaveAccountStateChange( + nil, + &state.UserAccountStub{}, + &data.StateChange{ + Type: "saveAccount", + Index: 2, + TxHash: []byte("txHash1"), + MainTrieKey: []byte("key1"), + }, + ) + + dsc.AddTxHashToCollectedStateChanges([]byte("txHash1"), &transaction.Transaction{}) + + stateChangesForTx := dsc.GetStateChanges() + require.Equal(t, 1, len(stateChangesForTx)) + + sc := stateChangesForTx[0].StateChanges[0] + dasc, ok := sc.(*dataAnalysisStateChangeDTO) + require.True(t, ok) + + require.False(t, dasc.Nonce) + require.False(t, dasc.Balance) + require.False(t, dasc.CodeHash) + require.False(t, dasc.RootHash) + require.False(t, dasc.DeveloperReward) + require.False(t, dasc.OwnerAddress) + require.False(t, dasc.UserName) + require.False(t, dasc.CodeMetadata) + }) + + t.Run("nil new account should return early", func(t *testing.T) { + t.Parallel() + + dsc, err := NewDataAnalysisStateChangesCollector(&mock.PersisterStub{}) + require.Nil(t, err) + + dsc.AddSaveAccountStateChange( + &state.UserAccountStub{}, + nil, + &data.StateChange{ + Type: "saveAccount", + Index: 2, + TxHash: []byte("txHash1"), + MainTrieKey: []byte("key1"), + }, + ) + + dsc.AddTxHashToCollectedStateChanges([]byte("txHash1"), &transaction.Transaction{}) + + stateChangesForTx := dsc.GetStateChanges() + require.Equal(t, 1, len(stateChangesForTx)) + + sc := stateChangesForTx[0].StateChanges[0] + dasc, ok := sc.(*dataAnalysisStateChangeDTO) + require.True(t, ok) + + require.False(t, dasc.Nonce) + require.False(t, dasc.Balance) + require.False(t, dasc.CodeHash) + require.False(t, dasc.RootHash) + require.False(t, dasc.DeveloperReward) + require.False(t, dasc.OwnerAddress) + require.False(t, dasc.UserName) + require.False(t, dasc.CodeMetadata) + }) + + t.Run("should work", func(t *testing.T) { + t.Parallel() + + dsc, err := NewDataAnalysisStateChangesCollector(&mock.PersisterStub{}) + require.Nil(t, err) + + dsc.AddSaveAccountStateChange( + &state.UserAccountStub{ + Nonce: 0, + Balance: big.NewInt(0), + DeveloperRewards: big.NewInt(0), + UserName: []byte{0}, + Owner: []byte{0}, + Address: []byte{0}, + CodeMetadata: []byte{0}, + CodeHash: []byte{0}, + GetRootHashCalled: func() []byte { + return []byte{0} + }, + }, + &state.UserAccountStub{ + Nonce: 1, + Balance: big.NewInt(1), + DeveloperRewards: big.NewInt(1), + UserName: []byte{1}, + Owner: []byte{1}, + Address: []byte{1}, + CodeMetadata: []byte{1}, + CodeHash: []byte{1}, + GetRootHashCalled: func() []byte { + return []byte{1} + }, + }, + &data.StateChange{ + Type: "saveAccount", + Index: 2, + TxHash: []byte("txHash1"), + MainTrieKey: []byte("key1"), + }, + ) + + dsc.AddTxHashToCollectedStateChanges([]byte("txHash1"), &transaction.Transaction{}) + + stateChangesForTx := dsc.GetStateChanges() + require.Equal(t, 1, len(stateChangesForTx)) + + sc := stateChangesForTx[0].StateChanges[0] + dasc, ok := sc.(*dataAnalysisStateChangeDTO) + require.True(t, ok) + + require.True(t, dasc.Nonce) + require.True(t, dasc.Balance) + require.True(t, dasc.CodeHash) + require.True(t, dasc.RootHash) + require.True(t, dasc.DeveloperReward) + require.True(t, dasc.OwnerAddress) + require.True(t, dasc.UserName) + require.True(t, dasc.CodeMetadata) + }) +} + +func TestDataAnalysisStateChangesCollector_Reset(t *testing.T) { + t.Parallel() + + dsc, err := NewDataAnalysisStateChangesCollector(&mock.PersisterStub{}) + require.Nil(t, err) + + numStateChanges := 10 + for i := 0; i < numStateChanges; i++ { + dsc.AddStateChange(getDefaultStateChange()) + } + require.Equal(t, numStateChanges, len(dsc.stateChanges)) + + dsc.Reset() + require.Equal(t, 0, len(dsc.GetStateChanges())) +} diff --git a/state/stateChanges/export_test.go b/state/stateChanges/export_test.go new file mode 100644 index 00000000000..ed4b541ee20 --- /dev/null +++ b/state/stateChanges/export_test.go @@ -0,0 +1,13 @@ +package stateChanges + +// GetStateChanges - +func (scc *stateChangesCollector) GetStateChanges() []StateChangesForTx { + scs, _ := scc.getStateChangesForTxs() + return scs +} + +// GetStateChanges - +func (dsc *dataAnalysisCollector) GetStateChanges() []dataAnalysisStateChangesForTx { + scs, _ := dsc.getDataAnalysisStateChangesForTxs() + return scs +} diff --git a/state/stateChanges/writeCollector.go b/state/stateChanges/writeCollector.go new file mode 100644 index 00000000000..1691ca0fedb --- /dev/null +++ b/state/stateChanges/writeCollector.go @@ -0,0 +1,195 @@ +package stateChanges + +import ( + "bytes" + "sync" + + data "github.com/multiversx/mx-chain-core-go/data/stateChange" + "github.com/multiversx/mx-chain-core-go/data/transaction" + "github.com/multiversx/mx-chain-go/state" + logger "github.com/multiversx/mx-chain-logger-go" + vmcommon "github.com/multiversx/mx-chain-vm-common-go" +) + +var log = logger.GetOrCreate("state/stateChanges") + +// StateChangesForTx is used to collect state changes for a transaction hash +type StateChangesForTx struct { + TxHash []byte `json:"txHash"` + StateChanges []state.StateChange `json:"stateChanges"` +} + +type stateChangesCollector struct { + stateChanges []state.StateChange + stateChangesMut sync.RWMutex +} + +// NewStateChangesCollector creates a new StateChangesCollector +func NewStateChangesCollector() *stateChangesCollector { + return &stateChangesCollector{ + stateChanges: make([]state.StateChange, 0), + } +} + +// AddSaveAccountStateChange adds a new state change for the save account operation +func (scc *stateChangesCollector) AddSaveAccountStateChange(_, _ vmcommon.AccountHandler, stateChange state.StateChange) { + scc.AddStateChange(stateChange) +} + +// AddStateChange adds a new state change to the collector +func (scc *stateChangesCollector) AddStateChange(stateChange state.StateChange) { + scc.stateChangesMut.Lock() + defer scc.stateChangesMut.Unlock() + + // TODO: add custom type for stateChange type + if stateChange.GetType() == "write" { + scc.stateChanges = append(scc.stateChanges, stateChange) + } +} + +func (scc *stateChangesCollector) getStateChangesForTxs() ([]StateChangesForTx, error) { + scc.stateChangesMut.Lock() + defer scc.stateChangesMut.Unlock() + + stateChangesForTxs := make([]StateChangesForTx, 0) + + for i := 0; i < len(scc.stateChanges); i++ { + txHash := scc.stateChanges[i].GetTxHash() + + if len(txHash) == 0 { + log.Warn("empty tx hash, state change event not associated to a transaction") + continue + } + + innerStateChangesForTx := make([]state.StateChange, 0) + for j := i; j < len(scc.stateChanges); j++ { + txHash2 := scc.stateChanges[j].GetTxHash() + if !bytes.Equal(txHash, txHash2) { + i = j + break + } + + innerStateChangesForTx = append(innerStateChangesForTx, scc.stateChanges[j]) + i = j + } + + stateChangesForTx := StateChangesForTx{ + TxHash: txHash, + StateChanges: innerStateChangesForTx, + } + stateChangesForTxs = append(stateChangesForTxs, stateChangesForTx) + } + + return stateChangesForTxs, nil +} + +// GetStateChangesForTxs will retrieve the state changes linked with the tx hash. +func (scc *stateChangesCollector) GetStateChangesForTxs() map[string]*data.StateChanges { + scc.stateChangesMut.RLock() + defer scc.stateChangesMut.RUnlock() + + stateChangesForTxs := make(map[string]*data.StateChanges) + + for _, stateChange := range scc.stateChanges { + txHash := string(stateChange.GetTxHash()) + + st, ok := stateChange.(*data.StateChange) + if !ok { + continue + } + + _, ok = stateChangesForTxs[txHash] + if !ok { + stateChangesForTxs[txHash] = &data.StateChanges{ + StateChanges: []*data.StateChange{st}, + } + } else { + stateChangesForTxs[txHash].StateChanges = append(stateChangesForTxs[txHash].StateChanges, st) + } + } + + return stateChangesForTxs +} + +// Reset resets the state changes collector +func (scc *stateChangesCollector) Reset() { + scc.stateChangesMut.Lock() + defer scc.stateChangesMut.Unlock() + + scc.resetStateChangesUnprotected() +} + +func (scc *stateChangesCollector) resetStateChangesUnprotected() { + scc.stateChanges = make([]state.StateChange, 0) +} + +// AddTxHashToCollectedStateChanges will try to set txHash field to each state change +// if the field is not already set +func (scc *stateChangesCollector) AddTxHashToCollectedStateChanges(txHash []byte, _ *transaction.Transaction) { + scc.addTxHashToCollectedStateChanges(txHash) +} + +func (scc *stateChangesCollector) addTxHashToCollectedStateChanges(txHash []byte) { + scc.stateChangesMut.Lock() + defer scc.stateChangesMut.Unlock() + + for i := len(scc.stateChanges) - 1; i >= 0; i-- { + if len(scc.stateChanges[i].GetTxHash()) > 0 { + break + } + + scc.stateChanges[i].SetTxHash(txHash) + } +} + +// SetIndexToLastStateChange will set index to the last state change +func (scc *stateChangesCollector) SetIndexToLastStateChange(index int) error { + scc.stateChangesMut.Lock() + defer scc.stateChangesMut.Unlock() + + if index > len(scc.stateChanges) || index < 0 { + return state.ErrStateChangesIndexOutOfBounds + } + + if len(scc.stateChanges) == 0 { + return nil + } + + scc.stateChanges[len(scc.stateChanges)-1].SetIndex(int32(index)) + + return nil +} + +// RevertToIndex will revert to index +func (scc *stateChangesCollector) RevertToIndex(index int) error { + if index > len(scc.stateChanges) || index < 0 { + return state.ErrStateChangesIndexOutOfBounds + } + + if index == 0 { + scc.Reset() + return nil + } + + scc.stateChangesMut.Lock() + defer scc.stateChangesMut.Unlock() + + for i := len(scc.stateChanges) - 1; i >= 0; i-- { + if scc.stateChanges[i].GetIndex() == int32(index) { + scc.stateChanges = scc.stateChanges[:i] + break + } + } + + return nil +} + +// Publish returns nil +func (scc *stateChangesCollector) Publish() error { + return nil +} + +// IsInterfaceNil returns true if there is no value under the interface +func (scc *stateChangesCollector) IsInterfaceNil() bool { + return scc == nil +} diff --git a/state/stateChanges/writeCollector_test.go b/state/stateChanges/writeCollector_test.go new file mode 100644 index 00000000000..1dc76a124c7 --- /dev/null +++ b/state/stateChanges/writeCollector_test.go @@ -0,0 +1,298 @@ +package stateChanges + +import ( + "fmt" + "strconv" + "testing" + + data "github.com/multiversx/mx-chain-core-go/data/stateChange" + "github.com/multiversx/mx-chain-core-go/data/transaction" + "github.com/stretchr/testify/assert" + + "github.com/multiversx/mx-chain-go/state" + + "github.com/stretchr/testify/require" +) + +func getDefaultStateChange() *data.StateChange { + return &data.StateChange{ + Type: "write", + } +} + +func TestNewStateChangesCollector(t *testing.T) { + t.Parallel() + + stateChangesCollector := NewStateChangesCollector() + require.False(t, stateChangesCollector.IsInterfaceNil()) +} + +func TestStateChangesCollector_AddStateChange(t *testing.T) { + t.Parallel() + + scc := NewStateChangesCollector() + assert.Equal(t, 0, len(scc.stateChanges)) + + numStateChanges := 10 + for i := 0; i < numStateChanges; i++ { + scc.AddStateChange(getDefaultStateChange()) + } + assert.Equal(t, numStateChanges, len(scc.stateChanges)) +} + +func TestStateChangesCollector_GetStateChanges(t *testing.T) { + t.Parallel() + + t.Run("getStateChanges with tx hash", func(t *testing.T) { + t.Parallel() + + scc := NewStateChangesCollector() + assert.Equal(t, 0, len(scc.stateChanges)) + assert.Equal(t, 0, len(scc.GetStateChanges())) + + numStateChanges := 10 + for i := 0; i < numStateChanges; i++ { + scc.AddStateChange(&data.StateChange{ + Type: "write", + MainTrieKey: []byte(strconv.Itoa(i)), + }) + } + assert.Equal(t, numStateChanges, len(scc.stateChanges)) + assert.Equal(t, 0, len(scc.GetStateChanges())) + scc.AddTxHashToCollectedStateChanges([]byte("txHash"), &transaction.Transaction{}) + assert.Equal(t, numStateChanges, len(scc.stateChanges)) + assert.Equal(t, 1, len(scc.GetStateChanges())) + assert.Equal(t, []byte("txHash"), scc.GetStateChanges()[0].TxHash) + assert.Equal(t, numStateChanges, len(scc.GetStateChanges()[0].StateChanges)) + + stateChangesForTx := scc.GetStateChanges() + assert.Equal(t, 1, len(stateChangesForTx)) + assert.Equal(t, []byte("txHash"), stateChangesForTx[0].TxHash) + for i := 0; i < len(stateChangesForTx[0].StateChanges); i++ { + sc, ok := stateChangesForTx[0].StateChanges[i].(*data.StateChange) + require.True(t, ok) + + assert.Equal(t, []byte(strconv.Itoa(i)), sc.MainTrieKey) + } + }) + + t.Run("getStateChanges without tx hash", func(t *testing.T) { + t.Parallel() + + scc := NewStateChangesCollector() + assert.Equal(t, 0, len(scc.stateChanges)) + assert.Equal(t, 0, len(scc.GetStateChanges())) + + numStateChanges := 10 + for i := 0; i < numStateChanges; i++ { + scc.AddStateChange(&data.StateChange{ + Type: "write", + MainTrieKey: []byte(strconv.Itoa(i)), + }) + } + assert.Equal(t, numStateChanges, len(scc.stateChanges)) + assert.Equal(t, 0, len(scc.GetStateChanges())) + + stateChangesForTx := scc.GetStateChanges() + assert.Equal(t, 0, len(stateChangesForTx)) + }) +} + +func TestStateChangesCollector_AddTxHashToCollectedStateChanges(t *testing.T) { + t.Parallel() + + scc := NewStateChangesCollector() + assert.Equal(t, 0, len(scc.stateChanges)) + assert.Equal(t, 0, len(scc.GetStateChanges())) + + scc.AddTxHashToCollectedStateChanges([]byte("txHash0"), &transaction.Transaction{}) + + stateChange := &data.StateChange{ + Type: "write", + MainTrieKey: []byte("mainTrieKey"), + MainTrieVal: []byte("mainTrieVal"), + DataTrieChanges: []*data.DataTrieChange{{Key: []byte("dataTrieKey"), Val: []byte("dataTrieVal")}}, + } + scc.AddStateChange(stateChange) + + assert.Equal(t, 1, len(scc.stateChanges)) + assert.Equal(t, 0, len(scc.GetStateChanges())) + scc.AddTxHashToCollectedStateChanges([]byte("txHash"), &transaction.Transaction{}) + assert.Equal(t, 1, len(scc.stateChanges)) + assert.Equal(t, 1, len(scc.GetStateChanges())) + + stateChangesForTx := scc.GetStateChanges() + assert.Equal(t, 1, len(stateChangesForTx)) + assert.Equal(t, []byte("txHash"), stateChangesForTx[0].TxHash) + assert.Equal(t, 1, len(stateChangesForTx[0].StateChanges)) + + sc, ok := stateChangesForTx[0].StateChanges[0].(*data.StateChange) + require.True(t, ok) + + assert.Equal(t, []byte("mainTrieKey"), sc.MainTrieKey) + assert.Equal(t, []byte("mainTrieVal"), sc.MainTrieVal) + assert.Equal(t, 1, len(sc.DataTrieChanges)) +} + +func TestStateChangesCollector_RevertToIndex_FailIfWrongIndex(t *testing.T) { + t.Parallel() + + scc := NewStateChangesCollector() + numStateChanges := len(scc.stateChanges) + + err := scc.RevertToIndex(-1) + require.Equal(t, state.ErrStateChangesIndexOutOfBounds, err) + + err = scc.RevertToIndex(numStateChanges + 1) + require.Equal(t, state.ErrStateChangesIndexOutOfBounds, err) +} + +func TestStateChangesCollector_RevertToIndex(t *testing.T) { + t.Parallel() + + scc := NewStateChangesCollector() + + numStateChanges := 10 + for i := 0; i < numStateChanges; i++ { + scc.AddStateChange(getDefaultStateChange()) + err := scc.SetIndexToLastStateChange(i) + require.Nil(t, err) + } + scc.AddTxHashToCollectedStateChanges([]byte("txHash1"), &transaction.Transaction{}) + + for i := numStateChanges; i < numStateChanges*2; i++ { + scc.AddStateChange(getDefaultStateChange()) + scc.AddTxHashToCollectedStateChanges([]byte("txHash"+fmt.Sprintf("%d", i)), &transaction.Transaction{}) + } + err := scc.SetIndexToLastStateChange(numStateChanges) + require.Nil(t, err) + + assert.Equal(t, numStateChanges*2, len(scc.stateChanges)) + + err = scc.RevertToIndex(numStateChanges) + require.Nil(t, err) + assert.Equal(t, numStateChanges*2-1, len(scc.stateChanges)) + + err = scc.RevertToIndex(numStateChanges - 1) + require.Nil(t, err) + assert.Equal(t, numStateChanges-1, len(scc.stateChanges)) + + err = scc.RevertToIndex(numStateChanges / 2) + require.Nil(t, err) + assert.Equal(t, numStateChanges/2, len(scc.stateChanges)) + + err = scc.RevertToIndex(1) + require.Nil(t, err) + assert.Equal(t, 1, len(scc.stateChanges)) + + err = scc.RevertToIndex(0) + require.Nil(t, err) + assert.Equal(t, 0, len(scc.stateChanges)) +} + +func TestStateChangesCollector_SetIndexToLastStateChange(t *testing.T) { + t.Parallel() + + t.Run("should fail if valid index", func(t *testing.T) { + t.Parallel() + + scc := NewStateChangesCollector() + + err := scc.SetIndexToLastStateChange(-1) + require.Equal(t, state.ErrStateChangesIndexOutOfBounds, err) + + numStateChanges := len(scc.stateChanges) + err = scc.SetIndexToLastStateChange(numStateChanges + 1) + require.Equal(t, state.ErrStateChangesIndexOutOfBounds, err) + }) + + t.Run("should work", func(t *testing.T) { + t.Parallel() + + scc := NewStateChangesCollector() + + numStateChanges := 10 + for i := 0; i < numStateChanges; i++ { + scc.AddStateChange(getDefaultStateChange()) + err := scc.SetIndexToLastStateChange(i) + require.Nil(t, err) + } + scc.AddTxHashToCollectedStateChanges([]byte("txHash1"), &transaction.Transaction{}) + + for i := numStateChanges; i < numStateChanges*2; i++ { + scc.AddStateChange(getDefaultStateChange()) + scc.AddTxHashToCollectedStateChanges([]byte("txHash"+fmt.Sprintf("%d", i)), &transaction.Transaction{}) + } + err := scc.SetIndexToLastStateChange(numStateChanges) + require.Nil(t, err) + + assert.Equal(t, numStateChanges*2, len(scc.stateChanges)) + }) +} + +func TestStateChangesCollector_Reset(t *testing.T) { + t.Parallel() + + scc := NewStateChangesCollector() + assert.Equal(t, 0, len(scc.stateChanges)) + + numStateChanges := 10 + for i := 0; i < numStateChanges; i++ { + scc.AddStateChange(getDefaultStateChange()) + } + scc.AddTxHashToCollectedStateChanges([]byte("txHash"), &transaction.Transaction{}) + for i := numStateChanges; i < numStateChanges*2; i++ { + scc.AddStateChange(getDefaultStateChange()) + } + assert.Equal(t, numStateChanges*2, len(scc.stateChanges)) + + assert.Equal(t, 1, len(scc.GetStateChanges())) + + scc.Reset() + assert.Equal(t, 0, len(scc.stateChanges)) + + assert.Equal(t, 0, len(scc.GetStateChanges())) +} + +func TestStateChangesCollector_GetStateChangesForTx(t *testing.T) { + t.Parallel() + + scc := NewStateChangesCollector() + assert.Equal(t, 0, len(scc.stateChanges)) + + numStateChanges := 10 + for i := 0; i < numStateChanges; i++ { + scc.AddStateChange(&data.StateChange{ + Type: "write", + // distribute evenly based on parity of the index + TxHash: []byte(fmt.Sprintf("hash%d", i%2)), + }) + } + + stateChangesForTx := scc.GetStateChangesForTxs() + + require.Len(t, stateChangesForTx, 2) + require.Len(t, stateChangesForTx["hash0"].StateChanges, 5) + require.Len(t, stateChangesForTx["hash1"].StateChanges, 5) + + require.Equal(t, stateChangesForTx, map[string]*data.StateChanges{ + "hash0": { + StateChanges: []*data.StateChange{ + {Type: "write", TxHash: []byte("hash0")}, + {Type: "write", TxHash: []byte("hash0")}, + {Type: "write", TxHash: []byte("hash0")}, + {Type: "write", TxHash: []byte("hash0")}, + {Type: "write", TxHash: []byte("hash0")}, + }, + }, + "hash1": { + StateChanges: []*data.StateChange{ + {Type: "write", TxHash: []byte("hash1")}, + {Type: "write", TxHash: []byte("hash1")}, + {Type: "write", TxHash: []byte("hash1")}, + {Type: "write", TxHash: []byte("hash1")}, + {Type: "write", TxHash: []byte("hash1")}, + }, + }, + }) +} diff --git a/state/stateChangesCollector.go b/state/stateChangesCollector.go deleted file mode 100644 index 9e3f8fabf64..00000000000 --- a/state/stateChangesCollector.go +++ /dev/null @@ -1,67 +0,0 @@ -package state - -// DataTrieChange represents a change in the data trie -type DataTrieChange struct { - Key []byte - Val []byte -} - -// StateChangeDTO is used to collect state changes -type StateChangeDTO struct { - MainTrieKey []byte - MainTrieVal []byte - DataTrieChanges []DataTrieChange -} - -// StateChangesForTx is used to collect state changes for a transaction hash -type StateChangesForTx struct { - TxHash []byte - StateChanges []StateChangeDTO -} - -type stateChangesCollector struct { - stateChanges []StateChangeDTO - stateChangesForTx []StateChangesForTx -} - -// NewStateChangesCollector creates a new StateChangesCollector -func NewStateChangesCollector() *stateChangesCollector { - return &stateChangesCollector{ - stateChanges: []StateChangeDTO{}, - } -} - -// AddStateChange adds a new state change to the collector -func (scc *stateChangesCollector) AddStateChange(stateChange StateChangeDTO) { - scc.stateChanges = append(scc.stateChanges, stateChange) -} - -// GetStateChanges returns the accumulated state changes -func (scc *stateChangesCollector) GetStateChanges() []StateChangesForTx { - if len(scc.stateChanges) > 0 { - scc.AddTxHashToCollectedStateChanges([]byte{}) - } - - return scc.stateChangesForTx -} - -// Reset resets the state changes collector -func (scc *stateChangesCollector) Reset() { - scc.stateChanges = make([]StateChangeDTO, 0) - scc.stateChangesForTx = make([]StateChangesForTx, 0) -} - -func (scc *stateChangesCollector) AddTxHashToCollectedStateChanges(txHash []byte) { - stateChangesForTx := StateChangesForTx{ - TxHash: txHash, - StateChanges: scc.stateChanges, - } - - scc.stateChanges = make([]StateChangeDTO, 0) - scc.stateChangesForTx = append(scc.stateChangesForTx, stateChangesForTx) -} - -// IsInterfaceNil returns true if there is no value under the interface -func (scc *stateChangesCollector) IsInterfaceNil() bool { - return scc == nil -} diff --git a/state/stateChangesCollector_test.go b/state/stateChangesCollector_test.go deleted file mode 100644 index 6a192601f2e..00000000000 --- a/state/stateChangesCollector_test.go +++ /dev/null @@ -1,137 +0,0 @@ -package state - -import ( - "github.com/stretchr/testify/assert" - "strconv" - "testing" - - "github.com/stretchr/testify/require" -) - -func TestNewStateChangesCollector(t *testing.T) { - t.Parallel() - - stateChangesCollector := NewStateChangesCollector() - require.False(t, stateChangesCollector.IsInterfaceNil()) -} - -func TestStateChangesCollector_AddStateChange(t *testing.T) { - t.Parallel() - - scc := NewStateChangesCollector() - assert.Equal(t, 0, len(scc.stateChanges)) - - numStateChanges := 10 - for i := 0; i < numStateChanges; i++ { - scc.AddStateChange(StateChangeDTO{}) - } - assert.Equal(t, numStateChanges, len(scc.stateChanges)) -} - -func TestStateChangesCollector_GetStateChanges(t *testing.T) { - t.Parallel() - - t.Run("getStateChanges with tx hash", func(t *testing.T) { - t.Parallel() - - scc := NewStateChangesCollector() - assert.Equal(t, 0, len(scc.stateChanges)) - assert.Equal(t, 0, len(scc.stateChangesForTx)) - - numStateChanges := 10 - for i := 0; i < numStateChanges; i++ { - scc.AddStateChange(StateChangeDTO{ - MainTrieKey: []byte(strconv.Itoa(i)), - }) - } - assert.Equal(t, numStateChanges, len(scc.stateChanges)) - assert.Equal(t, 0, len(scc.stateChangesForTx)) - scc.AddTxHashToCollectedStateChanges([]byte("txHash")) - assert.Equal(t, 0, len(scc.stateChanges)) - assert.Equal(t, 1, len(scc.stateChangesForTx)) - assert.Equal(t, []byte("txHash"), scc.stateChangesForTx[0].TxHash) - assert.Equal(t, numStateChanges, len(scc.stateChangesForTx[0].StateChanges)) - - stateChangesForTx := scc.GetStateChanges() - assert.Equal(t, 1, len(stateChangesForTx)) - assert.Equal(t, []byte("txHash"), stateChangesForTx[0].TxHash) - for i := 0; i < len(stateChangesForTx[0].StateChanges); i++ { - assert.Equal(t, []byte(strconv.Itoa(i)), stateChangesForTx[0].StateChanges[i].MainTrieKey) - } - }) - - t.Run("getStateChanges without tx hash", func(t *testing.T) { - t.Parallel() - - scc := NewStateChangesCollector() - assert.Equal(t, 0, len(scc.stateChanges)) - assert.Equal(t, 0, len(scc.stateChangesForTx)) - - numStateChanges := 10 - for i := 0; i < numStateChanges; i++ { - scc.AddStateChange(StateChangeDTO{ - MainTrieKey: []byte(strconv.Itoa(i)), - }) - } - assert.Equal(t, numStateChanges, len(scc.stateChanges)) - assert.Equal(t, 0, len(scc.stateChangesForTx)) - - stateChangesForTx := scc.GetStateChanges() - assert.Equal(t, 1, len(stateChangesForTx)) - assert.Equal(t, []byte{}, stateChangesForTx[0].TxHash) - for i := 0; i < len(stateChangesForTx[0].StateChanges); i++ { - assert.Equal(t, []byte(strconv.Itoa(i)), stateChangesForTx[0].StateChanges[i].MainTrieKey) - } - }) -} - -func TestStateChangesCollector_AddTxHashToCollectedStateChanges(t *testing.T) { - t.Parallel() - - scc := NewStateChangesCollector() - assert.Equal(t, 0, len(scc.stateChanges)) - assert.Equal(t, 0, len(scc.stateChangesForTx)) - - stateChange := StateChangeDTO{ - MainTrieKey: []byte("mainTrieKey"), - MainTrieVal: []byte("mainTrieVal"), - DataTrieChanges: []DataTrieChange{{Key: []byte("dataTrieKey"), Val: []byte("dataTrieVal")}}, - } - scc.AddStateChange(stateChange) - - assert.Equal(t, 1, len(scc.stateChanges)) - assert.Equal(t, 0, len(scc.stateChangesForTx)) - scc.AddTxHashToCollectedStateChanges([]byte("txHash")) - assert.Equal(t, 0, len(scc.stateChanges)) - assert.Equal(t, 1, len(scc.stateChangesForTx)) - - stateChangesForTx := scc.GetStateChanges() - assert.Equal(t, 1, len(stateChangesForTx)) - assert.Equal(t, []byte("txHash"), stateChangesForTx[0].TxHash) - assert.Equal(t, 1, len(stateChangesForTx[0].StateChanges)) - assert.Equal(t, []byte("mainTrieKey"), stateChangesForTx[0].StateChanges[0].MainTrieKey) - assert.Equal(t, []byte("mainTrieVal"), stateChangesForTx[0].StateChanges[0].MainTrieVal) - assert.Equal(t, 1, len(stateChangesForTx[0].StateChanges[0].DataTrieChanges)) -} - -func TestStateChangesCollector_Reset(t *testing.T) { - t.Parallel() - - scc := NewStateChangesCollector() - assert.Equal(t, 0, len(scc.stateChanges)) - - numStateChanges := 10 - for i := 0; i < numStateChanges; i++ { - scc.AddStateChange(StateChangeDTO{}) - } - scc.AddTxHashToCollectedStateChanges([]byte("txHash")) - for i := numStateChanges; i < numStateChanges*2; i++ { - scc.AddStateChange(StateChangeDTO{}) - } - assert.Equal(t, numStateChanges, len(scc.stateChanges)) - assert.Equal(t, 1, len(scc.stateChangesForTx)) - - scc.Reset() - assert.Equal(t, 0, len(scc.stateChanges)) - assert.Equal(t, 0, len(scc.stateChangesForTx)) -} diff --git a/state/storagePruningManager/storagePruningManager_test.go b/state/storagePruningManager/storagePruningManager_test.go index a66f979eefe..8f8c39cee1f 100644 --- a/state/storagePruningManager/storagePruningManager_test.go +++ b/state/storagePruningManager/storagePruningManager_test.go @@ -11,6 +11,7 @@ import ( "github.com/multiversx/mx-chain-go/state/factory" "github.com/multiversx/mx-chain-go/state/iteratorChannelsProvider" "github.com/multiversx/mx-chain-go/state/lastSnapshotMarker" + "github.com/multiversx/mx-chain-go/state/stateChanges" "github.com/multiversx/mx-chain-go/state/storagePruningManager/evictionWaitingList" "github.com/multiversx/mx-chain-go/testscommon" "github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock" @@ -39,10 +40,14 @@ func getDefaultTrieAndAccountsDbAndStoragePruningManager() (common.Trie, *state. } ewl, _ := evictionWaitingList.NewMemoryEvictionWaitingList(ewlArgs) spm, _ := NewStoragePruningManager(ewl, generalCfg.PruningBufferLen) + + stateChangesCollector := stateChanges.NewStateChangesCollector() + argsAccCreator := factory.ArgsAccountCreator{ - Hasher: hasher, - Marshaller: marshaller, - EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + Hasher: hasher, + Marshaller: marshaller, + EnableEpochsHandler: &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + StateChangesCollector: stateChangesCollector, } accCreator, _ := factory.NewAccountCreator(argsAccCreator) @@ -66,7 +71,7 @@ func getDefaultTrieAndAccountsDbAndStoragePruningManager() (common.Trie, *state. StoragePruningManager: spm, AddressConverter: &testscommon.PubkeyConverterMock{}, SnapshotsManager: snapshotsManager, - StateChangesCollector: state.NewStateChangesCollector(), + StateChangesCollector: stateChangesCollector, } adb, _ := state.NewAccountsDB(argsAccountsDB) diff --git a/state/trackableDataTrie/trackableDataTrie.go b/state/trackableDataTrie/trackableDataTrie.go index b8e15944fbb..4d4f52a8e27 100644 --- a/state/trackableDataTrie/trackableDataTrie.go +++ b/state/trackableDataTrie/trackableDataTrie.go @@ -8,15 +8,18 @@ import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/core/check" "github.com/multiversx/mx-chain-core-go/data" + "github.com/multiversx/mx-chain-core-go/data/stateChange" "github.com/multiversx/mx-chain-core-go/hashing" "github.com/multiversx/mx-chain-core-go/marshal" + + logger "github.com/multiversx/mx-chain-logger-go" + vmcommon "github.com/multiversx/mx-chain-vm-common-go" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/common/holders" errorsCommon "github.com/multiversx/mx-chain-go/errors" "github.com/multiversx/mx-chain-go/state" "github.com/multiversx/mx-chain-go/state/dataTrieValue" - logger "github.com/multiversx/mx-chain-logger-go" - vmcommon "github.com/multiversx/mx-chain-vm-common-go" ) var log = logger.GetOrCreate("state/trackableDataTrie") @@ -29,12 +32,13 @@ type dirtyData struct { // TrackableDataTrie wraps a PatriciaMerkelTrie adding modifying data capabilities type trackableDataTrie struct { - dirtyData map[string]dirtyData - tr common.Trie - hasher hashing.Hasher - marshaller marshal.Marshalizer - enableEpochsHandler common.EnableEpochsHandler - identifier []byte + dirtyData map[string]dirtyData + tr common.Trie + hasher hashing.Hasher + marshaller marshal.Marshalizer + enableEpochsHandler common.EnableEpochsHandler + identifier []byte + stateChangesCollector state.StateChangesCollector } // NewTrackableDataTrie returns an instance of trackableDataTrie @@ -43,6 +47,7 @@ func NewTrackableDataTrie( hasher hashing.Hasher, marshaller marshal.Marshalizer, enableEpochsHandler common.EnableEpochsHandler, + stateChangesCollector state.StateChangesCollector, ) (*trackableDataTrie, error) { if check.IfNil(hasher) { return nil, state.ErrNilHasher @@ -53,6 +58,10 @@ func NewTrackableDataTrie( if check.IfNil(enableEpochsHandler) { return nil, state.ErrNilEnableEpochsHandler } + if check.IfNil(stateChangesCollector) { + return nil, state.ErrNilStateChangesCollector + } + err := core.CheckHandlerCompatibility(enableEpochsHandler, []core.EnableEpochFlag{ common.AutoBalanceDataTriesFlag, }) @@ -61,12 +70,13 @@ func NewTrackableDataTrie( } return &trackableDataTrie{ - tr: nil, - hasher: hasher, - marshaller: marshaller, - dirtyData: make(map[string]dirtyData), - identifier: identifier, - enableEpochsHandler: enableEpochsHandler, + tr: nil, + hasher: hasher, + marshaller: marshaller, + dirtyData: make(map[string]dirtyData), + identifier: identifier, + enableEpochsHandler: enableEpochsHandler, + stateChangesCollector: stateChangesCollector, }, nil } @@ -77,6 +87,7 @@ func (tdt *trackableDataTrie) RetrieveValue(key []byte) ([]byte, uint32, error) // search in dirty data cache if dataEntry, found := tdt.dirtyData[string(key)]; found { log.Trace("retrieve value from dirty data", "key", key, "value", dataEntry.value, "account", tdt.identifier) + return dataEntry.value, 0, nil } @@ -96,6 +107,20 @@ func (tdt *trackableDataTrie) RetrieveValue(key []byte) ([]byte, uint32, error) log.Trace("retrieve value from trie", "key", key, "value", val, "account", tdt.identifier) + stateChange := &stateChange.StateChange{ + Type: "read", + MainTrieKey: tdt.identifier, + MainTrieVal: nil, + DataTrieChanges: []*stateChange.DataTrieChange{ + { + Type: "read", + Key: key, + Val: val, + }, + }, + } + tdt.stateChangesCollector.AddStateChange(stateChange) + return val, depth, nil } @@ -223,9 +248,9 @@ func (tdt *trackableDataTrie) DataTrie() common.DataTrieHandler { } // SaveDirtyData saved the dirty data to the trie -func (tdt *trackableDataTrie) SaveDirtyData(mainTrie common.Trie) ([]state.DataTrieChange, []core.TrieData, error) { +func (tdt *trackableDataTrie) SaveDirtyData(mainTrie common.Trie) ([]*stateChange.DataTrieChange, []core.TrieData, error) { if len(tdt.dirtyData) == 0 { - return make([]state.DataTrieChange, 0), make([]core.TrieData, 0), nil + return make([]*stateChange.DataTrieChange, 0), make([]core.TrieData, 0), nil } if check.IfNil(tdt.tr) { @@ -246,10 +271,10 @@ func (tdt *trackableDataTrie) SaveDirtyData(mainTrie common.Trie) ([]state.DataT return tdt.updateTrie(dtr) } -func (tdt *trackableDataTrie) updateTrie(dtr state.DataTrie) ([]state.DataTrieChange, []core.TrieData, error) { +func (tdt *trackableDataTrie) updateTrie(dtr state.DataTrie) ([]*stateChange.DataTrieChange, []core.TrieData, error) { oldValues := make([]core.TrieData, len(tdt.dirtyData)) - newData := make([]state.DataTrieChange, len(tdt.dirtyData)) - deletedKeys := make([]state.DataTrieChange, 0) + newData := make([]*stateChange.DataTrieChange, len(tdt.dirtyData)) + deletedKeys := make([]*stateChange.DataTrieChange, 0) index := 0 for key, dataEntry := range tdt.dirtyData { @@ -266,9 +291,10 @@ func (tdt *trackableDataTrie) updateTrie(dtr state.DataTrie) ([]state.DataTrieCh if wasDeleted { deletedKeys = append(deletedKeys, - state.DataTrieChange{ - Key: []byte(key), - Val: nil, + &stateChange.DataTrieChange{ + Type: "write", + Key: []byte(key), + Val: nil, }, ) } @@ -296,16 +322,20 @@ func (tdt *trackableDataTrie) updateTrie(dtr state.DataTrie) ([]state.DataTrieCh return nil, nil, fmt.Errorf("index out of range") } - newData[dataEntry.index] = state.DataTrieChange{ - Key: dataTrieKey, - Val: dataTrieVal, + newData[dataEntry.index] = &stateChange.DataTrieChange{ + Type: "write", + Key: dataTrieKey, + Val: dataTrieVal, } } tdt.dirtyData = make(map[string]dirtyData) - stateChanges := make([]state.DataTrieChange, 0) + stateChanges := make([]*stateChange.DataTrieChange, 0) for i := range newData { + if newData[i] == nil { + continue + } if len(newData[i].Key) == 0 { continue } diff --git a/state/trackableDataTrie/trackableDataTrie_test.go b/state/trackableDataTrie/trackableDataTrie_test.go index 376e84d8066..99e492f186c 100644 --- a/state/trackableDataTrie/trackableDataTrie_test.go +++ b/state/trackableDataTrie/trackableDataTrie_test.go @@ -11,6 +11,7 @@ import ( errorsCommon "github.com/multiversx/mx-chain-go/errors" "github.com/multiversx/mx-chain-go/state" "github.com/multiversx/mx-chain-go/state/dataTrieValue" + "github.com/multiversx/mx-chain-go/state/stateChanges" "github.com/multiversx/mx-chain-go/state/trackableDataTrie" "github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock" "github.com/multiversx/mx-chain-go/testscommon/hashingMocks" @@ -27,7 +28,13 @@ func TestNewTrackableDataTrie(t *testing.T) { t.Run("create with nil hasher", func(t *testing.T) { t.Parallel() - tdt, err := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), nil, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}) + tdt, err := trackableDataTrie.NewTrackableDataTrie( + []byte("identifier"), + nil, + &marshallerMock.MarshalizerMock{}, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + stateChanges.NewStateChangesCollector(), + ) assert.Equal(t, state.ErrNilHasher, err) assert.True(t, check.IfNil(tdt)) }) @@ -35,7 +42,13 @@ func TestNewTrackableDataTrie(t *testing.T) { t.Run("create with nil marshaller", func(t *testing.T) { t.Parallel() - tdt, err := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), &hashingMocks.HasherMock{}, nil, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}) + tdt, err := trackableDataTrie.NewTrackableDataTrie( + []byte("identifier"), + &hashingMocks.HasherMock{}, + nil, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + stateChanges.NewStateChangesCollector(), + ) assert.Equal(t, state.ErrNilMarshalizer, err) assert.True(t, check.IfNil(tdt)) }) @@ -43,7 +56,13 @@ func TestNewTrackableDataTrie(t *testing.T) { t.Run("create with nil enableEpochsHandler", func(t *testing.T) { t.Parallel() - tdt, err := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, nil) + tdt, err := trackableDataTrie.NewTrackableDataTrie( + []byte("identifier"), + &hashingMocks.HasherMock{}, + &marshallerMock.MarshalizerMock{}, + nil, + stateChanges.NewStateChangesCollector(), + ) assert.Equal(t, state.ErrNilEnableEpochsHandler, err) assert.True(t, check.IfNil(tdt)) }) @@ -55,7 +74,9 @@ func TestNewTrackableDataTrie(t *testing.T) { []byte("identifier"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, - enableEpochsHandlerMock.NewEnableEpochsHandlerStubWithNoFlagsDefined()) + enableEpochsHandlerMock.NewEnableEpochsHandlerStubWithNoFlagsDefined(), + stateChanges.NewStateChangesCollector(), + ) assert.True(t, errors.Is(err, core.ErrInvalidEnableEpochsHandler)) assert.True(t, check.IfNil(tdt)) }) @@ -63,7 +84,13 @@ func TestNewTrackableDataTrie(t *testing.T) { t.Run("should work", func(t *testing.T) { t.Parallel() - tdt, err := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}) + tdt, err := trackableDataTrie.NewTrackableDataTrie( + []byte("identifier"), + &hashingMocks.HasherMock{}, + &marshallerMock.MarshalizerMock{}, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + stateChanges.NewStateChangesCollector(), + ) assert.Nil(t, err) assert.False(t, check.IfNil(tdt)) }) @@ -75,7 +102,13 @@ func TestTrackableDataTrie_SaveKeyValue(t *testing.T) { t.Run("data too large", func(t *testing.T) { t.Parallel() - tdt, _ := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}) + tdt, _ := trackableDataTrie.NewTrackableDataTrie( + []byte("identifier"), + &hashingMocks.HasherMock{}, + &marshallerMock.MarshalizerMock{}, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + stateChanges.NewStateChangesCollector(), + ) err := tdt.SaveKeyValue([]byte("key"), make([]byte, core.MaxLeafSize+1)) assert.Equal(t, err, data.ErrLeafSizeTooBig) @@ -96,7 +129,13 @@ func TestTrackableDataTrie_SaveKeyValue(t *testing.T) { return nil, 0, nil }, } - tdt, _ := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}) + tdt, _ := trackableDataTrie.NewTrackableDataTrie( + []byte("identifier"), + &hashingMocks.HasherMock{}, + &marshallerMock.MarshalizerMock{}, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + stateChanges.NewStateChangesCollector(), + ) assert.NotNil(t, tdt) tdt.SetDataTrie(trie) @@ -129,13 +168,19 @@ func TestTrackableDataTrie_RetrieveValue(t *testing.T) { return nil, 0, nil }, } - tdt, _ := trackableDataTrie.NewTrackableDataTrie(identifier, &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}) + tdt, _ := trackableDataTrie.NewTrackableDataTrie( + identifier, + &hashingMocks.HasherMock{}, + &marshallerMock.MarshalizerMock{}, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + stateChanges.NewStateChangesCollector(), + ) assert.NotNil(t, tdt) tdt.SetDataTrie(trie) valRecovered, _, err := tdt.RetrieveValue(key) - assert.Equal(t, retrievedTrieVal, valRecovered) assert.Nil(t, err) + assert.Equal(t, retrievedTrieVal, valRecovered) _ = tdt.SaveKeyValue(key, newTrieValue) valRecovered, _, err = tdt.RetrieveValue(key) @@ -146,7 +191,13 @@ func TestTrackableDataTrie_RetrieveValue(t *testing.T) { t.Run("nil data trie should err", func(t *testing.T) { t.Parallel() - tdt, err := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}) + tdt, err := trackableDataTrie.NewTrackableDataTrie( + []byte("identifier"), + &hashingMocks.HasherMock{}, + &marshallerMock.MarshalizerMock{}, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + stateChanges.NewStateChangesCollector(), + ) assert.Nil(t, err) assert.NotNil(t, tdt) @@ -176,7 +227,13 @@ func TestTrackableDataTrie_RetrieveValue(t *testing.T) { return flag == common.AutoBalanceDataTriesFlag }, } - tdt, _ := trackableDataTrie.NewTrackableDataTrie(identifier, &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, enableEpochsHandler) + tdt, _ := trackableDataTrie.NewTrackableDataTrie( + identifier, + &hashingMocks.HasherMock{}, + &marshallerMock.MarshalizerMock{}, + enableEpochsHandler, + stateChanges.NewStateChangesCollector(), + ) assert.NotNil(t, tdt) tdt.SetDataTrie(trie) @@ -211,7 +268,13 @@ func TestTrackableDataTrie_RetrieveValue(t *testing.T) { return false }, } - tdt, _ := trackableDataTrie.NewTrackableDataTrie(identifier, &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, enableEpochsHandler) + tdt, _ := trackableDataTrie.NewTrackableDataTrie( + identifier, + &hashingMocks.HasherMock{}, + &marshallerMock.MarshalizerMock{}, + enableEpochsHandler, + stateChanges.NewStateChangesCollector(), + ) assert.NotNil(t, tdt) tdt.SetDataTrie(trie) @@ -250,7 +313,13 @@ func TestTrackableDataTrie_RetrieveValue(t *testing.T) { return flag == common.AutoBalanceDataTriesFlag }, } - tdt, _ := trackableDataTrie.NewTrackableDataTrie(identifier, hasher, marshaller, enableEpochsHandler) + tdt, _ := trackableDataTrie.NewTrackableDataTrie( + identifier, + hasher, + marshaller, + enableEpochsHandler, + stateChanges.NewStateChangesCollector(), + ) assert.NotNil(t, tdt) tdt.SetDataTrie(trie) @@ -269,7 +338,13 @@ func TestTrackableDataTrie_RetrieveValue(t *testing.T) { return nil, 0, errExpected }, } - tdt, _ := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}) + tdt, _ := trackableDataTrie.NewTrackableDataTrie( + []byte("identifier"), + &hashingMocks.HasherMock{}, + &marshallerMock.MarshalizerMock{}, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + stateChanges.NewStateChangesCollector(), + ) assert.NotNil(t, tdt) tdt.SetDataTrie(trie) @@ -304,6 +379,7 @@ func TestTrackableDataTrie_RetrieveValue(t *testing.T) { hasher, marshaller, enableEpochsHandler, + stateChanges.NewStateChangesCollector(), ) assert.NotNil(t, tdt) tdt.SetDataTrie(trie) @@ -339,6 +415,7 @@ func TestTrackableDataTrie_RetrieveValue(t *testing.T) { hasher, marshaller, enableEpochsHandler, + stateChanges.NewStateChangesCollector(), ) assert.NotNil(t, tdt) tdt.SetDataTrie(trie) @@ -355,7 +432,13 @@ func TestTrackableDataTrie_SaveDirtyData(t *testing.T) { t.Run("no dirty data", func(t *testing.T) { t.Parallel() - tdt, _ := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}) + tdt, _ := trackableDataTrie.NewTrackableDataTrie( + []byte("identifier"), + &hashingMocks.HasherMock{}, + &marshallerMock.MarshalizerMock{}, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + stateChanges.NewStateChangesCollector(), + ) stateChanges, oldValues, err := tdt.SaveDirtyData(&trieMock.TrieStub{}) assert.Nil(t, err) @@ -380,7 +463,14 @@ func TestTrackableDataTrie_SaveDirtyData(t *testing.T) { }, nil }, } - tdt, _ := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}) + + tdt, _ := trackableDataTrie.NewTrackableDataTrie( + []byte("identifier"), + &hashingMocks.HasherMock{}, + &marshallerMock.MarshalizerMock{}, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + stateChanges.NewStateChangesCollector(), + ) key := []byte("key") val := []byte("val") @@ -410,7 +500,13 @@ func TestTrackableDataTrie_SaveDirtyData(t *testing.T) { return flag == common.AutoBalanceDataTriesFlag }, } - tdt, _ := trackableDataTrie.NewTrackableDataTrie(identifier, hasher, marshaller, enableEpochsHandler) + tdt, _ := trackableDataTrie.NewTrackableDataTrie( + identifier, + hasher, + marshaller, + enableEpochsHandler, + stateChanges.NewStateChangesCollector(), + ) expectedKey := []byte("key") expectedVal := []byte("value") @@ -437,7 +533,7 @@ func TestTrackableDataTrie_SaveDirtyData(t *testing.T) { }, } - tdt, _ = trackableDataTrie.NewTrackableDataTrie(identifier, hasher, marshaller, enableEpochsHandler) + tdt, _ = trackableDataTrie.NewTrackableDataTrie(identifier, hasher, marshaller, enableEpochsHandler, stateChanges.NewStateChangesCollector()) tdt.SetDataTrie(trie) _ = tdt.SaveKeyValue(expectedKey, expectedVal) @@ -470,7 +566,13 @@ func TestTrackableDataTrie_SaveDirtyData(t *testing.T) { }, } - tdt, _ := trackableDataTrie.NewTrackableDataTrie(identifier, hasher, marshaller, enableEpochsHandler) + tdt, _ := trackableDataTrie.NewTrackableDataTrie( + identifier, + hasher, + marshaller, + enableEpochsHandler, + stateChanges.NewStateChangesCollector(), + ) expectedKey := []byte("key") val := []byte("value") @@ -495,7 +597,7 @@ func TestTrackableDataTrie_SaveDirtyData(t *testing.T) { }, } - tdt, _ = trackableDataTrie.NewTrackableDataTrie(identifier, hasher, marshaller, enableEpochsHandler) + tdt, _ = trackableDataTrie.NewTrackableDataTrie(identifier, hasher, marshaller, enableEpochsHandler, stateChanges.NewStateChangesCollector()) tdt.SetDataTrie(trie) _ = tdt.SaveKeyValue(expectedKey, val) @@ -522,7 +624,13 @@ func TestTrackableDataTrie_SaveDirtyData(t *testing.T) { return flag == common.AutoBalanceDataTriesFlag }, } - tdt, _ := trackableDataTrie.NewTrackableDataTrie(identifier, hasher, marshaller, enableEpochsHandler) + tdt, _ := trackableDataTrie.NewTrackableDataTrie( + identifier, + hasher, + marshaller, + enableEpochsHandler, + stateChanges.NewStateChangesCollector(), + ) expectedKey := []byte("key") newVal := []byte("value") @@ -549,7 +657,13 @@ func TestTrackableDataTrie_SaveDirtyData(t *testing.T) { }, } - tdt, _ = trackableDataTrie.NewTrackableDataTrie(identifier, hasher, marshaller, enableEpochsHandler) + tdt, _ = trackableDataTrie.NewTrackableDataTrie( + identifier, + hasher, + marshaller, + enableEpochsHandler, + stateChanges.NewStateChangesCollector(), + ) tdt.SetDataTrie(trie) _ = tdt.SaveKeyValue(expectedKey, newVal) @@ -576,7 +690,13 @@ func TestTrackableDataTrie_SaveDirtyData(t *testing.T) { return flag == common.AutoBalanceDataTriesFlag }, } - tdt, _ := trackableDataTrie.NewTrackableDataTrie(identifier, hasher, marshaller, enableEpochsHandler) + tdt, _ := trackableDataTrie.NewTrackableDataTrie( + identifier, + hasher, + marshaller, + enableEpochsHandler, + stateChanges.NewStateChangesCollector(), + ) expectedKey := []byte("key") newVal := []byte("value") @@ -598,7 +718,7 @@ func TestTrackableDataTrie_SaveDirtyData(t *testing.T) { }, } - tdt, _ = trackableDataTrie.NewTrackableDataTrie(identifier, hasher, marshaller, enableEpochsHandler) + tdt, _ = trackableDataTrie.NewTrackableDataTrie(identifier, hasher, marshaller, enableEpochsHandler, stateChanges.NewStateChangesCollector()) tdt.SetDataTrie(trie) _ = tdt.SaveKeyValue(expectedKey, newVal) @@ -628,7 +748,7 @@ func TestTrackableDataTrie_SaveDirtyData(t *testing.T) { }, } - tdt, _ := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}) + tdt, _ := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, stateChanges.NewStateChangesCollector()) tdt.SetDataTrie(trie) _ = tdt.SaveKeyValue(expectedKey, val) @@ -653,7 +773,7 @@ func TestTrackableDataTrie_SaveDirtyData(t *testing.T) { }, } - tdt, _ := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}) + tdt, _ := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, stateChanges.NewStateChangesCollector()) tdt.SetDataTrie(trie) _ = tdt.SaveKeyValue(expectedKey, nil) @@ -682,7 +802,7 @@ func TestTrackableDataTrie_SaveDirtyData(t *testing.T) { }, } - tdt, _ := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}) + tdt, _ := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, stateChanges.NewStateChangesCollector()) tdt.SetDataTrie(trie) _ = tdt.SaveKeyValue(expectedKey, nil) @@ -719,7 +839,7 @@ func TestTrackableDataTrie_SaveDirtyData(t *testing.T) { return flag == common.AutoBalanceDataTriesFlag }, } - tdt, _ := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, enableEpchs) + tdt, _ := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, enableEpchs, stateChanges.NewStateChangesCollector()) tdt.SetDataTrie(trie) _ = tdt.SaveKeyValue(expectedKey, nil) @@ -757,7 +877,7 @@ func TestTrackableDataTrie_SaveDirtyData(t *testing.T) { return flag == common.AutoBalanceDataTriesFlag }, } - tdt, _ := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, enableEpchs) + tdt, _ := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, enableEpchs, stateChanges.NewStateChangesCollector()) tdt.SetDataTrie(trie) _ = tdt.SaveKeyValue(expectedKey, nil) @@ -787,6 +907,7 @@ func TestTrackableDataTrie_SaveDirtyData(t *testing.T) { hasher, marshaller, enableEpochsHandler, + stateChanges.NewStateChangesCollector(), ) expectedKey := []byte("key") @@ -838,6 +959,7 @@ func TestTrackableDataTrie_SaveDirtyData(t *testing.T) { hasher, marshaller, enableEpochsHandler, + stateChanges.NewStateChangesCollector(), ) key1 := "key1" @@ -903,7 +1025,13 @@ func TestTrackableDataTrie_MigrateDataTrieLeaves(t *testing.T) { t.Run("nil trie", func(t *testing.T) { t.Parallel() - tdt, _ := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}) + tdt, _ := trackableDataTrie.NewTrackableDataTrie( + []byte("identifier"), + &hashingMocks.HasherMock{}, + &marshallerMock.MarshalizerMock{}, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + stateChanges.NewStateChangesCollector(), + ) args := vmcommon.ArgsMigrateDataTrieLeaves{ OldVersion: core.NotSpecified, NewVersion: core.AutoBalanceEnabled, @@ -916,7 +1044,13 @@ func TestTrackableDataTrie_MigrateDataTrieLeaves(t *testing.T) { t.Run("nil trie migrator", func(t *testing.T) { t.Parallel() - tdt, _ := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}) + tdt, _ := trackableDataTrie.NewTrackableDataTrie( + []byte("identifier"), + &hashingMocks.HasherMock{}, + &marshallerMock.MarshalizerMock{}, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + stateChanges.NewStateChangesCollector(), + ) tdt.SetDataTrie(&trieMock.TrieStub{}) args := vmcommon.ArgsMigrateDataTrieLeaves{ @@ -938,7 +1072,13 @@ func TestTrackableDataTrie_MigrateDataTrieLeaves(t *testing.T) { }, } - tdt, _ := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}) + tdt, _ := trackableDataTrie.NewTrackableDataTrie( + []byte("identifier"), + &hashingMocks.HasherMock{}, + &marshallerMock.MarshalizerMock{}, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + stateChanges.NewStateChangesCollector(), + ) tdt.SetDataTrie(tr) args := vmcommon.ArgsMigrateDataTrieLeaves{ OldVersion: core.NotSpecified, @@ -987,7 +1127,13 @@ func TestTrackableDataTrie_MigrateDataTrieLeaves(t *testing.T) { }, } - tdt, _ := trackableDataTrie.NewTrackableDataTrie(address, &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, enableEpchs) + tdt, _ := trackableDataTrie.NewTrackableDataTrie( + address, + &hashingMocks.HasherMock{}, + &marshallerMock.MarshalizerMock{}, + enableEpchs, + stateChanges.NewStateChangesCollector(), + ) tdt.SetDataTrie(tr) args := vmcommon.ArgsMigrateDataTrieLeaves{ OldVersion: core.NotSpecified, @@ -1010,7 +1156,13 @@ func TestTrackableDataTrie_MigrateDataTrieLeaves(t *testing.T) { func TestTrackableDataTrie_SetAndGetDataTrie(t *testing.T) { t.Parallel() - tdt, _ := trackableDataTrie.NewTrackableDataTrie([]byte("identifier"), &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}) + tdt, _ := trackableDataTrie.NewTrackableDataTrie( + []byte("identifier"), + &hashingMocks.HasherMock{}, + &marshallerMock.MarshalizerMock{}, + &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + stateChanges.NewStateChangesCollector(), + ) newTrie := &trieMock.TrieStub{} tdt.SetDataTrie(newTrie) diff --git a/storage/errors.go b/storage/errors.go index 4cf2716bfab..6eb89672527 100644 --- a/storage/errors.go +++ b/storage/errors.go @@ -82,6 +82,9 @@ var ErrNotSupportedCacheType = storageErrors.ErrNotSupportedCacheType // ErrDBIsClosed is raised when the DB is closed var ErrDBIsClosed = storageErrors.ErrDBIsClosed +// ErrNilPersister is raised when a nil persister is provided +var ErrNilPersister = storageErrors.ErrNilPersister + // ErrEpochKeepIsLowerThanNumActive signals that num epochs to keep is lower than num active epochs var ErrEpochKeepIsLowerThanNumActive = errors.New("num epochs to keep is lower than num active epochs") diff --git a/testscommon/factory/stateComponentsMock.go b/testscommon/factory/stateComponentsMock.go index 5aa541dffa0..eb2b586db9e 100644 --- a/testscommon/factory/stateComponentsMock.go +++ b/testscommon/factory/stateComponentsMock.go @@ -16,6 +16,7 @@ type StateComponentsMock struct { Tries common.TriesHolder StorageManagers map[string]common.StorageManager MissingNodesNotifier common.MissingTrieNodesNotifier + ChangesCollector state.StateChangesCollector } // NewStateComponentsMockFromRealComponent - @@ -89,6 +90,11 @@ func (scm *StateComponentsMock) MissingTrieNodesNotifier() common.MissingTrieNod return scm.MissingNodesNotifier } +// StateChangesCollector - +func (scm *StateComponentsMock) StateChangesCollector() state.StateChangesCollector { + return scm.ChangesCollector +} + // IsInterfaceNil - func (scm *StateComponentsMock) IsInterfaceNil() bool { return scm == nil diff --git a/testscommon/integrationtests/factory.go b/testscommon/integrationtests/factory.go index ef9d7ae2257..653d5375404 100644 --- a/testscommon/integrationtests/factory.go +++ b/testscommon/integrationtests/factory.go @@ -7,6 +7,7 @@ import ( "github.com/multiversx/mx-chain-go/common/statistics" "github.com/multiversx/mx-chain-go/config" "github.com/multiversx/mx-chain-go/state" + "github.com/multiversx/mx-chain-go/state/disabled" accountFactory "github.com/multiversx/mx-chain-go/state/factory" "github.com/multiversx/mx-chain-go/state/iteratorChannelsProvider" "github.com/multiversx/mx-chain-go/state/lastSnapshotMarker" @@ -104,9 +105,10 @@ func CreateAccountsDB(db storage.Storer, enableEpochs common.EnableEpochsHandler spm, _ := storagePruningManager.NewStoragePruningManager(ewl, 10) argsAccCreator := accountFactory.ArgsAccountCreator{ - Hasher: TestHasher, - Marshaller: TestMarshalizer, - EnableEpochsHandler: enableEpochs, + Hasher: TestHasher, + Marshaller: TestMarshalizer, + EnableEpochsHandler: enableEpochs, + StateChangesCollector: disabled.NewDisabledStateChangesCollector(), } accCreator, _ := accountFactory.NewAccountCreator(argsAccCreator) @@ -130,7 +132,7 @@ func CreateAccountsDB(db storage.Storer, enableEpochs common.EnableEpochsHandler StoragePruningManager: spm, AddressConverter: &testscommon.PubkeyConverterMock{}, SnapshotsManager: snapshotsManager, - StateChangesCollector: state.NewStateChangesCollector(), + StateChangesCollector: disabled.NewDisabledStateChangesCollector(), } adb, _ := state.NewAccountsDB(argsAccountsDB) diff --git a/testscommon/p2pmocks/messengerStub.go b/testscommon/p2pmocks/messengerStub.go index c48c95b9868..d3ab2154034 100644 --- a/testscommon/p2pmocks/messengerStub.go +++ b/testscommon/p2pmocks/messengerStub.go @@ -4,6 +4,7 @@ import ( "time" "github.com/multiversx/mx-chain-core-go/core" + "github.com/multiversx/mx-chain-go/p2p" ) diff --git a/testscommon/state/accountWrapperMock.go b/testscommon/state/accountWrapperMock.go index 75c7ab97517..8d67dfad6aa 100644 --- a/testscommon/state/accountWrapperMock.go +++ b/testscommon/state/accountWrapperMock.go @@ -7,13 +7,16 @@ import ( "math/big" "github.com/multiversx/mx-chain-core-go/core" + "github.com/multiversx/mx-chain-core-go/data/stateChange" + vmcommon "github.com/multiversx/mx-chain-vm-common-go" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/state" + "github.com/multiversx/mx-chain-go/state/disabled" "github.com/multiversx/mx-chain-go/state/trackableDataTrie" "github.com/multiversx/mx-chain-go/testscommon/enableEpochsHandlerMock" "github.com/multiversx/mx-chain-go/testscommon/hashingMocks" "github.com/multiversx/mx-chain-go/testscommon/marshallerMock" - vmcommon "github.com/multiversx/mx-chain-vm-common-go" ) var _ state.UserAccountHandler = (*AccountWrapMock)(nil) @@ -47,6 +50,7 @@ func NewAccountWrapMock(adr []byte) *AccountWrapMock { &hashingMocks.HasherMock{}, &marshallerMock.MarshalizerMock{}, &enableEpochsHandlerMock.EnableEpochsHandlerStub{}, + disabled.NewDisabledStateChangesCollector(), ) return &AccountWrapMock{ @@ -196,7 +200,7 @@ func (awm *AccountWrapMock) DataTrie() common.DataTrieHandler { } // SaveDirtyData - -func (awm *AccountWrapMock) SaveDirtyData(trie common.Trie) ([]state.DataTrieChange, []core.TrieData, error) { +func (awm *AccountWrapMock) SaveDirtyData(trie common.Trie) ([]*stateChange.DataTrieChange, []core.TrieData, error) { return awm.trackableDataTrie.SaveDirtyData(trie) } diff --git a/testscommon/state/accountsAdapterStub.go b/testscommon/state/accountsAdapterStub.go index 4ee84397516..a9d9a0bb1c4 100644 --- a/testscommon/state/accountsAdapterStub.go +++ b/testscommon/state/accountsAdapterStub.go @@ -4,6 +4,7 @@ import ( "context" "errors" + "github.com/multiversx/mx-chain-core-go/data/transaction" "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/state" vmcommon "github.com/multiversx/mx-chain-vm-common-go" @@ -38,8 +39,7 @@ type AccountsStub struct { CloseCalled func() error SetSyncerCalled func(syncer state.AccountsDBSyncer) error StartSnapshotIfNeededCalled func() error - SetTxHashForLatestStateChangesCalled func(txHash []byte) - ResetStateChangesCollectorCalled func() []state.StateChangesForTx + SetTxHashForLatestStateChangesCalled func(txHash []byte, tx *transaction.Transaction) } // CleanCache - @@ -250,21 +250,12 @@ func (as *AccountsStub) GetCodeWithBlockInfo(codeHash []byte, options common.Roo } // SetTxHashForLatestStateChanges - -func (as *AccountsStub) SetTxHashForLatestStateChanges(txHash []byte) { +func (as *AccountsStub) SetTxHashForLatestStateChanges(txHash []byte, tx *transaction.Transaction) { if as.SetTxHashForLatestStateChangesCalled != nil { - as.SetTxHashForLatestStateChangesCalled(txHash) + as.SetTxHashForLatestStateChangesCalled(txHash, tx) } } -// ResetStateChangesCollector - -func (as *AccountsStub) ResetStateChangesCollector() []state.StateChangesForTx { - if as.ResetStateChangesCollectorCalled != nil { - return as.ResetStateChangesCollectorCalled() - } - - return nil -} - // Close - func (as *AccountsStub) Close() error { if as.CloseCalled != nil { diff --git a/testscommon/state/stateChangesCollectorStub.go b/testscommon/state/stateChangesCollectorStub.go new file mode 100644 index 00000000000..c8fc099879f --- /dev/null +++ b/testscommon/state/stateChangesCollectorStub.go @@ -0,0 +1,95 @@ +package state + +import ( + "github.com/multiversx/mx-chain-core-go/data/stateChange" + "github.com/multiversx/mx-chain-core-go/data/transaction" + vmcommon "github.com/multiversx/mx-chain-vm-common-go" + + "github.com/multiversx/mx-chain-go/state" +) + +// StateChangesCollectorStub represents a mock for the StateChangesCollector interface +type StateChangesCollectorStub struct { + AddStateChangeCalled func(stateChange state.StateChange) + AddSaveAccountStateChangeCalled func(oldAccount, account vmcommon.AccountHandler, stateChange state.StateChange) + ResetCalled func() + AddTxHashToCollectedStateChangesCalled func(txHash []byte, tx *transaction.Transaction) + SetIndexToLastStateChangeCalled func(index int) error + RevertToIndexCalled func(index int) error + PublishCalled func() error + IsInterfaceNilCalled func() bool + GetStateChangesForTxsCalled func() map[string]*stateChange.StateChanges +} + +// AddStateChange - +func (s *StateChangesCollectorStub) AddStateChange(stateChange state.StateChange) { + if s.AddStateChangeCalled != nil { + s.AddStateChangeCalled(stateChange) + } +} + +// AddSaveAccountStateChange - +func (s *StateChangesCollectorStub) AddSaveAccountStateChange(oldAccount, account vmcommon.AccountHandler, stateChange state.StateChange) { + if s.AddSaveAccountStateChangeCalled != nil { + s.AddSaveAccountStateChangeCalled(oldAccount, account, stateChange) + } +} + +// Reset - +func (s *StateChangesCollectorStub) Reset() { + if s.ResetCalled != nil { + s.ResetCalled() + } +} + +// AddTxHashToCollectedStateChanges - +func (s *StateChangesCollectorStub) AddTxHashToCollectedStateChanges(txHash []byte, tx *transaction.Transaction) { + if s.AddTxHashToCollectedStateChangesCalled != nil { + s.AddTxHashToCollectedStateChangesCalled(txHash, tx) + } +} + +// SetIndexToLastStateChange - +func (s *StateChangesCollectorStub) SetIndexToLastStateChange(index int) error { + if s.SetIndexToLastStateChangeCalled != nil { + return s.SetIndexToLastStateChangeCalled(index) + } + + return nil +} + +// RevertToIndex - +func (s *StateChangesCollectorStub) RevertToIndex(index int) error { + if s.RevertToIndexCalled != nil { + return s.RevertToIndexCalled(index) + } + + return nil +} + +// Publish - +func (s *StateChangesCollectorStub) Publish() error { + if s.PublishCalled != nil { + return s.PublishCalled() + } + + return nil +} + +// IsInterfaceNil - +func (s *StateChangesCollectorStub) IsInterfaceNil() bool { + if s.IsInterfaceNilCalled != nil { + return s.IsInterfaceNilCalled() + } + + return false +} + +// GetStateChangesForTxs - +func (s *StateChangesCollectorStub) GetStateChangesForTxs() map[string]*stateChange.StateChanges { + if s.GetStateChangesForTxsCalled != nil { + return s.GetStateChangesForTxsCalled() + } + + return nil +} diff --git a/testscommon/state/userAccountStub.go b/testscommon/state/userAccountStub.go index ec386a68dbe..22f28958c6a 100644 --- a/testscommon/state/userAccountStub.go +++ b/testscommon/state/userAccountStub.go @@ -6,15 +6,18 @@ import ( "math/big" "github.com/multiversx/mx-chain-core-go/core" + "github.com/multiversx/mx-chain-core-go/data/stateChange" + vmcommon "github.com/multiversx/mx-chain-vm-common-go" + "github.com/multiversx/mx-chain-go/common" "github.com/multiversx/mx-chain-go/state" - vmcommon "github.com/multiversx/mx-chain-vm-common-go" ) var _ state.UserAccountHandler = (*UserAccountStub)(nil) // UserAccountStub - type UserAccountStub struct { + Nonce uint64 Balance *big.Int DeveloperRewards *big.Int UserName []byte @@ -106,7 +109,7 @@ func (u *UserAccountStub) IncreaseNonce(_ uint64) { // GetNonce - func (u *UserAccountStub) GetNonce() uint64 { - return 0 + return u.Nonce } // SetCode - @@ -189,7 +192,7 @@ func (u *UserAccountStub) IsGuarded() bool { } // SaveDirtyData - -func (u *UserAccountStub) SaveDirtyData(_ common.Trie) ([]state.DataTrieChange, []core.TrieData, error) { +func (u *UserAccountStub) SaveDirtyData(_ common.Trie) ([]*stateChange.DataTrieChange, []core.TrieData, error) { return nil, nil, nil } diff --git a/testscommon/trie/dataTrieTrackerStub.go b/testscommon/trie/dataTrieTrackerStub.go index 60eca7ef978..73c083b30c1 100644 --- a/testscommon/trie/dataTrieTrackerStub.go +++ b/testscommon/trie/dataTrieTrackerStub.go @@ -3,9 +3,10 @@ package trie import ( "github.com/multiversx/mx-chain-core-go/core" "github.com/multiversx/mx-chain-core-go/core/check" - "github.com/multiversx/mx-chain-go/common" - "github.com/multiversx/mx-chain-go/state" + "github.com/multiversx/mx-chain-core-go/data/stateChange" vmcommon "github.com/multiversx/mx-chain-vm-common-go" + + "github.com/multiversx/mx-chain-go/common" ) // DataTrieTrackerStub - @@ -16,7 +17,7 @@ type DataTrieTrackerStub struct { SaveKeyValueCalled func(key []byte, value []byte) error SetDataTrieCalled func(tr common.Trie) DataTrieCalled func() common.Trie - SaveDirtyDataCalled func(trie common.Trie) ([]state.DataTrieChange, []core.TrieData, error) + SaveDirtyDataCalled func(trie common.Trie) ([]*stateChange.DataTrieChange, []core.TrieData, error) SaveTrieDataCalled func(trieData core.TrieData) error MigrateDataTrieLeavesCalled func(args vmcommon.ArgsMigrateDataTrieLeaves) error } @@ -62,12 +63,12 @@ func (dtts *DataTrieTrackerStub) DataTrie() common.DataTrieHandler { } // SaveDirtyData - -func (dtts *DataTrieTrackerStub) SaveDirtyData(mainTrie common.Trie) ([]state.DataTrieChange, []core.TrieData, error) { +func (dtts *DataTrieTrackerStub) SaveDirtyData(mainTrie common.Trie) ([]*stateChange.DataTrieChange, []core.TrieData, error) { if dtts.SaveDirtyDataCalled != nil { return dtts.SaveDirtyDataCalled(mainTrie) } - return make([]state.DataTrieChange, 0), make([]core.TrieData, 0), nil + return make([]*stateChange.DataTrieChange, 0), make([]core.TrieData, 0), nil } // MigrateDataTrieLeaves - diff --git a/update/genesis/import.go b/update/genesis/import.go index 0568b58cb25..817e1ee57e1 100644 --- a/update/genesis/import.go +++ b/update/genesis/import.go @@ -287,9 +287,10 @@ func newAccountCreator( switch accType { case UserAccount: args := factory.ArgsAccountCreator{ - Hasher: hasher, - Marshaller: marshaller, - EnableEpochsHandler: handler, + Hasher: hasher, + Marshaller: marshaller, + EnableEpochsHandler: handler, + StateChangesCollector: disabledState.NewDisabledStateChangesCollector(), } return factory.NewAccountCreator(args) case ValidatorAccount: