Merge pull request #680 from XinFinOrg/mainnet-hot-fix-v2.2.0-api-epoch

Mainnet v2.3.0 merge hot fix branch and new epoch api
This commit is contained in:
Liam 2024-10-21 00:00:14 -07:00 committed by GitHub
commit 09fe4ec646
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 237 additions and 35 deletions

View file

@ -144,6 +144,7 @@ var (
rpcFlags = []cli.Flag{ rpcFlags = []cli.Flag{
utils.RPCEnabledFlag, utils.RPCEnabledFlag,
utils.RPCGlobalGasCapFlag,
utils.RPCListenAddrFlag, utils.RPCListenAddrFlag,
utils.RPCPortFlag, utils.RPCPortFlag,
utils.RPCHttpWriteTimeoutFlag, utils.RPCHttpWriteTimeoutFlag,

View file

@ -144,6 +144,7 @@ var AppHelpFlagGroups = []flagGroup{
Name: "API AND CONSOLE", Name: "API AND CONSOLE",
Flags: []cli.Flag{ Flags: []cli.Flag{
utils.RPCEnabledFlag, utils.RPCEnabledFlag,
utils.RPCGlobalGasCapFlag,
utils.RPCListenAddrFlag, utils.RPCListenAddrFlag,
utils.RPCPortFlag, utils.RPCPortFlag,
utils.RPCHttpWriteTimeoutFlag, utils.RPCHttpWriteTimeoutFlag,

View file

@ -374,7 +374,7 @@ var (
Usage: "Record information useful for VM and contract debugging", Usage: "Record information useful for VM and contract debugging",
} }
RPCGlobalGasCapFlag = cli.Uint64Flag{ RPCGlobalGasCapFlag = cli.Uint64Flag{
Name: "rpc.gascap", Name: "rpc-gascap",
Usage: "Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite)", Usage: "Sets a cap on gas that can be used in eth_call/estimateGas (0=infinite)",
Value: ethconfig.Defaults.RPCGasCap, Value: ethconfig.Defaults.RPCGasCap,
} }
@ -1242,6 +1242,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if ctx.GlobalIsSet(DocRootFlag.Name) { if ctx.GlobalIsSet(DocRootFlag.Name) {
cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name) cfg.DocRoot = ctx.GlobalString(DocRootFlag.Name)
} }
if ctx.GlobalIsSet(RPCGlobalGasCapFlag.Name) {
cfg.RPCGasCap = ctx.GlobalUint64(RPCGlobalGasCapFlag.Name)
}
if ctx.GlobalIsSet(RPCGlobalTxFeeCap.Name) { if ctx.GlobalIsSet(RPCGlobalTxFeeCap.Name) {
cfg.RPCTxFeeCap = ctx.GlobalFloat64(RPCGlobalTxFeeCap.Name) cfg.RPCTxFeeCap = ctx.GlobalFloat64(RPCGlobalTxFeeCap.Name)
} }

View file

@ -344,3 +344,23 @@ func (api *API) GetEpochNumbersBetween(begin, end *rpc.BlockNumber) ([]uint64, e
} }
return epochSwitchNumbers, nil return epochSwitchNumbers, nil
} }
/*
An API exclusively for V2 consensus, designed to assist in getting rewards of the epoch number.
Given the epoch number, search the epoch switch block.
*/
func (api *API) GetBlockInfoByEpochNum(epochNumber uint64) (*utils.EpochNumInfo, error) {
thisEpoch, nextEpoch, err := api.XDPoS.EngineV2.GetBlockByEpochNumber(api.chain, epochNumber)
if err != nil {
return nil, err
}
info := &utils.EpochNumInfo{
EpochBlockHash: thisEpoch.Hash,
EpochRound: thisEpoch.Round,
EpochFirstBlockNumber: thisEpoch.Number,
}
if nextEpoch != nil {
info.EpochLastBlockNumber = new(big.Int).Sub(nextEpoch.Number, big.NewInt(1))
}
return info, nil
}

View file

@ -654,6 +654,10 @@ func (x *XDPoS_v2) VoteHandler(chain consensus.ChainReader, voteMsg *types.Vote)
3. Broadcast(Not part of consensus) 3. Broadcast(Not part of consensus)
*/ */
func (x *XDPoS_v2) VerifyTimeoutMessage(chain consensus.ChainReader, timeoutMsg *types.Timeout) (bool, error) { func (x *XDPoS_v2) VerifyTimeoutMessage(chain consensus.ChainReader, timeoutMsg *types.Timeout) (bool, error) {
if timeoutMsg.Round < x.currentRound {
log.Debug("[VerifyTimeoutMessage] Disqualified timeout message as the proposed round does not match currentRound", "timeoutHash", timeoutMsg.Hash(), "timeoutRound", timeoutMsg.Round, "currentRound", x.currentRound)
return false, nil
}
snap, err := x.getSnapshot(chain, timeoutMsg.GapNumber, true) snap, err := x.getSnapshot(chain, timeoutMsg.GapNumber, true)
if err != nil || snap == nil { if err != nil || snap == nil {
log.Error("[VerifyTimeoutMessage] Fail to get snapshot when verifying timeout message!", "messageGapNumber", timeoutMsg.GapNumber, "err", err) log.Error("[VerifyTimeoutMessage] Fail to get snapshot when verifying timeout message!", "messageGapNumber", timeoutMsg.GapNumber, "err", err)

View file

@ -175,6 +175,10 @@ func (x *XDPoS_v2) GetEpochSwitchInfoBetween(chain consensus.ChainReader, begin,
return nil, err return nil, err
} }
iteratorHeader = nil iteratorHeader = nil
// V2 switch epoch switch info has nil parent
if epochSwitchInfo.EpochSwitchParentBlockInfo == nil {
break
}
iteratorHash = epochSwitchInfo.EpochSwitchParentBlockInfo.Hash iteratorHash = epochSwitchInfo.EpochSwitchParentBlockInfo.Hash
iteratorNum = epochSwitchInfo.EpochSwitchBlockInfo.Number iteratorNum = epochSwitchInfo.EpochSwitchBlockInfo.Number
if iteratorNum.Cmp(begin.Number) >= 0 { if iteratorNum.Cmp(begin.Number) >= 0 {

View file

@ -87,6 +87,7 @@ Forensics runs in a seperate go routine as its no system critical
Link to the flow diagram: https://hashlabs.atlassian.net/wiki/spaces/HASHLABS/pages/97878029/Forensics+Diagram+flow Link to the flow diagram: https://hashlabs.atlassian.net/wiki/spaces/HASHLABS/pages/97878029/Forensics+Diagram+flow
*/ */
func (f *Forensics) ProcessForensics(chain consensus.ChainReader, engine *XDPoS_v2, incomingQC types.QuorumCert) error { func (f *Forensics) ProcessForensics(chain consensus.ChainReader, engine *XDPoS_v2, incomingQC types.QuorumCert) error {
return nil
log.Debug("Received a QC in forensics", "QC", incomingQC) log.Debug("Received a QC in forensics", "QC", incomingQC)
// Clone the values to a temporary variable // Clone the values to a temporary variable
highestCommittedQCs := f.HighestCommittedQCs highestCommittedQCs := f.HighestCommittedQCs
@ -394,6 +395,7 @@ Forensics runs in a seperate go routine as its no system critical
Link to the flow diagram: https://hashlabs.atlassian.net/wiki/spaces/HASHLABS/pages/99516417/Vote+Equivocation+detection+specification Link to the flow diagram: https://hashlabs.atlassian.net/wiki/spaces/HASHLABS/pages/99516417/Vote+Equivocation+detection+specification
*/ */
func (f *Forensics) ProcessVoteEquivocation(chain consensus.ChainReader, engine *XDPoS_v2, incomingVote *types.Vote) error { func (f *Forensics) ProcessVoteEquivocation(chain consensus.ChainReader, engine *XDPoS_v2, incomingVote *types.Vote) error {
return nil
log.Debug("Received a vote in forensics", "vote", incomingVote) log.Debug("Received a vote in forensics", "vote", incomingVote)
// Clone the values to a temporary variable // Clone the values to a temporary variable
highestCommittedQCs := f.HighestCommittedQCs highestCommittedQCs := f.HighestCommittedQCs
@ -484,6 +486,7 @@ func (f *Forensics) isVoteBlamed(chain consensus.ChainReader, highestCommittedQC
} }
func (f *Forensics) DetectEquivocationInVotePool(vote *types.Vote, votePool *utils.Pool) { func (f *Forensics) DetectEquivocationInVotePool(vote *types.Vote, votePool *utils.Pool) {
return
poolKey := vote.PoolKey() poolKey := vote.PoolKey()
votePoolKeys := votePool.PoolObjKeysList() votePoolKeys := votePool.PoolObjKeysList()
signer, err := GetVoteSignerAddresses(vote) signer, err := GetVoteSignerAddresses(vote)

View file

@ -3,6 +3,7 @@ package engine_v2
import ( import (
"errors" "errors"
"fmt" "fmt"
"math/big"
"github.com/XinFinOrg/XDPoSChain/accounts" "github.com/XinFinOrg/XDPoSChain/accounts"
"github.com/XinFinOrg/XDPoSChain/common" "github.com/XinFinOrg/XDPoSChain/common"
@ -218,3 +219,44 @@ func (x *XDPoS_v2) CalculateMissingRounds(chain consensus.ChainReader, header *t
return missedRoundsMetadata, nil return missedRoundsMetadata, nil
} }
func (x *XDPoS_v2) GetBlockByEpochNumber(chain consensus.ChainReader, targetEpochNum uint64) (*types.BlockInfo, *types.BlockInfo, error) {
currentHeader := chain.CurrentHeader()
epochSwitchInfo, err := x.getEpochSwitchInfo(chain, currentHeader, currentHeader.Hash())
if err != nil {
return nil, nil, err
}
epochNum := x.config.V2.SwitchBlock.Uint64()/x.config.Epoch + uint64(epochSwitchInfo.EpochSwitchBlockInfo.Round)/x.config.Epoch
// since below function GetEpochSwitchInfoBetween(chain, start, end) return nil if start == end, we early return the result
if targetEpochNum == epochNum {
return epochSwitchInfo.EpochSwitchBlockInfo, nil, nil
}
if targetEpochNum > epochNum {
return nil, nil, errors.New("input epoch number > current epoch number")
}
if targetEpochNum < x.config.V2.SwitchBlock.Uint64()/x.config.Epoch {
return nil, nil, errors.New("input epoch number < v2 begin epoch number")
}
epoch := big.NewInt(int64(x.config.Epoch))
estblockNumDiff := new(big.Int).Mul(epoch, big.NewInt(int64(epochNum-targetEpochNum)))
estBlockNum := new(big.Int).Sub(epochSwitchInfo.EpochSwitchBlockInfo.Number, estblockNumDiff)
if estBlockNum.Cmp(x.config.V2.SwitchBlock) == -1 {
estBlockNum.Set(x.config.V2.SwitchBlock)
}
estBlockHeader := chain.GetHeaderByNumber(estBlockNum.Uint64())
epochSwitchInfos, err := x.GetEpochSwitchInfoBetween(chain, estBlockHeader, currentHeader)
if err != nil {
return nil, nil, err
}
for i, info := range epochSwitchInfos {
epochNum := x.config.V2.SwitchBlock.Uint64()/x.config.Epoch + uint64(info.EpochSwitchBlockInfo.Round)/x.config.Epoch
if epochNum == targetEpochNum {
if i < len(epochSwitchInfos)-1 {
nextEpoch := epochSwitchInfos[i+1].EpochSwitchBlockInfo
return info.EpochSwitchBlockInfo, nextEpoch, nil
}
return info.EpochSwitchBlockInfo, nil, nil
}
}
return nil, nil, errors.New("input epoch number not found (all rounds in this epoch are missed, which is very rare)")
}

View file

@ -71,3 +71,11 @@ type PublicApiMissedRoundsMetadata struct {
EpochBlockNumber *big.Int EpochBlockNumber *big.Int
MissedRounds []MissedRoundInfo MissedRounds []MissedRoundInfo
} }
// Given an epoch number, this struct records the epoch switch block (first block in epoch) infos such as block number
type EpochNumInfo struct {
EpochBlockHash common.Hash `json:"hash"`
EpochRound types.Round `json:"round"`
EpochFirstBlockNumber *big.Int `json:"firstBlock"`
EpochLastBlockNumber *big.Int `json:"lastBlock"`
}

View file

@ -168,3 +168,70 @@ func TestGetEpochNumbersBetween(t *testing.T) {
assert.Nil(t, numbers) assert.Nil(t, numbers)
assert.EqualError(t, err, "illegal begin block number") assert.EqualError(t, err, "illegal begin block number")
} }
func TestGetBlockByEpochNumber(t *testing.T) {
blockchain, _, currentBlock, signer, signFn := PrepareXDCTestBlockChainWithPenaltyForV2Engine(t, 1802, params.TestXDPoSMockChainConfig)
blockCoinBase := "0x111000000000000000000000000000000123"
largeRound := int64(1802)
newBlock := CreateBlock(blockchain, params.TestXDPoSMockChainConfig, currentBlock, int(currentBlock.NumberU64())+1, largeRound, blockCoinBase, signer, signFn, nil, nil, currentBlock.Header().Root.Hex())
err := blockchain.InsertBlock(newBlock)
assert.Nil(t, err)
largeRound2 := int64(3603)
newBlock2 := CreateBlock(blockchain, params.TestXDPoSMockChainConfig, newBlock, int(newBlock.NumberU64())+1, largeRound2, blockCoinBase, signer, signFn, nil, nil, newBlock.Header().Root.Hex())
err = blockchain.InsertBlock(newBlock2)
assert.Nil(t, err)
// block num, round, epoch is as follows
// 900,0,1 (v2 switch block, not v2 epoch switch block)
// 901,1,1 (1st epoch switch block)
// 902,2,1
// ...
// 1800,900,2 (2nd epoch switch block)
// 1801,901,2
// 1802,902,2
// 1803,1802,3 (epoch switch)
// epoch 4 has no block
// 1804,3603,5 (epoch switch)
engine := blockchain.Engine().(*XDPoS.XDPoS)
// init the snapshot, otherwise getEpochSwitchInfo would return error
checkpointHeader := blockchain.GetHeaderByNumber(blockchain.Config().XDPoS.V2.SwitchBlock.Uint64() + 1)
err = engine.Initial(blockchain, checkpointHeader)
assert.Nil(t, err)
info, err := engine.APIs(blockchain)[0].Service.(*XDPoS.API).GetBlockInfoByEpochNum(0)
assert.NotNil(t, err)
assert.Nil(t, info)
info, err = engine.APIs(blockchain)[0].Service.(*XDPoS.API).GetBlockInfoByEpochNum(1)
assert.Equal(t, info.EpochFirstBlockNumber.Int64(), int64(901))
assert.Equal(t, info.EpochLastBlockNumber.Int64(), int64(1799))
assert.Equal(t, info.EpochRound, types.Round(1))
assert.Nil(t, err)
info, err = engine.APIs(blockchain)[0].Service.(*XDPoS.API).GetBlockInfoByEpochNum(2)
assert.Equal(t, info.EpochFirstBlockNumber.Int64(), int64(1800))
assert.Equal(t, info.EpochLastBlockNumber.Int64(), int64(1802))
assert.Equal(t, info.EpochRound, types.Round(900))
assert.Nil(t, err)
info, err = engine.APIs(blockchain)[0].Service.(*XDPoS.API).GetBlockInfoByEpochNum(3)
assert.Equal(t, info.EpochFirstBlockNumber.Int64(), int64(1803))
assert.Equal(t, info.EpochLastBlockNumber.Int64(), int64(1803))
assert.Equal(t, info.EpochRound, types.Round(largeRound))
assert.Nil(t, err)
info, err = engine.APIs(blockchain)[0].Service.(*XDPoS.API).GetBlockInfoByEpochNum(4)
assert.NotNil(t, err)
assert.Nil(t, info)
info, err = engine.APIs(blockchain)[0].Service.(*XDPoS.API).GetBlockInfoByEpochNum(5)
assert.Equal(t, info.EpochRound, types.Round(largeRound2))
assert.Equal(t, info.EpochFirstBlockNumber.Int64(), int64(1804))
assert.Nil(t, info.EpochLastBlockNumber)
assert.Nil(t, err)
info, err = engine.APIs(blockchain)[0].Service.(*XDPoS.API).GetBlockInfoByEpochNum(6)
assert.NotNil(t, err)
assert.Nil(t, info)
}

View file

@ -17,6 +17,8 @@ import (
) )
func TestProcessQcShallSetForensicsCommittedQc(t *testing.T) { func TestProcessQcShallSetForensicsCommittedQc(t *testing.T) {
t.Skip("Skipping this test for now as we disable forensics")
blockchain, _, currentBlock, signer, signFn, _ := PrepareXDCTestBlockChainForV2Engine(t, 905, params.TestXDPoSMockChainConfig, nil) blockchain, _, currentBlock, signer, signFn, _ := PrepareXDCTestBlockChainForV2Engine(t, 905, params.TestXDPoSMockChainConfig, nil)
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2 engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2
@ -92,6 +94,8 @@ func TestProcessQcShallSetForensicsCommittedQc(t *testing.T) {
} }
func TestSetCommittedQCsInOrder(t *testing.T) { func TestSetCommittedQCsInOrder(t *testing.T) {
t.Skip("Skipping this test for now as we disable forensics")
blockchain, _, currentBlock, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 905, params.TestXDPoSMockChainConfig, nil) blockchain, _, currentBlock, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 905, params.TestXDPoSMockChainConfig, nil)
forensics := blockchain.Engine().(*XDPoS.XDPoS).EngineV2.GetForensicsFaker() forensics := blockchain.Engine().(*XDPoS.XDPoS).EngineV2.GetForensicsFaker()
@ -118,6 +122,8 @@ func TestSetCommittedQCsInOrder(t *testing.T) {
// Happty path // Happty path
func TestForensicsMonitoring(t *testing.T) { func TestForensicsMonitoring(t *testing.T) {
t.Skip("Skipping this test for now as we disable forensics")
blockchain, _, currentBlock, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 915, params.TestXDPoSMockChainConfig, nil) blockchain, _, currentBlock, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 915, params.TestXDPoSMockChainConfig, nil)
forensics := blockchain.Engine().(*XDPoS.XDPoS).EngineV2.GetForensicsFaker() forensics := blockchain.Engine().(*XDPoS.XDPoS).EngineV2.GetForensicsFaker()
var decodedCurrentblockExtraField types.ExtraFields_v2 var decodedCurrentblockExtraField types.ExtraFields_v2
@ -140,6 +146,7 @@ func TestForensicsMonitoring(t *testing.T) {
} }
func TestForensicsMonitoringNotOnSameChainButHaveSameRoundQC(t *testing.T) { func TestForensicsMonitoringNotOnSameChainButHaveSameRoundQC(t *testing.T) {
t.Skip("Skipping this test for now as we disable forensics")
var numOfForks = new(int) var numOfForks = new(int)
*numOfForks = 10 *numOfForks = 10
var forkRoundDifference = new(int) var forkRoundDifference = new(int)
@ -199,6 +206,8 @@ func TestForensicsMonitoringNotOnSameChainButHaveSameRoundQC(t *testing.T) {
} }
func TestForensicsMonitoringNotOnSameChainDoNotHaveSameRoundQC(t *testing.T) { func TestForensicsMonitoringNotOnSameChainDoNotHaveSameRoundQC(t *testing.T) {
t.Skip("Skipping this test for now as we disable forensics")
var numOfForks = new(int) var numOfForks = new(int)
*numOfForks = 10 *numOfForks = 10
var forkRoundDifference = new(int) var forkRoundDifference = new(int)
@ -260,6 +269,8 @@ func TestForensicsMonitoringNotOnSameChainDoNotHaveSameRoundQC(t *testing.T) {
// "prone to attack" test where the "across epoch" field is true // "prone to attack" test where the "across epoch" field is true
func TestForensicsAcrossEpoch(t *testing.T) { func TestForensicsAcrossEpoch(t *testing.T) {
t.Skip("Skipping this test for now as we disable forensics")
var numOfForks = new(int) var numOfForks = new(int)
*numOfForks = 10 *numOfForks = 10
var forkRoundDifference = new(int) var forkRoundDifference = new(int)
@ -322,6 +333,8 @@ func TestForensicsAcrossEpoch(t *testing.T) {
} }
func TestVoteEquivocationSameRound(t *testing.T) { func TestVoteEquivocationSameRound(t *testing.T) {
t.Skip("Skipping this test for now as we disable forensics")
var numOfForks = new(int) var numOfForks = new(int)
*numOfForks = 1 *numOfForks = 1
blockchain, _, currentBlock, signer, signFn, currentForkBlock := PrepareXDCTestBlockChainForV2Engine(t, 901, params.TestXDPoSMockChainConfig, &ForkedBlockOptions{numOfForkedBlocks: numOfForks}) blockchain, _, currentBlock, signer, signFn, currentForkBlock := PrepareXDCTestBlockChainForV2Engine(t, 901, params.TestXDPoSMockChainConfig, &ForkedBlockOptions{numOfForkedBlocks: numOfForks})
@ -388,6 +401,8 @@ func TestVoteEquivocationSameRound(t *testing.T) {
} }
func TestVoteEquivocationDifferentRound(t *testing.T) { func TestVoteEquivocationDifferentRound(t *testing.T) {
t.Skip("Skipping this test for now as we disable forensics")
var numOfForks = new(int) var numOfForks = new(int)
*numOfForks = 10 *numOfForks = 10
var forkRoundDifference = new(int) var forkRoundDifference = new(int)

View file

@ -442,11 +442,11 @@ func (b *EthApiBackend) GetVotersRewards(masternodeAddr common.Address) map[comm
// calculate for 2 epochs ago // calculate for 2 epochs ago
currentCheckpointNumber, _, err := engine.GetCurrentEpochSwitchBlock(chain, block.Number()) currentCheckpointNumber, _, err := engine.GetCurrentEpochSwitchBlock(chain, block.Number())
if err != nil { if err != nil {
log.Error("[GetVotersRewards] Fail to get GetCurrentEpochSwitchBlock for current checkpoint block", "block", block) log.Error("[GetVotersRewards] Fail to get GetCurrentEpochSwitchBlock for current checkpoint block", "block", block.Number(), "err", err)
} }
lastCheckpointNumber, _, err := engine.GetCurrentEpochSwitchBlock(chain, big.NewInt(int64(currentCheckpointNumber-1))) lastCheckpointNumber, _, err := engine.GetCurrentEpochSwitchBlock(chain, big.NewInt(int64(currentCheckpointNumber-1)))
if err != nil { if err != nil {
log.Error("[GetVotersRewards] Fail to get GetCurrentEpochSwitchBlock for last checkpoint block", "block", block) log.Error("[GetVotersRewards] Fail to get GetCurrentEpochSwitchBlock for last checkpoint block", "block", block.Number(), "err", err)
} }
lastCheckpointBlock := chain.GetBlockByNumber(lastCheckpointNumber) lastCheckpointBlock := chain.GetBlockByNumber(lastCheckpointNumber)

View file

@ -11,7 +11,7 @@ import (
const maxBlockDist = 7 // Maximum allowed backward distance from the chain head, 7 is just a magic number indicate very close block const maxBlockDist = 7 // Maximum allowed backward distance from the chain head, 7 is just a magic number indicate very close block
//Define Boradcast Group functions // Define Boradcast Group functions
type broadcastVoteFn func(*types.Vote) type broadcastVoteFn func(*types.Vote)
type broadcastTimeoutFn func(*types.Timeout) type broadcastTimeoutFn func(*types.Timeout)
type broadcastSyncInfoFn func(*types.SyncInfo) type broadcastSyncInfoFn func(*types.SyncInfo)
@ -93,9 +93,8 @@ func (b *Bfter) Vote(peer string, vote *types.Vote) error {
return err return err
} }
b.broadcastCh <- vote
if verified { if verified {
b.broadcastCh <- vote
err = b.consensus.voteHandler(b.blockChainReader, vote) err = b.consensus.voteHandler(b.blockChainReader, vote)
if err != nil { if err != nil {
if _, ok := err.(*utils.ErrIncomingMessageRoundTooFarFromCurrentRound); ok { if _, ok := err.(*utils.ErrIncomingMessageRoundTooFarFromCurrentRound); ok {
@ -126,8 +125,8 @@ func (b *Bfter) Timeout(peer string, timeout *types.Timeout) error {
return err return err
} }
b.broadcastCh <- timeout
if verified { if verified {
b.broadcastCh <- timeout
err = b.consensus.timeoutHandler(b.blockChainReader, timeout) err = b.consensus.timeoutHandler(b.blockChainReader, timeout)
if err != nil { if err != nil {
if _, ok := err.(*utils.ErrIncomingMessageRoundNotEqualCurrentRound); ok { if _, ok := err.(*utils.ErrIncomingMessageRoundNotEqualCurrentRound); ok {
@ -156,9 +155,9 @@ func (b *Bfter) SyncInfo(peer string, syncInfo *types.SyncInfo) error {
return err return err
} }
b.broadcastCh <- syncInfo
// Process only if verified and qualified // Process only if verified and qualified
if verified { if verified {
b.broadcastCh <- syncInfo
err = b.consensus.syncInfoHandler(b.blockChainReader, syncInfo) err = b.consensus.syncInfoHandler(b.blockChainReader, syncInfo)
if err != nil { if err != nil {
log.Error("handle BFT SyncInfo", "error", err) log.Error("handle BFT SyncInfo", "error", err)

View file

@ -144,7 +144,7 @@ func TestBoardcastButNotProcessDisqualifiedVotes(t *testing.T) {
tester.bfter.Vote(peerID, &vote) tester.bfter.Vote(peerID, &vote)
time.Sleep(50 * time.Millisecond) time.Sleep(50 * time.Millisecond)
if int(handlerCounter) != targetVotes || int(broadcastCounter) != 1 { if int(handlerCounter) != targetVotes || int(broadcastCounter) != 0 {
t.Fatalf("count mismatch: have %v on handler, %v on broadcast, want %v", handlerCounter, broadcastCounter, targetVotes) t.Fatalf("count mismatch: have %v on handler, %v on broadcast, want %v", handlerCounter, broadcastCounter, targetVotes)
} }
} }
@ -171,7 +171,7 @@ func TestBoardcastButNotProcessDisqualifiedTimeout(t *testing.T) {
tester.bfter.Timeout(peerID, &timeout) tester.bfter.Timeout(peerID, &timeout)
time.Sleep(50 * time.Millisecond) time.Sleep(50 * time.Millisecond)
if int(handlerCounter) != targetTimeout || int(broadcastCounter) != 1 { if int(handlerCounter) != targetTimeout || int(broadcastCounter) != 0 {
t.Fatalf("count mismatch: have %v on handler, %v on broadcast, want %v", handlerCounter, broadcastCounter, targetTimeout) t.Fatalf("count mismatch: have %v on handler, %v on broadcast, want %v", handlerCounter, broadcastCounter, targetTimeout)
} }
} }
@ -198,7 +198,7 @@ func TestBoardcastButNotProcessDisqualifiedSyncInfo(t *testing.T) {
tester.bfter.SyncInfo(peerID, &syncInfo) tester.bfter.SyncInfo(peerID, &syncInfo)
time.Sleep(50 * time.Millisecond) time.Sleep(50 * time.Millisecond)
if int(handlerCounter) != targetSyncInfo || int(broadcastCounter) != 1 { if int(handlerCounter) != targetSyncInfo || int(broadcastCounter) != 0 {
t.Fatalf("count mismatch: have %v on handler, %v on broadcast, want %v", handlerCounter, broadcastCounter, targetSyncInfo) t.Fatalf("count mismatch: have %v on handler, %v on broadcast, want %v", handlerCounter, broadcastCounter, targetSyncInfo)
} }
} }

View file

@ -69,7 +69,7 @@ var Defaults = Config{
GasPrice: big.NewInt(0.25 * params.Shannon), GasPrice: big.NewInt(0.25 * params.Shannon),
TxPool: core.DefaultTxPoolConfig, TxPool: core.DefaultTxPoolConfig,
RPCGasCap: 25000000, RPCGasCap: 50000000,
GPO: FullNodeGPO, GPO: FullNodeGPO,
RPCTxFeeCap: 1, // 1 ether RPCTxFeeCap: 1, // 1 ether
} }

View file

@ -37,13 +37,13 @@ var (
) )
const ( const (
maxKnownTxs = 32768 // Maximum transactions hashes to keep in the known list (prevent DOS) maxKnownTxs = 32768 // Maximum transactions hashes to keep in the known list (prevent DOS)
maxKnownOrderTxs = 32768 // Maximum transactions hashes to keep in the known list (prevent DOS) maxKnownOrderTxs = 32768 // Maximum transactions hashes to keep in the known list (prevent DOS)
maxKnownLendingTxs = 32768 // Maximum transactions hashes to keep in the known list (prevent DOS) maxKnownLendingTxs = 32768 // Maximum transactions hashes to keep in the known list (prevent DOS)
maxKnownBlocks = 1024 // Maximum block hashes to keep in the known list (prevent DOS) maxKnownBlocks = 1024 // Maximum block hashes to keep in the known list (prevent DOS)
maxKnownVote = 1024 // Maximum transactions hashes to keep in the known list (prevent DOS) maxKnownVote = 131072 // Maximum transactions hashes to keep in the known list (prevent DOS)
maxKnownTimeout = 1024 // Maximum transactions hashes to keep in the known list (prevent DOS) maxKnownTimeout = 131072 // Maximum transactions hashes to keep in the known list (prevent DOS)
maxKnownSyncInfo = 1024 // Maximum transactions hashes to keep in the known list (prevent DOS) maxKnownSyncInfo = 131072 // Maximum transactions hashes to keep in the known list (prevent DOS)
handshakeTimeout = 5 * time.Second handshakeTimeout = 5 * time.Second
) )

View file

@ -106,7 +106,7 @@ var Flags = []cli.Flag{
//blockprofilerateFlag, //blockprofilerateFlag,
cpuprofileFlag, cpuprofileFlag,
//traceFlag, //traceFlag,
//periodicProfilingFlag, periodicProfilingFlag,
debugDataDirFlag, debugDataDirFlag,
} }

View file

@ -877,7 +877,7 @@ func (s *PublicBlockChainAPI) GetCandidateStatus(ctx context.Context, coinbaseAd
epochConfig := s.b.ChainConfig().XDPoS.Epoch epochConfig := s.b.ChainConfig().XDPoS.Epoch
// checkpoint block // checkpoint block
checkpointNumber, epochNumber = s.GetPreviousCheckpointFromEpoch(ctx, epoch) checkpointNumber, epochNumber = s.GetCheckpointFromEpoch(ctx, epoch)
result[fieldEpoch] = epochNumber.Int64() result[fieldEpoch] = epochNumber.Int64()
block, err = s.b.BlockByNumber(ctx, checkpointNumber) block, err = s.b.BlockByNumber(ctx, checkpointNumber)
@ -1036,7 +1036,7 @@ func (s *PublicBlockChainAPI) GetCandidates(ctx context.Context, epoch rpc.Epoch
} }
epochConfig := s.b.ChainConfig().XDPoS.Epoch epochConfig := s.b.ChainConfig().XDPoS.Epoch
checkpointNumber, epochNumber = s.GetPreviousCheckpointFromEpoch(ctx, epoch) checkpointNumber, epochNumber = s.GetCheckpointFromEpoch(ctx, epoch)
result[fieldEpoch] = epochNumber.Int64() result[fieldEpoch] = epochNumber.Int64()
block, err = s.b.BlockByNumber(ctx, checkpointNumber) block, err = s.b.BlockByNumber(ctx, checkpointNumber)
@ -1184,25 +1184,31 @@ func (s *PublicBlockChainAPI) GetCandidates(ctx context.Context, epoch rpc.Epoch
return result, nil return result, nil
} }
// GetPreviousCheckpointFromEpoch returns header of the previous checkpoint // GetCheckpointFromEpoch returns header of the previous checkpoint
func (s *PublicBlockChainAPI) GetPreviousCheckpointFromEpoch(ctx context.Context, epochNum rpc.EpochNumber) (rpc.BlockNumber, rpc.EpochNumber) { func (s *PublicBlockChainAPI) GetCheckpointFromEpoch(ctx context.Context, epochNum rpc.EpochNumber) (rpc.BlockNumber, rpc.EpochNumber) {
var checkpointNumber uint64 var checkpointNumber uint64
epoch := s.b.ChainConfig().XDPoS.Epoch epoch := s.b.ChainConfig().XDPoS.Epoch
if epochNum == rpc.LatestEpochNumber { if epochNum == rpc.LatestEpochNumber {
blockNumer := s.b.CurrentBlock().Number().Uint64() blockNumer := s.b.CurrentBlock().Number()
diff := blockNumer % epoch if engine, ok := s.b.GetEngine().(*XDPoS.XDPoS); ok {
// checkpoint number var err error
checkpointNumber = blockNumer - diff var currentEpoch uint64
epochNum = rpc.EpochNumber(checkpointNumber / epoch) checkpointNumber, currentEpoch, err = engine.GetCurrentEpochSwitchBlock(s.chainReader, blockNumer)
if diff > 0 { if err != nil {
epochNum += 1 log.Error("[GetCheckpointFromEpoch] Fail to get GetCurrentEpochSwitchBlock for current checkpoint block", "block", blockNumer, "err", err)
return 0, epochNum
}
epochNum = rpc.EpochNumber(currentEpoch)
} }
} else if epochNum < 2 { } else if epochNum < 2 {
checkpointNumber = 0 checkpointNumber = 0
} else { } else {
// TODO this checkpointNumber needs to be recalculated for v2 blocks
checkpointNumber = epoch * (uint64(epochNum) - 1) checkpointNumber = epoch * (uint64(epochNum) - 1)
} }
return rpc.BlockNumber(checkpointNumber), epochNum return rpc.BlockNumber(checkpointNumber), epochNum
} }

View file

@ -168,6 +168,11 @@ web3._extend({
params: 2, params: 2,
inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter, web3._extend.formatters.inputBlockNumberFormatter] inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter, web3._extend.formatters.inputBlockNumberFormatter]
}), }),
new web3._extend.Method({
name: 'getBlockInfoByEpochNum',
call: 'XDPoS_getBlockInfoByEpochNum',
params: 1,
}),
], ],
properties: [ properties: [
new web3._extend.Property({ new web3._extend.Property({

View file

@ -56,6 +56,30 @@ var (
TimeoutPeriod: 600, TimeoutPeriod: 600,
MinePeriod: 2, MinePeriod: 2,
}, },
8000: {
MaxMasternodes: 108,
SwitchRound: 8000,
CertThreshold: 0.667,
TimeoutSyncThreshold: 2,
TimeoutPeriod: 60,
MinePeriod: 2,
},
220000: {
MaxMasternodes: 108,
SwitchRound: 220000,
CertThreshold: 0.667,
TimeoutSyncThreshold: 2,
TimeoutPeriod: 30,
MinePeriod: 2,
},
460000: {
MaxMasternodes: 108,
SwitchRound: 460000,
CertThreshold: 0.667,
TimeoutSyncThreshold: 2,
TimeoutPeriod: 20,
MinePeriod: 2,
},
} }
TestnetV2Configs = map[uint64]*V2Config{ TestnetV2Configs = map[uint64]*V2Config{

View file

@ -21,10 +21,10 @@ import (
) )
const ( const (
VersionMajor = 2 // Major version component of the current release VersionMajor = 2 // Major version component of the current release
VersionMinor = 3 // Minor version component of the current release VersionMinor = 3 // Minor version component of the current release
VersionPatch = 1 // Patch version component of the current release VersionPatch = 0 // Patch version component of the current release
VersionMeta = "beta1" // Version metadata to append to the version string VersionMeta = "stable" // Version metadata to append to the version string
) )
// Version holds the textual version string. // Version holds the textual version string.