diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index a84e5700a0..e91504c852 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1240,24 +1240,31 @@ func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) { } } -func setDurationLimit(ctx *cli.Context, cfg *ethconfig.Config) { +func setConsensusEngineConfig(ctx *cli.Context, cfg *ethconfig.Config) { if cfg.ConsensusEngine == "blake3" { // Override any default configs for hard coded networks. switch { case ctx.GlobalBool(ColosseumFlag.Name): cfg.Blake3Pow.DurationLimit = params.DurationLimit + cfg.Blake3Pow.GasCeil = params.ColosseumGasCeil case ctx.GlobalBool(GardenFlag.Name): cfg.Blake3Pow.DurationLimit = params.GardenDurationLimit + cfg.Blake3Pow.GasCeil = params.GardenGasCeil case ctx.GlobalBool(OrchardFlag.Name): cfg.Blake3Pow.DurationLimit = params.OrchardDurationLimit + cfg.Blake3Pow.GasCeil = params.OrchardGasCeil case ctx.GlobalBool(LighthouseFlag.Name): cfg.Blake3Pow.DurationLimit = params.LighthouseDurationLimit + cfg.Blake3Pow.GasCeil = params.LighthouseGasCeil case ctx.GlobalBool(LocalFlag.Name): cfg.Blake3Pow.DurationLimit = params.LocalDurationLimit + cfg.Blake3Pow.GasCeil = params.LocalGasCeil case ctx.GlobalBool(DeveloperFlag.Name): cfg.Blake3Pow.DurationLimit = params.DurationLimit + cfg.Blake3Pow.GasCeil = params.LocalGasCeil default: cfg.Blake3Pow.DurationLimit = params.DurationLimit + cfg.Blake3Pow.GasCeil = params.GasCeil } } else { @@ -1265,18 +1272,25 @@ func setDurationLimit(ctx *cli.Context, cfg *ethconfig.Config) { switch { case ctx.GlobalBool(ColosseumFlag.Name): cfg.Progpow.DurationLimit = params.DurationLimit + cfg.Progpow.GasCeil = params.ColosseumGasCeil case ctx.GlobalBool(GardenFlag.Name): cfg.Progpow.DurationLimit = params.GardenDurationLimit + cfg.Progpow.GasCeil = params.GardenGasCeil case ctx.GlobalBool(OrchardFlag.Name): cfg.Progpow.DurationLimit = params.OrchardDurationLimit + cfg.Progpow.GasCeil = params.OrchardGasCeil case ctx.GlobalBool(LighthouseFlag.Name): cfg.Progpow.DurationLimit = params.LighthouseDurationLimit + cfg.Progpow.GasCeil = params.LighthouseGasCeil case ctx.GlobalBool(LocalFlag.Name): cfg.Progpow.DurationLimit = params.LocalDurationLimit + cfg.Progpow.GasCeil = params.LocalGasCeil case ctx.GlobalBool(DeveloperFlag.Name): cfg.Progpow.DurationLimit = params.DurationLimit + cfg.Progpow.GasCeil = params.LocalGasCeil default: cfg.Progpow.DurationLimit = params.DurationLimit + cfg.Progpow.GasCeil = params.GasCeil } } @@ -1425,7 +1439,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { } else { cfg.ConsensusEngine = "progpow" } - setDurationLimit(ctx, cfg) + setConsensusEngineConfig(ctx, cfg) setWhitelist(ctx, cfg) diff --git a/consensus/blake3pow/blake3pow.go b/consensus/blake3pow/blake3pow.go index f5ea303a62..2cd4f16dc8 100644 --- a/consensus/blake3pow/blake3pow.go +++ b/consensus/blake3pow/blake3pow.go @@ -43,6 +43,8 @@ type Config struct { DurationLimit *big.Int + GasCeil uint64 + // When set, notifications sent by the remote sealer will // be block header JSON objects instead of work package arrays. NotifyFull bool diff --git a/consensus/blake3pow/consensus.go b/consensus/blake3pow/consensus.go index 2551ed2db6..f5844c537b 100644 --- a/consensus/blake3pow/consensus.go +++ b/consensus/blake3pow/consensus.go @@ -17,6 +17,7 @@ import ( "github.com/dominant-strategies/go-quai/log" "github.com/dominant-strategies/go-quai/params" "github.com/dominant-strategies/go-quai/trie" + "modernc.org/mathutil" ) // Blake3pow proof-of-work protocol constants. @@ -300,8 +301,10 @@ func (blake3pow *Blake3pow) verifyHeader(chain consensus.ChainHeaderReader, head } // Verify the block's gas usage and verify the base fee. // Verify that the gas limit remains within allowed bounds - if err := misc.VerifyGaslimit(parent.GasLimit(), header.GasLimit()); err != nil { - return err + expectedGasLimit := core.CalcGasLimit(parent, blake3pow.config.GasCeil) + if expectedGasLimit != header.GasLimit() { + return fmt.Errorf("invalid gasLimit: have %d, want %d", + header.GasLimit(), expectedGasLimit) } // Verify the header is not malformed if header.BaseFee() == nil { @@ -331,48 +334,41 @@ func (blake3pow *Blake3pow) CalcDifficulty(chain consensus.ChainHeaderReader, pa log.Error("Cannot CalcDifficulty for", "context", nodeCtx) return nil } - // algorithm: - // diff = (parent_diff + - // (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99)) - // ) + 2^(periodCount - 2) - time := parent.Time() + ///// Algorithm: + ///// e = (DurationLimit - (parent.Time() - parentOfParent.Time())) * parent.Difficulty() + ///// k = Floor(BinaryLog(parent.Difficulty()))/(DurationLimit*DifficultyAdjustmentFactor*AdjustmentPeriod) + ///// Difficulty = Max(parent.Difficulty() + e * k, MinimumDifficulty) if parent.Hash() == chain.Config().GenesisHash { return parent.Difficulty() } parentOfParent := chain.GetHeaderByHash(parent.ParentHash()) + if parentOfParent.Hash() == chain.Config().GenesisHash { + return parent.Difficulty() + } + time := parent.Time() bigTime := new(big.Int).SetUint64(time) bigParentTime := new(big.Int).SetUint64(parentOfParent.Time()) // holds intermediate values to make the algo easier to read & audit x := new(big.Int) - y := new(big.Int) - - // (2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) // duration_limit x.Sub(bigTime, bigParentTime) + x.Sub(blake3pow.config.DurationLimit, x) + x.Mul(x, parent.Difficulty()) + k, _ := mathutil.BinaryLog(new(big.Int).Set(parent.Difficulty()), 64) + x.Mul(x, big.NewInt(int64(k))) x.Div(x, blake3pow.config.DurationLimit) - if parent.UncleHash() == types.EmptyUncleHash { - x.Sub(big1, x) - } else { - x.Sub(big2, x) - } - // max((2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) // 9, -99) - if x.Cmp(bigMinus99) < 0 { - x.Set(bigMinus99) - } - // parent_diff + (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99)) - y.Div(parent.Difficulty(), params.DifficultyBoundDivisor) - x.Mul(y, x) - x.Add(parent.Difficulty(), x) + x.Div(x, big.NewInt(params.DifficultyAdjustmentFactor)) + x.Div(x, params.DifficultyAdjustmentPeriod) + x.Add(x, parent.Difficulty()) // minimum difficulty can ever be (before exponential factor) if x.Cmp(params.MinimumDifficulty) < 0 { x.Set(params.MinimumDifficulty) } - return x } diff --git a/consensus/misc/gaslimit.go b/consensus/misc/gaslimit.go deleted file mode 100644 index 24afc685e8..0000000000 --- a/consensus/misc/gaslimit.go +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2021 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// The go-ethereum library is free software: you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// The go-ethereum library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with the go-ethereum library. If not, see . - -package misc - -import ( - "errors" - "fmt" - - "github.com/dominant-strategies/go-quai/params" -) - -// VerifyGaslimit verifies the header gas limit according increase/decrease -// in relation to the parent gas limit. -func VerifyGaslimit(parentGasLimit, headerGasLimit uint64) error { - // Verify that the gas limit remains within allowed bounds - diff := int64(parentGasLimit) - int64(headerGasLimit) - if diff < 0 { - diff *= -1 - } - limit := parentGasLimit / params.GasLimitBoundDivisor - if uint64(diff) >= limit { - return fmt.Errorf("invalid gas limit: have %d, want %d +-= %d", headerGasLimit, parentGasLimit, limit-1) - } - if headerGasLimit < params.MinGasLimit { - return errors.New("invalid gas limit below 5000") - } - return nil -} diff --git a/consensus/progpow/consensus.go b/consensus/progpow/consensus.go index edcc66de24..5327102d24 100644 --- a/consensus/progpow/consensus.go +++ b/consensus/progpow/consensus.go @@ -18,6 +18,7 @@ import ( "github.com/dominant-strategies/go-quai/log" "github.com/dominant-strategies/go-quai/params" "github.com/dominant-strategies/go-quai/trie" + "modernc.org/mathutil" ) // Progpow proof-of-work protocol constants. @@ -299,8 +300,10 @@ func (progpow *Progpow) verifyHeader(chain consensus.ChainHeaderReader, header, } // Verify the block's gas usage and verify the base fee. // Verify that the gas limit remains within allowed bounds - if err := misc.VerifyGaslimit(parent.GasLimit(), header.GasLimit()); err != nil { - return err + expectedGasLimit := core.CalcGasLimit(parent, progpow.config.GasCeil) + if expectedGasLimit != header.GasLimit() { + return fmt.Errorf("invalid gasLimit: have %d, want %d", + header.GasLimit(), expectedGasLimit) } // Verify the header is not malformed if header.BaseFee() == nil { @@ -330,48 +333,40 @@ func (progpow *Progpow) CalcDifficulty(chain consensus.ChainHeaderReader, parent log.Error("Cannot CalcDifficulty for", "context", nodeCtx) return nil } - // algorithm: - // diff = (parent_diff + - // (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99)) - // ) + 2^(periodCount - 2) - time := parent.Time() + ///// Algorithm: + ///// e = (DurationLimit - (parent.Time() - parentOfParent.Time())) * parent.Difficulty() + ///// k = Floor(BinaryLog(parent.Difficulty()))/(DurationLimit*2*DifficultyAdjustmentFactor*AdjustmentPeriod) + ///// Difficulty = Max(parent.Difficulty() + e * k, MinimumDifficulty) if parent.Hash() == chain.Config().GenesisHash { return parent.Difficulty() } - parentOfParent := chain.GetHeaderByHash(parent.ParentHash()) + if parentOfParent.Hash() == chain.Config().GenesisHash { + return parent.Difficulty() + } + time := parent.Time() bigTime := new(big.Int).SetUint64(time) bigParentTime := new(big.Int).SetUint64(parentOfParent.Time()) // holds intermediate values to make the algo easier to read & audit x := new(big.Int) - y := new(big.Int) - - // (2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) // duration_limit x.Sub(bigTime, bigParentTime) + x.Sub(progpow.config.DurationLimit, x) + x.Mul(x, parent.Difficulty()) + k, _ := mathutil.BinaryLog(new(big.Int).Set(parent.Difficulty()), 64) + x.Mul(x, big.NewInt(int64(k))) x.Div(x, progpow.config.DurationLimit) - if parent.UncleHash() == types.EmptyUncleHash { - x.Sub(big1, x) - } else { - x.Sub(big2, x) - } - // max((2 if len(parent_uncles) else 1) - (block_timestamp - parent_timestamp) // 9, -99) - if x.Cmp(bigMinus99) < 0 { - x.Set(bigMinus99) - } - // parent_diff + (parent_diff / 2048 * max((2 if len(parent.uncles) else 1) - ((timestamp - parent.timestamp) // 9), -99)) - y.Div(parent.Difficulty(), params.DifficultyBoundDivisor) - x.Mul(y, x) - x.Add(parent.Difficulty(), x) + x.Div(x, big.NewInt(params.DifficultyAdjustmentFactor)) + x.Div(x, params.DifficultyAdjustmentPeriod) + x.Add(x, parent.Difficulty()) // minimum difficulty can ever be (before exponential factor) if x.Cmp(params.MinimumDifficulty) < 0 { x.Set(params.MinimumDifficulty) } - return x } diff --git a/consensus/progpow/progpow.go b/consensus/progpow/progpow.go index 0a2b95008c..3b62db7043 100644 --- a/consensus/progpow/progpow.go +++ b/consensus/progpow/progpow.go @@ -157,6 +157,7 @@ type Config struct { CachesOnDisk int CachesLockMmap bool DurationLimit *big.Int + GasCeil uint64 // When set, notifications sent by the remote sealer will // be block header JSON objects instead of work package arrays. diff --git a/core/block_validator.go b/core/block_validator.go index 3226bc2e48..0c905f0313 100644 --- a/core/block_validator.go +++ b/core/block_validator.go @@ -144,25 +144,42 @@ func (v *BlockValidator) ValidateState(block *types.Block, statedb *state.StateD // CalcGasLimit computes the gas limit of the next block after parent. It aims // to keep the baseline gas close to the provided target, and increase it towards // the target if the baseline gas is lower. -func CalcGasLimit(parentGasLimit, desiredLimit uint64) uint64 { +func CalcGasLimit(parent *types.Header, gasCeil uint64) uint64 { + + parentGasLimit := parent.GasLimit() + delta := parentGasLimit/params.GasLimitBoundDivisor - 1 limit := parentGasLimit - if desiredLimit < params.MinGasLimit { + + var desiredLimit uint64 + percentGasUsed := parent.GasUsed() * 100 / parent.GasLimit() + if percentGasUsed > params.PercentGasUsedThreshold { + desiredLimit = CalcGasCeil(parent.NumberU64(), gasCeil) + if desiredLimit > gasCeil { + desiredLimit = gasCeil + } + if limit+delta > desiredLimit { + return desiredLimit + } else { + return limit + delta + } + } else { desiredLimit = params.MinGasLimit - } - // If we're outside our allowed gas range, we try to hone towards them - if limit < desiredLimit { - limit = parentGasLimit + delta - if limit > desiredLimit { - limit = desiredLimit + if limit-delta/2 < desiredLimit { + return desiredLimit + } else { + return limit - delta/2 } - return limit } - if limit > desiredLimit { - limit = parentGasLimit - delta - if limit < desiredLimit { - limit = desiredLimit - } +} + +func CalcGasCeil(blockNumber uint64, gasCeil uint64) uint64 { + if blockNumber < params.GasLimitStepOneBlockThreshold { + return gasCeil / 4 + } else if blockNumber < params.GasLimitStepTwoBlockThreshold { + return gasCeil / 2 + } else if blockNumber < params.GasLimitStepThreeBlockThreshold { + return gasCeil * 3 / 4 } - return limit + return gasCeil } diff --git a/core/core.go b/core/core.go index 597d8a4606..dbb9234a1b 100644 --- a/core/core.go +++ b/core/core.go @@ -34,7 +34,7 @@ const ( c_primeRetryThreshold = 1800 // Number of times a block is retry to be appended before eviction from append queue in Prime c_regionRetryThreshold = 1200 // Number of times a block is retry to be appended before eviction from append queue in Region c_zoneRetryThreshold = 600 // Number of times a block is retry to be appended before eviction from append queue in Zone - c_maxFutureBlocks = 15 // Number of blocks ahead of the current block to be put in the hashNumberList + c_maxFutureBlocks = 100 // Number of blocks ahead of the current block to be put in the hashNumberList c_appendQueueRetryPriorityThreshold = 5 // If retry counter for a block is less than this number, then its put in the special list that is tried first to be appended c_appendQueueRemoveThreshold = 10 // Number of blocks behind the block should be from the current header to be eligble for removal from the append queue ) @@ -359,11 +359,12 @@ func (c *Core) WriteBlock(block *types.Block) { } nodeCtx := common.NodeLocation.Context() if order == nodeCtx { - c.addToAppendQueue(block) parentHeader := c.GetHeader(block.ParentHash(), block.NumberU64()-1) if parentHeader != nil { + c.sl.WriteBlock(block) c.InsertChain([]*types.Block{block}) } + c.addToAppendQueue(block) // If a dom block comes in and we havent appended it yet } else if order < nodeCtx && c.GetHeaderByHash(block.Hash()) == nil { if c.sl.domClient != nil { @@ -395,8 +396,8 @@ func (c *Core) SubRelayPendingHeader(slPendingHeader types.PendingHeader, newEnt c.sl.SubRelayPendingHeader(slPendingHeader, newEntropy, location, subReorg) } -func (c *Core) UpdateDom(oldTerminus common.Hash, newTerminus common.Hash, newEntropy *big.Int, location common.Location) { - c.sl.UpdateDom(oldTerminus, newTerminus, newEntropy, location) +func (c *Core) UpdateDom(oldTerminus common.Hash, newTerminus common.Hash, pendingHeader *types.Header, location common.Location) { + c.sl.UpdateDom(oldTerminus, newTerminus, pendingHeader, location) } func (c *Core) NewGenesisPendigHeader(pendingHeader *types.Header) { diff --git a/core/slice.go b/core/slice.go index fdbc7eae59..fa33f05818 100644 --- a/core/slice.go +++ b/core/slice.go @@ -241,6 +241,9 @@ func (sl *Slice) Append(header *types.Header, domPendingHeader *types.Header, do time7 := common.PrettyDuration(time.Since(start)) + sl.phCacheMu.Lock() + defer sl.phCacheMu.Unlock() + var time8, time9 common.PrettyDuration var bestPh types.PendingHeader var exist bool @@ -255,7 +258,12 @@ func (sl *Slice) Append(header *types.Header, domPendingHeader *types.Header, do time8 = common.PrettyDuration(time.Since(start)) - subReorg = sl.miningStrategy(bestPh, block) + tempPendingHeader, err := sl.generateSlicePendingHeader(block, newTermini, domPendingHeader, domOrigin, false, false) + if err != nil { + return nil, false, err + } + + subReorg = sl.miningStrategy(bestPh, tempPendingHeader) if order < nodeCtx { // Store the inbound etxs for dom blocks that did not get picked and use @@ -279,8 +287,6 @@ func (sl *Slice) Append(header *types.Header, domPendingHeader *types.Header, do time9 = common.PrettyDuration(time.Since(start)) } - sl.phCacheMu.Lock() - defer sl.phCacheMu.Unlock() sl.updatePhCache(pendingHeaderWithTermini, true, nil, subReorg) var updateDom bool @@ -316,16 +322,18 @@ func (sl *Slice) Append(header *types.Header, domPendingHeader *types.Header, do log.Info("times during append:", "t0_1", time0_1, "t0_2", time0_2, "t1:", time1, "t2:", time2, "t3:", time3, "t4:", time4, "t5:", time5, "t6:", time6, "t7:", time7, "t8:", time8, "t9:", time9, "t10:", time10) log.Info("times during sub append:", "t6_1:", time6_1, "t6_2:", time6_2, "t6_3:", time6_3) log.Info("Appended new block", "number", block.Header().Number(), "hash", block.Hash(), - "uncles", len(block.Uncles()), "txs", len(block.Transactions()), "etxs", len(block.ExtTransactions()), "gas", block.GasUsed(), + "difficulty", block.Header().Difficulty(), + "uncles", len(block.Uncles()), "txs", len(block.Transactions()), "etxs", len(block.ExtTransactions()), "gas", block.GasUsed(), "gasLimit", block.GasLimit(), "root", block.Root(), "order", order, + "location", block.Header().Location(), "elapsed", common.PrettyDuration(time.Since(start))) if nodeCtx == common.ZONE_CTX { if updateDom { log.Info("Append updateDom", "oldTermini():", bestPh.Termini().DomTerminus(), "newTermini():", pendingHeaderWithTermini.Termini().DomTerminus(), "location:", common.NodeLocation) if sl.domClient != nil { - go sl.domClient.UpdateDom(context.Background(), bestPh.Termini().DomTerminus(), pendingHeaderWithTermini.Termini().DomTerminus(), pendingHeaderWithTermini.Header().ParentEntropy(), common.NodeLocation) + go sl.domClient.UpdateDom(context.Background(), bestPh.Termini().DomTerminus(), pendingHeaderWithTermini.Termini().DomTerminus(), pendingHeaderWithTermini.Header(), common.NodeLocation) } } return block.ExtTransactions(), subReorg, nil @@ -333,11 +341,11 @@ func (sl *Slice) Append(header *types.Header, domPendingHeader *types.Header, do return subPendingEtxs, subReorg, nil } } -func (sl *Slice) miningStrategy(bestPh types.PendingHeader, block *types.Block) bool { +func (sl *Slice) miningStrategy(bestPh types.PendingHeader, pendingHeader types.PendingHeader) bool { if bestPh.Header() == nil { // This is the case where we try to append the block before we have not initialized the bestPh return true } - subReorg := sl.poem(sl.engine.TotalLogS(block.Header()), bestPh.Header().ParentEntropy()) + subReorg := sl.poem(sl.engine.TotalLogPhS(pendingHeader.Header()), sl.engine.TotalLogPhS(bestPh.Header())) return subReorg } @@ -359,7 +367,7 @@ func (sl *Slice) relayPh(block *types.Block, pendingHeaderWithTermini types.Pend } else { log.Warn("Pending Header for Best ph key does not exist", "best ph key", sl.bestPhKey) } - } else if !domOrigin { + } else if !domOrigin && subReorg { for _, i := range sl.randomRelayArray() { if sl.subClients[i] != nil { sl.subClients[i].SubRelayPendingHeader(context.Background(), pendingHeaderWithTermini, pendingHeaderWithTermini.Header().ParentEntropy(), location, subReorg) @@ -370,7 +378,7 @@ func (sl *Slice) relayPh(block *types.Block, pendingHeaderWithTermini types.Pend // If a zone changes its best ph key on a dom block, it sends a signal to the // dom and we can relay that information to the coords, to build on the right dom header -func (sl *Slice) UpdateDom(oldTerminus common.Hash, newTerminus common.Hash, newEntropy *big.Int, location common.Location) { +func (sl *Slice) UpdateDom(oldTerminus common.Hash, newTerminus common.Hash, pendingHeader *types.Header, location common.Location) { nodeCtx := common.NodeLocation.Context() sl.phCacheMu.Lock() defer sl.phCacheMu.Unlock() @@ -384,18 +392,12 @@ func (sl *Slice) UpdateDom(oldTerminus common.Hash, newTerminus common.Hash, new log.Info("UpdateDom:", "oldTerminus:", oldTerminus, "newTerminus:", newTerminus, "oldDomTerminus:", oldDomTermini.DomTerminus(), "newDomTerminus:", newDomTermini.DomTerminus()) if nodeCtx == common.REGION_CTX && oldDomTermini.DomTerminus() == newDomTermini.DomTerminus() { // Can update - block := sl.hc.GetBlockByHash(newTerminus) + newPh := types.NewPendingHeader(pendingHeader, *newDomTermini) sl.bestPhKey = newTerminus - if block != nil { - pendingHeaderWithTermini, err := sl.generateSlicePendingHeader(block, *newDomTermini, types.EmptyHeader(), false, true, false) - if err != nil { - return - } - log.Info("pendingHeaderWithTermini:", "parent Hash:", pendingHeaderWithTermini.Header().ParentHash(), "Number", pendingHeaderWithTermini.Header().NumberArray()) - for _, i := range sl.randomRelayArray() { - if sl.subClients[i] != nil { - sl.subClients[i].SubRelayPendingHeader(context.Background(), pendingHeaderWithTermini, newEntropy, common.Location{}, true) - } + log.Info("newPh:", "parent Hash:", newPh.Header().ParentHash(), "Number", newPh.Header().NumberArray()) + for _, i := range sl.randomRelayArray() { + if sl.subClients[i] != nil { + sl.subClients[i].SubRelayPendingHeader(context.Background(), newPh, pendingHeader.ParentEntropy(common.ZONE_CTX), common.Location{}, true) } } return @@ -403,21 +405,15 @@ func (sl *Slice) UpdateDom(oldTerminus common.Hash, newTerminus common.Hash, new // need to update dom log.Info("Append need to updateDom", "oldDomTermini:", oldDomTermini, "newDomTermini:", newDomTermini, "location:", common.NodeLocation) if sl.domClient != nil { - go sl.domClient.UpdateDom(context.Background(), oldDomTermini.DomTerminus(), newDomTermini.DomTerminus(), newEntropy, location) + go sl.domClient.UpdateDom(context.Background(), oldDomTermini.DomTerminus(), newDomTermini.DomTerminus(), pendingHeader, location) } else { // Can update - block := sl.hc.GetBlockByHash(newTerminus) + newPh := types.NewPendingHeader(pendingHeader, *newDomTermini) sl.bestPhKey = newTerminus - if block != nil { - pendingHeaderWithTermini, err := sl.generateSlicePendingHeader(block, *newDomTermini, types.EmptyHeader(), false, true, false) - if err != nil { - return - } - log.Info("pendingHeaderWithTermini:", "parent Hash:", pendingHeaderWithTermini.Header().ParentHash(), "Number", pendingHeaderWithTermini.Header().NumberArray()) - for _, i := range sl.randomRelayArray() { - if sl.subClients[i] != nil { - go sl.subClients[i].SubRelayPendingHeader(context.Background(), pendingHeaderWithTermini, newEntropy, location, true) - } + log.Info("newPh:", "parent Hash:", newPh.Header().ParentHash(), "Number", newPh.Header().NumberArray()) + for _, i := range sl.randomRelayArray() { + if sl.subClients[i] != nil { + sl.subClients[i].SubRelayPendingHeader(context.Background(), newPh, pendingHeader.ParentEntropy(common.ZONE_CTX), common.Location{}, true) } } return @@ -498,6 +494,14 @@ func (sl *Slice) generateSlicePendingHeader(block *types.Block, newTermini types localPendingHeader = types.EmptyHeader() localPendingHeader.SetParentHash(block.Hash(), nodeCtx) localPendingHeader.SetNumber(big.NewInt(int64(block.NumberU64()) + 1)) + localPendingHeader.SetParentEntropy(sl.engine.TotalLogS(block.Header())) + if nodeCtx != common.PRIME_CTX { + if domOrigin { + localPendingHeader.SetParentDeltaS(big.NewInt(0), nodeCtx) + } else { + localPendingHeader.SetParentDeltaS(sl.engine.DeltaLogS(block.Header()), nodeCtx) + } + } manifestHash := sl.miner.worker.ComputeManifestHash(block.Header()) localPendingHeader.SetManifestHash(manifestHash) @@ -705,6 +709,10 @@ func (sl *Slice) computePendingHeader(localPendingHeaderWithTermini types.Pendin var newPh *types.Header if exists { + if domOrigin { + newPh = sl.combinePendingHeader(localPendingHeaderWithTermini.Header(), domPendingHeader, nodeCtx, true) + return types.NewPendingHeader(types.CopyHeader(newPh), localPendingHeaderWithTermini.Termini()) + } newPh = sl.combinePendingHeader(localPendingHeaderWithTermini.Header(), cachedPendingHeaderWithTermini.Header(), nodeCtx, true) return types.NewPendingHeader(types.CopyHeader(newPh), localPendingHeaderWithTermini.Termini()) } else { @@ -718,6 +726,8 @@ func (sl *Slice) computePendingHeader(localPendingHeaderWithTermini types.Pendin // updatePhCacheFromDom combines the recieved pending header with the pending header stored locally at a given terminus for specified context func (sl *Slice) updatePhCacheFromDom(pendingHeader types.PendingHeader, terminiIndex int, indices []int, newEntropy *big.Int, subReorg bool) error { + sl.phCacheMu.Lock() + defer sl.phCacheMu.Unlock() hash := pendingHeader.Termini().SubTerminiAtIndex(terminiIndex) localPendingHeader, exists := sl.readPhCache(hash) @@ -730,11 +740,9 @@ func (sl *Slice) updatePhCacheFromDom(pendingHeader types.PendingHeader, termini bestPh, exists := sl.readPhCache(sl.bestPhKey) nodeCtx := common.NodeLocation.Context() if nodeCtx == common.ZONE_CTX && exists && sl.bestPhKey != localPendingHeader.Termini().DomTerminus() && !sl.poem(newEntropy, bestPh.Header().ParentEntropy()) { - log.Info("subrelay rejected", "local dom terminus", localPendingHeader.Termini().DomTerminus(), "Number", localPendingHeader.Header().NumberArray(), "best ph key", sl.bestPhKey, "number", bestPh.Header().NumberArray(), "newentropy", newEntropy) - sl.phCacheMu.Lock() + log.Info("subrelay rejected", "local dom terminus", localPendingHeader.Termini().DomTerminus(), "Number", combinedPendingHeader.NumberArray(), "best ph key", sl.bestPhKey, "number", bestPh.Header().NumberArray(), "newentropy", newEntropy) sl.updatePhCache(types.NewPendingHeader(combinedPendingHeader, localPendingHeader.Termini()), false, nil, sl.poem(newEntropy, localPendingHeader.Header().ParentEntropy())) - sl.phCacheMu.Unlock() - go sl.domClient.UpdateDom(context.Background(), localPendingHeader.Termini().DomTerminus(), sl.bestPhKey, bestPh.Header().ParentEntropy(), common.NodeLocation) + go sl.domClient.UpdateDom(context.Background(), localPendingHeader.Termini().DomTerminus(), sl.bestPhKey, bestPh.Header(), common.NodeLocation) return nil } // Pick the head @@ -747,7 +755,7 @@ func (sl *Slice) updatePhCacheFromDom(pendingHeader types.PendingHeader, termini log.Error("Error setting current header", "err", err, "Hash", block.Hash()) return err } - log.Info("Choosing phHeader pickPhHead:", "NumberArray:", localPendingHeader.Header().NumberArray(), "Number:", localPendingHeader.Header().Number(), "ParentHash:", localPendingHeader.Header().ParentHash(), "Terminus:", localPendingHeader.Termini().DomTerminus()) + log.Info("Choosing phHeader pickPhHead:", "NumberArray:", combinedPendingHeader.NumberArray(), "Number:", combinedPendingHeader.Number(), "ParentHash:", combinedPendingHeader.ParentHash(), "Terminus:", localPendingHeader.Termini().DomTerminus()) sl.bestPhKey = localPendingHeader.Termini().DomTerminus() if block.Hash() != sl.hc.CurrentHeader().Hash() { sl.hc.chainHeadFeed.Send(ChainHeadEvent{block}) @@ -780,9 +788,7 @@ func (sl *Slice) updatePhCacheFromDom(pendingHeader types.PendingHeader, termini } } - sl.phCacheMu.Lock() sl.updatePhCache(types.NewPendingHeader(combinedPendingHeader, localPendingHeader.Termini()), false, nil, subReorg) - sl.phCacheMu.Unlock() return nil } @@ -806,7 +812,7 @@ func (sl *Slice) updatePhCache(pendingHeaderWithTermini types.PendingHeader, inS if !exists { return } - if !sl.poem(pendingHeaderWithTermini.Header().ParentEntropy(), bestPh.Header().ParentEntropy()) { + if !sl.miningStrategy(bestPh, pendingHeaderWithTermini) { return } } diff --git a/core/worker.go b/core/worker.go index d58a4fe0a1..b5f18e0c2b 100644 --- a/core/worker.go +++ b/core/worker.go @@ -881,12 +881,7 @@ func (w *worker) fillTransactions(interrupt *int32, env *environment, block *typ // into the given sealing block. The transaction selection and ordering strategy can // be customized with the plugin in the future. func (w *worker) adjustGasLimit(interrupt *int32, env *environment, parent *types.Block) { - percentGasUsed := parent.GasUsed() * 100 / parent.GasLimit() - if percentGasUsed > params.PercentGasUsedThreshold { - env.header.SetGasLimit(CalcGasLimit(parent.GasLimit(), w.config.GasCeil)) - } else { - env.header.SetGasLimit(CalcGasLimit(parent.GasLimit(), w.config.GasFloor)) - } + env.header.SetGasLimit(CalcGasLimit(parent.Header(), w.config.GasCeil)) } // ComputeManifestHash given a header computes the manifest hash for the header diff --git a/eth/api_backend.go b/eth/api_backend.go index 69a91fd6d1..0b51d952a1 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -472,8 +472,8 @@ func (b *QuaiAPIBackend) SubRelayPendingHeader(pendingHeader types.PendingHeader b.eth.core.SubRelayPendingHeader(pendingHeader, newEntropy, location, subReorg) } -func (b *QuaiAPIBackend) UpdateDom(oldTerminus common.Hash, newTerminus common.Hash, newEntropy *big.Int, location common.Location) { - b.eth.core.UpdateDom(oldTerminus, newTerminus, newEntropy, location) +func (b *QuaiAPIBackend) UpdateDom(oldTerminus common.Hash, newTerminus common.Hash, pendingHeader *types.Header, location common.Location) { + b.eth.core.UpdateDom(oldTerminus, newTerminus, pendingHeader, location) } func (b *QuaiAPIBackend) RequestDomToAppendOrFetch(hash common.Hash, order int) { diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 13afbbf112..d0e8b9133b 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -181,6 +181,7 @@ func CreateProgpowConsensusEngine(stack *node.Node, chainConfig *params.ChainCon PowMode: config.PowMode, NotifyFull: config.NotifyFull, DurationLimit: config.DurationLimit, + GasCeil: config.GasCeil, }, notify, noverify) engine.SetThreads(-1) // Disable CPU mining return engine @@ -201,6 +202,7 @@ func CreateBlake3ConsensusEngine(stack *node.Node, chainConfig *params.ChainConf PowMode: config.PowMode, NotifyFull: config.NotifyFull, DurationLimit: config.DurationLimit, + GasCeil: config.GasCeil, }, notify, noverify) engine.SetThreads(-1) // Disable CPU mining return engine diff --git a/internal/quaiapi/backend.go b/internal/quaiapi/backend.go index 58f56177bb..563c17a487 100644 --- a/internal/quaiapi/backend.go +++ b/internal/quaiapi/backend.go @@ -77,7 +77,7 @@ type Backend interface { InsertBlock(ctx context.Context, block *types.Block) (int, error) PendingBlock() *types.Block SubRelayPendingHeader(pendingHeader types.PendingHeader, newEntropy *big.Int, location common.Location, subReorg bool) - UpdateDom(oldTerminus common.Hash, newTerminus common.Hash, newEntropy *big.Int, location common.Location) + UpdateDom(oldTerminus common.Hash, newTerminus common.Hash, pendingHeader *types.Header, location common.Location) RequestDomToAppendOrFetch(hash common.Hash, order int) NewGenesisPendingHeader(pendingHeader *types.Header) GetPendingHeader() (*types.Header, error) diff --git a/internal/quaiapi/quai_api.go b/internal/quaiapi/quai_api.go index c1466ef801..26192e34d8 100644 --- a/internal/quaiapi/quai_api.go +++ b/internal/quaiapi/quai_api.go @@ -667,7 +667,7 @@ type DomUpdate struct { OldTerminus common.Hash NewTerminus common.Hash Location common.Location - NewEntropy *big.Int + Header *types.Header } func (s *PublicBlockChainQuaiAPI) UpdateDom(ctx context.Context, raw json.RawMessage) { @@ -677,7 +677,7 @@ func (s *PublicBlockChainQuaiAPI) UpdateDom(ctx context.Context, raw json.RawMes return } - s.b.UpdateDom(domUpdate.OldTerminus, domUpdate.NewTerminus, domUpdate.NewEntropy, domUpdate.Location) + s.b.UpdateDom(domUpdate.OldTerminus, domUpdate.NewTerminus, domUpdate.Header, domUpdate.Location) } type RequestDomToAppendOrFetchArgs struct { diff --git a/params/protocol_params.go b/params/protocol_params.go index 186d47c737..ce9f445170 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -23,10 +23,13 @@ import ( ) const ( - GasLimitBoundDivisor uint64 = 1024 // The bound divisor of the gas limit, used in update calculations. - PercentGasUsedThreshold uint64 = 95 // Percent Gas used threshold at which the gas limit adjusts - MinGasLimit uint64 = 5000000 // Minimum the gas limit may ever be. - GenesisGasLimit uint64 = 5000000 // Gas limit of the Genesis block. + GasLimitBoundDivisor uint64 = 1024 // The bound divisor of the gas limit, used in update calculations. + PercentGasUsedThreshold uint64 = 50 // Percent Gas used threshold at which the gas limit adjusts + GasLimitStepOneBlockThreshold uint64 = 150000 + GasLimitStepTwoBlockThreshold uint64 = 300000 + GasLimitStepThreeBlockThreshold uint64 = 450000 + MinGasLimit uint64 = 5000000 // Minimum the gas limit may ever be. + GenesisGasLimit uint64 = 5000000 // Gas limit of the Genesis block. MaximumExtraDataSize uint64 = 32 // Maximum size extra data may be after Genesis. ExpByteGas uint64 = 10 // Times ceil(log256(exponent)) for the EXP instruction. @@ -138,21 +141,24 @@ const ( ) var ( - ColosseumGasCeil uint64 = 160000000 - GardenGasCeil uint64 = 160000000 - OrchardGasCeil uint64 = 50000000 - LighthouseGasCeil uint64 = 160000000 - LocalGasCeil uint64 = 20000000 - DifficultyBoundDivisor = big.NewInt(2048) // The bound divisor of the difficulty, used in the update calculations. - ZoneMinDifficulty = big.NewInt(1000) // The minimum difficulty in a zone. Prime & regions should be multiples of this value - MinimumDifficulty = ZoneMinDifficulty // The minimum that the difficulty may ever be. - GenesisDifficulty = ZoneMinDifficulty // Difficulty of the Genesis block. - DurationLimit = big.NewInt(12) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not. - GardenDurationLimit = big.NewInt(7) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not. - OrchardDurationLimit = big.NewInt(12) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not. - LighthouseDurationLimit = big.NewInt(7) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not. - LocalDurationLimit = big.NewInt(2) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not. - TimeFactor = big.NewInt(7) - PrimeEntropyTarget = big.NewInt(441) // This is TimeFactor*TimeFactor*common.NumZonesInRegion*common.NumRegionsInPrime - RegionEntropyTarget = big.NewInt(21) // This is TimeFactor*common.NumZonesInRegion + GasCeil uint64 = 20000000 + ColosseumGasCeil uint64 = 110000000 + GardenGasCeil uint64 = 160000000 + OrchardGasCeil uint64 = 50000000 + LighthouseGasCeil uint64 = 160000000 + LocalGasCeil uint64 = 20000000 + DifficultyBoundDivisor = big.NewInt(2048) // The bound divisor of the difficulty, used in the update calculations. + ZoneMinDifficulty = big.NewInt(1000) // The minimum difficulty in a zone. Prime & regions should be multiples of this value + MinimumDifficulty = ZoneMinDifficulty // The minimum that the difficulty may ever be. + GenesisDifficulty = ZoneMinDifficulty // Difficulty of the Genesis block. + DurationLimit = big.NewInt(12) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not. + GardenDurationLimit = big.NewInt(7) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not. + OrchardDurationLimit = big.NewInt(12) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not. + LighthouseDurationLimit = big.NewInt(7) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not. + LocalDurationLimit = big.NewInt(2) // The decision boundary on the blocktime duration used to determine whether difficulty should go up or not. + TimeFactor = big.NewInt(7) + PrimeEntropyTarget = big.NewInt(441) // This is TimeFactor*TimeFactor*common.NumZonesInRegion*common.NumRegionsInPrime + RegionEntropyTarget = big.NewInt(21) // This is TimeFactor*common.NumZonesInRegion + DifficultyAdjustmentPeriod = big.NewInt(360) // This is the number of blocks over which the average has to be taken + DifficultyAdjustmentFactor int64 = 40 // This is the factor that divides the log of the change in the difficulty ) diff --git a/quaiclient/quaiclient.go b/quaiclient/quaiclient.go index 40d9850c29..8f66a65891 100644 --- a/quaiclient/quaiclient.go +++ b/quaiclient/quaiclient.go @@ -122,11 +122,11 @@ func (ec *Client) SubRelayPendingHeader(ctx context.Context, pendingHeader types ec.c.CallContext(ctx, nil, "quai_subRelayPendingHeader", data) } -func (ec *Client) UpdateDom(ctx context.Context, oldTerminus common.Hash, newTerminus common.Hash, newEntropy *big.Int, location common.Location) { +func (ec *Client) UpdateDom(ctx context.Context, oldTerminus common.Hash, newTerminus common.Hash, pendingHeader *types.Header, location common.Location) { data := map[string]interface{}{"OldTerminus": oldTerminus} data["NewTerminus"] = newTerminus data["Location"] = location - data["NewEntropy"] = newEntropy + data["Header"] = pendingHeader.RPCMarshalHeader() ec.c.CallContext(ctx, nil, "quai_updateDom", data) }