eth/catalyst, miner: build the execution payload async (#24866)
* eth/catalyst: build the execution payload async * miner: added comment, added test case * eth/catalyst: miner: move async block production to miner * eth/catalyst, miner: support generate seal block async * miner: rework GetSealingBlockAsync to use a passed channel * miner: apply rjl's diff * eth/catalyst: nitpicks Co-authored-by: Gary Rong <garyrong0905@gmail.com>
This commit is contained in:
1 parent
e6fa102eb0
commit
cc9fb8e21d
6 files changed
+186
-53
No files matched your search
+24
-6
@@ -235,14 +235,32 @@ func (miner *Miner) DisablePreseal() {
|
||||
miner.worker.disablePreseal()
|
||||
}
|
||||
|
||||
// GetSealingBlock retrieves a sealing block based on the given parameters.
|
||||
// The returned block is not sealed but all other fields should be filled.
|
||||
func (miner *Miner) GetSealingBlock(parent common.Hash, timestamp uint64, coinbase common.Address, random common.Hash) (*types.Block, error) {
|
||||
return miner.worker.getSealingBlock(parent, timestamp, coinbase, random)
|
||||
}
|
||||
|
||||
// SubscribePendingLogs starts delivering logs from pending transactions
|
||||
// to the given channel.
|
||||
func (miner *Miner) SubscribePendingLogs(ch chan<- []*types.Log) event.Subscription {
|
||||
return miner.worker.pendingLogsFeed.Subscribe(ch)
|
||||
}
|
||||
|
||||
// GetSealingBlockAsync requests to generate a sealing block according to the
|
||||
// given parameters. Regardless of whether the generation is successful or not,
|
||||
// there is always a result that will be returned through the result channel.
|
||||
// The difference is that if the execution fails, the returned result is nil
|
||||
// and the concrete error is dropped silently.
|
||||
func (miner *Miner) GetSealingBlockAsync(parent common.Hash, timestamp uint64, coinbase common.Address, random common.Hash, noTxs bool) (chan *types.Block, error) {
|
||||
resCh, _, err := miner.worker.getSealingBlock(parent, timestamp, coinbase, random, noTxs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resCh, nil
|
||||
}
|
||||
|
||||
// GetSealingBlockSync creates a sealing block according to the given parameters.
|
||||
// If the generation is failed or the underlying work is already closed, an error
|
||||
// will be returned.
|
||||
func (miner *Miner) GetSealingBlockSync(parent common.Hash, timestamp uint64, coinbase common.Address, random common.Hash, noTxs bool) (*types.Block, error) {
|
||||
resCh, errCh, err := miner.worker.getSealingBlock(parent, timestamp, coinbase, random, noTxs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return <-resCh, <-errCh
|
||||
}
|
||||
+20
-15
@@ -170,8 +170,8 @@ type newWorkReq struct {
|
||||
// getWorkReq represents a request for getting a new sealing work with provided parameters.
|
||||
type getWorkReq struct {
|
||||
params *generateParams
|
||||
err error
|
||||
result chan *types.Block
|
||||
result chan *types.Block // non-blocking channel
|
||||
err chan error
|
||||
}
|
||||
|
||||
// intervalAdjust represents a resubmitting interval adjustment.
|
||||
@@ -536,12 +536,12 @@ func (w *worker) mainLoop() {
|
||||
case req := <-w.getWorkCh:
|
||||
block, err := w.generateWork(req.params)
|
||||
if err != nil {
|
||||
req.err = err
|
||||
req.err <- err
|
||||
req.result <- nil
|
||||
} else {
|
||||
req.err <- nil
|
||||
req.result <- block
|
||||
}
|
||||
|
||||
case ev := <-w.chainSideCh:
|
||||
// Short circuit for duplicate side blocks
|
||||
if _, exist := w.localUncles[ev.Block.Hash()]; exist {
|
||||
@@ -969,6 +969,7 @@ type generateParams struct {
|
||||
random common.Hash // The randomness generated by beacon chain, empty before the merge
|
||||
noUncle bool // Flag whether the uncle block inclusion is allowed
|
||||
noExtra bool // Flag whether the extra field assignment is allowed
|
||||
noTxs bool // Flag whether an empty block without any transaction is expected
|
||||
}
|
||||
|
||||
// prepareWork constructs the sealing task according to the given parameters,
|
||||
@@ -1090,8 +1091,9 @@ func (w *worker) generateWork(params *generateParams) (*types.Block, error) {
|
||||
}
|
||||
defer work.discard()
|
||||
|
||||
w.fillTransactions(nil, work)
|
||||
|
||||
if !params.noTxs {
|
||||
w.fillTransactions(nil, work)
|
||||
}
|
||||
return w.engine.FinalizeAndAssemble(w.chain, work.header, work.state, work.txs, work.unclelist(), work.receipts)
|
||||
}
|
||||
|
||||
@@ -1128,7 +1130,6 @@ func (w *worker) commitWork(interrupt *int32, noempty bool, timestamp int64) {
|
||||
work.discard()
|
||||
return
|
||||
}
|
||||
|
||||
w.commit(work.copy(), w.fullTaskHook, true, start)
|
||||
|
||||
// Swap out the old work with the new one, terminating any leftover
|
||||
@@ -1177,7 +1178,13 @@ func (w *worker) commit(env *environment, interval func(), update bool, start ti
|
||||
}
|
||||
|
||||
// getSealingBlock generates the sealing block based on the given parameters.
|
||||
func (w *worker) getSealingBlock(parent common.Hash, timestamp uint64, coinbase common.Address, random common.Hash) (*types.Block, error) {
|
||||
// The generation result will be passed back via the given channel no matter
|
||||
// the generation itself succeeds or not.
|
||||
func (w *worker) getSealingBlock(parent common.Hash, timestamp uint64, coinbase common.Address, random common.Hash, noTxs bool) (chan *types.Block, chan error, error) {
|
||||
var (
|
||||
resCh = make(chan *types.Block, 1)
|
||||
errCh = make(chan error, 1)
|
||||
)
|
||||
req := &getWorkReq{
|
||||
params: &generateParams{
|
||||
timestamp: timestamp,
|
||||
@@ -1187,18 +1194,16 @@ func (w *worker) getSealingBlock(parent common.Hash, timestamp uint64, coinbase
|
||||
random: random,
|
||||
noUncle: true,
|
||||
noExtra: true,
|
||||
noTxs: noTxs,
|
||||
},
|
||||
result: make(chan *types.Block, 1),
|
||||
result: resCh,
|
||||
err: errCh,
|
||||
}
|
||||
select {
|
||||
case w.getWorkCh <- req:
|
||||
block := <-req.result
|
||||
if block == nil {
|
||||
return nil, req.err
|
||||
}
|
||||
return block, nil
|
||||
return resCh, errCh, nil
|
||||
case <-w.exitCh:
|
||||
return nil, errors.New("miner closed")
|
||||
return nil, nil, errors.New("miner closed")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -638,7 +638,9 @@ func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine co
|
||||
|
||||
// This API should work even when the automatic sealing is not enabled
|
||||
for _, c := range cases {
|
||||
block, err := w.getSealingBlock(c.parent, timestamp, c.coinbase, c.random)
|
||||
resChan, errChan, _ := w.getSealingBlock(c.parent, timestamp, c.coinbase, c.random, false)
|
||||
block := <-resChan
|
||||
err := <-errChan
|
||||
if c.expectErr {
|
||||
if err == nil {
|
||||
t.Error("Expect error but get nil")
|
||||
@@ -654,7 +656,9 @@ func testGetSealingWork(t *testing.T, chainConfig *params.ChainConfig, engine co
|
||||
// This API should work even when the automatic sealing is enabled
|
||||
w.start()
|
||||
for _, c := range cases {
|
||||
block, err := w.getSealingBlock(c.parent, timestamp, c.coinbase, c.random)
|
||||
resChan, errChan, _ := w.getSealingBlock(c.parent, timestamp, c.coinbase, c.random, false)
|
||||
block := <-resChan
|
||||
err := <-errChan
|
||||
if c.expectErr {
|
||||
if err == nil {
|
||||
t.Error("Expect error but get nil")
|
||||
|
||||
Reference in new issue
Block a user