2023-07-14 14:38:17 +00:00
|
|
|
package eth1
|
|
|
|
|
|
|
|
import (
|
2023-07-15 16:31:15 +00:00
|
|
|
"context"
|
2023-07-28 22:22:38 +00:00
|
|
|
"math/big"
|
2023-07-15 16:31:15 +00:00
|
|
|
|
2023-07-27 12:37:49 +00:00
|
|
|
"github.com/ledgerwatch/erigon-lib/chain"
|
2023-07-15 16:31:15 +00:00
|
|
|
libcommon "github.com/ledgerwatch/erigon-lib/common"
|
2023-07-20 16:35:02 +00:00
|
|
|
"github.com/ledgerwatch/erigon-lib/gointerfaces"
|
2023-07-14 14:38:17 +00:00
|
|
|
"github.com/ledgerwatch/erigon-lib/gointerfaces/execution"
|
2023-07-20 16:35:02 +00:00
|
|
|
"github.com/ledgerwatch/log/v3"
|
2023-07-23 17:10:24 +00:00
|
|
|
"golang.org/x/sync/semaphore"
|
2023-07-14 14:38:17 +00:00
|
|
|
|
|
|
|
"github.com/ledgerwatch/erigon-lib/kv"
|
2023-07-27 12:37:49 +00:00
|
|
|
"github.com/ledgerwatch/erigon/core"
|
2023-07-15 16:31:15 +00:00
|
|
|
"github.com/ledgerwatch/erigon/core/rawdb"
|
|
|
|
"github.com/ledgerwatch/erigon/core/types"
|
2023-07-20 16:35:02 +00:00
|
|
|
"github.com/ledgerwatch/erigon/eth/stagedsync"
|
2023-07-27 12:37:49 +00:00
|
|
|
"github.com/ledgerwatch/erigon/turbo/builder"
|
2023-07-23 17:10:24 +00:00
|
|
|
"github.com/ledgerwatch/erigon/turbo/engineapi/engine_helpers"
|
|
|
|
"github.com/ledgerwatch/erigon/turbo/engineapi/engine_types"
|
2023-07-14 14:38:17 +00:00
|
|
|
"github.com/ledgerwatch/erigon/turbo/services"
|
2023-07-30 21:35:55 +00:00
|
|
|
"github.com/ledgerwatch/erigon/turbo/shards"
|
2023-07-14 14:38:17 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// EthereumExecutionModule describes ethereum execution logic and indexing.
|
|
|
|
type EthereumExecutionModule struct {
|
|
|
|
// Snapshots + MDBX
|
|
|
|
blockReader services.FullBlockReader
|
|
|
|
|
|
|
|
// MDBX database
|
2023-07-20 16:35:02 +00:00
|
|
|
db kv.RwDB // main database
|
2023-07-23 17:10:24 +00:00
|
|
|
semaphore *semaphore.Weighted
|
2023-07-20 16:35:02 +00:00
|
|
|
executionPipeline *stagedsync.Sync
|
2023-07-23 17:10:24 +00:00
|
|
|
forkValidator *engine_helpers.ForkValidator
|
2023-07-20 16:35:02 +00:00
|
|
|
|
|
|
|
logger log.Logger
|
2023-07-27 12:37:49 +00:00
|
|
|
// Block building
|
|
|
|
nextPayloadId uint64
|
|
|
|
lastParameters *core.BlockBuilderParameters
|
|
|
|
builderFunc builder.BlockBuilderFunc
|
|
|
|
builders map[uint64]*builder.BlockBuilder
|
|
|
|
|
2023-07-30 21:35:55 +00:00
|
|
|
// Changes accumulator
|
|
|
|
accumulator *shards.Accumulator
|
|
|
|
stateChangeConsumer shards.StateChangeConsumer
|
|
|
|
|
2023-07-27 12:37:49 +00:00
|
|
|
// configuration
|
2023-07-27 23:32:19 +00:00
|
|
|
config *chain.Config
|
|
|
|
historyV3 bool
|
2023-07-14 14:38:17 +00:00
|
|
|
|
|
|
|
execution.UnimplementedExecutionServer
|
|
|
|
}
|
|
|
|
|
2023-07-27 23:32:19 +00:00
|
|
|
func NewEthereumExecutionModule(blockReader services.FullBlockReader, db kv.RwDB, executionPipeline *stagedsync.Sync, forkValidator *engine_helpers.ForkValidator,
|
2023-07-30 21:35:55 +00:00
|
|
|
config *chain.Config, builderFunc builder.BlockBuilderFunc, accumulator *shards.Accumulator, stateChangeConsumer shards.StateChangeConsumer, logger log.Logger, historyV3 bool) *EthereumExecutionModule {
|
2023-07-15 16:31:15 +00:00
|
|
|
return &EthereumExecutionModule{
|
2023-07-30 21:35:55 +00:00
|
|
|
blockReader: blockReader,
|
|
|
|
db: db,
|
|
|
|
executionPipeline: executionPipeline,
|
|
|
|
logger: logger,
|
|
|
|
forkValidator: forkValidator,
|
|
|
|
builders: make(map[uint64]*builder.BlockBuilder),
|
|
|
|
builderFunc: builderFunc,
|
|
|
|
config: config,
|
|
|
|
semaphore: semaphore.NewWeighted(1),
|
|
|
|
accumulator: accumulator,
|
|
|
|
stateChangeConsumer: stateChangeConsumer,
|
2023-07-15 16:31:15 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-20 16:35:02 +00:00
|
|
|
func (e *EthereumExecutionModule) getHeader(ctx context.Context, tx kv.Tx, blockHash libcommon.Hash, blockNumber uint64) (*types.Header, error) {
|
2023-07-15 16:31:15 +00:00
|
|
|
if e.blockReader == nil {
|
2023-07-20 16:35:02 +00:00
|
|
|
return rawdb.ReadHeader(tx, blockHash, blockNumber), nil
|
2023-07-15 16:31:15 +00:00
|
|
|
}
|
2023-07-20 16:35:02 +00:00
|
|
|
return e.blockReader.Header(ctx, tx, blockHash, blockNumber)
|
2023-07-15 16:31:15 +00:00
|
|
|
}
|
2023-07-14 14:38:17 +00:00
|
|
|
|
2023-07-28 22:22:38 +00:00
|
|
|
func (e *EthereumExecutionModule) getTD(ctx context.Context, tx kv.Tx, blockHash libcommon.Hash, blockNumber uint64) (*big.Int, error) {
|
|
|
|
return rawdb.ReadTd(tx, blockHash, blockNumber)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2023-07-20 16:35:02 +00:00
|
|
|
func (e *EthereumExecutionModule) getBody(ctx context.Context, tx kv.Tx, blockHash libcommon.Hash, blockNumber uint64) (*types.Body, error) {
|
2023-07-15 16:31:15 +00:00
|
|
|
if e.blockReader == nil {
|
2023-07-20 16:35:02 +00:00
|
|
|
body, _, _ := rawdb.ReadBody(tx, blockHash, blockNumber)
|
2023-07-15 16:31:15 +00:00
|
|
|
return body, nil
|
|
|
|
}
|
2023-07-20 16:35:02 +00:00
|
|
|
return e.blockReader.BodyWithTransactions(ctx, tx, blockHash, blockNumber)
|
2023-07-15 16:31:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (e *EthereumExecutionModule) canonicalHash(ctx context.Context, tx kv.Tx, blockNumber uint64) (libcommon.Hash, error) {
|
|
|
|
if e.blockReader == nil {
|
|
|
|
return rawdb.ReadCanonicalHash(tx, blockNumber)
|
|
|
|
}
|
|
|
|
return e.blockReader.CanonicalHash(ctx, tx, blockNumber)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Remaining
|
2023-07-14 14:38:17 +00:00
|
|
|
|
2023-07-23 17:10:24 +00:00
|
|
|
func (e *EthereumExecutionModule) ValidateChain(ctx context.Context, req *execution.ValidationRequest) (*execution.ValidationReceipt, error) {
|
|
|
|
if !e.semaphore.TryAcquire(1) {
|
|
|
|
return &execution.ValidationReceipt{
|
|
|
|
LatestValidHash: gointerfaces.ConvertHashToH256(libcommon.Hash{}),
|
|
|
|
ValidationStatus: execution.ValidationStatus_Busy,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
defer e.semaphore.Release(1)
|
|
|
|
tx, err := e.db.BeginRw(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer tx.Rollback()
|
2023-07-30 21:35:55 +00:00
|
|
|
e.forkValidator.ClearWithUnwind(tx, e.accumulator, e.stateChangeConsumer)
|
2023-07-23 17:10:24 +00:00
|
|
|
blockHash := gointerfaces.ConvertH256ToHash(req.Hash)
|
|
|
|
header, err := e.blockReader.Header(ctx, tx, blockHash, req.Number)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
body, err := e.blockReader.BodyWithTransactions(ctx, tx, blockHash, req.Number)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2023-07-30 21:35:55 +00:00
|
|
|
|
2023-07-23 17:10:24 +00:00
|
|
|
if header == nil || body == nil {
|
|
|
|
return &execution.ValidationReceipt{
|
|
|
|
LatestValidHash: gointerfaces.ConvertHashToH256(libcommon.Hash{}),
|
|
|
|
MissingHash: req.Hash,
|
|
|
|
ValidationStatus: execution.ValidationStatus_MissingSegment,
|
|
|
|
}, nil
|
|
|
|
}
|
2023-07-30 21:35:55 +00:00
|
|
|
|
2023-07-23 17:10:24 +00:00
|
|
|
status, lvh, validationError, criticalError := e.forkValidator.ValidatePayload(tx, header, body.RawBody(), false)
|
|
|
|
if criticalError != nil {
|
|
|
|
return nil, criticalError
|
|
|
|
}
|
|
|
|
validationStatus := execution.ValidationStatus_Success
|
|
|
|
if status == engine_types.AcceptedStatus {
|
|
|
|
validationStatus = execution.ValidationStatus_MissingSegment
|
|
|
|
}
|
|
|
|
if status == engine_types.InvalidStatus || status == engine_types.InvalidBlockHashStatus || validationError != nil {
|
|
|
|
e.logger.Warn("ethereumExecutionModule.ValidateChain: chain %x is invalid. reason %s", blockHash, err)
|
|
|
|
validationStatus = execution.ValidationStatus_BadBlock
|
|
|
|
}
|
|
|
|
return &execution.ValidationReceipt{
|
|
|
|
ValidationStatus: validationStatus,
|
|
|
|
LatestValidHash: gointerfaces.ConvertHashToH256(lvh),
|
|
|
|
MissingHash: gointerfaces.ConvertHashToH256(libcommon.Hash{}), // TODO: implement
|
|
|
|
}, nil
|
|
|
|
}
|