Skip to content

Commit

Permalink
Probabilistic choosing of Quai vs Qi accorrding to preference
Browse files Browse the repository at this point in the history
  • Loading branch information
Djadih committed Oct 14, 2024
1 parent e35cf4c commit 57ee80b
Show file tree
Hide file tree
Showing 7 changed files with 170 additions and 130 deletions.
146 changes: 75 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,
QiCoinbaseFlag,
QuaiCoinbaseFlag,
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",
QiCoinbaseFlag = Flag{
Name: c_NodeFlagPrefix + "qi-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+"qi-coinbase"),
}

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

MinerPreferenceFlag = Flag{
Name: c_NodeFlagPrefix + "miner-preference",
Value: 0.5,
Usage: "Indicates preference towards mining Qi or Quai (Neutral: 0.5, Qi only: 0, Quai 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) {
qiCoinbase := viper.GetString(QiCoinbaseFlag.Name)
quaiCoinbase := viper.GetString(QuaiCoinbaseFlag.Name)
coinbases := make(map[string]common.Address)

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

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

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

log.Global.Infof("Coinbase Addresses: %v", coinbases)
log.Global.WithFields(log.Fields{
"qi": qiAddr,
"quai": quaiAddr,
}).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,19 @@ 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
qiCoinbase, ok := coinbaseMap[cfg.NodeLocation.Name()+"qi"]
if !ok {
log.Global.Fatal("Missing Qi 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
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
cfg.Miner.QiCoinbase = qiCoinbase
// Convert the coinbase into an address and configure it
cfg.Miner.QuaiCoinbase = quaiCoinbase
}

// MakePasswordList reads password lines from the file specified by the global --password flag.
Expand Down Expand Up @@ -1371,10 +1370,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 = "QiCoinbase"
} else {
coinbaseType = "QuaiCoinbase"
}
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 @@ -535,6 +535,11 @@ func (wo *WorkObject) SetNumber(val *big.Int, nodeCtx int) {
}
}

func (wo *WorkObject) SetCoinbases(primary common.Address, secondary common.Address) {
wo.WorkObjectHeader().SetPrimaryCoinbase(primary)
wo.Header().SetSecondaryCoinbase(secondary)
}

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

0 comments on commit 57ee80b

Please sign in to comment.