Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validator nodes return error on tx submission #1792

Merged
merged 18 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go/enclave/enclave.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ func NewEnclave(
blockchain,
)
} else {
service = nodetype.NewValidator(blockProcessor, batchExecutor, registry, rConsumer, chainConfig, config.SequencerID, storage, sigVerifier, logger)
service = nodetype.NewValidator(blockProcessor, batchExecutor, registry, rConsumer, chainConfig, config.SequencerID, storage, sigVerifier, mempool, logger)
}

chain := l2chain.NewChain(
Expand Down
45 changes: 28 additions & 17 deletions go/enclave/nodetype/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"fmt"
"math/big"

"github.com/ten-protocol/go-ten/go/enclave/txpool"

"github.com/ethereum/go-ethereum/core/types"

"github.com/ten-protocol/go-ten/go/common/errutil"
Expand All @@ -30,22 +32,14 @@ type obsValidator struct {
sequencerID gethcommon.Address
storage storage.Storage
sigValidator *components.SignatureValidator
logger gethlog.Logger
}
mempool *txpool.TxPool

func NewValidator(
consumer components.L1BlockProcessor,
batchExecutor components.BatchExecutor,
registry components.BatchRegistry,
rollupConsumer components.RollupConsumer,
logger gethlog.Logger
}

chainConfig *params.ChainConfig,
func NewValidator(consumer components.L1BlockProcessor, batchExecutor components.BatchExecutor, registry components.BatchRegistry, rollupConsumer components.RollupConsumer, chainConfig *params.ChainConfig, sequencerID gethcommon.Address, storage storage.Storage, sigValidator *components.SignatureValidator, mempool *txpool.TxPool, logger gethlog.Logger) ObsValidator {
startMempool(registry, mempool)

sequencerID gethcommon.Address,
storage storage.Storage,
sigValidator *components.SignatureValidator,
logger gethlog.Logger,
) ObsValidator {
return &obsValidator{
blockProcessor: consumer,
batchExecutor: batchExecutor,
Expand All @@ -55,13 +49,17 @@ func NewValidator(
sequencerID: sequencerID,
storage: storage,
sigValidator: sigValidator,
mempool: mempool,
logger: logger,
}
}

func (val *obsValidator) SubmitTransaction(transaction *common.L2Tx) error {
val.logger.Trace(fmt.Sprintf("Transaction %s submitted to validator but there is nothing to do with it.", transaction.Hash().Hex()))
return nil
func (val *obsValidator) SubmitTransaction(tx *common.L2Tx) error {
headBatch := val.batchRegistry.HeadBatchSeq()
if headBatch != nil && headBatch.Uint64() > common.L2GenesisSeqNo+1 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick but I think this would read more naturally in Go if you flip it to let the happy path be the final return, like:

if headBatch == nil || headBatch.Uint64() <= common.L2GenesisSeqNo+1 {
   return fmt.Errorf("not initialised")
}
return val.mempool.Validate(tx)

return val.mempool.Validate(tx)
}
return fmt.Errorf("not initialised")
}

func (val *obsValidator) OnL1Fork(_ *common.ChainFork) error {
Expand All @@ -86,6 +84,8 @@ func (val *obsValidator) ExecuteStoredBatches() error {
return err
}

startMempool(val.batchRegistry, val.mempool)

for _, batch := range batches {
if batch.IsGenesis() {
if err = val.handleGenesis(batch); err != nil {
Expand Down Expand Up @@ -155,5 +155,16 @@ func (val *obsValidator) OnL1Block(_ types.Block, _ *components.BlockIngestionTy
}

func (val *obsValidator) Close() error {
return nil
return val.mempool.Close()
}

func startMempool(registry components.BatchRegistry, mempool *txpool.TxPool) {
// the mempool can only be started when there are a couple of blocks already processed
headBatchSeq := registry.HeadBatchSeq()
if !mempool.Running() && headBatchSeq != nil && headBatchSeq.Uint64() > common.L2GenesisSeqNo+1 {
err := mempool.Start()
if err != nil {
panic(fmt.Errorf("could not start mempool: %w", err))
}
}
}
12 changes: 12 additions & 0 deletions go/enclave/txpool/txpool.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import (
"math/big"
"strings"

// unsafe package imported in order to link to a private function in go-ethereum.
// This allows us to validate transactions against the tx pool rules.
_ "unsafe"

gethlog "github.com/ethereum/go-ethereum/log"
"github.com/ten-protocol/go-ten/go/common/log"

Expand Down Expand Up @@ -78,6 +82,14 @@ func (t *TxPool) Add(transaction *common.L2Tx) error {
return nil
}

//go:linkname validateTxBasics github.com/ethereum/go-ethereum/core/txpool/legacypool.(*LegacyPool).validateTxBasics
func validateTxBasics(_ *legacypool.LegacyPool, _ *types.Transaction, _ bool) error

// Validate - run the underlying tx pool validation logic
func (t *TxPool) Validate(tx *common.L2Tx) error {
return validateTxBasics(t.legacyPool, tx, false)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will be hacky no matter how we do it.
At least this is simple

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah fair enough. Not seen the go:linkname incantation before haha, that's a fun one.

}

func (t *TxPool) Running() bool {
return t.running
}
Expand Down
Loading