mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-11 23:44:27 +00:00
Merge pull request #58 from hash-laboratories-au/XIN-125-happy-path-fix
Xin 125 happy path fix
This commit is contained in:
commit
0ab7bfbcbd
7 changed files with 208 additions and 39 deletions
|
|
@ -153,7 +153,7 @@ func (x *XDPoS) Author(header *types.Header) (common.Address, error) {
|
||||||
func (x *XDPoS) VerifyHeader(chain consensus.ChainReader, header *types.Header, fullVerify bool) error {
|
func (x *XDPoS) VerifyHeader(chain consensus.ChainReader, header *types.Header, fullVerify bool) error {
|
||||||
switch x.config.BlockConsensusVersion(header.Number) {
|
switch x.config.BlockConsensusVersion(header.Number) {
|
||||||
case params.ConsensusEngineVersion2:
|
case params.ConsensusEngineVersion2:
|
||||||
return nil
|
return x.EngineV2.VerifyHeader(chain, header, fullVerify)
|
||||||
default: // Default "v1"
|
default: // Default "v1"
|
||||||
return x.EngineV1.VerifyHeader(chain, header, fullVerify)
|
return x.EngineV1.VerifyHeader(chain, header, fullVerify)
|
||||||
}
|
}
|
||||||
|
|
@ -180,10 +180,10 @@ func (x *XDPoS) VerifyHeaders(chain consensus.ChainReader, headers []*types.Head
|
||||||
}
|
}
|
||||||
|
|
||||||
if v1headers != nil {
|
if v1headers != nil {
|
||||||
x.EngineV1.VerifyHeaders(chain, headers, fullVerifies, abort, results)
|
x.EngineV1.VerifyHeaders(chain, v1headers, fullVerifies, abort, results)
|
||||||
}
|
}
|
||||||
if v2headers != nil {
|
if v2headers != nil {
|
||||||
x.EngineV2.VerifyHeaders(chain, headers, fullVerifies, abort, results)
|
x.EngineV2.VerifyHeaders(chain, v2headers, fullVerifies, abort, results)
|
||||||
}
|
}
|
||||||
|
|
||||||
return abort, results
|
return abort, results
|
||||||
|
|
@ -314,11 +314,15 @@ func (x *XDPoS) GetMasternodesByNumber(chain consensus.ChainReader, blockNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *XDPoS) YourTurn(chain consensus.ChainReader, parent *types.Header, signer common.Address) (bool, error) {
|
func (x *XDPoS) YourTurn(chain consensus.ChainReader, parent *types.Header, signer common.Address) (bool, error) {
|
||||||
if x.config.V2.SwitchBlock != nil && parent.Number.Cmp(x.config.V2.SwitchBlock) == 0 {
|
if x.config.V2.SwitchBlock != nil && parent.Number.Cmp(x.config.V2.SwitchBlock) != -1 {
|
||||||
err := x.initialV2(chain, parent)
|
if parent.Number.Cmp(x.config.V2.SwitchBlock) == 0 {
|
||||||
if err != nil {
|
err := x.initialV2FromLastV1(chain, parent)
|
||||||
log.Error("[YourTurn] Error when initialise v2", "Error", err, "ParentBlock", parent)
|
if err != nil {
|
||||||
return false, err
|
log.Error("[YourTurn] Error while initilising first v2 block from the last v1 block", "ParentBlockHash", parent.Hash(), "Error", err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
} else if parent.Number.Cmp(x.config.V2.SwitchBlock) == 1 { // TODO: XIN-147
|
||||||
|
log.Info("[YourTurn] Initilising v2 after sync or restarted", "currentBlockNum", chain.CurrentHeader().Number, "currentBlockHash", chain.CurrentHeader().Hash())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch x.config.BlockConsensusVersion(big.NewInt(parent.Number.Int64() + 1)) {
|
switch x.config.BlockConsensusVersion(big.NewInt(parent.Number.Int64() + 1)) {
|
||||||
|
|
@ -481,12 +485,15 @@ func (x *XDPoS) GetCachedSigningTxs(hash common.Hash) (interface{}, bool) {
|
||||||
return x.signingTxsCache.Get(hash)
|
return x.signingTxsCache.Get(hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
//V2
|
// V2 specific helper function to initilise consensus engine variables
|
||||||
func (x *XDPoS) initialV2(chain consensus.ChainReader, header *types.Header) error {
|
func (x *XDPoS) initialV2FromLastV1(chain consensus.ChainReader, header *types.Header) error {
|
||||||
checkpointBlockNumber := header.Number.Uint64() - header.Number.Uint64()%x.config.Epoch
|
checkpointBlockNumber := header.Number.Uint64() - header.Number.Uint64()%x.config.Epoch
|
||||||
checkpointHeader := chain.GetHeaderByNumber(checkpointBlockNumber)
|
checkpointHeader := chain.GetHeaderByNumber(checkpointBlockNumber)
|
||||||
masternodes := x.EngineV1.GetMasternodesFromCheckpointHeader(checkpointHeader)
|
masternodes := x.EngineV1.GetMasternodesFromCheckpointHeader(checkpointHeader)
|
||||||
x.EngineV2.Initial(chain, header, masternodes)
|
err := x.EngineV2.Initial(chain, header, masternodes)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -148,7 +148,7 @@ func (x *XDPoS_v1) verifyHeaderWithCache(chain consensus.ChainReader, header *ty
|
||||||
// a batch of new headers.
|
// a batch of new headers.
|
||||||
func (x *XDPoS_v1) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error {
|
func (x *XDPoS_v1) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error {
|
||||||
// If we're running a engine faking, accept any block as valid
|
// If we're running a engine faking, accept any block as valid
|
||||||
if x.config.SkipValidation {
|
if x.config.SkipV1Validation {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if common.IsTestnet {
|
if common.IsTestnet {
|
||||||
|
|
@ -929,7 +929,7 @@ func (x *XDPoS_v1) CalcDifficulty(chain consensus.ChainReader, time uint64, pare
|
||||||
|
|
||||||
func (x *XDPoS_v1) calcDifficulty(chain consensus.ChainReader, parent *types.Header, signer common.Address) *big.Int {
|
func (x *XDPoS_v1) calcDifficulty(chain consensus.ChainReader, parent *types.Header, signer common.Address) *big.Int {
|
||||||
// If we're running a engine faking, skip calculation
|
// If we're running a engine faking, skip calculation
|
||||||
if x.config.SkipValidation {
|
if x.config.SkipV1Validation {
|
||||||
return big.NewInt(1)
|
return big.NewInt(1)
|
||||||
}
|
}
|
||||||
len, preIndex, curIndex, _, err := x.yourTurn(chain, parent, signer)
|
len, preIndex, curIndex, _, err := x.yourTurn(chain, parent, signer)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package engine_v2
|
package engine_v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
@ -16,6 +17,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/consensus"
|
"github.com/XinFinOrg/XDPoSChain/consensus"
|
||||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
|
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
|
||||||
"github.com/XinFinOrg/XDPoSChain/consensus/clique"
|
"github.com/XinFinOrg/XDPoSChain/consensus/clique"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/consensus/misc"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||||
|
|
@ -29,9 +31,10 @@ type XDPoS_v2 struct {
|
||||||
config *params.XDPoSConfig // Consensus engine configuration parameters
|
config *params.XDPoSConfig // Consensus engine configuration parameters
|
||||||
db ethdb.Database // Database to store and retrieve snapshot checkpoints
|
db ethdb.Database // Database to store and retrieve snapshot checkpoints
|
||||||
|
|
||||||
snapshots *lru.ARCCache // Snapshots for gap block
|
snapshots *lru.ARCCache // Snapshots for gap block
|
||||||
signatures *lru.ARCCache // Signatures of recent blocks to speed up mining
|
signatures *lru.ARCCache // Signatures of recent blocks to speed up mining
|
||||||
epochSwitches *lru.ARCCache // infos of epoch: master nodes, epoch switch block info, parent of that info
|
epochSwitches *lru.ARCCache // infos of epoch: master nodes, epoch switch block info, parent of that info
|
||||||
|
verifiedHeaders *lru.ARCCache
|
||||||
|
|
||||||
signer common.Address // Ethereum address of the signing key
|
signer common.Address // Ethereum address of the signing key
|
||||||
signFn clique.SignerFn // Signer function to authorize hashes with
|
signFn clique.SignerFn // Signer function to authorize hashes with
|
||||||
|
|
@ -66,6 +69,7 @@ func New(config *params.XDPoSConfig, db ethdb.Database, waitPeriodCh chan int) *
|
||||||
snapshots, _ := lru.NewARC(utils.InmemorySnapshots)
|
snapshots, _ := lru.NewARC(utils.InmemorySnapshots)
|
||||||
signatures, _ := lru.NewARC(utils.InmemorySnapshots)
|
signatures, _ := lru.NewARC(utils.InmemorySnapshots)
|
||||||
epochSwitches, _ := lru.NewARC(int(utils.InmemoryEpochs))
|
epochSwitches, _ := lru.NewARC(int(utils.InmemoryEpochs))
|
||||||
|
verifiedHeaders, _ := lru.NewARC(utils.InmemorySnapshots)
|
||||||
|
|
||||||
votePool := utils.NewPool(config.V2.CertThreshold)
|
votePool := utils.NewPool(config.V2.CertThreshold)
|
||||||
engine := &XDPoS_v2{
|
engine := &XDPoS_v2{
|
||||||
|
|
@ -73,11 +77,12 @@ func New(config *params.XDPoSConfig, db ethdb.Database, waitPeriodCh chan int) *
|
||||||
db: db,
|
db: db,
|
||||||
signatures: signatures,
|
signatures: signatures,
|
||||||
|
|
||||||
snapshots: snapshots,
|
verifiedHeaders: verifiedHeaders,
|
||||||
epochSwitches: epochSwitches,
|
snapshots: snapshots,
|
||||||
timeoutWorker: timer,
|
epochSwitches: epochSwitches,
|
||||||
BroadcastCh: make(chan interface{}),
|
timeoutWorker: timer,
|
||||||
waitPeriodCh: waitPeriodCh,
|
BroadcastCh: make(chan interface{}),
|
||||||
|
waitPeriodCh: waitPeriodCh,
|
||||||
|
|
||||||
timeoutPool: timeoutPool,
|
timeoutPool: timeoutPool,
|
||||||
votePool: votePool,
|
votePool: votePool,
|
||||||
|
|
@ -119,8 +124,8 @@ func (x *XDPoS_v2) SignHash(header *types.Header) (hash common.Hash) {
|
||||||
func (x *XDPoS_v2) Initial(chain consensus.ChainReader, header *types.Header, masternodes []common.Address) error {
|
func (x *XDPoS_v2) Initial(chain consensus.ChainReader, header *types.Header, masternodes []common.Address) error {
|
||||||
log.Info("[Initial] initial v2 related parameters")
|
log.Info("[Initial] initial v2 related parameters")
|
||||||
|
|
||||||
if x.highestQuorumCert.ProposedBlockInfo.Round != 0 { //already initialized
|
if x.highestQuorumCert.ProposedBlockInfo.Hash != (common.Hash{}) { // already initialized
|
||||||
log.Warn("[Initial] Already initialized")
|
log.Error("[Initial] Already initialized", "blockNum", header.Number, "Hash", header.Hash())
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -128,7 +133,7 @@ func (x *XDPoS_v2) Initial(chain consensus.ChainReader, header *types.Header, ma
|
||||||
defer x.lock.Unlock()
|
defer x.lock.Unlock()
|
||||||
// Check header if it is the first consensus v2 block, if so, assign initial values to current round and highestQC
|
// Check header if it is the first consensus v2 block, if so, assign initial values to current round and highestQC
|
||||||
|
|
||||||
log.Info("[Initial] highest QC for consensus v2 first block", "Block Num", header.Number.String(), "BlockHash", header.Hash())
|
log.Info("[Initial] highest QC for consensus v2 first block", "BlockNum", header.Number.String(), "BlockHash", header.Hash())
|
||||||
// Generate new parent blockInfo and put it into QC
|
// Generate new parent blockInfo and put it into QC
|
||||||
blockInfo := &utils.BlockInfo{
|
blockInfo := &utils.BlockInfo{
|
||||||
Hash: header.Hash(),
|
Hash: header.Hash(),
|
||||||
|
|
@ -148,16 +153,22 @@ func (x *XDPoS_v2) Initial(chain consensus.ChainReader, header *types.Header, ma
|
||||||
|
|
||||||
snap := newSnapshot(lastGapNum, lastGapHeader.Hash(), x.currentRound, x.highestQuorumCert, masternodes)
|
snap := newSnapshot(lastGapNum, lastGapHeader.Hash(), x.currentRound, x.highestQuorumCert, masternodes)
|
||||||
x.snapshots.Add(snap.Hash, snap)
|
x.snapshots.Add(snap.Hash, snap)
|
||||||
storeSnapshot(snap, x.db)
|
err := storeSnapshot(snap, x.db)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("[Initial] Error while storo snapshot", "error", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Initial timeout
|
// Initial timeout
|
||||||
log.Info("[Initial] miner wait period", "period", x.config.WaitPeriod)
|
log.Info("[Initial] miner wait period", "period", x.config.WaitPeriod)
|
||||||
|
|
||||||
// avoid deadlock
|
// avoid deadlock
|
||||||
go func() {
|
go func() {
|
||||||
x.waitPeriodCh <- x.config.V2.WaitPeriod
|
x.waitPeriodCh <- x.config.V2.WaitPeriod
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
// Kick-off the countdown timer
|
||||||
|
x.timeoutWorker.Reset()
|
||||||
|
|
||||||
log.Info("[Initial] finish initialisation")
|
log.Info("[Initial] finish initialisation")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -430,7 +441,11 @@ func (x *XDPoS_v2) IsAuthorisedAddress(chain consensus.ChainReader, header *type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Warn("Not authorised address", "Address", address, "MN", masterNodes, "Hash", header.Hash())
|
log.Warn("Not authorised address", "Address", address.Hex(), "Hash", header.Hash())
|
||||||
|
for index, mn := range masterNodes {
|
||||||
|
log.Warn("Master node list item", "mn", mn.Hex(), "index", index)
|
||||||
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -483,7 +498,11 @@ func (x *XDPoS_v2) UpdateMasternodes(chain consensus.ChainReader, header *types.
|
||||||
snap := newSnapshot(number, header.Hash(), x.currentRound, x.highestQuorumCert, masterNodes)
|
snap := newSnapshot(number, header.Hash(), x.currentRound, x.highestQuorumCert, masterNodes)
|
||||||
x.lock.RUnlock()
|
x.lock.RUnlock()
|
||||||
|
|
||||||
storeSnapshot(snap, x.db)
|
err := storeSnapshot(snap, x.db)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("[UpdateMasternodes] Error while store snashot", "hash", header.Hash(), "currentRound", x.currentRound, "error", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
x.snapshots.Add(snap.Hash, snap)
|
x.snapshots.Add(snap.Hash, snap)
|
||||||
|
|
||||||
nm := []string{}
|
nm := []string{}
|
||||||
|
|
@ -496,22 +515,124 @@ func (x *XDPoS_v2) UpdateMasternodes(chain consensus.ChainReader, header *types.
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *XDPoS_v2) VerifyHeader(chain consensus.ChainReader, header *types.Header, fullVerify bool) error {
|
func (x *XDPoS_v2) VerifyHeader(chain consensus.ChainReader, header *types.Header, fullVerify bool) error {
|
||||||
return nil
|
err := x.verifyHeader(chain, header, nil, fullVerify)
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("[VerifyHeader] Fail to verify header", "fullVerify", fullVerify, "blockNum", header.Number, "blockHash", header.Hash(), "error", err)
|
||||||
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Yet to be implemented XIN-135
|
// Verify a list of headers
|
||||||
func (x *XDPoS_v2) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, fullVerifies []bool, abort <-chan struct{}, results chan<- error) {
|
func (x *XDPoS_v2) VerifyHeaders(chain consensus.ChainReader, headers []*types.Header, fullVerifies []bool, abort <-chan struct{}, results chan<- error) {
|
||||||
go func() {
|
go func() {
|
||||||
for range headers {
|
for i, header := range headers {
|
||||||
|
err := x.verifyHeader(chain, header, headers[:i], fullVerifies[i])
|
||||||
|
log.Warn("[VerifyHeaders] Fail to verify header", "fullVerify", fullVerifies[i], "blockNum", header.Number, "blockHash", header.Hash(), "error", err)
|
||||||
select {
|
select {
|
||||||
case <-abort:
|
case <-abort:
|
||||||
return
|
return
|
||||||
case results <- nil:
|
case results <- err:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Verify individual header
|
||||||
|
func (x *XDPoS_v2) verifyHeader(chain consensus.ChainReader, header *types.Header, parents []*types.Header, fullVerify bool) error {
|
||||||
|
// If we're running a engine faking, accept any block as valid
|
||||||
|
if x.config.V2.SkipV2Validation {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
_, check := x.verifiedHeaders.Get(header.Hash())
|
||||||
|
if check {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if header.Number == nil {
|
||||||
|
return utils.ErrUnknownBlock
|
||||||
|
}
|
||||||
|
|
||||||
|
if fullVerify {
|
||||||
|
if len(header.Validator) == 0 {
|
||||||
|
return consensus.ErrNoValidatorSignature
|
||||||
|
}
|
||||||
|
// Don't waste time checking blocks from the future
|
||||||
|
if header.Time.Int64() > time.Now().Unix() {
|
||||||
|
return consensus.ErrFutureBlock
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify this is truely a v2 block first
|
||||||
|
var decodedExtraField utils.ExtraFields_v2
|
||||||
|
err := utils.DecodeBytesExtraFields(header.Extra, &decodedExtraField)
|
||||||
|
if err != nil {
|
||||||
|
return utils.ErrInvalidV2Extra
|
||||||
|
}
|
||||||
|
quorumCert := decodedExtraField.QuorumCert
|
||||||
|
if quorumCert == nil || quorumCert.Signatures == nil || len(quorumCert.Signatures) == 0 {
|
||||||
|
return utils.ErrInvalidQC
|
||||||
|
}
|
||||||
|
|
||||||
|
if quorumCert.ProposedBlockInfo.Hash == (common.Hash{}) {
|
||||||
|
return utils.ErrEmptyBlockInfoHash
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nonces must be 0x00..0 or 0xff..f, zeroes enforced on checkpoints
|
||||||
|
if !bytes.Equal(header.Nonce[:], utils.NonceAuthVote) && !bytes.Equal(header.Nonce[:], utils.NonceDropVote) {
|
||||||
|
return utils.ErrInvalidVote
|
||||||
|
}
|
||||||
|
// Ensure that the mix digest is zero as we don't have fork protection currently
|
||||||
|
if header.MixDigest != (common.Hash{}) {
|
||||||
|
return utils.ErrInvalidMixDigest
|
||||||
|
}
|
||||||
|
// Ensure that the block doesn't contain any uncles which are meaningless in XDPoS_v1
|
||||||
|
if header.UncleHash != utils.UncleHash {
|
||||||
|
return utils.ErrInvalidUncleHash
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify v2 block that is on the epoch switch
|
||||||
|
if header.Validators != nil {
|
||||||
|
// Skip if it's the first v2 block as it wil inherit from last v1 epoch block
|
||||||
|
if header.Number.Uint64() > x.config.V2.SwitchBlock.Uint64()+1 && header.Coinbase != (common.Address{}) {
|
||||||
|
return utils.ErrInvalidCheckpointBeneficiary
|
||||||
|
}
|
||||||
|
if !bytes.Equal(header.Nonce[:], utils.NonceDropVote) {
|
||||||
|
return utils.ErrInvalidCheckpointVote
|
||||||
|
}
|
||||||
|
if len(header.Validators) == 0 {
|
||||||
|
return utils.ErrEmptyEpochSwitchValidators
|
||||||
|
}
|
||||||
|
if len(header.Validators)%common.AddressLength != 0 {
|
||||||
|
return utils.ErrInvalidCheckpointSigners
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If all checks passed, validate any special fields for hard forks
|
||||||
|
if err := misc.VerifyForkHashes(chain.Config(), header, false); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ensure that the block's timestamp isn't too close to it's parent
|
||||||
|
var parent *types.Header
|
||||||
|
number := header.Number.Uint64()
|
||||||
|
|
||||||
|
if len(parents) > 0 {
|
||||||
|
parent = parents[len(parents)-1]
|
||||||
|
} else {
|
||||||
|
parent = chain.GetHeader(header.ParentHash, number-1)
|
||||||
|
}
|
||||||
|
if parent == nil || parent.Number.Uint64() != number-1 || parent.Hash() != header.ParentHash {
|
||||||
|
return consensus.ErrUnknownAncestor
|
||||||
|
}
|
||||||
|
if parent.Time.Uint64()+uint64(x.config.V2.MinePeriod) > header.Time.Uint64() {
|
||||||
|
return utils.ErrInvalidTimestamp
|
||||||
|
}
|
||||||
|
// TODO: verifySeal XIN-135
|
||||||
|
|
||||||
|
x.verifiedHeaders.Add(header.Hash(), true)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// Utils for test to get current Pool size
|
// Utils for test to get current Pool size
|
||||||
func (x *XDPoS_v2) GetVotePoolSize(vote *utils.Vote) int {
|
func (x *XDPoS_v2) GetVotePoolSize(vote *utils.Vote) int {
|
||||||
return x.votePool.Size(vote)
|
return x.votePool.Size(vote)
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,12 @@ var (
|
||||||
ErrWaitTransactions = errors.New("waiting for transactions")
|
ErrWaitTransactions = errors.New("waiting for transactions")
|
||||||
|
|
||||||
ErrInvalidCheckpointValidators = errors.New("invalid validators list on checkpoint block")
|
ErrInvalidCheckpointValidators = errors.New("invalid validators list on checkpoint block")
|
||||||
|
|
||||||
|
ErrEmptyEpochSwitchValidators = errors.New("empty validators list on epoch switch block")
|
||||||
|
|
||||||
|
ErrInvalidV2Extra = errors.New("Invalid v2 extra in the block")
|
||||||
|
ErrInvalidQC = errors.New("Invalid QC content")
|
||||||
|
ErrEmptyBlockInfoHash = errors.New("BlockInfo hash is empty")
|
||||||
)
|
)
|
||||||
|
|
||||||
type ErrIncomingMessageRoundNotEqualCurrentRound struct {
|
type ErrIncomingMessageRoundNotEqualCurrentRound struct {
|
||||||
|
|
|
||||||
33
consensus/tests/verify_block_test.go
Normal file
33
consensus/tests/verify_block_test.go
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
package tests
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/params"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestShouldVerifyBlock(t *testing.T) {
|
||||||
|
b, err := json.Marshal(params.TestXDPoSMockChainConfig)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
configString := string(b)
|
||||||
|
|
||||||
|
var config params.ChainConfig
|
||||||
|
err = json.Unmarshal([]byte(configString), &config)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
// Enable verify
|
||||||
|
config.XDPoS.V2.SkipV2Validation = false
|
||||||
|
// Skip the mining time validation by set mine time to 0
|
||||||
|
config.XDPoS.V2.MinePeriod = 0
|
||||||
|
// Block 901 is the first v2 block with round of 1
|
||||||
|
blockchain, _, currentBlock, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 901, &config, 0)
|
||||||
|
adaptor := blockchain.Engine().(*XDPoS.XDPoS)
|
||||||
|
|
||||||
|
// Happy path
|
||||||
|
err = adaptor.VerifyHeader(blockchain, currentBlock.Header(), true)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
|
||||||
|
// TODO: unhappy path XIN-135: https://hashlabs.atlassian.net/wiki/spaces/HASHLABS/pages/95944705/Verify+header
|
||||||
|
}
|
||||||
|
|
@ -45,9 +45,10 @@ var (
|
||||||
WaitPeriod: 1,
|
WaitPeriod: 1,
|
||||||
MinePeriod: 2,
|
MinePeriod: 2,
|
||||||
SwitchBlock: big.NewInt(900),
|
SwitchBlock: big.NewInt(900),
|
||||||
|
SkipV2Validation: true,
|
||||||
}
|
}
|
||||||
DevnetXDPoSV2Config = &V2{
|
DevnetXDPoSV2Config = &V2{
|
||||||
SwitchBlock: big.NewInt(9999999), // Temporary set it to very high
|
SwitchBlock: big.NewInt(7218000),
|
||||||
TimeoutWorkerDuration: 50,
|
TimeoutWorkerDuration: 50,
|
||||||
CertThreshold: 6,
|
CertThreshold: 6,
|
||||||
WaitPeriod: 2,
|
WaitPeriod: 2,
|
||||||
|
|
@ -139,7 +140,7 @@ var (
|
||||||
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil}
|
AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil}
|
||||||
|
|
||||||
// XDPoS config with v2 engine after block 901
|
// XDPoS config with v2 engine after block 901
|
||||||
TestXDPoSMockChainConfig = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, &XDPoSConfig{Epoch: 900, Gap: 450, SkipValidation: true, V2: TestXDPoSV2Config, FoudationWalletAddr: common.HexToAddress("0x0000000000000000000000000000000000000068"), Reward: 250}}
|
TestXDPoSMockChainConfig = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, &XDPoSConfig{Epoch: 900, Gap: 450, SkipV1Validation: true, V2: TestXDPoSV2Config, FoudationWalletAddr: common.HexToAddress("0x0000000000000000000000000000000000000068"), Reward: 250}}
|
||||||
|
|
||||||
TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, nil}
|
TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, nil}
|
||||||
TestRules = TestChainConfig.Rules(new(big.Int))
|
TestRules = TestChainConfig.Rules(new(big.Int))
|
||||||
|
|
@ -202,7 +203,7 @@ type XDPoSConfig struct {
|
||||||
Gap uint64 `json:"gap"` // Gap time preparing for the next epoch
|
Gap uint64 `json:"gap"` // Gap time preparing for the next epoch
|
||||||
FoudationWalletAddr common.Address `json:"foudationWalletAddr"` // Foundation Address Wallet
|
FoudationWalletAddr common.Address `json:"foudationWalletAddr"` // Foundation Address Wallet
|
||||||
WaitPeriod int `json:"waitPeriod"` // Miner wait period
|
WaitPeriod int `json:"waitPeriod"` // Miner wait period
|
||||||
SkipValidation bool //Skip Block Validation for testing purpose
|
SkipV1Validation bool //Skip Block Validation for testing purpose, V1 consensus only
|
||||||
V2 *V2 `json:"v2"`
|
V2 *V2 `json:"v2"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -212,6 +213,7 @@ type V2 struct {
|
||||||
SwitchBlock *big.Int `json:"switchBlock"` // v1 to v2 switch block number
|
SwitchBlock *big.Int `json:"switchBlock"` // v1 to v2 switch block number
|
||||||
TimeoutWorkerDuration int64 `json:"timeoutWorkerDuration"` // Duration in ms
|
TimeoutWorkerDuration int64 `json:"timeoutWorkerDuration"` // Duration in ms
|
||||||
CertThreshold int `json:"certificateThreshold"` // Necessary number of messages from master nodes to form a certificate
|
CertThreshold int `json:"certificateThreshold"` // Necessary number of messages from master nodes to form a certificate
|
||||||
|
SkipV2Validation bool //Skip Block Validation for testing purpose, V2 consensus only
|
||||||
}
|
}
|
||||||
|
|
||||||
// String implements the stringer interface, returning the consensus engine details.
|
// String implements the stringer interface, returning the consensus engine details.
|
||||||
|
|
|
||||||
|
|
@ -21,10 +21,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
VersionMajor = 1 // Major version component of the current release
|
VersionMajor = 2 // Major version component of the current release
|
||||||
VersionMinor = 4 // Minor version component of the current release
|
VersionMinor = 0 // Minor version component of the current release
|
||||||
VersionPatch = 4 // Patch version component of the current release
|
VersionPatch = 0 // Patch version component of the current release
|
||||||
VersionMeta = "stable" // Version metadata to append to the version string
|
VersionMeta = "unstable" // Version metadata to append to the version string
|
||||||
)
|
)
|
||||||
|
|
||||||
// Version holds the textual version string.
|
// Version holds the textual version string.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue