From c8e3b6d496c3b292ccf32ef3937f05c5f8f10cdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Fri, 16 Feb 2024 21:52:50 +0200 Subject: [PATCH 01/12] Integrate VM branches with shim for wasmer 1. --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index fbd61b07d8d..d9001fd8c47 100644 --- a/go.mod +++ b/go.mod @@ -19,13 +19,13 @@ require ( github.com/multiversx/mx-chain-crypto-go v1.2.9 github.com/multiversx/mx-chain-es-indexer-go v1.4.18 github.com/multiversx/mx-chain-logger-go v1.0.13 - github.com/multiversx/mx-chain-scenario-go v1.3.0 + github.com/multiversx/mx-chain-scenario-go v1.4.1 github.com/multiversx/mx-chain-storage-go v1.0.14 github.com/multiversx/mx-chain-vm-common-go v1.5.11 - github.com/multiversx/mx-chain-vm-go v1.5.26 - github.com/multiversx/mx-chain-vm-v1_2-go v1.2.65 - github.com/multiversx/mx-chain-vm-v1_3-go v1.3.66 - github.com/multiversx/mx-chain-vm-v1_4-go v1.4.94 + github.com/multiversx/mx-chain-vm-go v1.5.28-0.20240216193401-b4cb46e6e87b + github.com/multiversx/mx-chain-vm-v1_2-go v1.2.66-0.20240216194327-581d1a5e62d9 + github.com/multiversx/mx-chain-vm-v1_3-go v1.3.67-0.20240216194415-8ed1f3b92aac + github.com/multiversx/mx-chain-vm-v1_4-go v1.4.96-0.20240216194026-53c42d212ddd github.com/pelletier/go-toml v1.9.3 github.com/pkg/errors v0.9.1 github.com/shirou/gopsutil v3.21.11+incompatible diff --git a/go.sum b/go.sum index b7cb342ed43..c7693c9c761 100644 --- a/go.sum +++ b/go.sum @@ -395,20 +395,20 @@ github.com/multiversx/mx-chain-es-indexer-go v1.4.18 h1:rCA+/mn/77MyB7c8FjtabdQe github.com/multiversx/mx-chain-es-indexer-go v1.4.18/go.mod h1:maraR9xXcfi0lLifhGMc+DVHpw1IOPX/c89HVckF1Js= github.com/multiversx/mx-chain-logger-go v1.0.13 h1:eru/TETo0MkO4ZTnXsQDKf4PBRpAXmqjT02klNT/JnY= github.com/multiversx/mx-chain-logger-go v1.0.13/go.mod h1:MZJhTAtZTJxT+yK2EHc4ZW3YOHUc1UdjCD0iahRNBZk= -github.com/multiversx/mx-chain-scenario-go v1.3.0 h1:Vm6jYipJuIcJt8kamgXkePtKkwXaF5Lv5DglZjE5o8I= -github.com/multiversx/mx-chain-scenario-go v1.3.0/go.mod h1:Sdgz8nzA9Ki/pdY/e2a4k90LALBKQB1Eo8HeCV3Bkzo= +github.com/multiversx/mx-chain-scenario-go v1.4.1 h1:CrVXb1aNBRiFfSfpoMAUoGUy2aNXke5WnoesLdFxC2g= +github.com/multiversx/mx-chain-scenario-go v1.4.1/go.mod h1:Sdgz8nzA9Ki/pdY/e2a4k90LALBKQB1Eo8HeCV3Bkzo= github.com/multiversx/mx-chain-storage-go v1.0.14 h1:h0acoqPS3FKJ4S3cKBEriTU0OabSQnpxai5WKhi1YCs= github.com/multiversx/mx-chain-storage-go v1.0.14/go.mod h1:sJ2q49tgjxNpMpsHysjABqCAB0FLBmDblbjBkQ8XfmA= github.com/multiversx/mx-chain-vm-common-go v1.5.11 h1:rAQR00ALKOmWAuNA8XW8hR02M9gmrAE4WZwyJH4dMMU= github.com/multiversx/mx-chain-vm-common-go v1.5.11/go.mod h1:T04rZt/VdwjPXcXVxltMmDmrhxNXsqlByYbWNWcNLYA= -github.com/multiversx/mx-chain-vm-go v1.5.26 h1:ZjUJTG9cO2h5WNRIZ50ZSZNsTEPqXXPGS9Y/SAGyC2A= -github.com/multiversx/mx-chain-vm-go v1.5.26/go.mod h1:gNZ/s4Z6OHg6ZeBsW6aDxWQduXsRS0Bsv4pfkmHeRzs= -github.com/multiversx/mx-chain-vm-v1_2-go v1.2.65 h1:TxFjQH0dXC/ACQxlIgJbO7pVoh00rcqeKSnIjWTDMxg= -github.com/multiversx/mx-chain-vm-v1_2-go v1.2.65/go.mod h1:UUUxIU7mlRkz+Jz4GWV2GkgJt2mKd+j1kky++RNYc9s= -github.com/multiversx/mx-chain-vm-v1_3-go v1.3.66 h1:xgrXfHKa0Za4xjFj5W0FcYEivjrQIhLvGEFXXa1uQZU= -github.com/multiversx/mx-chain-vm-v1_3-go v1.3.66/go.mod h1:mx6IOAqo7zjSinYd8D2YqlpMWsuqFoYXJ6bntnTOeQg= -github.com/multiversx/mx-chain-vm-v1_4-go v1.4.94 h1:MZFEBjDmfwLGB0cZb/pvlLx+qRv/9tO83bEgHUk34is= -github.com/multiversx/mx-chain-vm-v1_4-go v1.4.94/go.mod h1:uuSbZGe0UwOWQyHA4EeJWhs8UeDdhtmMwlhNaX9ppx0= +github.com/multiversx/mx-chain-vm-go v1.5.28-0.20240216193401-b4cb46e6e87b h1:xZiHpFFei/tC8hPRaKMl13BDFXLM7GVBzbXUA1oe8n0= +github.com/multiversx/mx-chain-vm-go v1.5.28-0.20240216193401-b4cb46e6e87b/go.mod h1:Y1O50Z7+suo4D1hnSBA7n34KvgKs5W9jzoEGwpfAjks= +github.com/multiversx/mx-chain-vm-v1_2-go v1.2.66-0.20240216194327-581d1a5e62d9 h1:txF01BBn2rpSi6W91r1z0wPa8jdr0srs1v+dju0TSl0= +github.com/multiversx/mx-chain-vm-v1_2-go v1.2.66-0.20240216194327-581d1a5e62d9/go.mod h1:UUUxIU7mlRkz+Jz4GWV2GkgJt2mKd+j1kky++RNYc9s= +github.com/multiversx/mx-chain-vm-v1_3-go v1.3.67-0.20240216194415-8ed1f3b92aac h1:RQn1xU7tIXmOEIUp38UjKzzwWPhsxa8Kmu7URg8EZ2A= +github.com/multiversx/mx-chain-vm-v1_3-go v1.3.67-0.20240216194415-8ed1f3b92aac/go.mod h1:mx6IOAqo7zjSinYd8D2YqlpMWsuqFoYXJ6bntnTOeQg= +github.com/multiversx/mx-chain-vm-v1_4-go v1.4.96-0.20240216194026-53c42d212ddd h1:aEv/+/nd8HZt7WaKmrM4rt+aB2OTysDP0viMJp2+WQU= +github.com/multiversx/mx-chain-vm-v1_4-go v1.4.96-0.20240216194026-53c42d212ddd/go.mod h1:t4YcFK6VJkG1wGKx1JK4jyowo9zfGFpi8Jl3ycfqAxw= github.com/multiversx/mx-components-big-int v1.0.0 h1:Wkr8lSzK2nDqixOrrBa47VNuqdhV1m/aJhaP1EMaiS8= github.com/multiversx/mx-components-big-int v1.0.0/go.mod h1:maIEMgHlNE2u78JaDD0oLzri+ShgU4okHfzP3LWGdQM= github.com/multiversx/protobuf v1.3.2 h1:RaNkxvGTGbA0lMcnHAN24qE1G1i+Xs5yHA6MDvQ4mSM= From d553a937ee08c7b743f8371dcfb98d22c22ae74c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Fri, 16 Feb 2024 22:06:41 +0200 Subject: [PATCH 02/12] Fix reference. --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d9001fd8c47..b80e90eade5 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/multiversx/mx-chain-scenario-go v1.4.1 github.com/multiversx/mx-chain-storage-go v1.0.14 github.com/multiversx/mx-chain-vm-common-go v1.5.11 - github.com/multiversx/mx-chain-vm-go v1.5.28-0.20240216193401-b4cb46e6e87b + github.com/multiversx/mx-chain-vm-go v1.5.28-0.20240216200544-4034119a7e4f github.com/multiversx/mx-chain-vm-v1_2-go v1.2.66-0.20240216194327-581d1a5e62d9 github.com/multiversx/mx-chain-vm-v1_3-go v1.3.67-0.20240216194415-8ed1f3b92aac github.com/multiversx/mx-chain-vm-v1_4-go v1.4.96-0.20240216194026-53c42d212ddd diff --git a/go.sum b/go.sum index c7693c9c761..af8a32eea2f 100644 --- a/go.sum +++ b/go.sum @@ -401,8 +401,8 @@ github.com/multiversx/mx-chain-storage-go v1.0.14 h1:h0acoqPS3FKJ4S3cKBEriTU0Oab github.com/multiversx/mx-chain-storage-go v1.0.14/go.mod h1:sJ2q49tgjxNpMpsHysjABqCAB0FLBmDblbjBkQ8XfmA= github.com/multiversx/mx-chain-vm-common-go v1.5.11 h1:rAQR00ALKOmWAuNA8XW8hR02M9gmrAE4WZwyJH4dMMU= github.com/multiversx/mx-chain-vm-common-go v1.5.11/go.mod h1:T04rZt/VdwjPXcXVxltMmDmrhxNXsqlByYbWNWcNLYA= -github.com/multiversx/mx-chain-vm-go v1.5.28-0.20240216193401-b4cb46e6e87b h1:xZiHpFFei/tC8hPRaKMl13BDFXLM7GVBzbXUA1oe8n0= -github.com/multiversx/mx-chain-vm-go v1.5.28-0.20240216193401-b4cb46e6e87b/go.mod h1:Y1O50Z7+suo4D1hnSBA7n34KvgKs5W9jzoEGwpfAjks= +github.com/multiversx/mx-chain-vm-go v1.5.28-0.20240216200544-4034119a7e4f h1:Jh2jT7vS2Z7A21DVA0ahua0nAAFb2PrJC4fI4Y08xZE= +github.com/multiversx/mx-chain-vm-go v1.5.28-0.20240216200544-4034119a7e4f/go.mod h1:Y1O50Z7+suo4D1hnSBA7n34KvgKs5W9jzoEGwpfAjks= github.com/multiversx/mx-chain-vm-v1_2-go v1.2.66-0.20240216194327-581d1a5e62d9 h1:txF01BBn2rpSi6W91r1z0wPa8jdr0srs1v+dju0TSl0= github.com/multiversx/mx-chain-vm-v1_2-go v1.2.66-0.20240216194327-581d1a5e62d9/go.mod h1:UUUxIU7mlRkz+Jz4GWV2GkgJt2mKd+j1kky++RNYc9s= github.com/multiversx/mx-chain-vm-v1_3-go v1.3.67-0.20240216194415-8ed1f3b92aac h1:RQn1xU7tIXmOEIUp38UjKzzwWPhsxa8Kmu7URg8EZ2A= From a6aa80b8c7141975a5d0eee03bca7acb5f175200 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Sat, 17 Feb 2024 14:29:30 +0200 Subject: [PATCH 03/12] Do not create older VMs. --- process/factory/shard/vmContainerFactory.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/process/factory/shard/vmContainerFactory.go b/process/factory/shard/vmContainerFactory.go index 92eb6292008..39b7d91183b 100644 --- a/process/factory/shard/vmContainerFactory.go +++ b/process/factory/shard/vmContainerFactory.go @@ -282,12 +282,12 @@ func (vmf *vmContainerFactory) getMatchingVersion(epoch uint32) config.WasmVMVer func (vmf *vmContainerFactory) createInProcessWasmVMByVersion(version config.WasmVMVersionByEpoch) (vmcommon.VMExecutionHandler, error) { logVMContainerFactory.Debug("createInProcessWasmVMByVersion", "version", version) switch version.Version { - case "v1.2": - return vmf.createInProcessWasmVMV12() - case "v1.3": - return vmf.createInProcessWasmVMV13() - case "v1.4": - return vmf.createInProcessWasmVMV14() + // case "v1.2": + // return vmf.createInProcessWasmVMV12() + // case "v1.3": + // return vmf.createInProcessWasmVMV13() + // case "v1.4": + // return vmf.createInProcessWasmVMV14() default: return vmf.createInProcessWasmVMV15() } From 22e0cd2a39aa351d50df84fbdec86716855be729 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Sat, 17 Feb 2024 21:26:09 +0200 Subject: [PATCH 04/12] Remove legacy checks. Add extra logs. --- process/smartContract/scQueryService.go | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/process/smartContract/scQueryService.go b/process/smartContract/scQueryService.go index eb3d9b95e4e..0848fb77882 100644 --- a/process/smartContract/scQueryService.go +++ b/process/smartContract/scQueryService.go @@ -39,7 +39,6 @@ type SCQueryService struct { blockChainHook process.BlockChainHookWithAccountsAdapter mainBlockChain data.ChainHandler apiBlockChain data.ChainHandler - numQueries int gasForQuery uint64 wasmVMChangeLocker common.Locker bootstrapper process.Bootstrapper @@ -179,8 +178,7 @@ func (service *SCQueryService) shouldAllowQueriesExecution() bool { } func (service *SCQueryService) executeScCall(query *process.SCQuery, gasPrice uint64) (*vmcommon.VMOutput, common.BlockInfo, error) { - log.Trace("executeScCall", "function", query.FuncName, "numQueries", service.numQueries) - service.numQueries++ + log.Trace("executeScCall", "address", query.ScAddress, "function", query.FuncName, "blockNonce", query.BlockNonce.Value, "blockHash", query.BlockHash) shouldEarlyExitBecauseOfSyncState := query.ShouldBeSynced && service.bootstrapper.GetNodeState() == common.NsNotSynchronized if shouldEarlyExitBecauseOfSyncState { @@ -193,6 +191,8 @@ func (service *SCQueryService) executeScCall(query *process.SCQuery, gasPrice ui } if len(blockRootHash) > 0 { + log.Trace("preparing execution for block and root hash", "block", blockHeader.GetNonce(), "rootHash", blockRootHash) + err = service.apiBlockChain.SetCurrentBlockHeaderAndRootHash(blockHeader, blockRootHash) if err != nil { return nil, nil, err @@ -229,15 +229,6 @@ func (service *SCQueryService) executeScCall(query *process.SCQuery, gasPrice ui return nil, nil, err } - if service.hasRetriableExecutionError(vmOutput) { - log.Error("Retriable execution error detected. Will retry (once) executeScCall()", "returnCode", vmOutput.ReturnCode, "returnMessage", vmOutput.ReturnMessage) - - vmOutput, err = vm.RunSmartContractCall(vmInput) - if err != nil { - return nil, nil, err - } - } - if query.SameScState { err = service.checkForRootHashChanges(rootHashBeforeExecution) if err != nil { @@ -417,10 +408,6 @@ func (service *SCQueryService) createVMCallInput(query *process.SCQuery, gasPric return vmContractCallInput } -func (service *SCQueryService) hasRetriableExecutionError(vmOutput *vmcommon.VMOutput) bool { - return vmOutput.ReturnMessage == "allocation error" -} - // ComputeScCallGasLimit will estimate how many gas a transaction will consume func (service *SCQueryService) ComputeScCallGasLimit(tx *transaction.Transaction) (uint64, error) { argParser := parsers.NewCallArgsParser() From 3e3aed07dc8fcb691a40fb001ddd32751b037559 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Sat, 17 Feb 2024 21:31:27 +0200 Subject: [PATCH 05/12] Separate logs. --- process/smartContract/scQueryService.go | 7 +++++-- process/smartContract/scQueryServiceDispatcher.go | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/process/smartContract/scQueryService.go b/process/smartContract/scQueryService.go index 0848fb77882..2e7a974ff99 100644 --- a/process/smartContract/scQueryService.go +++ b/process/smartContract/scQueryService.go @@ -22,12 +22,15 @@ import ( "github.com/multiversx/mx-chain-go/process" "github.com/multiversx/mx-chain-go/process/smartContract/scrCommon" "github.com/multiversx/mx-chain-go/sharding" + 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" ) var _ process.SCQueryService = (*SCQueryService)(nil) +var logQueryService = logger.GetOrCreate("process/smartcontract.queryService") + // MaxGasLimitPerQuery - each unit is the equivalent of 1 nanosecond processing time const MaxGasLimitPerQuery = 300_000_000_000 @@ -178,7 +181,7 @@ func (service *SCQueryService) shouldAllowQueriesExecution() bool { } func (service *SCQueryService) executeScCall(query *process.SCQuery, gasPrice uint64) (*vmcommon.VMOutput, common.BlockInfo, error) { - log.Trace("executeScCall", "address", query.ScAddress, "function", query.FuncName, "blockNonce", query.BlockNonce.Value, "blockHash", query.BlockHash) + logQueryService.Trace("executeScCall", "address", query.ScAddress, "function", query.FuncName, "blockNonce", query.BlockNonce.Value, "blockHash", query.BlockHash) shouldEarlyExitBecauseOfSyncState := query.ShouldBeSynced && service.bootstrapper.GetNodeState() == common.NsNotSynchronized if shouldEarlyExitBecauseOfSyncState { @@ -191,7 +194,7 @@ func (service *SCQueryService) executeScCall(query *process.SCQuery, gasPrice ui } if len(blockRootHash) > 0 { - log.Trace("preparing execution for block and root hash", "block", blockHeader.GetNonce(), "rootHash", blockRootHash) + logQueryService.Trace("preparing execution for block and root hash", "block", blockHeader.GetNonce(), "rootHash", blockRootHash) err = service.apiBlockChain.SetCurrentBlockHeaderAndRootHash(blockHeader, blockRootHash) if err != nil { diff --git a/process/smartContract/scQueryServiceDispatcher.go b/process/smartContract/scQueryServiceDispatcher.go index 2c51b47d55d..981f71f3dd9 100644 --- a/process/smartContract/scQueryServiceDispatcher.go +++ b/process/smartContract/scQueryServiceDispatcher.go @@ -78,7 +78,7 @@ func (sqsd *scQueryServiceDispatcher) Close() error { for _, scQueryService := range sqsd.list { err := scQueryService.Close() if err != nil { - log.Error("error while closing inner SC query service in scQueryServiceDispatcher.Close", "error", err) + logQueryService.Error("error while closing inner SC query service in scQueryServiceDispatcher.Close", "error", err) errFound = err } } From abfecd3de93ae8b926d36c21d2998c8bc2b83471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Sat, 17 Feb 2024 22:03:54 +0200 Subject: [PATCH 06/12] Undo changes. --- process/factory/shard/vmContainerFactory.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/process/factory/shard/vmContainerFactory.go b/process/factory/shard/vmContainerFactory.go index 39b7d91183b..92eb6292008 100644 --- a/process/factory/shard/vmContainerFactory.go +++ b/process/factory/shard/vmContainerFactory.go @@ -282,12 +282,12 @@ func (vmf *vmContainerFactory) getMatchingVersion(epoch uint32) config.WasmVMVer func (vmf *vmContainerFactory) createInProcessWasmVMByVersion(version config.WasmVMVersionByEpoch) (vmcommon.VMExecutionHandler, error) { logVMContainerFactory.Debug("createInProcessWasmVMByVersion", "version", version) switch version.Version { - // case "v1.2": - // return vmf.createInProcessWasmVMV12() - // case "v1.3": - // return vmf.createInProcessWasmVMV13() - // case "v1.4": - // return vmf.createInProcessWasmVMV14() + case "v1.2": + return vmf.createInProcessWasmVMV12() + case "v1.3": + return vmf.createInProcessWasmVMV13() + case "v1.4": + return vmf.createInProcessWasmVMV14() default: return vmf.createInProcessWasmVMV15() } From 13bc2e4865fcded4d24cfbb6edd0580767c43583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 20 Feb 2024 13:09:41 +0200 Subject: [PATCH 07/12] Omit re-create if possible. --- state/accountsDBApi.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/state/accountsDBApi.go b/state/accountsDBApi.go index d9bd467d7d2..ae3ca439984 100644 --- a/state/accountsDBApi.go +++ b/state/accountsDBApi.go @@ -175,13 +175,18 @@ func (accountsDB *accountsDBApi) RecreateTrieFromEpoch(options common.RootHashHo accountsDB.mutRecreatedTrieBlockInfo.Lock() defer accountsDB.mutRecreatedTrieBlockInfo.Unlock() + newBlockInfo := holders.NewBlockInfo([]byte{}, 0, options.GetRootHash()) + if newBlockInfo.Equal(accountsDB.blockInfo) { + return nil + } + err := accountsDB.innerAccountsAdapter.RecreateTrieFromEpoch(options) if err != nil { accountsDB.blockInfo = nil return err } - accountsDB.blockInfo = holders.NewBlockInfo([]byte{}, 0, options.GetRootHash()) + accountsDB.blockInfo = newBlockInfo return nil } From 6be2c90afe33a2d8c8dcda5a8909bf749281e7f4 Mon Sep 17 00:00:00 2001 From: Iulian Pascalau Date: Tue, 20 Feb 2024 15:52:12 +0200 Subject: [PATCH 08/12] - fixed recreate trie in sc query service --- process/smartContract/scQueryService.go | 27 +- process/smartContract/scQueryService_test.go | 360 ++++++++++++++++++- 2 files changed, 381 insertions(+), 6 deletions(-) diff --git a/process/smartContract/scQueryService.go b/process/smartContract/scQueryService.go index 0c1501bac45..0090c9d16b4 100644 --- a/process/smartContract/scQueryService.go +++ b/process/smartContract/scQueryService.go @@ -33,6 +33,7 @@ var logQueryService = logger.GetOrCreate("process/smartcontract.queryService") // MaxGasLimitPerQuery - each unit is the equivalent of 1 nanosecond processing time const MaxGasLimitPerQuery = 300_000_000_000 +const epochDifferenceToConsiderHistory = 2 // SCQueryService can execute Get functions over SC to fetch stored values type SCQueryService struct { @@ -201,10 +202,7 @@ func (service *SCQueryService) executeScCall(query *process.SCQuery, gasPrice ui return nil, nil, err } - accountsAdapter := service.blockChainHook.GetAccountsAdapter() - - holder := holders.NewRootHashHolder(blockRootHash, core.OptionalUint32{Value: blockHeader.GetEpoch(), HasValue: true}) - err = accountsAdapter.RecreateTrieFromEpoch(holder) + err = service.recreateTrie(blockRootHash, blockHeader) if err != nil { return nil, nil, err } @@ -253,6 +251,27 @@ func (service *SCQueryService) executeScCall(query *process.SCQuery, gasPrice ui return vmOutput, blockInfo, nil } +func (service *SCQueryService) recreateTrie(blockRootHash []byte, blockHeader data.HeaderHandler) error { + accountsAdapter := service.blockChainHook.GetAccountsAdapter() + if blockHeader.GetEpoch()+epochDifferenceToConsiderHistory >= service.getCurrentEpoch() { + // recent history + return accountsAdapter.RecreateTrie(blockRootHash) + } + + // old history, this will take a little longer + holder := holders.NewRootHashHolder(blockRootHash, core.OptionalUint32{Value: blockHeader.GetEpoch(), HasValue: true}) + return accountsAdapter.RecreateTrieFromEpoch(holder) +} + +func (service *SCQueryService) getCurrentEpoch() uint32 { + header := service.mainBlockChain.GetCurrentBlockHeader() + if check.IfNil(header) { + return 0 + } + + return header.GetEpoch() +} + // TODO: extract duplicated code with nodeBlocks.go func (service *SCQueryService) extractBlockHeaderAndRootHash(query *process.SCQuery) (data.HeaderHandler, []byte, error) { if len(query.BlockHash) > 0 { diff --git a/process/smartContract/scQueryService_test.go b/process/smartContract/scQueryService_test.go index 69672531752..ed57b9f1689 100644 --- a/process/smartContract/scQueryService_test.go +++ b/process/smartContract/scQueryService_test.go @@ -367,7 +367,7 @@ func TestExecuteQuery_ShouldReceiveQueryCorrectly(t *testing.T) { _, _, _ = target.ExecuteQuery(&query) assert.True(t, runWasCalled) }) - t.Run("block hash should work", func(t *testing.T) { + t.Run("block hash should work - old epoch", func(t *testing.T) { t.Parallel() runWasCalled := false @@ -396,6 +396,13 @@ func TestExecuteQuery_ShouldReceiveQueryCorrectly(t *testing.T) { return uint64(math.MaxUint64) }, } + argsNewSCQuery.MainBlockChain = &testscommon.ChainHandlerStub{ + GetCurrentBlockHeaderCalled: func() data.HeaderHandler { + return &block.Header{ + Epoch: 37, + } + }, + } providedHash := []byte("provided hash") providedRootHash := []byte("provided root hash") argsNewSCQuery.Marshaller = &marshallerMock.MarshalizerMock{} @@ -457,7 +464,97 @@ func TestExecuteQuery_ShouldReceiveQueryCorrectly(t *testing.T) { assert.True(t, wasRecreateTrieCalled) assert.Nil(t, err) }) - t.Run("block nonce should work", func(t *testing.T) { + t.Run("block hash should work - current epoch", func(t *testing.T) { + t.Parallel() + + runWasCalled := false + + mockVM := &mock.VMExecutionHandlerStub{ + RunSmartContractCallCalled: func(input *vmcommon.ContractCallInput) (output *vmcommon.VMOutput, e error) { + runWasCalled = true + assert.Equal(t, int64(42), big.NewInt(0).SetBytes(input.Arguments[0]).Int64()) + assert.Equal(t, int64(43), big.NewInt(0).SetBytes(input.Arguments[1]).Int64()) + assert.Equal(t, scAddress, input.CallerAddr) + assert.Equal(t, funcName, input.Function) + + return &vmcommon.VMOutput{ + ReturnCode: vmcommon.Ok, + }, nil + }, + } + argsNewSCQuery := createMockArgumentsForSCQuery() + argsNewSCQuery.VmContainer = &mock.VMContainerMock{ + GetCalled: func(key []byte) (handler vmcommon.VMExecutionHandler, e error) { + return mockVM, nil + }, + } + argsNewSCQuery.EconomicsFee = &economicsmocks.EconomicsHandlerStub{ + MaxGasLimitPerBlockCalled: func(_ uint32) uint64 { + return uint64(math.MaxUint64) + }, + } + providedHash := []byte("provided hash") + providedRootHash := []byte("provided root hash") + argsNewSCQuery.Marshaller = &marshallerMock.MarshalizerMock{} + counter := 0 + argsNewSCQuery.StorageService = &storageStubs.ChainStorerStub{ + GetStorerCalled: func(unitType dataRetriever.UnitType) (storage.Storer, error) { + return &storageStubs.StorerStub{ + GetFromEpochCalled: func(key []byte, epoch uint32) ([]byte, error) { + counter++ + if counter > 2 { + return nil, fmt.Errorf("no scheduled") + } + hdr := &block.Header{ + RootHash: providedRootHash, + } + buff, _ := argsNewSCQuery.Marshaller.Marshal(hdr) + return buff, nil + }, + }, nil + }, + } + argsNewSCQuery.HistoryRepository = &dblookupext.HistoryRepositoryStub{ + IsEnabledCalled: func() bool { + return true + }, + GetEpochByHashCalled: func(hash []byte) (uint32, error) { + return 12, nil + }, + } + wasRecreateTrieCalled := false + providedAccountsAdapter := &stateMocks.AccountsStub{ + RecreateTrieCalled: func(rootHash []byte) error { + wasRecreateTrieCalled = true + assert.Equal(t, providedRootHash, rootHash) + return nil + }, + } + argsNewSCQuery.BlockChainHook = &testscommon.BlockChainHookStub{ + GetAccountsAdapterCalled: func() state.AccountsAdapter { + return providedAccountsAdapter + }, + } + + target, _ := NewSCQueryService(argsNewSCQuery) + + dataArgs := make([][]byte, len(args)) + for i, arg := range args { + dataArgs[i] = append(dataArgs[i], arg.Bytes()...) + } + query := process.SCQuery{ + ScAddress: scAddress, + FuncName: funcName, + Arguments: dataArgs, + BlockHash: providedHash, + } + + _, _, err := target.ExecuteQuery(&query) + assert.True(t, runWasCalled) + assert.True(t, wasRecreateTrieCalled) + assert.Nil(t, err) + }) + t.Run("block nonce should work - old epoch", func(t *testing.T) { t.Parallel() runWasCalled := false @@ -476,6 +573,13 @@ func TestExecuteQuery_ShouldReceiveQueryCorrectly(t *testing.T) { }, } argsNewSCQuery := createMockArgumentsForSCQuery() + argsNewSCQuery.MainBlockChain = &testscommon.ChainHandlerStub{ + GetCurrentBlockHeaderCalled: func() data.HeaderHandler { + return &block.Header{ + Epoch: 37, + } + }, + } argsNewSCQuery.VmContainer = &mock.VMContainerMock{ GetCalled: func(key []byte) (handler vmcommon.VMExecutionHandler, e error) { return mockVM, nil @@ -554,6 +658,258 @@ func TestExecuteQuery_ShouldReceiveQueryCorrectly(t *testing.T) { assert.True(t, runWasCalled) assert.True(t, wasRecreateTrieCalled) }) + t.Run("block nonce should work - current epoch", func(t *testing.T) { + t.Parallel() + + runWasCalled := false + + mockVM := &mock.VMExecutionHandlerStub{ + RunSmartContractCallCalled: func(input *vmcommon.ContractCallInput) (output *vmcommon.VMOutput, e error) { + runWasCalled = true + assert.Equal(t, int64(42), big.NewInt(0).SetBytes(input.Arguments[0]).Int64()) + assert.Equal(t, int64(43), big.NewInt(0).SetBytes(input.Arguments[1]).Int64()) + assert.Equal(t, scAddress, input.CallerAddr) + assert.Equal(t, funcName, input.Function) + + return &vmcommon.VMOutput{ + ReturnCode: vmcommon.Ok, + }, nil + }, + } + argsNewSCQuery := createMockArgumentsForSCQuery() + argsNewSCQuery.VmContainer = &mock.VMContainerMock{ + GetCalled: func(key []byte) (handler vmcommon.VMExecutionHandler, e error) { + return mockVM, nil + }, + } + argsNewSCQuery.EconomicsFee = &economicsmocks.EconomicsHandlerStub{ + MaxGasLimitPerBlockCalled: func(_ uint32) uint64 { + return uint64(math.MaxUint64) + }, + } + providedHash := []byte("provided hash") + providedRootHash := []byte("provided root hash") + providedNonce := uint64(123) + argsNewSCQuery.Marshaller = &marshallerMock.MarshalizerMock{} + counter := 0 + argsNewSCQuery.StorageService = &storageStubs.ChainStorerStub{ + GetStorerCalled: func(unitType dataRetriever.UnitType) (storage.Storer, error) { + return &storageStubs.StorerStub{ + GetCalled: func(key []byte) ([]byte, error) { + return providedHash, nil + }, + GetFromEpochCalled: func(key []byte, epoch uint32) ([]byte, error) { + counter++ + if counter > 2 { + return nil, fmt.Errorf("no scheduled") + } + hdr := &block.Header{ + RootHash: providedRootHash, + } + buff, _ := argsNewSCQuery.Marshaller.Marshal(hdr) + return buff, nil + }, + }, nil + }, + } + argsNewSCQuery.HistoryRepository = &dblookupext.HistoryRepositoryStub{ + IsEnabledCalled: func() bool { + return true + }, + GetEpochByHashCalled: func(hash []byte) (uint32, error) { + require.Equal(t, providedHash, hash) + return 12, nil + }, + } + wasRecreateTrieCalled := false + providedAccountsAdapter := &stateMocks.AccountsStub{ + RecreateTrieCalled: func(rootHash []byte) error { + wasRecreateTrieCalled = true + assert.Equal(t, providedRootHash, rootHash) + return nil + }, + } + argsNewSCQuery.BlockChainHook = &testscommon.BlockChainHookStub{ + GetAccountsAdapterCalled: func() state.AccountsAdapter { + return providedAccountsAdapter + }, + } + + target, _ := NewSCQueryService(argsNewSCQuery) + + dataArgs := make([][]byte, len(args)) + for i, arg := range args { + dataArgs[i] = append(dataArgs[i], arg.Bytes()...) + } + query := process.SCQuery{ + ScAddress: scAddress, + FuncName: funcName, + Arguments: dataArgs, + BlockNonce: core.OptionalUint64{ + Value: providedNonce, + HasValue: true, + }, + } + + _, _, _ = target.ExecuteQuery(&query) + assert.True(t, runWasCalled) + assert.True(t, wasRecreateTrieCalled) + }) +} + +func TestSCQueryService_RecreateTrie(t *testing.T) { + t.Parallel() + + testRootHash := []byte("test root hash") + t.Run("should call RecreateTrie for genesis block", func(t *testing.T) { + t.Parallel() + + recreateTrieCalled := false + argsNewSCQuery := createMockArgumentsForSCQuery() + argsNewSCQuery.MainBlockChain = &testscommon.ChainHandlerStub{ + GetCurrentBlockHeaderCalled: func() data.HeaderHandler { + return nil // after the genesis we do not have a header as current block + }, + } + argsNewSCQuery.BlockChainHook = &testscommon.BlockChainHookStub{ + GetAccountsAdapterCalled: func() state.AccountsAdapter { + return &stateMocks.AccountsStub{ + RecreateTrieCalled: func(rootHash []byte) error { + recreateTrieCalled = true + assert.Equal(t, testRootHash, rootHash) + return nil + }, + } + }, + } + + service, _ := NewSCQueryService(argsNewSCQuery) + err := service.recreateTrie(testRootHash, &block.Header{}) + assert.Nil(t, err) + assert.True(t, recreateTrieCalled) + }) + t.Run("should call RecreateTrie for block on epoch 0", func(t *testing.T) { + t.Parallel() + + recreateTrieCalled := false + argsNewSCQuery := createMockArgumentsForSCQuery() + argsNewSCQuery.MainBlockChain = &testscommon.ChainHandlerStub{ + GetCurrentBlockHeaderCalled: func() data.HeaderHandler { + return &block.Header{ + Epoch: 0, + } + }, + } + argsNewSCQuery.BlockChainHook = &testscommon.BlockChainHookStub{ + GetAccountsAdapterCalled: func() state.AccountsAdapter { + return &stateMocks.AccountsStub{ + RecreateTrieCalled: func(rootHash []byte) error { + recreateTrieCalled = true + assert.Equal(t, testRootHash, rootHash) + return nil + }, + } + }, + } + + service, _ := NewSCQueryService(argsNewSCQuery) + err := service.recreateTrie(testRootHash, &block.Header{}) + assert.Nil(t, err) + assert.True(t, recreateTrieCalled) + }) + t.Run("should call RecreateTrie for block on epoch 1", func(t *testing.T) { + t.Parallel() + + recreateTrieCalled := false + argsNewSCQuery := createMockArgumentsForSCQuery() + argsNewSCQuery.MainBlockChain = &testscommon.ChainHandlerStub{ + GetCurrentBlockHeaderCalled: func() data.HeaderHandler { + return &block.Header{ + Epoch: 1, + } + }, + } + argsNewSCQuery.BlockChainHook = &testscommon.BlockChainHookStub{ + GetAccountsAdapterCalled: func() state.AccountsAdapter { + return &stateMocks.AccountsStub{ + RecreateTrieCalled: func(rootHash []byte) error { + recreateTrieCalled = true + assert.Equal(t, testRootHash, rootHash) + return nil + }, + } + }, + } + + service, _ := NewSCQueryService(argsNewSCQuery) + err := service.recreateTrie(testRootHash, &block.Header{ + Epoch: 0, + }) + assert.Nil(t, err) + assert.True(t, recreateTrieCalled) + }) + t.Run("should call RecreateTrie for block on epoch 2", func(t *testing.T) { + t.Parallel() + + recreateTrieCalled := false + argsNewSCQuery := createMockArgumentsForSCQuery() + argsNewSCQuery.MainBlockChain = &testscommon.ChainHandlerStub{ + GetCurrentBlockHeaderCalled: func() data.HeaderHandler { + return &block.Header{ + Epoch: 3, + } + }, + } + argsNewSCQuery.BlockChainHook = &testscommon.BlockChainHookStub{ + GetAccountsAdapterCalled: func() state.AccountsAdapter { + return &stateMocks.AccountsStub{ + RecreateTrieCalled: func(rootHash []byte) error { + recreateTrieCalled = true + assert.Equal(t, testRootHash, rootHash) + return nil + }, + } + }, + } + + service, _ := NewSCQueryService(argsNewSCQuery) + err := service.recreateTrie(testRootHash, &block.Header{ + Epoch: 2, + }) + assert.Nil(t, err) + assert.True(t, recreateTrieCalled) + }) + t.Run("should call RecreateTrieFromEpoch for block on epoch 3", func(t *testing.T) { + t.Parallel() + + recreateTrieCalled := false + argsNewSCQuery := createMockArgumentsForSCQuery() + argsNewSCQuery.MainBlockChain = &testscommon.ChainHandlerStub{ + GetCurrentBlockHeaderCalled: func() data.HeaderHandler { + return &block.Header{ + Epoch: 3, + } + }, + } + argsNewSCQuery.BlockChainHook = &testscommon.BlockChainHookStub{ + GetAccountsAdapterCalled: func() state.AccountsAdapter { + return &stateMocks.AccountsStub{ + RecreateTrieFromEpochCalled: func(options common.RootHashHolder) error { + recreateTrieCalled = true + assert.Equal(t, testRootHash, options.GetRootHash()) + return nil + }, + } + }, + } + + service, _ := NewSCQueryService(argsNewSCQuery) + err := service.recreateTrie(testRootHash, &block.Header{ + Epoch: 0, + }) + assert.Nil(t, err) + assert.True(t, recreateTrieCalled) + }) } func TestExecuteQuery_ReturnsCorrectly(t *testing.T) { From b9ecacf7c4fa449d7876b41912473e0172c560af Mon Sep 17 00:00:00 2001 From: Iulian Pascalau Date: Tue, 20 Feb 2024 16:28:04 +0200 Subject: [PATCH 09/12] - fixes --- state/accountsDBApi.go | 3 +++ state/accountsDBApi_test.go | 7 +++---- state/errors.go | 3 +++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/state/accountsDBApi.go b/state/accountsDBApi.go index ae3ca439984..e94610f0fcb 100644 --- a/state/accountsDBApi.go +++ b/state/accountsDBApi.go @@ -175,6 +175,9 @@ func (accountsDB *accountsDBApi) RecreateTrieFromEpoch(options common.RootHashHo accountsDB.mutRecreatedTrieBlockInfo.Lock() defer accountsDB.mutRecreatedTrieBlockInfo.Unlock() + if options == nil { + return ErrNilRootHashHolder + } newBlockInfo := holders.NewBlockInfo([]byte{}, 0, options.GetRootHash()) if newBlockInfo.Equal(accountsDB.blockInfo) { return nil diff --git a/state/accountsDBApi_test.go b/state/accountsDBApi_test.go index 1544e5691b1..1a22366ab06 100644 --- a/state/accountsDBApi_test.go +++ b/state/accountsDBApi_test.go @@ -230,17 +230,16 @@ func TestAccountsDBApi_RecreateTrieFromEpoch(t *testing.T) { t.Parallel() t.Run("should error if the roothash holder is nil", func(t *testing.T) { - wasCalled := false accountsApi, _ := state.NewAccountsDBApi(&mockState.AccountsStub{ RecreateTrieFromEpochCalled: func(options common.RootHashHolder) error { - wasCalled = true - return trie.ErrNilRootHashHolder + assert.Fail(t, "should have not called accountsApi.RecreateTrieFromEpochCalled") + + return nil }, }, createBlockInfoProviderStub(dummyRootHash)) err := accountsApi.RecreateTrieFromEpoch(nil) assert.Equal(t, trie.ErrNilRootHashHolder, err) - assert.True(t, wasCalled) }) t.Run("should work", func(t *testing.T) { wasCalled := false diff --git a/state/errors.go b/state/errors.go index 5a56aff40ff..893d65d7ec0 100644 --- a/state/errors.go +++ b/state/errors.go @@ -144,3 +144,6 @@ var ErrNilStateMetrics = errors.New("nil sstate metrics") // ErrNilChannelsProvider signals that a nil channels provider has been given var ErrNilChannelsProvider = errors.New("nil channels provider") + +// ErrNilRootHashHolder signals that a nil root hash holder was provided +var ErrNilRootHashHolder = errors.New("nil root hash holder provided") From 9f3d0108d24508598ab45ae2eb29522f665e50bb Mon Sep 17 00:00:00 2001 From: Iulian Pascalau Date: Tue, 20 Feb 2024 16:44:52 +0200 Subject: [PATCH 10/12] - fixes after review --- process/smartContract/scQueryService_test.go | 64 +++++++++----------- 1 file changed, 27 insertions(+), 37 deletions(-) diff --git a/process/smartContract/scQueryService_test.go b/process/smartContract/scQueryService_test.go index ed57b9f1689..818fa9c2f73 100644 --- a/process/smartContract/scQueryService_test.go +++ b/process/smartContract/scQueryService_test.go @@ -432,10 +432,10 @@ func TestExecuteQuery_ShouldReceiveQueryCorrectly(t *testing.T) { return 12, nil }, } - wasRecreateTrieCalled := false + recreateTrieWasCalled := false providedAccountsAdapter := &stateMocks.AccountsStub{ RecreateTrieFromEpochCalled: func(options common.RootHashHolder) error { - wasRecreateTrieCalled = true + recreateTrieWasCalled = true assert.Equal(t, providedRootHash, options.GetRootHash()) return nil }, @@ -461,7 +461,7 @@ func TestExecuteQuery_ShouldReceiveQueryCorrectly(t *testing.T) { _, _, err := target.ExecuteQuery(&query) assert.True(t, runWasCalled) - assert.True(t, wasRecreateTrieCalled) + assert.True(t, recreateTrieWasCalled) assert.Nil(t, err) }) t.Run("block hash should work - current epoch", func(t *testing.T) { @@ -496,15 +496,10 @@ func TestExecuteQuery_ShouldReceiveQueryCorrectly(t *testing.T) { providedHash := []byte("provided hash") providedRootHash := []byte("provided root hash") argsNewSCQuery.Marshaller = &marshallerMock.MarshalizerMock{} - counter := 0 argsNewSCQuery.StorageService = &storageStubs.ChainStorerStub{ GetStorerCalled: func(unitType dataRetriever.UnitType) (storage.Storer, error) { return &storageStubs.StorerStub{ GetFromEpochCalled: func(key []byte, epoch uint32) ([]byte, error) { - counter++ - if counter > 2 { - return nil, fmt.Errorf("no scheduled") - } hdr := &block.Header{ RootHash: providedRootHash, } @@ -522,10 +517,10 @@ func TestExecuteQuery_ShouldReceiveQueryCorrectly(t *testing.T) { return 12, nil }, } - wasRecreateTrieCalled := false + recreateTrieWasCalled := false providedAccountsAdapter := &stateMocks.AccountsStub{ RecreateTrieCalled: func(rootHash []byte) error { - wasRecreateTrieCalled = true + recreateTrieWasCalled = true assert.Equal(t, providedRootHash, rootHash) return nil }, @@ -551,7 +546,7 @@ func TestExecuteQuery_ShouldReceiveQueryCorrectly(t *testing.T) { _, _, err := target.ExecuteQuery(&query) assert.True(t, runWasCalled) - assert.True(t, wasRecreateTrieCalled) + assert.True(t, recreateTrieWasCalled) assert.Nil(t, err) }) t.Run("block nonce should work - old epoch", func(t *testing.T) { @@ -624,10 +619,10 @@ func TestExecuteQuery_ShouldReceiveQueryCorrectly(t *testing.T) { return 12, nil }, } - wasRecreateTrieCalled := false + recreateTrieWasCalled := false providedAccountsAdapter := &stateMocks.AccountsStub{ RecreateTrieFromEpochCalled: func(options common.RootHashHolder) error { - wasRecreateTrieCalled = true + recreateTrieWasCalled = true assert.Equal(t, providedRootHash, options.GetRootHash()) return nil }, @@ -656,7 +651,7 @@ func TestExecuteQuery_ShouldReceiveQueryCorrectly(t *testing.T) { _, _, _ = target.ExecuteQuery(&query) assert.True(t, runWasCalled) - assert.True(t, wasRecreateTrieCalled) + assert.True(t, recreateTrieWasCalled) }) t.Run("block nonce should work - current epoch", func(t *testing.T) { t.Parallel() @@ -691,7 +686,6 @@ func TestExecuteQuery_ShouldReceiveQueryCorrectly(t *testing.T) { providedRootHash := []byte("provided root hash") providedNonce := uint64(123) argsNewSCQuery.Marshaller = &marshallerMock.MarshalizerMock{} - counter := 0 argsNewSCQuery.StorageService = &storageStubs.ChainStorerStub{ GetStorerCalled: func(unitType dataRetriever.UnitType) (storage.Storer, error) { return &storageStubs.StorerStub{ @@ -699,10 +693,6 @@ func TestExecuteQuery_ShouldReceiveQueryCorrectly(t *testing.T) { return providedHash, nil }, GetFromEpochCalled: func(key []byte, epoch uint32) ([]byte, error) { - counter++ - if counter > 2 { - return nil, fmt.Errorf("no scheduled") - } hdr := &block.Header{ RootHash: providedRootHash, } @@ -721,10 +711,10 @@ func TestExecuteQuery_ShouldReceiveQueryCorrectly(t *testing.T) { return 12, nil }, } - wasRecreateTrieCalled := false + recreateTrieWasCalled := false providedAccountsAdapter := &stateMocks.AccountsStub{ RecreateTrieCalled: func(rootHash []byte) error { - wasRecreateTrieCalled = true + recreateTrieWasCalled = true assert.Equal(t, providedRootHash, rootHash) return nil }, @@ -753,7 +743,7 @@ func TestExecuteQuery_ShouldReceiveQueryCorrectly(t *testing.T) { _, _, _ = target.ExecuteQuery(&query) assert.True(t, runWasCalled) - assert.True(t, wasRecreateTrieCalled) + assert.True(t, recreateTrieWasCalled) }) } @@ -764,7 +754,7 @@ func TestSCQueryService_RecreateTrie(t *testing.T) { t.Run("should call RecreateTrie for genesis block", func(t *testing.T) { t.Parallel() - recreateTrieCalled := false + recreateTrieWasCalled := false argsNewSCQuery := createMockArgumentsForSCQuery() argsNewSCQuery.MainBlockChain = &testscommon.ChainHandlerStub{ GetCurrentBlockHeaderCalled: func() data.HeaderHandler { @@ -775,7 +765,7 @@ func TestSCQueryService_RecreateTrie(t *testing.T) { GetAccountsAdapterCalled: func() state.AccountsAdapter { return &stateMocks.AccountsStub{ RecreateTrieCalled: func(rootHash []byte) error { - recreateTrieCalled = true + recreateTrieWasCalled = true assert.Equal(t, testRootHash, rootHash) return nil }, @@ -786,12 +776,12 @@ func TestSCQueryService_RecreateTrie(t *testing.T) { service, _ := NewSCQueryService(argsNewSCQuery) err := service.recreateTrie(testRootHash, &block.Header{}) assert.Nil(t, err) - assert.True(t, recreateTrieCalled) + assert.True(t, recreateTrieWasCalled) }) t.Run("should call RecreateTrie for block on epoch 0", func(t *testing.T) { t.Parallel() - recreateTrieCalled := false + recreateTrieWasCalled := false argsNewSCQuery := createMockArgumentsForSCQuery() argsNewSCQuery.MainBlockChain = &testscommon.ChainHandlerStub{ GetCurrentBlockHeaderCalled: func() data.HeaderHandler { @@ -804,7 +794,7 @@ func TestSCQueryService_RecreateTrie(t *testing.T) { GetAccountsAdapterCalled: func() state.AccountsAdapter { return &stateMocks.AccountsStub{ RecreateTrieCalled: func(rootHash []byte) error { - recreateTrieCalled = true + recreateTrieWasCalled = true assert.Equal(t, testRootHash, rootHash) return nil }, @@ -815,12 +805,12 @@ func TestSCQueryService_RecreateTrie(t *testing.T) { service, _ := NewSCQueryService(argsNewSCQuery) err := service.recreateTrie(testRootHash, &block.Header{}) assert.Nil(t, err) - assert.True(t, recreateTrieCalled) + assert.True(t, recreateTrieWasCalled) }) t.Run("should call RecreateTrie for block on epoch 1", func(t *testing.T) { t.Parallel() - recreateTrieCalled := false + recreateTrieWasCalled := false argsNewSCQuery := createMockArgumentsForSCQuery() argsNewSCQuery.MainBlockChain = &testscommon.ChainHandlerStub{ GetCurrentBlockHeaderCalled: func() data.HeaderHandler { @@ -833,7 +823,7 @@ func TestSCQueryService_RecreateTrie(t *testing.T) { GetAccountsAdapterCalled: func() state.AccountsAdapter { return &stateMocks.AccountsStub{ RecreateTrieCalled: func(rootHash []byte) error { - recreateTrieCalled = true + recreateTrieWasCalled = true assert.Equal(t, testRootHash, rootHash) return nil }, @@ -846,12 +836,12 @@ func TestSCQueryService_RecreateTrie(t *testing.T) { Epoch: 0, }) assert.Nil(t, err) - assert.True(t, recreateTrieCalled) + assert.True(t, recreateTrieWasCalled) }) t.Run("should call RecreateTrie for block on epoch 2", func(t *testing.T) { t.Parallel() - recreateTrieCalled := false + recreateTrieWasCalled := false argsNewSCQuery := createMockArgumentsForSCQuery() argsNewSCQuery.MainBlockChain = &testscommon.ChainHandlerStub{ GetCurrentBlockHeaderCalled: func() data.HeaderHandler { @@ -864,7 +854,7 @@ func TestSCQueryService_RecreateTrie(t *testing.T) { GetAccountsAdapterCalled: func() state.AccountsAdapter { return &stateMocks.AccountsStub{ RecreateTrieCalled: func(rootHash []byte) error { - recreateTrieCalled = true + recreateTrieWasCalled = true assert.Equal(t, testRootHash, rootHash) return nil }, @@ -877,12 +867,12 @@ func TestSCQueryService_RecreateTrie(t *testing.T) { Epoch: 2, }) assert.Nil(t, err) - assert.True(t, recreateTrieCalled) + assert.True(t, recreateTrieWasCalled) }) t.Run("should call RecreateTrieFromEpoch for block on epoch 3", func(t *testing.T) { t.Parallel() - recreateTrieCalled := false + recreateTrieWasCalled := false argsNewSCQuery := createMockArgumentsForSCQuery() argsNewSCQuery.MainBlockChain = &testscommon.ChainHandlerStub{ GetCurrentBlockHeaderCalled: func() data.HeaderHandler { @@ -895,7 +885,7 @@ func TestSCQueryService_RecreateTrie(t *testing.T) { GetAccountsAdapterCalled: func() state.AccountsAdapter { return &stateMocks.AccountsStub{ RecreateTrieFromEpochCalled: func(options common.RootHashHolder) error { - recreateTrieCalled = true + recreateTrieWasCalled = true assert.Equal(t, testRootHash, options.GetRootHash()) return nil }, @@ -908,7 +898,7 @@ func TestSCQueryService_RecreateTrie(t *testing.T) { Epoch: 0, }) assert.Nil(t, err) - assert.True(t, recreateTrieCalled) + assert.True(t, recreateTrieWasCalled) }) } From 8e7be72af369323e5995e08345ebebb89896d7cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 20 Feb 2024 21:12:34 +0200 Subject: [PATCH 11/12] Fix after review. --- process/smartContract/scQueryService.go | 8 ++++++-- process/smartContract/scQueryService_test.go | 19 +++++++++++++++++++ state/accountsDBApi.go | 3 ++- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/process/smartContract/scQueryService.go b/process/smartContract/scQueryService.go index 0090c9d16b4..af522e88d83 100644 --- a/process/smartContract/scQueryService.go +++ b/process/smartContract/scQueryService.go @@ -195,8 +195,6 @@ func (service *SCQueryService) executeScCall(query *process.SCQuery, gasPrice ui } if len(blockRootHash) > 0 { - logQueryService.Trace("preparing execution for block and root hash", "block", blockHeader.GetNonce(), "rootHash", blockRootHash) - err = service.apiBlockChain.SetCurrentBlockHeaderAndRootHash(blockHeader, blockRootHash) if err != nil { return nil, nil, err @@ -252,6 +250,12 @@ func (service *SCQueryService) executeScCall(query *process.SCQuery, gasPrice ui } func (service *SCQueryService) recreateTrie(blockRootHash []byte, blockHeader data.HeaderHandler) error { + if check.IfNil(blockHeader) { + return process.ErrNilBlockHeader + } + + logQueryService.Trace("preparing execution for block and root hash", "block", blockHeader.GetNonce(), "rootHash", blockRootHash) + accountsAdapter := service.blockChainHook.GetAccountsAdapter() if blockHeader.GetEpoch()+epochDifferenceToConsiderHistory >= service.getCurrentEpoch() { // recent history diff --git a/process/smartContract/scQueryService_test.go b/process/smartContract/scQueryService_test.go index 818fa9c2f73..cd31bc165ec 100644 --- a/process/smartContract/scQueryService_test.go +++ b/process/smartContract/scQueryService_test.go @@ -751,6 +751,25 @@ func TestSCQueryService_RecreateTrie(t *testing.T) { t.Parallel() testRootHash := []byte("test root hash") + t.Run("should not call RecreateTrie if block header is nil", func(t *testing.T) { + t.Parallel() + + argsNewSCQuery := createMockArgumentsForSCQuery() + argsNewSCQuery.BlockChainHook = &testscommon.BlockChainHookStub{ + GetAccountsAdapterCalled: func() state.AccountsAdapter { + return &stateMocks.AccountsStub{ + RecreateTrieCalled: func(rootHash []byte) error { + require.Fail(t, "should not be called") + return nil + }, + } + }, + } + + service, _ := NewSCQueryService(argsNewSCQuery) + err := service.recreateTrie(testRootHash, nil) + assert.ErrorIs(t, err, process.ErrNilBlockHeader) + }) t.Run("should call RecreateTrie for genesis block", func(t *testing.T) { t.Parallel() diff --git a/state/accountsDBApi.go b/state/accountsDBApi.go index e94610f0fcb..791bfc658df 100644 --- a/state/accountsDBApi.go +++ b/state/accountsDBApi.go @@ -175,9 +175,10 @@ func (accountsDB *accountsDBApi) RecreateTrieFromEpoch(options common.RootHashHo accountsDB.mutRecreatedTrieBlockInfo.Lock() defer accountsDB.mutRecreatedTrieBlockInfo.Unlock() - if options == nil { + if check.IfNil(options) { return ErrNilRootHashHolder } + newBlockInfo := holders.NewBlockInfo([]byte{}, 0, options.GetRootHash()) if newBlockInfo.Equal(accountsDB.blockInfo) { return nil From f9bcc00f9385127e0cfb2c94dce2a4ae38f69d14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrei=20B=C4=83ncioiu?= Date: Tue, 20 Feb 2024 21:16:54 +0200 Subject: [PATCH 12/12] Fix logs. --- process/smartContract/scQueryService.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/process/smartContract/scQueryService.go b/process/smartContract/scQueryService.go index af522e88d83..b243a8db2b0 100644 --- a/process/smartContract/scQueryService.go +++ b/process/smartContract/scQueryService.go @@ -254,15 +254,13 @@ func (service *SCQueryService) recreateTrie(blockRootHash []byte, blockHeader da return process.ErrNilBlockHeader } - logQueryService.Trace("preparing execution for block and root hash", "block", blockHeader.GetNonce(), "rootHash", blockRootHash) - accountsAdapter := service.blockChainHook.GetAccountsAdapter() if blockHeader.GetEpoch()+epochDifferenceToConsiderHistory >= service.getCurrentEpoch() { - // recent history + logQueryService.Trace("calling RecreateTrie, for recent history", "block", blockHeader.GetNonce(), "rootHash", blockRootHash) return accountsAdapter.RecreateTrie(blockRootHash) } - // old history, this will take a little longer + logQueryService.Trace("calling RecreateTrieFromEpoch, for older history", "block", blockHeader.GetNonce(), "rootHash", blockRootHash) holder := holders.NewRootHashHolder(blockRootHash, core.OptionalUint32{Value: blockHeader.GetEpoch(), HasValue: true}) return accountsAdapter.RecreateTrieFromEpoch(holder) }