diff --git a/consensus/model/difficulty_manager.go b/consensus/model/difficulty_manager.go new file mode 100644 index 00000000..98218a1d --- /dev/null +++ b/consensus/model/difficulty_manager.go @@ -0,0 +1,17 @@ +package model + +import ( + "math/big" + "time" + + "github.com/Qitmeer/qng/core/types/pow" +) + +// DifficultyManager provides a method to resolve the +// difficulty value of a block +type DifficultyManager interface { + CalcNextRequiredDifficulty(timestamp time.Time, powType pow.PowType) (uint32, error) + RequiredDifficulty(block Block, newBlockTime time.Time, powInstance pow.IPow) (uint32, error) + CalcEasiestDifficulty(bits uint32, duration time.Duration, powInstance pow.IPow) uint32 + GetCurrentPowDiff(ib Block, powType pow.PowType) *big.Int +} diff --git a/core/blockchain/blockchain.go b/core/blockchain/blockchain.go index ae5d7b22..65a53598 100644 --- a/core/blockchain/blockchain.go +++ b/core/blockchain/blockchain.go @@ -22,6 +22,7 @@ import ( "github.com/Qitmeer/qng/core/state" "github.com/Qitmeer/qng/core/types" "github.com/Qitmeer/qng/core/types/pow" + "github.com/Qitmeer/qng/core/types/pow/difficultymanager" "github.com/Qitmeer/qng/database/common" "github.com/Qitmeer/qng/engine/txscript" l "github.com/Qitmeer/qng/log" @@ -136,7 +137,8 @@ type BlockChain struct { wg sync.WaitGroup quit chan struct{} - meerChain *meer.MeerChain + meerChain *meer.MeerChain + difficultyManager model.DifficultyManager } func (b *BlockChain) Init() error { @@ -1070,6 +1072,7 @@ func New(consensus model.Consensus) (*BlockChain, error) { } b.meerChain = mchain b.Services().RegisterService(b.meerChain) + b.difficultyManager = difficultymanager.NewDiffManager(b.Consensus().BlockChain(), par) return &b, nil } diff --git a/core/blockchain/difficulty.go b/core/blockchain/difficulty.go new file mode 100644 index 00000000..d89ffd2d --- /dev/null +++ b/core/blockchain/difficulty.go @@ -0,0 +1,48 @@ +// Copyright (c) 2017-2018 The qitmeer developers +// Copyright (c) 2013-2016 The btcsuite developers +// Copyright (c) 2015-2018 The Decred developers +// Use of this source code is governed by an ISC +// license that can be found in the LICENSE file. + +package blockchain + +import ( + "math/big" + "time" + + "github.com/Qitmeer/qng/consensus/model" + "github.com/Qitmeer/qng/core/types/pow" +) + +// CalcEasiestDifficulty calculates the easiest possible difficulty that a block +// can have given starting difficulty bits and a duration. It is mainly used to +// verify that claimed proof of work by a block is sane as compared to a +// known good checkpoint. +func (m *BlockChain) calcEasiestDifficulty(bits uint32, duration time.Duration, powInstance pow.IPow) uint32 { + return m.difficultyManager.CalcEasiestDifficulty(bits, duration, powInstance) +} + +func (m *BlockChain) calcNextRequiredDifficulty(block model.Block, newBlockTime time.Time, powInstance pow.IPow) (uint32, error) { + return m.difficultyManager.RequiredDifficulty(block, newBlockTime, powInstance) +} + +// CalcNextRequiredDifficulty calculates the required difficulty for the block +// after the end of the current best chain based on the difficulty retarget +// rules. +// +// This function is safe for concurrent access. +func (b *BlockChain) CalcNextRequiredDifficulty(timestamp time.Time, powType pow.PowType) (uint32, error) { + b.ChainRLock() + block := b.GetMainChainTip() + instance := pow.GetInstance(powType, 0, []byte{}) + instance.SetParams(b.params.PowConfig) + instance.SetMainHeight(pow.MainHeight(block.GetHeight() + 1)) + difficulty, err := b.difficultyManager.RequiredDifficulty(block, timestamp, instance) + b.ChainRUnlock() + return difficulty, err +} + +// find block node by pow type +func (b *BlockChain) GetCurrentPowDiff(ib model.Block, powType pow.PowType) *big.Int { + return b.GetCurrentPowDiff(ib, powType) +} diff --git a/core/blockchain/process.go b/core/blockchain/process.go index 84f4a1ff..efce5d44 100644 --- a/core/blockchain/process.go +++ b/core/blockchain/process.go @@ -16,7 +16,6 @@ import ( "github.com/Qitmeer/qng/core/state" "github.com/Qitmeer/qng/core/types" "github.com/Qitmeer/qng/core/types/pow" - "github.com/Qitmeer/qng/core/types/pow/difficultymanager" "github.com/Qitmeer/qng/engine/txscript" l "github.com/Qitmeer/qng/log" "github.com/Qitmeer/qng/meerdag" @@ -155,7 +154,7 @@ func (b *BlockChain) preProcessBlock(block *types.SerializedBlock, flags Behavio // expected based on elapsed time since the last checkpoint and // maximum adjustment allowed by the retarget rules. duration := blockHeader.Timestamp.Sub(checkpointTime) - requiredTarget := pow.CompactToBig(difficultymanager.NewDiffManager(b.consensus.BlockChain(), b.params).CalcEasiestDifficulty( + requiredTarget := pow.CompactToBig(b.calcEasiestDifficulty( checkpointNode.Difficulty, duration, block.Block().Header.Pow)) currentTarget := pow.CompactToBig(blockHeader.Difficulty) if !block.Block().Header.Pow.CompareDiff(currentTarget, requiredTarget) { diff --git a/core/blockchain/validate.go b/core/blockchain/validate.go index b8588b20..50c6eb64 100644 --- a/core/blockchain/validate.go +++ b/core/blockchain/validate.go @@ -25,7 +25,6 @@ import ( "github.com/Qitmeer/qng/core/state" "github.com/Qitmeer/qng/core/types" "github.com/Qitmeer/qng/core/types/pow" - "github.com/Qitmeer/qng/core/types/pow/difficultymanager" "github.com/Qitmeer/qng/engine/txscript" "github.com/Qitmeer/qng/meerdag" "github.com/Qitmeer/qng/params" @@ -761,7 +760,7 @@ func (b *BlockChain) checkBlockHeaderContext(block *types.SerializedBlock, prevN // the calculated difficulty based on the previous block and // difficulty retarget rules. - expDiff, err := difficultymanager.NewDiffManager(b.consensus.BlockChain(), b.params).RequiredDifficulty(prevNode, + expDiff, err := b.calcNextRequiredDifficulty(prevNode, header.Timestamp, instance) if err != nil { return err diff --git a/core/types/pow/difficultymanager/interface_difficultymanager.go b/core/types/pow/difficultymanager/difficultymanager.go similarity index 53% rename from core/types/pow/difficultymanager/interface_difficultymanager.go rename to core/types/pow/difficultymanager/difficultymanager.go index 05889613..0280b8f2 100644 --- a/core/types/pow/difficultymanager/interface_difficultymanager.go +++ b/core/types/pow/difficultymanager/difficultymanager.go @@ -1,25 +1,12 @@ package difficultymanager import ( - "math/big" - "time" - "github.com/Qitmeer/qng/consensus/model" "github.com/Qitmeer/qng/core/types" - "github.com/Qitmeer/qng/core/types/pow" "github.com/Qitmeer/qng/params" ) -// DifficultyManager provides a method to resolve the -// difficulty value of a block -type DifficultyManager interface { - CalcNextRequiredDifficulty(timestamp time.Time, powType pow.PowType) (uint32, error) - RequiredDifficulty(block model.Block, newBlockTime time.Time, powInstance pow.IPow) (uint32, error) - CalcEasiestDifficulty(bits uint32, duration time.Duration, powInstance pow.IPow) uint32 - GetCurrentPowDiff(ib model.Block, powType pow.PowType) *big.Int -} - -func NewDiffManager(b model.BlockChain, cfg *params.Params) DifficultyManager { +func NewDiffManager(b model.BlockChain, cfg *params.Params) model.DifficultyManager { switch cfg.PowConfig.DifficultyMode { case types.DIFFICULTY_MODE_KASPAD: return &kaspadDiff{ diff --git a/node/api.go b/node/api.go index aa889af8..9a25e58d 100644 --- a/node/api.go +++ b/node/api.go @@ -18,7 +18,6 @@ import ( "github.com/Qitmeer/qng/core/json" "github.com/Qitmeer/qng/core/protocol" "github.com/Qitmeer/qng/core/types/pow" - "github.com/Qitmeer/qng/core/types/pow/difficultymanager" "github.com/Qitmeer/qng/meerdag" "github.com/Qitmeer/qng/meerevm/eth" "github.com/Qitmeer/qng/params" @@ -60,7 +59,7 @@ func NewPublicBlockChainAPI(node *QitmeerFull) *PublicBlockChainAPI { func (api *PublicBlockChainAPI) GetNodeInfo() (interface{}, error) { best := api.node.GetBlockChain().BestSnapshot() node := api.node.GetBlockChain().BlockDAG().GetBlock(&best.Hash) - powNodes := difficultymanager.NewDiffManager(api.node.GetBlockChain().Consensus().BlockChain(), api.node.GetBlockChain().ChainParams()).GetCurrentPowDiff(node, pow.MEERXKECCAKV1) + powNodes := api.node.GetBlockChain().GetCurrentPowDiff(node, pow.MEERXKECCAKV1) ret := &json.InfoNodeResult{ ID: api.node.GetPeerServer().PeerID().String(), Version: int32(1000000*version.Major + 10000*version.Minor + 100*version.Patch), diff --git a/services/mining/newblocktemplate.go b/services/mining/newblocktemplate.go index ca7d94f8..a83804b0 100644 --- a/services/mining/newblocktemplate.go +++ b/services/mining/newblocktemplate.go @@ -13,7 +13,6 @@ import ( s "github.com/Qitmeer/qng/core/serialization" "github.com/Qitmeer/qng/core/types" "github.com/Qitmeer/qng/core/types/pow" - "github.com/Qitmeer/qng/core/types/pow/difficultymanager" "github.com/Qitmeer/qng/engine/txscript" "github.com/Qitmeer/qng/log" "github.com/Qitmeer/qng/meerdag" @@ -506,7 +505,7 @@ mempool: ts := MedianAdjustedTime(bc, timeSource) // - reqCompactDifficulty, err := difficultymanager.NewDiffManager(bc.Consensus().BlockChain(), bc.ChainParams()).CalcNextRequiredDifficulty(ts, powType) + reqCompactDifficulty, err := bc.CalcNextRequiredDifficulty(ts, powType) if err != nil { return nil, miningRuleError(ErrGettingDifficulty, err.Error()) } @@ -599,7 +598,7 @@ func UpdateBlockTime(msgBlock *types.Block, chain *blockchain.BlockChain, timeSo // If running on a network that requires recalculating the difficulty, // do so now. if activeNetParams.ReduceMinDifficulty { - difficulty, err := difficultymanager.NewDiffManager(chain.Consensus().BlockChain(), chain.ChainParams()).CalcNextRequiredDifficulty( + difficulty, err := chain.CalcNextRequiredDifficulty( newTimestamp, msgBlock.Header.Pow.GetPowType()) if err != nil { return miningRuleError(ErrGettingDifficulty, err.Error())