Skip to content

Commit

Permalink
Merge pull request #5977 from multiversx/vm-query-logs
Browse files Browse the repository at this point in the history
Optimized trie re-creation for VM Queries, adjust some logs
  • Loading branch information
iulianpascalau authored Feb 23, 2024
2 parents 6faf35a + f9bcc00 commit 688b8ff
Show file tree
Hide file tree
Showing 6 changed files with 421 additions and 34 deletions.
51 changes: 31 additions & 20 deletions process/smartContract/scQueryService.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,18 @@ 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
const epochDifferenceToConsiderHistory = 2

// SCQueryService can execute Get functions over SC to fetch stored values
type SCQueryService struct {
Expand All @@ -39,7 +43,6 @@ type SCQueryService struct {
blockChainHook process.BlockChainHookWithAccountsAdapter
mainBlockChain data.ChainHandler
apiBlockChain data.ChainHandler
numQueries int
gasForQuery uint64
wasmVMChangeLocker common.Locker
bootstrapper process.Bootstrapper
Expand Down Expand Up @@ -179,8 +182,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++
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 {
Expand All @@ -198,10 +200,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
}
Expand Down Expand Up @@ -230,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 {
Expand All @@ -259,6 +249,31 @@ func (service *SCQueryService) executeScCall(query *process.SCQuery, gasPrice ui
return vmOutput, blockInfo, nil
}

func (service *SCQueryService) recreateTrie(blockRootHash []byte, blockHeader data.HeaderHandler) error {
if check.IfNil(blockHeader) {
return process.ErrNilBlockHeader
}

accountsAdapter := service.blockChainHook.GetAccountsAdapter()
if blockHeader.GetEpoch()+epochDifferenceToConsiderHistory >= service.getCurrentEpoch() {
logQueryService.Trace("calling RecreateTrie, for recent history", "block", blockHeader.GetNonce(), "rootHash", blockRootHash)
return accountsAdapter.RecreateTrie(blockRootHash)
}

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)
}

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 {
Expand Down Expand Up @@ -417,10 +432,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()
Expand Down
2 changes: 1 addition & 1 deletion process/smartContract/scQueryServiceDispatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
Expand Down
Loading

0 comments on commit 688b8ff

Please sign in to comment.