Skip to content

Commit

Permalink
optimize bidder's workflow
Browse files Browse the repository at this point in the history
  • Loading branch information
pythonberg1997 committed Feb 4, 2024
1 parent bd9d9f6 commit 991826c
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 64 deletions.
2 changes: 1 addition & 1 deletion build/ci.go
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ func doLint(cmdline []string) {

// downloadLinter downloads and unpacks golangci-lint.
func downloadLinter(cachedir string) string {
const version = "1.52.2"
const version = "1.55.2"

csdb := build.MustLoadChecksums("build/checksums.txt")
arch := runtime.GOARCH
Expand Down
105 changes: 48 additions & 57 deletions miner/bidder.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"fmt"
"net"
"net/http"
"sync"
"time"

"github.com/ethereum/go-ethereum/accounts"
Expand All @@ -19,6 +18,8 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"golang.org/x/exp/slices"
"sync"
)

var (
Expand Down Expand Up @@ -47,9 +48,10 @@ type ValidatorConfig struct {
}

type BidderConfig struct {
Enable bool
Validators []ValidatorConfig
Account common.Address
Enable bool
Validators []ValidatorConfig
Account common.Address
DelayLeftOver time.Duration
}

type Bidder struct {
Expand All @@ -59,8 +61,12 @@ type Bidder struct {

validators map[common.Address]*ethclient.Client // validator address -> ethclient.Client

bestWorksMu sync.RWMutex
bestWorks map[int64]*environment
works map[int64][]*environment

newBidCh chan *environment
exitCh chan struct{}

wg sync.WaitGroup

wallet accounts.Wallet
}
Expand All @@ -71,7 +77,9 @@ func NewBidder(config *BidderConfig, engine consensus.Engine, chain *core.BlockC
engine: engine,
chain: chain,
validators: make(map[common.Address]*ethclient.Client),
bestWorks: make(map[int64]*environment),
works: make(map[int64][]*environment),
newBidCh: make(chan *environment, 10),
exitCh: make(chan struct{}),
}

if !config.Enable {
Expand All @@ -95,30 +103,40 @@ func NewBidder(config *BidderConfig, engine consensus.Engine, chain *core.BlockC
return b
}

// Bid called by go routine
// 1. ignore and return if bidder is disabled
// 2. panic if no valid validators
// 3. ignore and return if the work is not better than the current best work
// 4. update the bestWork and do bid
func (b *Bidder) Bid(work *environment) {
if !b.config.Enable {
log.Warn("Bidder: disabled")
return
}

if len(b.validators) == 0 {
log.Crit("Bidder: No valid validators")
return
}

// if the work is not better than the current best work, ignore it
if !b.isBestWork(work) {
return
func (b *Bidder) mainLoop() {
defer b.wg.Done()

timer := time.NewTimer(0)
defer timer.Stop()
<-timer.C // discard the initial tick

currentHeight := b.chain.CurrentBlock().Number.Int64()
for {
select {
case work := <-b.newBidCh:
if work.header.Number.Int64() > currentHeight {
currentHeight = work.header.Number.Int64()
nextHeaderTimestamp := work.header.Time + b.chain.Config().Parlia.Period
timer.Reset(time.Until(time.Unix(int64(nextHeaderTimestamp), 0).Add(-b.config.DelayLeftOver)))
}
b.works[work.header.Number.Int64()] = append(b.works[work.header.Number.Int64()], work)
case <-timer.C:
works := b.works[currentHeight]
slices.SortStableFunc(works, func(i, j *environment) int {
return j.profit.Cmp(i.profit)
})

for i, work := range works {
// only bid for the top 3 most profitable works
if i >= 3 {
break
}
b.bid(work)
}
case <-b.exitCh:
return
}
}

// update the bestWork and do bid
b.setBestWork(work)
b.bid(work)
}

func (b *Bidder) SetWallet(wallet accounts.Wallet) {
Expand Down Expand Up @@ -208,33 +226,6 @@ func (b *Bidder) bid(work *environment) {
}

log.Debug("Bidder: bidding success")

return
}

// isBestWork returns the work is better than the current best work
func (b *Bidder) isBestWork(work *environment) bool {
if work.profit == nil {
return false
}

return b.getBestWork(work.header.Number.Int64()).profit.Cmp(work.profit) < 0
}

// setBestWork sets the best work
func (b *Bidder) setBestWork(work *environment) {
b.bestWorksMu.Lock()
defer b.bestWorksMu.Unlock()

b.bestWorks[work.header.Number.Int64()] = work
}

// getBestWork returns the best work
func (b *Bidder) getBestWork(blockNumber int64) *environment {
b.bestWorksMu.RLock()
defer b.bestWorksMu.RUnlock()

return b.bestWorks[blockNumber]
}

// signBid signs the bid with builder's account
Expand Down
16 changes: 10 additions & 6 deletions miner/worker.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,6 @@ type worker struct {
startCh chan struct{}
exitCh chan struct{}
resubmitIntervalCh chan time.Duration
bidCh chan *environment

wg sync.WaitGroup

Expand Down Expand Up @@ -256,7 +255,6 @@ func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus
resubmitIntervalCh: make(chan time.Duration),
recentMinedBlocks: recentMinedBlocks,
Bidder: NewBidder(&config.Bidder, engine, eth.BlockChain()),
bidCh: make(chan *environment, 10),
bundleCache: NewBundleCache(),
}
// Subscribe events for blockchain
Expand Down Expand Up @@ -289,6 +287,9 @@ func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus
worker.wg.Add(2)
go worker.resultLoop()
go worker.taskLoop()
} else {
worker.Bidder.wg.Add(1)
go worker.Bidder.mainLoop()
}

// Submit first work to initialize pending state.
Expand Down Expand Up @@ -493,11 +494,12 @@ func (w *worker) mainLoop() {
fees: fees,
}

case work := <-w.bidCh:
w.Bidder.Bid(work)

// System stopped
case <-w.exitCh:
if w.Bidder.isEnabled() {
close(w.Bidder.exitCh)
w.Bidder.wg.Wait()
}
return
case <-w.chainHeadSub.Err():
return
Expand Down Expand Up @@ -1120,7 +1122,9 @@ LOOP:
break LOOP
}

w.bidCh <- work
if w.Bidder.isEnabled() {
w.Bidder.newBidCh <- work
}

if interruptCh == nil || stopTimer == nil {
// it is single commit work, no need to try several time.
Expand Down

0 comments on commit 991826c

Please sign in to comment.