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() e.mu.Lock()
defer e.mu.Unlock() defer e.mu.Unlock()
tx, err := e.db.BeginRw(ctx) tx, err := e.db.BeginRw(ctx)
@ -54,10 +54,12 @@ func (e *Eth1Execution) InsertHeaders(ctx context.Context, req *execution.Insert
return nil, err 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() e.mu.Lock()
defer e.mu.Unlock() defer e.mu.Unlock()
tx, err := e.db.BeginRw(ctx) tx, err := e.db.BeginRw(ctx)
@ -94,7 +96,9 @@ func (e *Eth1Execution) InsertBodies(ctx context.Context, req *execution.InsertB
return nil, err return nil, err
} }
} }
return &execution.EmptyMessage{}, tx.Commit() return &execution.InsertionResult{
Result: execution.ValidationStatus_Success,
}, tx.Commit()
} }
type canonicalEntry struct { type canonicalEntry struct {

2
go.mod
View File

@ -3,7 +3,7 @@ module github.com/ledgerwatch/erigon
go 1.19 go 1.19
require ( 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/erigon-snapshot v1.2.1-0.20230622075030-1d69651854c2
github.com/ledgerwatch/log/v3 v3.8.0 github.com/ledgerwatch/log/v3 v3.8.0
github.com/ledgerwatch/secp256k1 v1.0.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/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 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c=
github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= 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-20230723163836-9e08d02f75b8 h1:P8CdtNh0DDKhzTVnwuCQY1lg8Jn1N21nmSHGOl4Kjxo=
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/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 h1:Ls2itRGHMOr2PbHRDA4g1HH8HQdwfJhRVfMPEaLQe94=
github.com/ledgerwatch/erigon-snapshot v1.2.1-0.20230622075030-1d69651854c2/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo= 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= 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"
"github.com/ledgerwatch/erigon-lib/gointerfaces/execution" "github.com/ledgerwatch/erigon-lib/gointerfaces/execution"
"github.com/ledgerwatch/erigon-lib/kv/memdb" "github.com/ledgerwatch/erigon-lib/kv/memdb"
"github.com/ledgerwatch/erigon/core/rawdb"
"github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/core/types"
"github.com/ledgerwatch/erigon/turbo/execution/eth1" "github.com/ledgerwatch/erigon/turbo/execution/eth1"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -20,7 +21,11 @@ func TestInsertGetterHeader(t *testing.T) {
Difficulty: big.NewInt(0), Difficulty: big.NewInt(0),
Number: big.NewInt(int64(bn)), 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{ _, err := e.InsertHeaders(context.TODO(), &execution.InsertHeadersRequest{
Headers: []*execution.Header{ Headers: []*execution.Header{
eth1.HeaderToHeaderRPC(header), eth1.HeaderToHeaderRPC(header),
@ -41,7 +46,7 @@ func TestInsertGetterBody(t *testing.T) {
body := &types.RawBody{ body := &types.RawBody{
Transactions: txs, 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{ _, err := e.InsertBodies(context.TODO(), &execution.InsertBodiesRequest{
Bodies: []*execution.BlockBody{ Bodies: []*execution.BlockBody{
eth1.ConvertRawBlockBodyToRpc(body, bn, bhash), eth1.ConvertRawBlockBodyToRpc(body, bn, bhash),

View File

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

View File

@ -9,9 +9,13 @@ import (
"github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/rawdb"
) )
func (e *EthereumExecutionModule) InsertBodies(ctx context.Context, req *execution.InsertBodiesRequest) (*execution.EmptyMessage, error) { func (e *EthereumExecutionModule) InsertBodies(ctx context.Context, req *execution.InsertBodiesRequest) (*execution.InsertionResult, error) {
e.lock.Lock() if !e.semaphore.TryAcquire(1) {
defer e.lock.Unlock() return &execution.InsertionResult{
Result: execution.ValidationStatus_Busy,
}, nil
}
defer e.semaphore.Release(1)
tx, err := e.db.BeginRw(ctx) tx, err := e.db.BeginRw(ctx)
if err != nil { if err != nil {
return nil, fmt.Errorf("ethereumExecutionModule.InsertBodies: could not begin transaction: %s", err) 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 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) { func (e *EthereumExecutionModule) InsertHeaders(ctx context.Context, req *execution.InsertHeadersRequest) (*execution.InsertionResult, error) {
e.lock.Lock() if !e.semaphore.TryAcquire(1) {
defer e.lock.Unlock() return &execution.InsertionResult{
Result: execution.ValidationStatus_Busy,
}, nil
}
defer e.semaphore.Release(1)
tx, err := e.db.BeginRw(ctx) tx, err := e.db.BeginRw(ctx)
if err != nil { if err != nil {
return nil, fmt.Errorf("ethereumExecutionModule.InsertHeaders: could not begin transaction: %s", err) 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 { if err != nil {
return nil, fmt.Errorf("ethereumExecutionModule.InsertHeaders: cannot convert headers: %s", err) 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 { if err := rawdb.WriteHeader(tx, header); err != nil {
return nil, fmt.Errorf("ethereumExecutionModule.InsertHeaders: could not insert: %s", err) 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 { if err := tx.Commit(); err != nil {
return nil, fmt.Errorf("ethereumExecutionModule.InsertHeaders: could not commit: %s", err) 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()
} }