Skip to content

Commit

Permalink
Update block builder to enforce predicate one tx at a time (ava-labs#773
Browse files Browse the repository at this point in the history
)

* Update block builder to enforce predicate one tx at a time

* remove dead code

* Update miner/worker.go

Co-authored-by: Darioush Jalali <[email protected]>
Signed-off-by: aaronbuchwald <[email protected]>

---------

Signed-off-by: aaronbuchwald <[email protected]>
Co-authored-by: Darioush Jalali <[email protected]>
  • Loading branch information
aaronbuchwald and darioush authored Aug 2, 2023
1 parent df0124c commit 490fc29
Showing 1 changed file with 18 additions and 48 deletions.
66 changes: 18 additions & 48 deletions miner/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ type environment struct {
receipts []*types.Receipt
size uint64

rules params.Rules
predicateContext *precompileconfig.ProposerPredicateContext

start time.Time // Time that block building began
}

Expand Down Expand Up @@ -181,7 +184,7 @@ func (w *worker) commitNewWork(predicateContext *precompileconfig.ProposerPredic
return nil, fmt.Errorf("failed to prepare header for mining: %w", err)
}

env, err := w.createCurrentEnvironment(parent, header, tstart)
env, err := w.createCurrentEnvironment(predicateContext, parent, header, tstart)
if err != nil {
return nil, fmt.Errorf("failed to create new current environment: %w", err)
}
Expand All @@ -194,9 +197,6 @@ func (w *worker) commitNewWork(predicateContext *precompileconfig.ProposerPredic

// Get the pending txs from TxPool
pending := w.eth.TxPool().Pending(true)
// Filter out transactions that don't satisfy predicateContext and remove them from TxPool
rules := w.chainConfig.AvalancheRules(header.Number, header.Time)
pending = w.enforcePredicates(rules, predicateContext, pending)

// Split the pending transactions into locals and remotes
localTxs := make(map[common.Address]types.Transactions)
Expand All @@ -219,19 +219,21 @@ func (w *worker) commitNewWork(predicateContext *precompileconfig.ProposerPredic
return w.commit(env)
}

func (w *worker) createCurrentEnvironment(parent *types.Header, header *types.Header, tstart time.Time) (*environment, error) {
func (w *worker) createCurrentEnvironment(predicateContext *precompileconfig.ProposerPredicateContext, parent *types.Header, header *types.Header, tstart time.Time) (*environment, error) {
state, err := w.chain.StateAt(parent.Root)
if err != nil {
return nil, err
}
return &environment{
signer: types.MakeSigner(w.chainConfig, header.Number, header.Time),
state: state,
parent: parent,
header: header,
tcount: 0,
gasPool: new(core.GasPool).AddGas(header.GasLimit),
start: tstart,
signer: types.MakeSigner(w.chainConfig, header.Number, header.Time),
state: state,
parent: parent,
header: header,
tcount: 0,
gasPool: new(core.GasPool).AddGas(header.GasLimit),
rules: w.chainConfig.AvalancheRules(header.Number, header.Time),
predicateContext: predicateContext,
start: tstart,
}, nil
}

Expand All @@ -241,6 +243,10 @@ func (w *worker) commitTransaction(env *environment, tx *types.Transaction, coin
gp = env.gasPool.Gas()
)

if err := core.CheckPredicates(env.rules, env.predicateContext, tx); err != nil {
log.Debug("Transaction predicate failed verification in miner", "tx", tx.Hash(), "err", err)
return nil, err
}
receipt, err := core.ApplyTransaction(w.chainConfig, w.chain, &coinbase, env.gasPool, env.state, env.header, tx, &env.header.GasUsed, *w.chain.GetVMConfig())
if err != nil {
env.state.RevertToSnapshot(snap)
Expand Down Expand Up @@ -394,39 +400,3 @@ func copyReceipts(receipts []*types.Receipt) []*types.Receipt {
}
return result
}

// enforcePredicates takes a set of pending transactions (grouped by sender, and ordered by nonce)
// and returns the subset of those transactions (following the same grouping) that satisfy predicateContext.
// Any transaction that fails predicate verification will be removed from the tx pool and excluded
// from the return value.
// Transactions with a nonce that follows a removed transaction will be added back to the future
// queue of the tx pool.
func (w *worker) enforcePredicates(
rules params.Rules,
predicateContext *precompileconfig.ProposerPredicateContext,
pending map[common.Address]types.Transactions,
) map[common.Address]types.Transactions {
// Short circuit early if there are no precompile predicates to verify and return the
// unmodified pending transactions.
if !rules.PredicatesExist() {
return pending
}
result := make(map[common.Address]types.Transactions, len(pending))
for addr, txs := range pending {
for i, tx := range txs {
if err := core.CheckPredicates(rules, predicateContext, tx); err != nil {
log.Debug("Transaction predicate failed verification in miner", "sender", addr, "err", err)
// If the transaction fails the predicate check, we remove the transaction from the mempool
// and move all transactions from the same address with a subsequent nonce back to the
// future queue of the transaction pool.
w.eth.TxPool().RemoveTx(tx.Hash())
txs = txs[:i] // Cut off any transactions past the failed predicate in the return value
break
}
}
if len(txs) > 0 {
result[addr] = txs
}
}
return result
}

0 comments on commit 490fc29

Please sign in to comment.