Skip to content

Commit e0d0e64

Browse files
committed
cmd, core, miner: add --txpool.locals and priority mining
1 parent b2c644f commit e0d0e64

File tree

5 files changed

+70
-8
lines changed

5 files changed

+70
-8
lines changed

cmd/geth/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ var (
7272
utils.EthashDatasetDirFlag,
7373
utils.EthashDatasetsInMemoryFlag,
7474
utils.EthashDatasetsOnDiskFlag,
75+
utils.TxPoolLocalsFlag,
7576
utils.TxPoolNoLocalsFlag,
7677
utils.TxPoolJournalFlag,
7778
utils.TxPoolRejournalFlag,

cmd/geth/usage.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ var AppHelpFlagGroups = []flagGroup{
114114
{
115115
Name: "TRANSACTION POOL",
116116
Flags: []cli.Flag{
117+
utils.TxPoolLocalsFlag,
117118
utils.TxPoolNoLocalsFlag,
118119
utils.TxPoolJournalFlag,
119120
utils.TxPoolRejournalFlag,

cmd/utils/flags.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,10 @@ var (
233233
Value: eth.DefaultConfig.Ethash.DatasetsOnDisk,
234234
}
235235
// Transaction pool settings
236+
TxPoolLocalsFlag = cli.StringFlag{
237+
Name: "txpool.locals",
238+
Usage: "Comma separated accounts to treat as locals (no flush, priority inclusion)",
239+
}
236240
TxPoolNoLocalsFlag = cli.BoolFlag{
237241
Name: "txpool.nolocals",
238242
Usage: "Disables price exemptions for locally submitted transactions",
@@ -977,6 +981,16 @@ func setGPO(ctx *cli.Context, cfg *gasprice.Config) {
977981
}
978982

979983
func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) {
984+
if ctx.GlobalIsSet(TxPoolLocalsFlag.Name) {
985+
locals := strings.Split(ctx.GlobalString(TxPoolLocalsFlag.Name), ",")
986+
for _, account := range locals {
987+
if trimmed := strings.TrimSpace(account); !common.IsHexAddress(trimmed) {
988+
Fatalf("Invalid account in --txpool.locals: %s", trimmed)
989+
} else {
990+
cfg.Locals = append(cfg.Locals, common.HexToAddress(account))
991+
}
992+
}
993+
}
980994
if ctx.GlobalIsSet(TxPoolNoLocalsFlag.Name) {
981995
cfg.NoLocals = ctx.GlobalBool(TxPoolNoLocalsFlag.Name)
982996
}

core/tx_pool.go

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,10 @@ type blockChain interface {
123123

124124
// TxPoolConfig are the configuration parameters of the transaction pool.
125125
type TxPoolConfig struct {
126-
NoLocals bool // Whether local transaction handling should be disabled
127-
Journal string // Journal of local transactions to survive node restarts
128-
Rejournal time.Duration // Time interval to regenerate the local transaction journal
126+
Locals []common.Address // Addresses that should be treated by default as local
127+
NoLocals bool // Whether local transaction handling should be disabled
128+
Journal string // Journal of local transactions to survive node restarts
129+
Rejournal time.Duration // Time interval to regenerate the local transaction journal
129130

130131
PriceLimit uint64 // Minimum gas price to enforce for acceptance into the pool
131132
PriceBump uint64 // Minimum price bump percentage to replace an already existing transaction (nonce)
@@ -231,6 +232,10 @@ func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain block
231232
gasPrice: new(big.Int).SetUint64(config.PriceLimit),
232233
}
233234
pool.locals = newAccountSet(pool.signer)
235+
for _, addr := range config.Locals {
236+
log.Info("Setting new local account", "address", addr)
237+
pool.locals.add(addr)
238+
}
234239
pool.priced = newTxPricedList(pool.all)
235240
pool.reset(nil, chain.CurrentBlock().Header())
236241

@@ -534,6 +539,14 @@ func (pool *TxPool) Pending() (map[common.Address]types.Transactions, error) {
534539
return pending, nil
535540
}
536541

542+
// Locals retrieves the accounts currently considered local by the pool.
543+
func (pool *TxPool) Locals() []common.Address {
544+
pool.mu.Lock()
545+
defer pool.mu.Unlock()
546+
547+
return pool.locals.flatten()
548+
}
549+
537550
// local retrieves all currently known local transactions, groupped by origin
538551
// account and sorted by nonce. The returned transaction set is a copy and can be
539552
// freely modified by calling code.
@@ -665,7 +678,10 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) {
665678
}
666679
// Mark local addresses and journal local transactions
667680
if local {
668-
pool.locals.add(from)
681+
if !pool.locals.contains(from) {
682+
log.Info("Setting new local account", "address", from)
683+
pool.locals.add(from)
684+
}
669685
}
670686
pool.journalTx(from, tx)
671687

@@ -1138,6 +1154,7 @@ func (a addressesByHeartbeat) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
11381154
type accountSet struct {
11391155
accounts map[common.Address]struct{}
11401156
signer types.Signer
1157+
cache *[]common.Address
11411158
}
11421159

11431160
// newAccountSet creates a new address set with an associated signer for sender
@@ -1167,6 +1184,20 @@ func (as *accountSet) containsTx(tx *types.Transaction) bool {
11671184
// add inserts a new address into the set to track.
11681185
func (as *accountSet) add(addr common.Address) {
11691186
as.accounts[addr] = struct{}{}
1187+
as.cache = nil
1188+
}
1189+
1190+
// flatten returns the list of addresses within this set, also caching it for later
1191+
// reuse. The returned slice should not be changed!
1192+
func (as *accountSet) flatten() []common.Address {
1193+
if as.cache == nil {
1194+
accounts := make([]common.Address, 0, len(as.accounts))
1195+
for account := range as.accounts {
1196+
accounts = append(accounts, account)
1197+
}
1198+
as.cache = &accounts
1199+
}
1200+
return *as.cache
11701201
}
11711202

11721203
// txLookup is used internally by TxPool to track transactions while allowing lookup without

miner/worker.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -877,11 +877,26 @@ func (w *worker) commitNewWork(interrupt *int32, noempty bool) {
877877
w.updateSnapshot()
878878
return
879879
}
880-
txs := types.NewTransactionsByPriceAndNonce(w.current.signer, pending)
881-
if w.commitTransactions(txs, w.coinbase, interrupt) {
882-
return
880+
// Split the pending transactions into locals and remotes
881+
localTxs, remoteTxs := make(map[common.Address]types.Transactions), pending
882+
for _, account := range w.eth.TxPool().Locals() {
883+
if txs := remoteTxs[account]; len(txs) > 0 {
884+
delete(remoteTxs, account)
885+
localTxs[account] = txs
886+
}
887+
}
888+
if len(localTxs) > 0 {
889+
txs := types.NewTransactionsByPriceAndNonce(w.current.signer, localTxs)
890+
if w.commitTransactions(txs, w.coinbase, interrupt) {
891+
return
892+
}
893+
}
894+
if len(remoteTxs) > 0 {
895+
txs := types.NewTransactionsByPriceAndNonce(w.current.signer, remoteTxs)
896+
if w.commitTransactions(txs, w.coinbase, interrupt) {
897+
return
898+
}
883899
}
884-
885900
w.commit(uncles, w.fullTaskHook, true, tstart)
886901
}
887902

0 commit comments

Comments
 (0)