Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allows switching of Quai and Qi coinbases based on MinerPreference flag #2215

Merged
merged 1 commit into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
144 changes: 73 additions & 71 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@ var NodeFlags = []Flag{
VMEnableDebugFlag,
PprofFlag,
InsecureUnlockAllowedFlag,
CoinbaseAddressFlag,
QuaiCoinbaseFlag,
QiCoinbaseFlag,
MinerPreferenceFlag,
EnvironmentFlag,
QuaiStatsURLFlag,
SendFullStatsFlag,
Expand Down Expand Up @@ -504,10 +506,22 @@ var (
Usage: "Allow insecure account unlocking when account-related RPCs are exposed by http" + generateEnvDoc(c_NodeFlagPrefix+"allow-insecure-unlock"),
}

CoinbaseAddressFlag = Flag{
Name: c_NodeFlagPrefix + "coinbases",
QuaiCoinbaseFlag = Flag{
Name: c_NodeFlagPrefix + "quai-coinbase",
Value: "",
Usage: "Input TOML string or path to TOML file" + generateEnvDoc(c_NodeFlagPrefix+"coinbases"),
Usage: "Input TOML string or path to TOML file" + generateEnvDoc(c_NodeFlagPrefix+"quai-coinbase"),
}

QiCoinbaseFlag = Flag{
Name: c_NodeFlagPrefix + "qi-coinbase",
Value: "",
Usage: "Input TOML string or path to TOML file" + generateEnvDoc(c_NodeFlagPrefix+"qi-coinbase"),
}

MinerPreferenceFlag = Flag{
Djadih marked this conversation as resolved.
Show resolved Hide resolved
Name: c_NodeFlagPrefix + "miner-preference",
Value: 0.5,
Usage: "Indicates preference towards mining Quai or Qi. Any value between 0 and 1 is valid. Neutral: 0.5, Quai only: 0, Qi only: 1" + generateEnvDoc(c_NodeFlagPrefix+"miner-preference"),
}

IndexAddressUtxos = Flag{
Expand Down Expand Up @@ -728,62 +742,50 @@ var (
}
)

/*
ParseCoinbaseAddresses parses the coinbase addresses from different sources based on the user input.
It handles three scenarios:

1. File Path Input:
If the user specifies a file path, the function expects a TOML file containing the coinbase addresses.
The file should have a 'coinbases' section with shard-address mappings.
Example:
Command: --coinbases "0x00Address0, 0x01Address1, 0x02Address2, ..."

The function reads the coinbase addresses and performs necessary validation as per the above scenarios.
*/
func ParseCoinbaseAddresses() (map[string]string, error) {
coinbaseInput := viper.GetString(CoinbaseAddressFlag.Name)
coinbases := make(map[string]string)

if coinbaseInput == "" {
log.Global.Info("No coinbase addresses provided")
return coinbases, nil
}

for _, coinbase := range strings.Split(coinbaseInput, ",") {
coinbase = strings.TrimSpace(coinbase)
address := common.HexToAddress(coinbase, common.Location{0, 0})
location := address.Location()

// check if the primary key exists, otherwise, the first address in the given shard becomes the primary coinbase
// second one becomes the secondary coinbase
primaryCoinbaseKey := location.Name() + "primary"
if _, exists := coinbases[primaryCoinbaseKey]; exists {
// add this address to the secondary coinbases list
secondaryCoinbaseKey := location.Name() + "secondary"
if _, exists := coinbases[secondaryCoinbaseKey]; exists {
log.Global.WithField("key", secondaryCoinbaseKey).Fatalf("Duplicate secondary coinbase address for the given ledger in the shard")
}
coinbases[secondaryCoinbaseKey] = coinbase
} else {
coinbases[primaryCoinbaseKey] = coinbase
}
// ParseCoinbaseAddresses reads the coinbase addresses and performs necessary validation.
func ParseCoinbaseAddresses() (map[string]common.Address, error) {
quaiCoinbase := viper.GetString(QuaiCoinbaseFlag.Name)
qiCoinbase := viper.GetString(QiCoinbaseFlag.Name)
coinbases := make(map[string]common.Address)

if err := isValidAddress(coinbase); err != nil {
log.Global.WithField("err", err).Fatalf("Error parsing coinbase addresses")
}
if quaiCoinbase == "" || qiCoinbase == "" {
missingCoinbaseErr := errors.New("must provide both a Quai and Qi coinbase address")
log.Global.Fatal(missingCoinbaseErr)
return nil, missingCoinbaseErr
}

log.Global.Infof("Coinbase Addresses: %v", coinbases)
quaiAddr, err := isValidAddress(quaiCoinbase)
if err != nil {
log.Global.WithField("err", err).Fatalf("Error parsing quai address")
return nil, err
}
quaiAddrCoinbaseKey := quaiAddr.Location().Name() + "quai"
coinbases[quaiAddrCoinbaseKey] = quaiAddr

qiAddr, err := isValidAddress(qiCoinbase)
if err != nil {
log.Global.WithField("err", err).Fatalf("Error parsing qi address")
return nil, err
}
qiAddrCoinbaseKey := qiAddr.Location().Name() + "qi"
coinbases[qiAddrCoinbaseKey] = qiAddr

log.Global.WithFields(log.Fields{
"quai": quaiAddr,
"qi": qiAddr,
}).Info("Coinbase Addresses")

return coinbases, nil
}

func isValidAddress(address string) error {
func isValidAddress(addressStr string) (common.Address, error) {
addressStr = strings.TrimSpace(addressStr)
address := common.HexToAddress(addressStr, common.Location{0, 0})
re := regexp.MustCompile(`^(0x)?[0-9a-fA-F]{40}$`)
if !re.MatchString(address) {
return fmt.Errorf("invalid address: %s", address)
if !re.MatchString(addressStr) {
return common.Address{}, fmt.Errorf("invalid address: %s", address)
}
return nil
return address, nil
}

func CreateAndBindFlag(flag Flag, cmd *cobra.Command) {
Expand All @@ -802,6 +804,8 @@ func CreateAndBindFlag(flag Flag, cmd *cobra.Command) {
cmd.PersistentFlags().Int64P(flag.GetName(), flag.GetAbbreviation(), val, flag.GetUsage())
case uint64:
cmd.PersistentFlags().Uint64P(flag.GetName(), flag.GetAbbreviation(), val, flag.GetUsage())
case float64:
cmd.PersistentFlags().Float64P(flag.GetName(), flag.GetAbbreviation(), val, flag.GetUsage())
case *TextMarshalerValue:
cmd.PersistentFlags().VarP(val, flag.GetName(), flag.GetAbbreviation(), flag.GetUsage())
case *BigIntValue:
Expand Down Expand Up @@ -964,24 +968,17 @@ func setCoinbase(cfg *quaiconfig.Config) {
if err != nil {
log.Global.Fatalf("error parsing coinbase addresses: %s", err)
}
primaryCoinbase := coinbaseMap[cfg.NodeLocation.Name()+"primary"]
secondaryCoinbase := coinbaseMap[cfg.NodeLocation.Name()+"secondary"]
// Convert the coinbase into an address and configure it
if primaryCoinbase != "" {
account, err := HexAddress(primaryCoinbase, cfg.NodeLocation)
if err != nil {
Fatalf("Invalid primary coinbase: %v", err)
}
cfg.Miner.PrimaryCoinbase = account
quaiCoinbase, ok := coinbaseMap[cfg.NodeLocation.Name()+"quai"]
if !ok {
log.Global.Fatal("Missing Quai coinbase for this location")
}
// Convert the coinbase into an address and configure it
if secondaryCoinbase != "" {
account, err := HexAddress(secondaryCoinbase, cfg.NodeLocation)
if err != nil {
Fatalf("Invalid secondary coinbase: %v", err)
}
cfg.Miner.SecondaryCoinbase = account
qiCoinbase, ok := coinbaseMap[cfg.NodeLocation.Name()+"qi"]
if !ok {
log.Global.Fatal("Missing Qi coinbase for this location")
}

cfg.Miner.QuaiCoinbase = quaiCoinbase
cfg.Miner.QiCoinbase = qiCoinbase
}

// MakePasswordList reads password lines from the file specified by the global --password flag.
Expand Down Expand Up @@ -1370,10 +1367,15 @@ func SetQuaiConfig(stack *node.Node, cfg *quaiconfig.Config, slicesRunning []com

cfg.Miner.WorkShareMining = viper.GetBool(WorkShareMiningFlag.Name)
cfg.Miner.WorkShareThreshold = params.WorkSharesThresholdDiff + viper.GetInt(WorkShareThresholdFlag.Name)
if viper.IsSet(WorkShareMinerEndpoints.Name) {
if viper.GetString(WorkShareMinerEndpoints.Name) != "" {
cfg.Miner.Endpoints = []string{viper.GetString(WorkShareMinerEndpoints.Name)}
}
if viper.GetString(WorkShareMinerEndpoints.Name) != "" {
cfg.Miner.Endpoints = []string{viper.GetString(WorkShareMinerEndpoints.Name)}
}

minerPreference := viper.GetFloat64(MinerPreferenceFlag.Name)
if minerPreference < 0 || minerPreference > 1 {
log.Global.WithField("MinerPreference", minerPreference).Fatal("Invalid MinerPreference field. Must be [0,1]")
} else {
cfg.Miner.MinerPreference = minerPreference
}

// Override any default configs for hard coded networks.
Expand Down
24 changes: 9 additions & 15 deletions core/miner.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,23 +35,19 @@ import (

// Miner creates blocks and searches for proof-of-work values.
type Miner struct {
worker *worker
primaryCoinbase common.Address
secondaryCoinbase common.Address
hc *HeaderChain
engine consensus.Engine
startCh chan []common.Address
logger *log.Logger
worker *worker
hc *HeaderChain
engine consensus.Engine
startCh chan []common.Address
logger *log.Logger
}

func New(hc *HeaderChain, txPool *TxPool, config *Config, db ethdb.Database, chainConfig *params.ChainConfig, engine consensus.Engine, isLocalBlock func(block *types.WorkObject) bool, processingState bool, logger *log.Logger) *Miner {
miner := &Miner{
hc: hc,
engine: engine,
startCh: make(chan []common.Address, 2),
worker: newWorker(config, chainConfig, db, engine, hc, txPool, isLocalBlock, true, processingState, logger),
primaryCoinbase: config.PrimaryCoinbase,
secondaryCoinbase: config.SecondaryCoinbase,
hc: hc,
engine: engine,
startCh: make(chan []common.Address, 2),
worker: newWorker(config, chainConfig, db, engine, hc, txPool, isLocalBlock, true, processingState, logger),
}

miner.SetExtra(miner.MakeExtraData(config.ExtraData))
Expand Down Expand Up @@ -131,12 +127,10 @@ func (miner *Miner) PendingBlockAndReceipts() (*types.WorkObject, types.Receipts
}

func (miner *Miner) SetPrimaryCoinbase(addr common.Address) {
miner.primaryCoinbase = addr
miner.worker.setPrimaryCoinbase(addr)
}

func (miner *Miner) SetSecondaryCoinbase(addr common.Address) {
miner.secondaryCoinbase = addr
miner.worker.setSecondaryCoinbase(addr)
}

Expand Down
15 changes: 13 additions & 2 deletions core/slice.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,7 @@ func (sl *Slice) Append(header *types.WorkObject, domTerminus common.Hash, domOr
}
time5_1 = common.PrettyDuration(time.Since(start))
// Cache the subordinate's pending ETXs
pEtxs := types.PendingEtxs{header.ConvertToPEtxView(), subPendingEtxs}
pEtxs := types.PendingEtxs{Header: header.ConvertToPEtxView(), OutboundEtxs: subPendingEtxs}
time5_2 = common.PrettyDuration(time.Since(start))
// Add the pending etx given by the sub in the rollup
sl.AddPendingEtxs(pEtxs)
Expand All @@ -330,7 +330,7 @@ func (sl *Slice) Append(header *types.WorkObject, domTerminus common.Hash, domOr
}
}
// We also need to store the pendingEtxRollup to the dom
pEtxRollup := types.PendingEtxsRollup{header.ConvertToPEtxView(), crossPrimeRollup}
pEtxRollup := types.PendingEtxsRollup{Header: header.ConvertToPEtxView(), EtxsRollup: crossPrimeRollup}
sl.AddPendingEtxsRollup(pEtxRollup)
}
time5_3 = common.PrettyDuration(time.Since(start))
Expand Down Expand Up @@ -396,6 +396,12 @@ func (sl *Slice) Append(header *types.WorkObject, domTerminus common.Hash, domOr
sl.logger.WithFields(block.TransactionsInfo()).Info("Transactions info for Block")
}

var coinbaseType string
if block.PrimaryCoinbase().IsInQiLedgerScope() {
coinbaseType = "QuaiCoinbase"
} else {
coinbaseType = "QiCoinbase"
}
sl.logger.WithFields(log.Fields{
"number": block.NumberArray(),
"hash": block.Hash(),
Expand All @@ -413,6 +419,7 @@ func (sl *Slice) Append(header *types.WorkObject, domTerminus common.Hash, domOr
"order": order,
"location": block.Location(),
"elapsed": common.PrettyDuration(time.Since(start)),
"coinbaseType": coinbaseType,
}).Info("Appended new block")

if nodeCtx == common.ZONE_CTX {
Expand Down Expand Up @@ -738,6 +745,10 @@ func (sl *Slice) GetPendingEtxsFromSub(hash common.Hash, location common.Locatio
return types.PendingEtxs{}, ErrPendingEtxNotFound
}

func (sl *Slice) GetPrimaryCoinbase() common.Address {
return sl.miner.worker.GetPrimaryCoinbase()
}

// init checks if the headerchain is empty and if it's empty appends the Knot
// otherwise loads the last stored state of the chain.
func (sl *Slice) init() error {
Expand Down
5 changes: 5 additions & 0 deletions core/types/wo.go
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,11 @@ func (wo *WorkObject) SetNumber(val *big.Int, nodeCtx int) {
}
}

func (wo *WorkObject) SetCoinbases(primary common.Address, secondary common.Address) {
wizeguyy marked this conversation as resolved.
Show resolved Hide resolved
wo.WorkObjectHeader().SetPrimaryCoinbase(primary)
wo.Header().SetSecondaryCoinbase(secondary)
}

////////////////////////////////////////////////////////////
/////////////////// Work Object Header Getters ///////////////
////////////////////////////////////////////////////////////
Expand Down
Loading
Loading