prototype of ValidataChain (#7921)

This commit is contained in:
Giulio rebuffo 2023-07-23 19:10:24 +02:00 committed by GitHub
parent 837ffb5b7e
commit 9d3551f8cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 113 additions and 22 deletions

View File

@ -36,7 +36,7 @@ func NewEth1Execution(db kv.RwDB, blockReader services.FullBlockReader) *Eth1Exe
}
}
func (e *Eth1Execution) InsertHeaders(ctx context.Context, req *execution.InsertHeadersRequest) (*execution.EmptyMessage, error) {
func (e *Eth1Execution) InsertHeaders(ctx context.Context, req *execution.InsertHeadersRequest) (*execution.InsertionResult, error) {
e.mu.Lock()
defer e.mu.Unlock()
tx, err := e.db.BeginRw(ctx)
@ -54,10 +54,12 @@ func (e *Eth1Execution) InsertHeaders(ctx context.Context, req *execution.Insert
return nil, err
}
}
return &execution.EmptyMessage{}, tx.Commit()
return &execution.InsertionResult{
Result: execution.ValidationStatus_Success,
}, tx.Commit()
}
func (e *Eth1Execution) InsertBodies(ctx context.Context, req *execution.InsertBodiesRequest) (*execution.EmptyMessage, error) {
func (e *Eth1Execution) InsertBodies(ctx context.Context, req *execution.InsertBodiesRequest) (*execution.InsertionResult, error) {
e.mu.Lock()
defer e.mu.Unlock()
tx, err := e.db.BeginRw(ctx)
@ -94,7 +96,9 @@ func (e *Eth1Execution) InsertBodies(ctx context.Context, req *execution.InsertB
return nil, err
}
}
return &execution.EmptyMessage{}, tx.Commit()
return &execution.InsertionResult{
Result: execution.ValidationStatus_Success,
}, tx.Commit()
}
type canonicalEntry struct {

2
go.mod
View File

@ -3,7 +3,7 @@ module github.com/ledgerwatch/erigon
go 1.19
require (
github.com/ledgerwatch/erigon-lib v0.0.0-20230714001632-a0450f4fddd1
github.com/ledgerwatch/erigon-lib v0.0.0-20230723163836-9e08d02f75b8
github.com/ledgerwatch/erigon-snapshot v1.2.1-0.20230622075030-1d69651854c2
github.com/ledgerwatch/log/v3 v3.8.0
github.com/ledgerwatch/secp256k1 v1.0.0

4
go.sum
View File

@ -415,8 +415,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758 h1:0D5M2HQSGD3PYPwICLl+/9oulQauOuETfgFvhBDffs0=
github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c=
github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8=
github.com/ledgerwatch/erigon-lib v0.0.0-20230714001632-a0450f4fddd1 h1:dSsZV1wEVixmc+aXO6fv2XyZ05JOrj4gGIuxoTPIjYM=
github.com/ledgerwatch/erigon-lib v0.0.0-20230714001632-a0450f4fddd1/go.mod h1:S/p/qNKN8yFyBy0WjBVjATpm1uwjPmhdcrDmseWHBVQ=
github.com/ledgerwatch/erigon-lib v0.0.0-20230723163836-9e08d02f75b8 h1:P8CdtNh0DDKhzTVnwuCQY1lg8Jn1N21nmSHGOl4Kjxo=
github.com/ledgerwatch/erigon-lib v0.0.0-20230723163836-9e08d02f75b8/go.mod h1:ZkH1giM9x/HgdvjWzeCiOIx2lLDo98T/uvmRkG6xet0=
github.com/ledgerwatch/erigon-snapshot v1.2.1-0.20230622075030-1d69651854c2 h1:Ls2itRGHMOr2PbHRDA4g1HH8HQdwfJhRVfMPEaLQe94=
github.com/ledgerwatch/erigon-snapshot v1.2.1-0.20230622075030-1d69651854c2/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo=
github.com/ledgerwatch/log/v3 v3.8.0 h1:gCpp7uGtIerEz1jKVPeDnbIopFPud9ZnCpBLlLBGqPU=

View File

@ -9,6 +9,7 @@ import (
"github.com/ledgerwatch/erigon-lib/gointerfaces"
"github.com/ledgerwatch/erigon-lib/gointerfaces/execution"
"github.com/ledgerwatch/erigon-lib/kv/memdb"
"github.com/ledgerwatch/erigon/core/rawdb"
"github.com/ledgerwatch/erigon/core/types"
"github.com/ledgerwatch/erigon/turbo/execution/eth1"
"github.com/stretchr/testify/require"
@ -20,7 +21,11 @@ func TestInsertGetterHeader(t *testing.T) {
Difficulty: big.NewInt(0),
Number: big.NewInt(int64(bn)),
}
e := eth1.NewEthereumExecutionModule(nil, memdb.NewTestDB(t), nil, nil)
db := memdb.NewTestDB(t)
tx, _ := db.BeginRw(context.TODO())
rawdb.WriteTd(tx, libcommon.Hash{}, 1, libcommon.Big0)
tx.Commit()
e := eth1.NewEthereumExecutionModule(nil, db, nil, nil, nil)
_, err := e.InsertHeaders(context.TODO(), &execution.InsertHeadersRequest{
Headers: []*execution.Header{
eth1.HeaderToHeaderRPC(header),
@ -41,7 +46,7 @@ func TestInsertGetterBody(t *testing.T) {
body := &types.RawBody{
Transactions: txs,
}
e := eth1.NewEthereumExecutionModule(nil, memdb.NewTestDB(t), nil, nil)
e := eth1.NewEthereumExecutionModule(nil, memdb.NewTestDB(t), nil, nil, nil)
_, err := e.InsertBodies(context.TODO(), &execution.InsertBodiesRequest{
Bodies: []*execution.BlockBody{
eth1.ConvertRawBlockBodyToRpc(body, bn, bhash),

View File

@ -3,18 +3,20 @@ package eth1
import (
"context"
"github.com/anacrolix/sync"
libcommon "github.com/ledgerwatch/erigon-lib/common"
"github.com/ledgerwatch/erigon-lib/gointerfaces"
"github.com/ledgerwatch/erigon-lib/gointerfaces/execution"
types2 "github.com/ledgerwatch/erigon-lib/gointerfaces/types"
"github.com/ledgerwatch/log/v3"
"golang.org/x/sync/semaphore"
"github.com/ledgerwatch/erigon-lib/kv"
"github.com/ledgerwatch/erigon/core/rawdb"
"github.com/ledgerwatch/erigon/core/types"
"github.com/ledgerwatch/erigon/eth/stagedsync"
"github.com/ledgerwatch/erigon/eth/stagedsync/stages"
"github.com/ledgerwatch/erigon/turbo/engineapi/engine_helpers"
"github.com/ledgerwatch/erigon/turbo/engineapi/engine_types"
"github.com/ledgerwatch/erigon/turbo/services"
)
@ -25,20 +27,23 @@ type EthereumExecutionModule struct {
// MDBX database
db kv.RwDB // main database
lock sync.Mutex
semaphore *semaphore.Weighted
executionPipeline *stagedsync.Sync
forkValidator *engine_helpers.ForkValidator
logger log.Logger
execution.UnimplementedExecutionServer
}
func NewEthereumExecutionModule(blockReader services.FullBlockReader, db kv.RwDB, executionPipeline *stagedsync.Sync, logger log.Logger) *EthereumExecutionModule {
func NewEthereumExecutionModule(blockReader services.FullBlockReader, db kv.RwDB, executionPipeline *stagedsync.Sync, forkValidator *engine_helpers.ForkValidator, logger log.Logger) *EthereumExecutionModule {
return &EthereumExecutionModule{
blockReader: blockReader,
db: db,
executionPipeline: executionPipeline,
logger: logger,
forkValidator: forkValidator,
semaphore: semaphore.NewWeighted(1),
}
}
@ -71,8 +76,14 @@ func (e *EthereumExecutionModule) UpdateForkChoice(ctx context.Context, req *typ
hash libcommon.Hash
number uint64
}
e.lock.Lock()
defer e.lock.Unlock()
if !e.semaphore.TryAcquire(1) {
return &execution.ForkChoiceReceipt{
LatestValidHash: gointerfaces.ConvertHashToH256(libcommon.Hash{}),
Status: execution.ValidationStatus_Busy,
}, nil
}
defer e.semaphore.Release(1)
tx, err := e.db.BeginRw(ctx)
if err != nil {
return nil, err
@ -169,4 +180,53 @@ func (e *EthereumExecutionModule) UpdateForkChoice(ctx context.Context, req *typ
}, tx.Commit()
}
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()
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
}
if header == nil || body == nil {
return &execution.ValidationReceipt{
LatestValidHash: gointerfaces.ConvertHashToH256(libcommon.Hash{}),
MissingHash: req.Hash,
ValidationStatus: execution.ValidationStatus_MissingSegment,
}, nil
}
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
}
// Missing: NewPayload, AssembleBlock

View File

@ -9,9 +9,13 @@ import (
"github.com/ledgerwatch/erigon/core/rawdb"
)
func (e *EthereumExecutionModule) InsertBodies(ctx context.Context, req *execution.InsertBodiesRequest) (*execution.EmptyMessage, error) {
e.lock.Lock()
defer e.lock.Unlock()
func (e *EthereumExecutionModule) InsertBodies(ctx context.Context, req *execution.InsertBodiesRequest) (*execution.InsertionResult, error) {
if !e.semaphore.TryAcquire(1) {
return &execution.InsertionResult{
Result: execution.ValidationStatus_Busy,
}, nil
}
defer e.semaphore.Release(1)
tx, err := e.db.BeginRw(ctx)
if err != nil {
return nil, fmt.Errorf("ethereumExecutionModule.InsertBodies: could not begin transaction: %s", err)
@ -26,12 +30,18 @@ func (e *EthereumExecutionModule) InsertBodies(ctx context.Context, req *executi
return nil, fmt.Errorf("ethereumExecutionModule.InsertBodies: could not commit: %s", err)
}
return &execution.EmptyMessage{}, tx.Commit()
return &execution.InsertionResult{
Result: execution.ValidationStatus_Success,
}, tx.Commit()
}
func (e *EthereumExecutionModule) InsertHeaders(ctx context.Context, req *execution.InsertHeadersRequest) (*execution.EmptyMessage, error) {
e.lock.Lock()
defer e.lock.Unlock()
func (e *EthereumExecutionModule) InsertHeaders(ctx context.Context, req *execution.InsertHeadersRequest) (*execution.InsertionResult, error) {
if !e.semaphore.TryAcquire(1) {
return &execution.InsertionResult{
Result: execution.ValidationStatus_Busy,
}, nil
}
defer e.semaphore.Release(1)
tx, err := e.db.BeginRw(ctx)
if err != nil {
return nil, fmt.Errorf("ethereumExecutionModule.InsertHeaders: could not begin transaction: %s", err)
@ -42,13 +52,25 @@ func (e *EthereumExecutionModule) InsertHeaders(ctx context.Context, req *execut
if err != nil {
return nil, fmt.Errorf("ethereumExecutionModule.InsertHeaders: cannot convert headers: %s", err)
}
// Parent's total difficulty
parentTd, err := rawdb.ReadTd(tx, header.ParentHash, header.Number.Uint64()-1)
if err != nil || parentTd == nil {
return nil, fmt.Errorf("parent's total difficulty not found with hash %x and height %d: %v", header.ParentHash, header.Number.Uint64()-1, err)
}
// Sum TDs.
td := parentTd.Add(parentTd, header.Difficulty)
if err := rawdb.WriteHeader(tx, header); err != nil {
return nil, fmt.Errorf("ethereumExecutionModule.InsertHeaders: could not insert: %s", err)
}
if err := rawdb.WriteTd(tx, header.Hash(), header.Number.Uint64(), td); err != nil {
return nil, fmt.Errorf("ethereumExecutionModule.InsertHeaders: could not insert: %s", err)
}
}
if err := tx.Commit(); err != nil {
return nil, fmt.Errorf("ethereumExecutionModule.InsertHeaders: could not commit: %s", err)
}
return &execution.EmptyMessage{}, tx.Commit()
return &execution.InsertionResult{
Result: execution.ValidationStatus_Success,
}, tx.Commit()
}