diff --git a/docs/rpc.md b/docs/rpc.md index 3e0b2fa81..acf02bdf0 100644 --- a/docs/rpc.md +++ b/docs/rpc.md @@ -174,10 +174,12 @@ These methods provide the ability of *historical* calls and accept block hash or block index or stateroot hash as the first parameter and the list of parameters that is the same as of `invokecontractverify`, `invokefunction` and `invokescript` correspondingly. The historical call assumes that the contracts' -storage state has all its values got from MPT with the specified stateroot and -the transaction will be invoked using interop context with block of the specified -height. This allows to perform test invocation using the specified past chain -state. These methods may be useful for debugging purposes. +storage state has all its values got from MPT with the specified stateroot (or, +which is the same, with the stateroot of the block of the specified height) and +the transaction will be invoked using interop context with block which is next to +the block with the specified height. This allows to perform test invocation using +the specified past chain state. These methods may be useful for debugging +purposes. Behavior note: any historical RPC call need the historical chain state to be presented in the node storage, thus if the node keeps only latest MPT state diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index bd2a7d318..c0e386c8c 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -2187,7 +2187,11 @@ func (bc *Blockchain) GetTestHistoricVM(t trigger.Type, tx *transaction.Transact } mode |= mpt.ModeGCFlag } - sr, err := bc.stateRoot.GetStateRoot(b.Index) + if b.Index < 1 || b.Index > bc.BlockHeight()+1 { + return nil, fmt.Errorf("unsupported historic chain's height: requested state for %d, chain height %d", b.Index, bc.blockHeight) + } + // Assuming that block N-th is processing during historic call, the historic invocation should be based on the storage state of height N-1. + sr, err := bc.stateRoot.GetStateRoot(b.Index - 1) if err != nil { return nil, fmt.Errorf("failed to retrieve stateroot for height %d: %w", b.Index, err) } diff --git a/pkg/rpc/server/server.go b/pkg/rpc/server/server.go index 91eabe359..6e37d75a5 100644 --- a/pkg/rpc/server/server.go +++ b/pkg/rpc/server/server.go @@ -1780,9 +1780,9 @@ func (s *Server) getHistoricParams(reqParams request.Params) (*block.Block, *res height = int(b.Index) } } - b, err := s.getFakeNextBlock(uint32(height)) + b, err := s.getFakeNextBlock(uint32(height + 1)) if err != nil { - return nil, response.NewInternalServerError(fmt.Sprintf("can't create fake block for height %d: %s", height, err)) + return nil, response.NewInternalServerError(fmt.Sprintf("can't create fake block for height %d: %s", height+1, err)) } return b, nil }