Skip to content
This repository has been archived by the owner on Jun 9, 2024. It is now read-only.

protecccc validators bls #1473

Closed
wants to merge 16 commits into from
9 changes: 9 additions & 0 deletions cosmos/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,15 @@ func readConfigFromAppOptsParser(parser AppOptionsParser) (*Config, error) {
return nil, err
}

if conf.Polar.IsValidator, err = parser.GetBool(flags.IsValidator); err != nil {
return nil, err
}

if conf.Polar.ValidatorJSONRPCEndpoint, err =
parser.GetString(flags.ValidatorJSONRPCEndpoint); err != nil {
return nil, err
}

// Polar Miner settings
if conf.Polar.Miner.Etherbase, err =
parser.GetCommonAddress(flags.MinerEtherbase); err != nil {
Expand Down
8 changes: 5 additions & 3 deletions cosmos/config/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ const (
OptimisticExecution = "polaris.optimistic-execution"

// Polar Root.
RPCEvmTimeout = "polaris.polar.rpc-evm-timeout"
RPCTxFeeCap = "polaris.polar.rpc-tx-fee-cap"
RPCGasCap = "polaris.polar.rpc-gas-cap"
RPCEvmTimeout = "polaris.polar.rpc-evm-timeout"
RPCTxFeeCap = "polaris.polar.rpc-tx-fee-cap"
RPCGasCap = "polaris.polar.rpc-gas-cap"
IsValidator = "polaris.polar.is-validator"
ValidatorJSONRPCEndpoint = "polaris.polar.validator-jsonrpc-endpoint"

// Miner.
MinerEtherbase = "polaris.polar.miner.etherbase"
Expand Down
3 changes: 3 additions & 0 deletions cosmos/config/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ rpc-evm-timeout = "{{ .Polaris.Polar.RPCEVMTimeout }}"
# Transaction fee cap for RPC requests
rpc-tx-fee-cap = "{{ .Polaris.Polar.RPCTxFeeCap }}"

validator-jsonrpc-endpoint = "{{ .Polaris.Polar.ValidatorJSONRPCEndpoint }}"
is-validator = {{ .Polaris.Polar.IsValidator }}

# Chain config
[polaris.polar.chain]
chain-id = "{{ .Polaris.Polar.Chain.ChainID }}"
Expand Down
9 changes: 7 additions & 2 deletions cosmos/runtime/ante/ante.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,13 @@ import (
type Provider struct {
evmAnteHandler sdk.AnteHandler // Ante handler for EVM transactions
cosmosAnteHandler sdk.AnteHandler // Ante handler for Cosmos transactions
isValidator bool
}

// NewAnteHandler creates a new Provider with a mempool and Cosmos ante handler.
// It sets up the EVM ante handler with the necessary decorators.
func NewAnteHandler(
mempool *txpool.Mempool, cosmosAnteHandler sdk.AnteHandler,
mempool *txpool.Mempool, cosmosAnteHandler sdk.AnteHandler, isValidator bool,
) *Provider {
evmAnteDecorators := []sdk.AnteDecorator{
ante.NewSetUpContextDecorator(), // Set up the context decorator for the EVM ante handler
Expand All @@ -55,6 +56,7 @@ func NewAnteHandler(
return &Provider{
evmAnteHandler: sdk.ChainAnteDecorators(evmAnteDecorators...),
cosmosAnteHandler: cosmosAnteHandler,
isValidator: isValidator,
}
}

Expand All @@ -65,8 +67,11 @@ func (ah *Provider) AnteHandler() func(
) (sdk.Context, error) {
return func(ctx sdk.Context, tx sdk.Tx, simulate bool) (sdk.Context, error) {
// If the transaction contains a single EVM transaction, use the EVM ante handler
if len(tx.GetMsgs()) == 1 {
if len(tx.GetMsgs()) == 1 { //nolint:nestif // todo:fix.
if _, ok := tx.GetMsgs()[0].(*evmtypes.WrappedEthereumTransaction); ok {
if ah.isValidator {
return ctx, errors.New("validator cannot accept EVM from comet")
}
return ah.evmAnteHandler(ctx, tx, simulate)
} else if _, ok = tx.GetMsgs()[0].(*evmtypes.WrappedPayloadEnvelope); ok {
if ctx.ExecMode() != sdk.ExecModeCheck {
Expand Down
10 changes: 8 additions & 2 deletions cosmos/runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ type Polaris struct {
// into the txpool are happening during this process. The mempool object then read locks for
// adding transactions into the txpool.
blockBuilderMu sync.RWMutex

cfg *eth.Config
}

// New creates a new Polaris runtime from the provided dependencies.
Expand All @@ -105,6 +107,7 @@ func New(
var err error
p := &Polaris{
logger: logger,
cfg: cfg,
}

ctx := sdk.Context{}.
Expand All @@ -124,11 +127,14 @@ func New(

priceLimit := big.NewInt(0).SetUint64(cfg.Polar.LegacyTxPool.PriceLimit)
p.WrappedTxPool = txpool.New(
p.logger,
p.ExecutionLayer.Backend().Blockchain(),
p.ExecutionLayer.Backend().TxPool(),
int64(cfg.Polar.LegacyTxPool.Lifetime),
&p.blockBuilderMu,
priceLimit,
p.cfg.Polar.IsValidator,
p.cfg.Polar.ValidatorJSONRPCEndpoint,
)

return p
Expand Down Expand Up @@ -163,7 +169,7 @@ func (p *Polaris) Build(
}

app.SetAnteHandler(
antelib.NewAnteHandler(p.WrappedTxPool, cosmHandler).AnteHandler(),
antelib.NewAnteHandler(p.WrappedTxPool, cosmHandler, p.cfg.Polar.IsValidator).AnteHandler(),
)

return nil
Expand All @@ -177,7 +183,7 @@ func (p *Polaris) SetupServices(clientCtx client.Context) error {
clientCtx.TxConfig, evmtypes.WrapPayload))

// Initialize the txpool with a new transaction serializer.
p.WrappedTxPool.Init(p.logger, clientCtx, libtx.NewSerializer[*ethtypes.Transaction](
p.WrappedTxPool.Init(clientCtx, libtx.NewSerializer[*ethtypes.Transaction](
clientCtx.TxConfig, evmtypes.WrapTx))

// Register services with Polaris.
Expand Down
28 changes: 19 additions & 9 deletions cosmos/runtime/txpool/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,28 +96,35 @@ type handler struct {

// Queue for failed transactions
failedTxs chan *failedTx

isValidator bool
}

// newHandler creates a new handler.
func newHandler(
clientCtx TxBroadcaster, txPool TxSubProvider, serializer TxSerializer,
crc CometRemoteCache, logger log.Logger,
crc CometRemoteCache, logger log.Logger, isValidator bool,
) *handler {
h := &handler{
logger: logger,
clientCtx: clientCtx,
serializer: serializer,
crc: crc,
txPool: txPool,
txsCh: make(chan core.NewTxsEvent, txChanSize),
stopCh: make(chan struct{}),
failedTxs: make(chan *failedTx, txChanSize),
logger: logger,
clientCtx: clientCtx,
serializer: serializer,
crc: crc,
txPool: txPool,
txsCh: make(chan core.NewTxsEvent, txChanSize),
stopCh: make(chan struct{}),
failedTxs: make(chan *failedTx, txChanSize),
isValidator: isValidator,
}
return h
}

// Start starts the handler.
func (h *handler) Start() error {
if h.isValidator {
return nil
}

if h.running.Load() {
return errors.New("handler already started")
}
Expand All @@ -129,6 +136,9 @@ func (h *handler) Start() error {

// Stop stops the handler.
func (h *handler) Stop() error {
if h.isValidator {
return nil
}
if !h.Running() {
return errors.New("handler already stopped")
}
Expand Down
4 changes: 3 additions & 1 deletion cosmos/runtime/txpool/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,9 @@ var _ = Describe("", func() {
subprovider = mocks.NewTxSubProvider(t)
subprovider.On("SubscribeTransactions", mock.Anything, mock.Anything).Return(subscription)
serializer = mocks.NewTxSerializer(t)
h = newHandler(broadcaster, subprovider, serializer, newCometRemoteCache(), log.NewTestLogger(t))
h = newHandler(
broadcaster, subprovider, serializer,
newCometRemoteCache(), log.NewTestLogger(t), false)
err := h.Start()
Expect(err).NotTo(HaveOccurred())
for !h.Running() {
Expand Down
77 changes: 68 additions & 9 deletions cosmos/runtime/txpool/mempool.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"errors"
"math/big"
"sync"
"time"

"cosmossdk.io/log"

Expand All @@ -39,6 +40,12 @@ import (

ethtxpool "github.com/ethereum/go-ethereum/core/txpool"
ethtypes "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
)

const (
attempts = 5
retryInterval = 5 * time.Second
)

// Mempool implements the mempool.Mempool & Lifecycle interfaces.
Expand All @@ -64,36 +71,72 @@ type GethTxPool interface {
// geth txpool during `CheckTx`, that is the only purpose of `Mempool“.
type Mempool struct {
eth.TxPool
logger log.Logger
lifetime int64
chain core.ChainReader
handler Lifecycle
crc CometRemoteCache
blockBuilderMu *sync.RWMutex
priceLimit *big.Int

isValidator bool
validatorJSONRPC string
ethclient *ethclient.Client
itsdevbear marked this conversation as resolved.
Show resolved Hide resolved
}

// New creates a new Mempool.
func New(
logger log.Logger,
chain core.ChainReader, txpool eth.TxPool, lifetime int64,
blockBuilderMu *sync.RWMutex, priceLimit *big.Int,
blockBuilderMu *sync.RWMutex, priceLimit *big.Int, isValidator bool,
validatorJSONRPC string,
) *Mempool {
var (
ec *ethclient.Client
err error
)

if validatorJSONRPC != "" {
for attempt := 0; attempt < attempts; attempt++ {
logger.Info("Attempting to dial validator JSON RPC",
"url", validatorJSONRPC, "attempt", attempt+1)
ec, err = ethclient.Dial(validatorJSONRPC)
if err == nil {
logger.Info(
"Successfully connected to validator JSON RPC", "url", validatorJSONRPC)
break
}
if attempt < attempts-1 {
logger.Error("Failed to dial validator JSON RPC, retrying...", "error", err)
time.Sleep(retryInterval)
} else {
logger.Error(
"Failed to dial validator JSON RPC, no more retries left", "error", err)
panic(err)
itsdevbear marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

return &Mempool{
TxPool: txpool,
chain: chain,
lifetime: lifetime,
crc: newCometRemoteCache(),
blockBuilderMu: blockBuilderMu,
priceLimit: priceLimit,
logger: logger,
TxPool: txpool,
chain: chain,
lifetime: lifetime,
crc: newCometRemoteCache(),
blockBuilderMu: blockBuilderMu,
priceLimit: priceLimit,
isValidator: isValidator,
validatorJSONRPC: validatorJSONRPC,
ethclient: ec,
}
}

// Init initializes the Mempool (notably the TxHandler).
func (m *Mempool) Init(
logger log.Logger,
txBroadcaster TxBroadcaster,
txSerializer TxSerializer,
) {
m.handler = newHandler(txBroadcaster, m.TxPool, txSerializer, m.crc, logger)
m.handler = newHandler(txBroadcaster, m.TxPool, txSerializer, m.crc, m.logger, m.isValidator)
}

// Start starts the Mempool TxHandler.
Expand All @@ -108,6 +151,10 @@ func (m *Mempool) Stop() error {

// Insert attempts to insert a Tx into the app-side mempool returning an error upon failure.
func (m *Mempool) Insert(ctx context.Context, sdkTx sdk.Tx) error {
if m.isValidator {
return errors.New("validator cannot insert transactions into the mempool from comet")
}
itsdevbear marked this conversation as resolved.
Show resolved Hide resolved

sCtx := sdk.UnwrapSDKContext(ctx)
msgs := sdkTx.GetMsgs()
if len(msgs) != 1 {
Expand All @@ -123,6 +170,18 @@ func (m *Mempool) Insert(ctx context.Context, sdkTx sdk.Tx) error {
// Add the eth tx to the Geth txpool.
ethTx := wet.Unwrap()

// Optmistically send to the validator.
if m.ethclient != nil {
// Broadcast the transaction to the validator.
// Note: we don't care about the response here.
go func() {
sCtx.Logger().Info("broadcasting transaction to validator", "hash", ethTx.Hash().Hex())
if err := m.ethclient.SendTransaction(context.Background(), ethTx); err != nil {
sCtx.Logger().Error("failed to broadcast transaction to validator", "error", err)
}
}()
}
itsdevbear marked this conversation as resolved.
Show resolved Hide resolved

// Insert the tx into the txpool as a remote.
m.blockBuilderMu.RLock()
errs := m.TxPool.Add([]*ethtypes.Transaction{ethTx}, false, false)
Expand Down
3 changes: 3 additions & 0 deletions eth/polar/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,7 @@ type Config struct {
// RPCTxFeeCap is the global transaction fee(price * gaslimit) cap for
// send-transaction variants. The unit is ether.
RPCTxFeeCap float64

ValidatorJSONRPCEndpoint string
IsValidator bool
}
Loading