mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 06:36:43 +00:00
Implement PIP-12, Time Based StateSync Confirmations Delay (#864)
* updated Indore HF related changes by adding stateSyncConfirmationDelay * converted StateSyncConfirmationDelay to map[string]uint64 and cleanup * calculate last state ID from incoming state object with eth call (#883) * removed IndoreBlock from configs * fix * remove code duplication and refactor --------- Co-authored-by: Manav Darji <manavdarji.india@gmail.com>
This commit is contained in:
parent
3d30c341c4
commit
47f8e8682a
11 changed files with 152 additions and 61 deletions
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
)
|
)
|
||||||
|
|
@ -11,4 +12,5 @@ import (
|
||||||
//go:generate mockgen -destination=./caller_mock.go -package=api . Caller
|
//go:generate mockgen -destination=./caller_mock.go -package=api . Caller
|
||||||
type Caller interface {
|
type Caller interface {
|
||||||
Call(ctx context.Context, args ethapi.TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *ethapi.StateOverride) (hexutil.Bytes, error)
|
Call(ctx context.Context, args ethapi.TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *ethapi.StateOverride) (hexutil.Bytes, error)
|
||||||
|
CallWithState(ctx context.Context, args ethapi.TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, state *state.StateDB, overrides *ethapi.StateOverride) (hexutil.Bytes, error)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import (
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
|
|
||||||
hexutil "github.com/ethereum/go-ethereum/common/hexutil"
|
hexutil "github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
state "github.com/ethereum/go-ethereum/core/state"
|
||||||
ethapi "github.com/ethereum/go-ethereum/internal/ethapi"
|
ethapi "github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
rpc "github.com/ethereum/go-ethereum/rpc"
|
rpc "github.com/ethereum/go-ethereum/rpc"
|
||||||
gomock "github.com/golang/mock/gomock"
|
gomock "github.com/golang/mock/gomock"
|
||||||
|
|
@ -51,3 +52,18 @@ func (mr *MockCallerMockRecorder) Call(arg0, arg1, arg2, arg3 interface{}) *gomo
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Call", reflect.TypeOf((*MockCaller)(nil).Call), arg0, arg1, arg2, arg3)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Call", reflect.TypeOf((*MockCaller)(nil).Call), arg0, arg1, arg2, arg3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CallWithState mocks base method.
|
||||||
|
func (m *MockCaller) CallWithState(arg0 context.Context, arg1 ethapi.TransactionArgs, arg2 rpc.BlockNumberOrHash, arg3 *state.StateDB, arg4 *ethapi.StateOverride) (hexutil.Bytes, error) {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "CallWithState", arg0, arg1, arg2, arg3, arg4)
|
||||||
|
ret0, _ := ret[0].(hexutil.Bytes)
|
||||||
|
ret1, _ := ret[1].(error)
|
||||||
|
return ret0, ret1
|
||||||
|
}
|
||||||
|
|
||||||
|
// CallWithState indicates an expected call of CallWithState.
|
||||||
|
func (mr *MockCallerMockRecorder) CallWithState(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CallWithState", reflect.TypeOf((*MockCaller)(nil).CallWithState), arg0, arg1, arg2, arg3, arg4)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1184,22 +1184,42 @@ func (c *Bor) CommitStates(
|
||||||
fetchStart := time.Now()
|
fetchStart := time.Now()
|
||||||
number := header.Number.Uint64()
|
number := header.Number.Uint64()
|
||||||
|
|
||||||
_lastStateID, err := c.GenesisContractsClient.LastStateId(number - 1)
|
var (
|
||||||
if err != nil {
|
lastStateIDBig *big.Int
|
||||||
return nil, err
|
from uint64
|
||||||
|
to time.Time
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if c.config.IsIndore(header.Number) {
|
||||||
|
// Fetch the LastStateId from contract via current state instance
|
||||||
|
lastStateIDBig, err = c.GenesisContractsClient.LastStateId(state.Copy(), number-1, header.ParentHash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
stateSyncDelay := c.config.CalculateStateSyncDelay(number)
|
||||||
|
to = time.Unix(int64(header.Time-stateSyncDelay), 0)
|
||||||
|
} else {
|
||||||
|
lastStateIDBig, err = c.GenesisContractsClient.LastStateId(nil, number-1, header.ParentHash)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
to = time.Unix(int64(chain.Chain.GetHeaderByNumber(number-c.config.CalculateSprint(number)).Time), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
to := time.Unix(int64(chain.Chain.GetHeaderByNumber(number-c.config.CalculateSprint(number)).Time), 0)
|
lastStateID := lastStateIDBig.Uint64()
|
||||||
lastStateID := _lastStateID.Uint64()
|
from = lastStateID + 1
|
||||||
|
|
||||||
log.Info(
|
log.Info(
|
||||||
"Fetching state updates from Heimdall",
|
"Fetching state updates from Heimdall",
|
||||||
"fromID", lastStateID+1,
|
"fromID", from,
|
||||||
"to", to.Format(time.RFC3339))
|
"to", to.Format(time.RFC3339))
|
||||||
|
|
||||||
eventRecords, err := c.HeimdallClient.StateSyncEvents(ctx, lastStateID+1, to.Unix())
|
eventRecords, err := c.HeimdallClient.StateSyncEvents(ctx, from, to.Unix())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error occurred when fetching state sync events", "stateID", lastStateID+1, "error", err)
|
log.Error("Error occurred when fetching state sync events", "fromID", from, "to", to.Unix(), "err", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.config.OverrideStateSyncRecords != nil {
|
if c.config.OverrideStateSyncRecords != nil {
|
||||||
|
|
@ -1222,7 +1242,7 @@ func (c *Bor) CommitStates(
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = validateEventRecord(eventRecord, number, to, lastStateID, chainID); err != nil {
|
if err = validateEventRecord(eventRecord, number, to, lastStateID, chainID); err != nil {
|
||||||
log.Error("while validating event record", "block", number, "to", to, "stateID", lastStateID, "error", err.Error())
|
log.Error("while validating event record", "block", number, "to", to, "stateID", lastStateID+1, "error", err.Error())
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -100,8 +100,8 @@ func (gc *GenesisContractsClient) CommitState(
|
||||||
return gasUsed, nil
|
return gasUsed, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (gc *GenesisContractsClient) LastStateId(snapshotNumber uint64) (*big.Int, error) {
|
func (gc *GenesisContractsClient) LastStateId(state *state.StateDB, number uint64, hash common.Hash) (*big.Int, error) {
|
||||||
blockNr := rpc.BlockNumber(snapshotNumber)
|
blockNr := rpc.BlockNumber(number)
|
||||||
|
|
||||||
const method = "lastStateId"
|
const method = "lastStateId"
|
||||||
|
|
||||||
|
|
@ -116,11 +116,13 @@ func (gc *GenesisContractsClient) LastStateId(snapshotNumber uint64) (*big.Int,
|
||||||
toAddress := common.HexToAddress(gc.StateReceiverContract)
|
toAddress := common.HexToAddress(gc.StateReceiverContract)
|
||||||
gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
|
gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
|
||||||
|
|
||||||
result, err := gc.ethAPI.Call(context.Background(), ethapi.TransactionArgs{
|
// Do a call with state so that we can fetch the last state ID from a given (incoming)
|
||||||
|
// state instead of local(canonical) chain.
|
||||||
|
result, err := gc.ethAPI.CallWithState(context.Background(), ethapi.TransactionArgs{
|
||||||
Gas: &gas,
|
Gas: &gas,
|
||||||
To: &toAddress,
|
To: &toAddress,
|
||||||
Data: &msgData,
|
Data: &msgData,
|
||||||
}, rpc.BlockNumberOrHash{BlockNumber: &blockNr}, nil)
|
}, rpc.BlockNumberOrHash{BlockNumber: &blockNr, BlockHash: &hash}, state, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package bor
|
||||||
import (
|
import (
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/consensus/bor/clerk"
|
"github.com/ethereum/go-ethereum/consensus/bor/clerk"
|
||||||
"github.com/ethereum/go-ethereum/consensus/bor/statefull"
|
"github.com/ethereum/go-ethereum/consensus/bor/statefull"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
|
|
@ -12,5 +13,5 @@ import (
|
||||||
//go:generate mockgen -destination=./genesis_contract_mock.go -package=bor . GenesisContract
|
//go:generate mockgen -destination=./genesis_contract_mock.go -package=bor . GenesisContract
|
||||||
type GenesisContract interface {
|
type GenesisContract interface {
|
||||||
CommitState(event *clerk.EventRecordWithTime, state *state.StateDB, header *types.Header, chCtx statefull.ChainContext) (uint64, error)
|
CommitState(event *clerk.EventRecordWithTime, state *state.StateDB, header *types.Header, chCtx statefull.ChainContext) (uint64, error)
|
||||||
LastStateId(snapshotNumber uint64) (*big.Int, error)
|
LastStateId(state *state.StateDB, number uint64, hash common.Hash) (*big.Int, error)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
big "math/big"
|
big "math/big"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
|
|
||||||
|
common "github.com/ethereum/go-ethereum/common"
|
||||||
clerk "github.com/ethereum/go-ethereum/consensus/bor/clerk"
|
clerk "github.com/ethereum/go-ethereum/consensus/bor/clerk"
|
||||||
statefull "github.com/ethereum/go-ethereum/consensus/bor/statefull"
|
statefull "github.com/ethereum/go-ethereum/consensus/bor/statefull"
|
||||||
state "github.com/ethereum/go-ethereum/core/state"
|
state "github.com/ethereum/go-ethereum/core/state"
|
||||||
|
|
@ -54,16 +55,16 @@ func (mr *MockGenesisContractMockRecorder) CommitState(arg0, arg1, arg2, arg3 in
|
||||||
}
|
}
|
||||||
|
|
||||||
// LastStateId mocks base method.
|
// LastStateId mocks base method.
|
||||||
func (m *MockGenesisContract) LastStateId(arg0 uint64) (*big.Int, error) {
|
func (m *MockGenesisContract) LastStateId(arg0 *state.StateDB, arg1 uint64, arg2 common.Hash) (*big.Int, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "LastStateId", arg0)
|
ret := m.ctrl.Call(m, "LastStateId", arg0, arg1, arg2)
|
||||||
ret0, _ := ret[0].(*big.Int)
|
ret0, _ := ret[0].(*big.Int)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// LastStateId indicates an expected call of LastStateId.
|
// LastStateId indicates an expected call of LastStateId.
|
||||||
func (mr *MockGenesisContractMockRecorder) LastStateId(arg0 interface{}) *gomock.Call {
|
func (mr *MockGenesisContractMockRecorder) LastStateId(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LastStateId", reflect.TypeOf((*MockGenesisContract)(nil).LastStateId), arg0)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LastStateId", reflect.TypeOf((*MockGenesisContract)(nil).LastStateId), arg0, arg1, arg2)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
// Code generated by MockGen. DO NOT EDIT.
|
// Code generated by MockGen. DO NOT EDIT.
|
||||||
// Source: consensus/bor/span.go
|
// Source: github.com/ethereum/go-ethereum/consensus/bor (interfaces: Spanner)
|
||||||
|
|
||||||
// Package bor is a generated GoMock package.
|
// Package bor is a generated GoMock package.
|
||||||
package bor
|
package bor
|
||||||
|
|
@ -42,60 +42,60 @@ func (m *MockSpanner) EXPECT() *MockSpannerMockRecorder {
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommitSpan mocks base method.
|
// CommitSpan mocks base method.
|
||||||
func (m *MockSpanner) CommitSpan(ctx context.Context, heimdallSpan span.HeimdallSpan, state *state.StateDB, header *types.Header, chainContext core.ChainContext) error {
|
func (m *MockSpanner) CommitSpan(arg0 context.Context, arg1 span.HeimdallSpan, arg2 *state.StateDB, arg3 *types.Header, arg4 core.ChainContext) error {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "CommitSpan", ctx, heimdallSpan, state, header, chainContext)
|
ret := m.ctrl.Call(m, "CommitSpan", arg0, arg1, arg2, arg3, arg4)
|
||||||
ret0, _ := ret[0].(error)
|
ret0, _ := ret[0].(error)
|
||||||
return ret0
|
return ret0
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommitSpan indicates an expected call of CommitSpan.
|
// CommitSpan indicates an expected call of CommitSpan.
|
||||||
func (mr *MockSpannerMockRecorder) CommitSpan(ctx, heimdallSpan, state, header, chainContext interface{}) *gomock.Call {
|
func (mr *MockSpannerMockRecorder) CommitSpan(arg0, arg1, arg2, arg3, arg4 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitSpan", reflect.TypeOf((*MockSpanner)(nil).CommitSpan), ctx, heimdallSpan, state, header, chainContext)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CommitSpan", reflect.TypeOf((*MockSpanner)(nil).CommitSpan), arg0, arg1, arg2, arg3, arg4)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentSpan mocks base method.
|
// GetCurrentSpan mocks base method.
|
||||||
func (m *MockSpanner) GetCurrentSpan(ctx context.Context, headerHash common.Hash) (*span.Span, error) {
|
func (m *MockSpanner) GetCurrentSpan(arg0 context.Context, arg1 common.Hash) (*span.Span, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetCurrentSpan", ctx, headerHash)
|
ret := m.ctrl.Call(m, "GetCurrentSpan", arg0, arg1)
|
||||||
ret0, _ := ret[0].(*span.Span)
|
ret0, _ := ret[0].(*span.Span)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentSpan indicates an expected call of GetCurrentSpan.
|
// GetCurrentSpan indicates an expected call of GetCurrentSpan.
|
||||||
func (mr *MockSpannerMockRecorder) GetCurrentSpan(ctx, headerHash interface{}) *gomock.Call {
|
func (mr *MockSpannerMockRecorder) GetCurrentSpan(arg0, arg1 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentSpan", reflect.TypeOf((*MockSpanner)(nil).GetCurrentSpan), ctx, headerHash)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentSpan", reflect.TypeOf((*MockSpanner)(nil).GetCurrentSpan), arg0, arg1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentValidatorsByBlockNrOrHash mocks base method.
|
// GetCurrentValidatorsByBlockNrOrHash mocks base method.
|
||||||
func (m *MockSpanner) GetCurrentValidatorsByBlockNrOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash, blockNumber uint64) ([]*valset.Validator, error) {
|
func (m *MockSpanner) GetCurrentValidatorsByBlockNrOrHash(arg0 context.Context, arg1 rpc.BlockNumberOrHash, arg2 uint64) ([]*valset.Validator, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetCurrentValidatorsByBlockNrOrHash", ctx, blockNrOrHash, blockNumber)
|
ret := m.ctrl.Call(m, "GetCurrentValidatorsByBlockNrOrHash", arg0, arg1, arg2)
|
||||||
ret0, _ := ret[0].([]*valset.Validator)
|
ret0, _ := ret[0].([]*valset.Validator)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentValidatorsByBlockNrOrHash indicates an expected call of GetCurrentValidatorsByBlockNrOrHash.
|
// GetCurrentValidatorsByBlockNrOrHash indicates an expected call of GetCurrentValidatorsByBlockNrOrHash.
|
||||||
func (mr *MockSpannerMockRecorder) GetCurrentValidatorsByBlockNrOrHash(ctx, blockNrOrHash, blockNumber interface{}) *gomock.Call {
|
func (mr *MockSpannerMockRecorder) GetCurrentValidatorsByBlockNrOrHash(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentValidatorsByBlockNrOrHash", reflect.TypeOf((*MockSpanner)(nil).GetCurrentValidatorsByBlockNrOrHash), ctx, blockNrOrHash, blockNumber)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentValidatorsByBlockNrOrHash", reflect.TypeOf((*MockSpanner)(nil).GetCurrentValidatorsByBlockNrOrHash), arg0, arg1, arg2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentValidatorsByHash mocks base method.
|
// GetCurrentValidatorsByHash mocks base method.
|
||||||
func (m *MockSpanner) GetCurrentValidatorsByHash(ctx context.Context, headerHash common.Hash, blockNumber uint64) ([]*valset.Validator, error) {
|
func (m *MockSpanner) GetCurrentValidatorsByHash(arg0 context.Context, arg1 common.Hash, arg2 uint64) ([]*valset.Validator, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
ret := m.ctrl.Call(m, "GetCurrentValidatorsByHash", ctx, headerHash, blockNumber)
|
ret := m.ctrl.Call(m, "GetCurrentValidatorsByHash", arg0, arg1, arg2)
|
||||||
ret0, _ := ret[0].([]*valset.Validator)
|
ret0, _ := ret[0].([]*valset.Validator)
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCurrentValidatorsByHash indicates an expected call of GetCurrentValidatorsByHash.
|
// GetCurrentValidatorsByHash indicates an expected call of GetCurrentValidatorsByHash.
|
||||||
func (mr *MockSpannerMockRecorder) GetCurrentValidatorsByHash(ctx, headerHash, blockNumber interface{}) *gomock.Call {
|
func (mr *MockSpannerMockRecorder) GetCurrentValidatorsByHash(arg0, arg1, arg2 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentValidatorsByHash", reflect.TypeOf((*MockSpanner)(nil).GetCurrentValidatorsByHash), ctx, headerHash, blockNumber)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCurrentValidatorsByHash", reflect.TypeOf((*MockSpanner)(nil).GetCurrentValidatorsByHash), arg0, arg1, arg2)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1006,7 +1006,8 @@ func (b *Block) Call(ctx context.Context, args struct {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result, err := ethapi.DoCall(ctx, b.backend, args.Data, *b.numberOrHash, nil, b.backend.RPCEVMTimeout(), b.backend.RPCGasCap())
|
|
||||||
|
result, err := ethapi.DoCall(ctx, b.backend, args.Data, *b.numberOrHash, nil, nil, b.backend.RPCEVMTimeout(), b.backend.RPCGasCap())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -1076,7 +1077,7 @@ func (p *Pending) Call(ctx context.Context, args struct {
|
||||||
Data ethapi.TransactionArgs
|
Data ethapi.TransactionArgs
|
||||||
}) (*CallResult, error) {
|
}) (*CallResult, error) {
|
||||||
pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
|
pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
|
||||||
result, err := ethapi.DoCall(ctx, p.backend, args.Data, pendingBlockNr, nil, p.backend.RPCEVMTimeout(), p.backend.RPCGasCap())
|
result, err := ethapi.DoCall(ctx, p.backend, args.Data, pendingBlockNr, nil, nil, p.backend.RPCEVMTimeout(), p.backend.RPCGasCap())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -987,16 +987,40 @@ func (diff *StateOverride) Apply(state *state.StateDB) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) {
|
func DoCall(ctx context.Context, b Backend, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, state *state.StateDB, overrides *StateOverride, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) {
|
||||||
defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now())
|
defer func(start time.Time) { log.Debug("Executing EVM call finished", "runtime", time.Since(start)) }(time.Now())
|
||||||
|
|
||||||
state, header, err := b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
var (
|
||||||
if state == nil || err != nil {
|
header *types.Header
|
||||||
return nil, err
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
// Fetch the state and header from blockNumberOrHash if it's coming from normal eth_call path.
|
||||||
|
if state == nil {
|
||||||
|
state, header, err = b.StateAndHeaderByNumberOrHash(ctx, blockNrOrHash)
|
||||||
|
if state == nil || err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Fetch the header from the given blockNumberOrHash. Note that this path is only taken
|
||||||
|
// when we're doing a call from bor consensus to fetch data from genesis contracts. It's
|
||||||
|
// necessary to fetch header using header hash as we might be experiencing a reorg and there
|
||||||
|
// can be multiple headers with same number.
|
||||||
|
header, err = b.HeaderByHash(ctx, *blockNrOrHash.BlockHash)
|
||||||
|
if header == nil || err != nil {
|
||||||
|
log.Warn("Error fetching header on CallWithState", "err", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := overrides.Apply(state); err != nil {
|
if err := overrides.Apply(state); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return doCallWithState(ctx, b, args, header, state, timeout, globalGasCap)
|
||||||
|
}
|
||||||
|
|
||||||
|
func doCallWithState(ctx context.Context, b Backend, args TransactionArgs, header *types.Header, state *state.StateDB, timeout time.Duration, globalGasCap uint64) (*core.ExecutionResult, error) {
|
||||||
// Setup context so it may be cancelled the call has completed
|
// Setup context so it may be cancelled the call has completed
|
||||||
// or, in case of unmetered gas, setup a context with a timeout.
|
// or, in case of unmetered gas, setup a context with a timeout.
|
||||||
var cancel context.CancelFunc
|
var cancel context.CancelFunc
|
||||||
|
|
@ -1080,7 +1104,20 @@ func (e *revertError) ErrorData() interface{} {
|
||||||
// Note, this function doesn't make and changes in the state/blockchain and is
|
// Note, this function doesn't make and changes in the state/blockchain and is
|
||||||
// useful to execute and retrieve values.
|
// useful to execute and retrieve values.
|
||||||
func (s *PublicBlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride) (hexutil.Bytes, error) {
|
func (s *PublicBlockChainAPI) Call(ctx context.Context, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, overrides *StateOverride) (hexutil.Bytes, error) {
|
||||||
result, err := DoCall(ctx, s.b, args, blockNrOrHash, overrides, s.b.RPCEVMTimeout(), s.b.RPCGasCap())
|
return s.CallWithState(ctx, args, blockNrOrHash, nil, overrides)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CallWithState executes the given transaction on the given state for
|
||||||
|
// the given block number. Note that as it does an EVM call, fields in
|
||||||
|
// the underlying state will change. Make sure to handle it outside of
|
||||||
|
// this function (ideally by sending a copy of state).
|
||||||
|
//
|
||||||
|
// Additionally, the caller can specify a batch of contract for fields overriding.
|
||||||
|
//
|
||||||
|
// Note, this function doesn't make and changes in the state/blockchain and is
|
||||||
|
// useful to execute and retrieve values.
|
||||||
|
func (s *PublicBlockChainAPI) CallWithState(ctx context.Context, args TransactionArgs, blockNrOrHash rpc.BlockNumberOrHash, state *state.StateDB, overrides *StateOverride) (hexutil.Bytes, error) {
|
||||||
|
result, err := DoCall(ctx, s.b, args, blockNrOrHash, state, overrides, s.b.RPCEVMTimeout(), s.b.RPCGasCap())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -1093,6 +1130,7 @@ func (s *PublicBlockChainAPI) Call(ctx context.Context, args TransactionArgs, bl
|
||||||
if len(result.Revert()) > 0 {
|
if len(result.Revert()) > 0 {
|
||||||
return nil, newRevertError(result)
|
return nil, newRevertError(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result.Return(), result.Err
|
return result.Return(), result.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1170,7 +1208,7 @@ func DoEstimateGas(ctx context.Context, b Backend, args TransactionArgs, blockNr
|
||||||
executable := func(gas uint64) (bool, *core.ExecutionResult, error) {
|
executable := func(gas uint64) (bool, *core.ExecutionResult, error) {
|
||||||
args.Gas = (*hexutil.Uint64)(&gas)
|
args.Gas = (*hexutil.Uint64)(&gas)
|
||||||
|
|
||||||
result, err := DoCall(ctx, b, args, blockNrOrHash, nil, 0, gasCap)
|
result, err := DoCall(ctx, b, args, blockNrOrHash, nil, nil, 0, gasCap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, core.ErrIntrinsicGas) {
|
if errors.Is(err, core.ErrIntrinsicGas) {
|
||||||
return true, nil, nil // Special case, raise gas limit
|
return true, nil, nil // Special case, raise gas limit
|
||||||
|
|
|
||||||
|
|
@ -406,8 +406,8 @@ var (
|
||||||
LondonBlock: big.NewInt(23850000),
|
LondonBlock: big.NewInt(23850000),
|
||||||
Bor: &BorConfig{
|
Bor: &BorConfig{
|
||||||
JaipurBlock: big.NewInt(23850000),
|
JaipurBlock: big.NewInt(23850000),
|
||||||
ParallelUniverseBlock: big.NewInt(0),
|
|
||||||
DelhiBlock: big.NewInt(38189056),
|
DelhiBlock: big.NewInt(38189056),
|
||||||
|
ParallelUniverseBlock: big.NewInt(0),
|
||||||
Period: map[string]uint64{
|
Period: map[string]uint64{
|
||||||
"0": 2,
|
"0": 2,
|
||||||
},
|
},
|
||||||
|
|
@ -578,18 +578,20 @@ func (c *CliqueConfig) String() string {
|
||||||
|
|
||||||
// BorConfig is the consensus engine configs for Matic bor based sealing.
|
// BorConfig is the consensus engine configs for Matic bor based sealing.
|
||||||
type BorConfig struct {
|
type BorConfig struct {
|
||||||
Period map[string]uint64 `json:"period"` // Number of seconds between blocks to enforce
|
Period map[string]uint64 `json:"period"` // Number of seconds between blocks to enforce
|
||||||
ProducerDelay map[string]uint64 `json:"producerDelay"` // Number of seconds delay between two producer interval
|
ProducerDelay map[string]uint64 `json:"producerDelay"` // Number of seconds delay between two producer interval
|
||||||
Sprint map[string]uint64 `json:"sprint"` // Epoch length to proposer
|
Sprint map[string]uint64 `json:"sprint"` // Epoch length to proposer
|
||||||
BackupMultiplier map[string]uint64 `json:"backupMultiplier"` // Backup multiplier to determine the wiggle time
|
BackupMultiplier map[string]uint64 `json:"backupMultiplier"` // Backup multiplier to determine the wiggle time
|
||||||
ValidatorContract string `json:"validatorContract"` // Validator set contract
|
ValidatorContract string `json:"validatorContract"` // Validator set contract
|
||||||
StateReceiverContract string `json:"stateReceiverContract"` // State receiver contract
|
StateReceiverContract string `json:"stateReceiverContract"` // State receiver contract
|
||||||
OverrideStateSyncRecords map[string]int `json:"overrideStateSyncRecords"` // override state records count
|
OverrideStateSyncRecords map[string]int `json:"overrideStateSyncRecords"` // override state records count
|
||||||
BlockAlloc map[string]interface{} `json:"blockAlloc"`
|
BlockAlloc map[string]interface{} `json:"blockAlloc"`
|
||||||
BurntContract map[string]string `json:"burntContract"` // governance contract where the token will be sent to and burnt in london fork
|
BurntContract map[string]string `json:"burntContract"` // governance contract where the token will be sent to and burnt in london fork
|
||||||
JaipurBlock *big.Int `json:"jaipurBlock"` // Jaipur switch block (nil = no fork, 0 = already on jaipur)
|
JaipurBlock *big.Int `json:"jaipurBlock"` // Jaipur switch block (nil = no fork, 0 = already on jaipur)
|
||||||
DelhiBlock *big.Int `json:"delhiBlock"` // Delhi switch block (nil = no fork, 0 = already on delhi)
|
DelhiBlock *big.Int `json:"delhiBlock"` // Delhi switch block (nil = no fork, 0 = already on delhi)
|
||||||
ParallelUniverseBlock *big.Int `json:"parallelUniverseBlock"` // TODO: update all occurrence, change name and finalize number (hardfork for block-stm related changes)
|
ParallelUniverseBlock *big.Int `json:"parallelUniverseBlock"` // TODO: update all occurrence, change name and finalize number (hardfork for block-stm related changes)
|
||||||
|
IndoreBlock *big.Int `json:"indoreBlock"` // Indore switch block (nil = no fork, 0 = already on indore)
|
||||||
|
StateSyncConfirmationDelay map[string]uint64 `json:"stateSyncConfirmationDelay"` // StateSync Confirmation Delay, in seconds, to calculate `to`
|
||||||
}
|
}
|
||||||
|
|
||||||
// String implements the stringer interface, returning the consensus engine details.
|
// String implements the stringer interface, returning the consensus engine details.
|
||||||
|
|
@ -598,11 +600,11 @@ func (b *BorConfig) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *BorConfig) CalculateProducerDelay(number uint64) uint64 {
|
func (c *BorConfig) CalculateProducerDelay(number uint64) uint64 {
|
||||||
return c.calculateSprintSizeHelper(c.ProducerDelay, number)
|
return borKeyValueConfigHelper(c.ProducerDelay, number)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *BorConfig) CalculateSprint(number uint64) uint64 {
|
func (c *BorConfig) CalculateSprint(number uint64) uint64 {
|
||||||
return c.calculateSprintSizeHelper(c.Sprint, number)
|
return borKeyValueConfigHelper(c.Sprint, number)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *BorConfig) CalculateBackupMultiplier(number uint64) uint64 {
|
func (c *BorConfig) CalculateBackupMultiplier(number uint64) uint64 {
|
||||||
|
|
@ -621,6 +623,14 @@ func (c *BorConfig) IsDelhi(number *big.Int) bool {
|
||||||
return isForked(c.DelhiBlock, number)
|
return isForked(c.DelhiBlock, number)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *BorConfig) IsIndore(number *big.Int) bool {
|
||||||
|
return isForked(c.IndoreBlock, number)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *BorConfig) CalculateStateSyncDelay(number uint64) uint64 {
|
||||||
|
return borKeyValueConfigHelper(c.StateSyncConfirmationDelay, number)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: modify this function once the block number is finalized
|
// TODO: modify this function once the block number is finalized
|
||||||
func (c *BorConfig) IsParallelUniverse(number *big.Int) bool {
|
func (c *BorConfig) IsParallelUniverse(number *big.Int) bool {
|
||||||
if c.ParallelUniverseBlock == big.NewInt(0) {
|
if c.ParallelUniverseBlock == big.NewInt(0) {
|
||||||
|
|
@ -654,7 +664,7 @@ func (c *BorConfig) calculateBorConfigHelper(field map[string]uint64, number uin
|
||||||
return field[keys[len(keys)-1]]
|
return field[keys[len(keys)-1]]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *BorConfig) calculateSprintSizeHelper(field map[string]uint64, number uint64) uint64 {
|
func borKeyValueConfigHelper(field map[string]uint64, number uint64) uint64 {
|
||||||
keys := make([]string, 0, len(field))
|
keys := make([]string, 0, len(field))
|
||||||
for k := range field {
|
for k := range field {
|
||||||
keys = append(keys, k)
|
keys = append(keys, k)
|
||||||
|
|
|
||||||
|
|
@ -544,7 +544,7 @@ func TestFetchStateSyncEvents_2(t *testing.T) {
|
||||||
insertNewBlock(t, chain, block)
|
insertNewBlock(t, chain, block)
|
||||||
}
|
}
|
||||||
|
|
||||||
lastStateID, _ := _bor.GenesisContractsClient.LastStateId(sprintSize)
|
lastStateID, _ := _bor.GenesisContractsClient.LastStateId(nil, sprintSize, block.Hash())
|
||||||
|
|
||||||
// state 6 was not written
|
// state 6 was not written
|
||||||
require.Equal(t, uint64(4), lastStateID.Uint64())
|
require.Equal(t, uint64(4), lastStateID.Uint64())
|
||||||
|
|
@ -573,7 +573,7 @@ func TestFetchStateSyncEvents_2(t *testing.T) {
|
||||||
insertNewBlock(t, chain, block)
|
insertNewBlock(t, chain, block)
|
||||||
}
|
}
|
||||||
|
|
||||||
lastStateID, _ = _bor.GenesisContractsClient.LastStateId(spanSize)
|
lastStateID, _ = _bor.GenesisContractsClient.LastStateId(nil, spanSize, block.Hash())
|
||||||
require.Equal(t, uint64(6), lastStateID.Uint64())
|
require.Equal(t, uint64(6), lastStateID.Uint64())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue