From 33991f44469f53cb79f20085ea8b01d51ead4255 Mon Sep 17 00:00:00 2001 From: Hussam Date: Fri, 11 Oct 2024 15:26:49 -0500 Subject: [PATCH] Probabilistic choosing of Quai vs Qi accorrding to preference --- cmd/utils/flags.go | 141 ++++++++++++++++++++++----------------------- core/miner.go | 24 +++----- core/slice.go | 4 +- core/types/wo.go | 5 ++ core/worker.go | 81 ++++++++++++++++++-------- quai/api.go | 5 -- quai/backend.go | 26 +++------ 7 files changed, 152 insertions(+), 134 deletions(-) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 6d7639844..39a40b344 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -105,7 +105,9 @@ var NodeFlags = []Flag{ VMEnableDebugFlag, PprofFlag, InsecureUnlockAllowedFlag, - CoinbaseAddressFlag, + QiCoinbaseFlag, + QuaiCoinbaseFlag, + MinerPreferenceFlag, EnvironmentFlag, QuaiStatsURLFlag, SendFullStatsFlag, @@ -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{ @@ -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 } - log.Global.Infof("Coinbase Addresses: %v", coinbases) + 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.WithFields(log.Fields{ + "qi": qiAddr, + "quai": quaiAddr, + }).Infof("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) { @@ -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: @@ -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. @@ -1371,12 +1370,12 @@ 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)} } + cfg.Miner.MinerPreference = viper.GetFloat64(MinerPreferenceFlag.Name) + // Override any default configs for hard coded networks. switch viper.GetString(EnvironmentFlag.Name) { case params.ColosseumName: diff --git a/core/miner.go b/core/miner.go index b562a3470..c7c78cf8e 100644 --- a/core/miner.go +++ b/core/miner.go @@ -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)) @@ -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) } diff --git a/core/slice.go b/core/slice.go index 89f1d0bcc..7a121b944 100644 --- a/core/slice.go +++ b/core/slice.go @@ -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) @@ -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)) diff --git a/core/types/wo.go b/core/types/wo.go index 8a3a23164..328a1c93e 100644 --- a/core/types/wo.go +++ b/core/types/wo.go @@ -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 /////////////// //////////////////////////////////////////////////////////// diff --git a/core/worker.go b/core/worker.go index 81400d415..15d7b553c 100644 --- a/core/worker.go +++ b/core/worker.go @@ -6,6 +6,7 @@ import ( "fmt" "math" "math/big" + "math/rand" "runtime/debug" "sort" "strings" @@ -100,8 +101,9 @@ func (env *environment) unclelist() []*types.WorkObjectHeader { // Config is the configuration parameters of mining. type Config struct { - PrimaryCoinbase common.Address `toml:",omitempty"` // Public address for block mining rewards (default = first account) - SecondaryCoinbase common.Address `toml:",omitempty"` // Public address for block mining rewards (second account) + QiCoinbase common.Address `toml:",omitempty"` // Public address for Qi mining rewards + QuaiCoinbase common.Address `toml:",omitempty"` // Public address for Quai mining rewards + MinerPreference float64 // Determines the relative preference of Qi or Quai [0, 1] respectively Notify []string `toml:",omitempty"` // HTTP URL list to be notified of new work packages (only useful in ethash). NotifyFull bool `toml:",omitempty"` // Notify with pending block headers instead of work packages ExtraData hexutil.Bytes `toml:",omitempty"` // Block extra data set by the miner @@ -154,6 +156,8 @@ type worker struct { uncleMu sync.RWMutex mu sync.RWMutex // The lock used to protect the coinbase and extra fields + qiCoinbase common.Address + quaiCoinbase common.Address primaryCoinbase common.Address secondaryCoinbase common.Address extra []byte @@ -220,8 +224,8 @@ func newWorker(config *Config, chainConfig *params.ChainConfig, db ethdb.Databas engine: engine, hc: headerchain, txPool: txPool, - primaryCoinbase: config.PrimaryCoinbase, - secondaryCoinbase: config.SecondaryCoinbase, + qiCoinbase: config.QiCoinbase, + quaiCoinbase: config.QuaiCoinbase, isLocalBlock: isLocalBlock, workerDb: db, chainSideCh: make(chan ChainSideEvent, chainSideChanSize), @@ -271,6 +275,21 @@ func newWorker(config *Config, chainConfig *params.ChainConfig, db ethdb.Databas return worker } +func (w *worker) setCoinbases(primaryAddress common.Address, secondaryAddress common.Address) { + w.mu.Lock() + defer w.mu.Unlock() + + // Use the MinerPreference to bias the decision + biasedFloat := math.Pow(rand.Float64(), (1-w.config.MinerPreference)*2) + if biasedFloat < 0.5 { + w.primaryCoinbase = primaryAddress + w.secondaryCoinbase = secondaryAddress + } else { + w.primaryCoinbase = primaryAddress + w.secondaryCoinbase = secondaryAddress + } +} + // setPrimaryCoinbase sets the coinbase used to initialize the block primary coinbase field. func (w *worker) setPrimaryCoinbase(addr common.Address) { w.mu.Lock() @@ -285,6 +304,20 @@ func (w *worker) setSecondaryCoinbase(addr common.Address) { w.secondaryCoinbase = addr } +func (w *worker) GetPrimaryCoinbase() common.Address { + w.mu.RLock() + defer w.mu.RUnlock() + + return w.primaryCoinbase +} + +func (w *worker) GetSecondaryCoinbase() common.Address { + w.mu.RLock() + defer w.mu.RUnlock() + + return w.secondaryCoinbase +} + func (w *worker) setGasCeil(ceil uint64) { w.mu.Lock() defer w.mu.Unlock() @@ -484,30 +517,27 @@ func (w *worker) GeneratePendingHeader(block *types.WorkObject, fill bool, txs t ) start := time.Now() + w.setCoinbases(w.GetPrimaryCoinbase(), w.GetSecondaryCoinbase()) // Set the primary coinbase if the worker is running or it's required - var primaryCoinbase common.Address - if w.hc.NodeCtx() == common.ZONE_CTX && w.primaryCoinbase.Equal(common.Address{}) && w.hc.ProcessingState() { + if w.hc.NodeCtx() == common.ZONE_CTX && w.GetPrimaryCoinbase().Equal(common.Address{}) && w.hc.ProcessingState() { w.logger.Warn("Refusing to mine without primaryCoinbase") return nil, errors.New("etherbase not found") - } else if w.primaryCoinbase.Equal(common.Address{}) { - w.primaryCoinbase = common.Zero + } else if w.GetPrimaryCoinbase().Equal(common.Address{}) { + w.setPrimaryCoinbase(common.Zero) } - primaryCoinbase = w.primaryCoinbase // Use the preset address as the fee recipient // Set the secondary coinbase if the worker is running or it's required - var secondaryCoinbase common.Address - if w.hc.NodeCtx() == common.ZONE_CTX && w.primaryCoinbase.Equal(common.Address{}) && w.hc.ProcessingState() { + if w.hc.NodeCtx() == common.ZONE_CTX && w.GetPrimaryCoinbase().Equal(common.Address{}) && w.hc.ProcessingState() { w.logger.Warn("Refusing to mine without primaryCoinbase") return nil, errors.New("etherbase not found") - } else if w.primaryCoinbase.Equal(common.Address{}) { - w.primaryCoinbase = common.Zero + } else if w.GetPrimaryCoinbase().Equal(common.Address{}) { + w.setPrimaryCoinbase(common.Zero) } - secondaryCoinbase = w.secondaryCoinbase // Use the preset address as the fee recipient work, err := w.prepareWork(&generateParams{ timestamp: uint64(timestamp), - primaryCoinbase: primaryCoinbase, - secondaryCoinbase: secondaryCoinbase, + primaryCoinbase: w.GetPrimaryCoinbase(), + secondaryCoinbase: w.GetSecondaryCoinbase(), }, block) if err != nil { return nil, err @@ -550,11 +580,11 @@ func (w *worker) GeneratePendingHeader(block *types.WorkObject, fill bool, txs t return nil, fmt.Errorf("parent order not set") } - if (w.config.PrimaryCoinbase == common.Address{}) { + if (w.GetPrimaryCoinbase() == common.Address{}) { return nil, fmt.Errorf("primary coinbase is not set") } - if (w.config.SecondaryCoinbase == common.Address{}) { + if (w.GetSecondaryCoinbase() == common.Address{}) { return nil, fmt.Errorf("secondary coinbase is not set") } @@ -577,18 +607,22 @@ func (w *worker) GeneratePendingHeader(block *types.WorkObject, fill bool, txs t if bytes.Equal(work.wo.PrimaryCoinbase().Bytes(), quaiCoinbase.Bytes()) { coinbaseReward := misc.CalculateReward(work.wo.WorkObjectHeader()) blockReward := new(big.Int).Add(coinbaseReward, work.quaiFees) + primaryCoinbase := w.GetPrimaryCoinbase() coinbaseEtx := types.NewTx(&types.ExternalTx{To: &primaryCoinbase, Gas: params.TxGas, Value: blockReward, EtxType: types.CoinbaseType, OriginatingTxHash: origin, ETXIndex: uint16(len(work.etxs)), Sender: primaryCoinbase, Data: []byte{defaultCoinbaseLockup}}) work.etxs = append(work.etxs, coinbaseEtx) if work.utxoFees.Cmp(big.NewInt(0)) != 0 { - coinbaseEtx := types.NewTx(&types.ExternalTx{To: &secondaryCoinbase, Gas: params.TxGas, Value: work.utxoFees, EtxType: types.CoinbaseType, OriginatingTxHash: origin, ETXIndex: uint16(len(work.etxs)), Sender: secondaryCoinbase, Data: []byte{defaultCoinbaseLockup}}) + secondaryCoinbase := w.GetSecondaryCoinbase() + coinbaseEtx := types.NewTx(&types.ExternalTx{To: &secondaryCoinbase, Gas: params.TxGas, Value: work.utxoFees, EtxType: types.CoinbaseType, OriginatingTxHash: origin, ETXIndex: uint16(len(work.etxs)), Sender: w.secondaryCoinbase, Data: []byte{defaultCoinbaseLockup}}) work.etxs = append(work.etxs, coinbaseEtx) } } else if bytes.Equal(work.wo.PrimaryCoinbase().Bytes(), qiCoinbase.Bytes()) { coinbaseReward := misc.CalculateReward(work.wo.WorkObjectHeader()) blockReward := new(big.Int).Add(coinbaseReward, work.utxoFees) + primaryCoinbase := w.GetPrimaryCoinbase() coinbaseEtx := types.NewTx(&types.ExternalTx{To: &primaryCoinbase, Gas: params.TxGas, Value: blockReward, EtxType: types.CoinbaseType, OriginatingTxHash: origin, ETXIndex: uint16(len(work.etxs)), Sender: primaryCoinbase, Data: []byte{defaultCoinbaseLockup}}) work.etxs = append(work.etxs, coinbaseEtx) if work.quaiFees.Cmp(big.NewInt(0)) != 0 { + secondaryCoinbase := w.GetSecondaryCoinbase() coinbaseEtx := types.NewTx(&types.ExternalTx{To: &secondaryCoinbase, Gas: params.TxGas, Value: work.quaiFees, EtxType: types.CoinbaseType, OriginatingTxHash: origin, ETXIndex: uint16(len(work.etxs)), Sender: secondaryCoinbase, Data: []byte{defaultCoinbaseLockup}}) work.etxs = append(work.etxs, coinbaseEtx) } @@ -1533,16 +1567,15 @@ func (w *worker) prepareWork(genParams *generateParams, wo *types.WorkObject) (* newWo.Header().SetExtra(w.extra) newWo.Header().SetStateLimit(misc.CalcStateLimit(parent, w.config.GasCeil)) if w.isRunning() { - if w.primaryCoinbase.Equal(common.Zero) { + if w.GetPrimaryCoinbase().Equal(common.Zero) { w.logger.Error("Refusing to mine without primary coinbase") return nil, errors.New("refusing to mine without primary coinbase") } - if w.secondaryCoinbase.Equal(common.Zero) { + if w.GetSecondaryCoinbase().Equal(common.Zero) { w.logger.Error("Refusing to mine without secondary coinbase") return nil, errors.New("refusing to mine without secondary coinbase") } - newWo.WorkObjectHeader().SetPrimaryCoinbase(w.primaryCoinbase) - newWo.Header().SetSecondaryCoinbase(w.secondaryCoinbase) + newWo.SetCoinbases(w.GetPrimaryCoinbase(), w.GetSecondaryCoinbase()) } // Get the latest transactions to be broadcasted from the pool @@ -1568,7 +1601,7 @@ func (w *worker) prepareWork(genParams *generateParams, wo *types.WorkObject) (* proposedWoHeader := types.NewWorkObjectHeader(newWo.Hash(), newWo.ParentHash(nodeCtx), newWo.Number(nodeCtx), newWo.Difficulty(), newWo.WorkObjectHeader().PrimeTerminusNumber(), newWo.TxHash(), newWo.Nonce(), newWo.Lock(), newWo.Time(), newWo.Location(), newWo.PrimaryCoinbase()) proposedWoBody := types.NewWoBody(newWo.Header(), nil, nil, nil, nil, nil) proposedWo := types.NewWorkObject(proposedWoHeader, proposedWoBody, nil) - env, err := w.makeEnv(parent, proposedWo, w.primaryCoinbase, w.secondaryCoinbase) + env, err := w.makeEnv(parent, proposedWo, w.GetPrimaryCoinbase(), w.GetSecondaryCoinbase()) if err != nil { w.logger.WithField("err", err).Error("Failed to create sealing context") return nil, err diff --git a/quai/api.go b/quai/api.go index 582eda0eb..1b7f47eef 100644 --- a/quai/api.go +++ b/quai/api.go @@ -49,11 +49,6 @@ func NewPublicQuaiAPI(e *Quai) *PublicQuaiAPI { return &PublicQuaiAPI{e} } -// PrimaryCoinbase is the address that mining rewards will be send to -func (api *PublicQuaiAPI) PrimaryCoinbase() (common.Address, error) { - return api.e.PrimaryCoinbase() -} - // PublicMinerAPI provides an API to control the miner. // It offers only methods that operate on data that pose no security risk when it is publicly accessible. type PublicMinerAPI struct { diff --git a/quai/backend.go b/quai/backend.go index 16ef2e148..757cfbccb 100644 --- a/quai/backend.go +++ b/quai/backend.go @@ -70,8 +70,10 @@ type Quai struct { APIBackend *QuaiAPIBackend - gasPrice *big.Int - primaryCoinbase common.Address + qiCoinbase common.Address + quaiCoinbase common.Address + + gasPrice *big.Int lock sync.RWMutex // Protects the variadic fields (e.g. gas price and etherbase) @@ -158,7 +160,8 @@ func New(stack *node.Node, p2p NetworkingAPI, config *quaiconfig.Config, nodeCtx eventMux: stack.EventMux(), closeBloomHandler: make(chan struct{}), gasPrice: config.Miner.GasPrice, - primaryCoinbase: config.Miner.PrimaryCoinbase, + qiCoinbase: config.Miner.QiCoinbase, + quaiCoinbase: config.Miner.QuaiCoinbase, bloomRequests: make(chan chan *bloombits.Retrieval), logger: logger, maxWsSubs: maxWsSubs, @@ -319,18 +322,6 @@ func (s *Quai) APIs() []rpc.API { }...) } -func (s *Quai) PrimaryCoinbase() (eb common.Address, err error) { - s.lock.RLock() - primaryCoinbase := s.primaryCoinbase - s.lock.RUnlock() - - if !primaryCoinbase.Equal(common.Zero) { - return primaryCoinbase, nil - } - - return common.Zero, fmt.Errorf("etherbase must be explicitly specified") -} - // isLocalBlock checks whether the specified block is mined // by local miner accounts. // @@ -348,9 +339,10 @@ func (s *Quai) isLocalBlock(header *types.WorkObject) bool { } // Check whether the given address is etherbase. s.lock.RLock() - etherbase := s.primaryCoinbase + qiBase := s.qiCoinbase + quaiBase := s.quaiCoinbase s.lock.RUnlock() - if author.Equal(etherbase) { + if author.Equal(qiBase) || author.Equal(quaiBase) { return true } internal, err := author.InternalAddress()