mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 13:21:37 +00:00
Make masternode dynamic (#356)
* make masternode dynamic * fix all the tests * remove cmt * fix test again
This commit is contained in:
parent
041b667fb0
commit
c215316744
15 changed files with 160 additions and 97 deletions
|
|
@ -145,8 +145,8 @@ func (w *wizard) makeGenesis() {
|
|||
genesis.Config.XDPoS.V2.CurrentConfig.TimeoutSyncThreshold = w.readDefaultInt(3)
|
||||
|
||||
fmt.Println()
|
||||
fmt.Printf("How many v2 vote collection to generate a QC, should be two thirds of masternodes? (default = %d)\n", common.MaxMasternodesV2/3*2+1)
|
||||
genesis.Config.XDPoS.V2.CurrentConfig.CertThreshold = w.readDefaultInt(common.MaxMasternodesV2)/3*2 + 1
|
||||
fmt.Printf("How many v2 vote collection to generate a QC, should be two thirds of masternodes? (default = %f)\n", 0.666)
|
||||
genesis.Config.XDPoS.V2.CurrentConfig.CertThreshold = w.readDefaultFloat(0.666)
|
||||
|
||||
genesis.Config.XDPoS.V2.AllConfigs[0] = genesis.Config.XDPoS.V2.CurrentConfig
|
||||
|
||||
|
|
|
|||
|
|
@ -772,17 +772,6 @@ func (x *XDPoS_v2) VerifyBlockInfo(blockChainReader consensus.ChainReader, block
|
|||
}
|
||||
|
||||
func (x *XDPoS_v2) verifyQC(blockChainReader consensus.ChainReader, quorumCert *types.QuorumCert, parentHeader *types.Header) error {
|
||||
/*
|
||||
1. Check if num of QC signatures is >= x.config.v2.CertThreshold
|
||||
2. Get epoch master node list by hash
|
||||
3. Verify signer signatures: (List of signatures)
|
||||
- Use ecRecover to get the public key
|
||||
- Use the above public key to find out the xdc address
|
||||
- Use the above xdc address to check against the master node list from step 1(For the received QC epoch)
|
||||
4. Verify gapNumber = epochSwitchNumber - epochSwitchNumber%Epoch - Gap
|
||||
5. Verify blockInfo
|
||||
*/
|
||||
|
||||
if quorumCert == nil {
|
||||
log.Warn("[verifyQC] QC is Nil")
|
||||
return utils.ErrInvalidQC
|
||||
|
|
@ -803,9 +792,9 @@ func (x *XDPoS_v2) verifyQC(blockChainReader consensus.ChainReader, quorumCert *
|
|||
|
||||
qcRound := quorumCert.ProposedBlockInfo.Round
|
||||
certThreshold := x.config.V2.Config(uint64(qcRound)).CertThreshold
|
||||
if (qcRound > 0) && (signatures == nil || (len(signatures) < certThreshold)) {
|
||||
if (qcRound > 0) && (signatures == nil || float64(len(signatures)) < float64(epochInfo.MasternodesLen)*certThreshold) {
|
||||
//First V2 Block QC, QC Signatures is initial nil
|
||||
log.Warn("[verifyHeader] Invalid QC Signature is nil or less then config", "QC", quorumCert, "QCNumber", quorumCert.ProposedBlockInfo.Number, "Signatures len", len(signatures), "CertThreshold", certThreshold)
|
||||
log.Warn("[verifyHeader] Invalid QC Signature is nil or less then config", "QC", quorumCert, "QCNumber", quorumCert.ProposedBlockInfo.Number, "Signatures len", len(signatures), "CertThreshold", float64(epochInfo.MasternodesLen)*certThreshold)
|
||||
return utils.ErrInvalidQCSignatures
|
||||
}
|
||||
start := time.Now()
|
||||
|
|
@ -1045,17 +1034,8 @@ func (x *XDPoS_v2) calcMasternodes(chain consensus.ChainReader, blockNum *big.In
|
|||
if len(masternodes) > maxMasternodes {
|
||||
masternodes = masternodes[:maxMasternodes]
|
||||
}
|
||||
if len(masternodes) < x.config.V2.CurrentConfig.CertThreshold {
|
||||
log.Warn("[calcMasternodes] Current epoch masternodes less than threshold", "number", blockNum, "masternodes", len(masternodes), "threshold", x.config.V2.CurrentConfig.CertThreshold)
|
||||
for i, a := range masternodes {
|
||||
log.Warn("final masternode", "i", i, "addr", a)
|
||||
}
|
||||
for i, a := range penalties {
|
||||
log.Warn("penalty", "i", i, "addr", a)
|
||||
}
|
||||
}
|
||||
return masternodes, penalties, nil
|
||||
|
||||
return masternodes, penalties, nil
|
||||
}
|
||||
|
||||
// Given hash, get master node from the epoch switch block of the epoch
|
||||
|
|
|
|||
|
|
@ -72,9 +72,10 @@ func (x *XDPoS_v2) getEpochSwitchInfo(chain consensus.ChainReader, header *types
|
|||
}
|
||||
|
||||
epochSwitchInfo := &types.EpochSwitchInfo{
|
||||
Penalties: penalties,
|
||||
Standbynodes: standbynodes,
|
||||
Masternodes: masternodes,
|
||||
Penalties: penalties,
|
||||
Standbynodes: standbynodes,
|
||||
Masternodes: masternodes,
|
||||
MasternodesLen: len(masternodes),
|
||||
EpochSwitchBlockInfo: &types.BlockInfo{
|
||||
Hash: hash,
|
||||
Number: h.Number,
|
||||
|
|
|
|||
|
|
@ -80,10 +80,10 @@ func (f *Forensics) SetCommittedQCs(headers []types.Header, incomingQC types.Quo
|
|||
}
|
||||
|
||||
/*
|
||||
Entry point for processing forensics.
|
||||
Triggered once processQC is successfully.
|
||||
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
|
||||
Entry point for processing forensics.
|
||||
Triggered once processQC is successfully.
|
||||
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
|
||||
*/
|
||||
func (f *Forensics) ProcessForensics(chain consensus.ChainReader, engine *XDPoS_v2, incomingQC types.QuorumCert) error {
|
||||
log.Debug("Received a QC in forensics", "QC", incomingQC)
|
||||
|
|
@ -387,10 +387,10 @@ func generateVoteEquivocationId(signer common.Address, round1, round2 types.Roun
|
|||
}
|
||||
|
||||
/*
|
||||
Entry point for processing vote equivocation.
|
||||
Triggered once handle vote is successfully.
|
||||
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
|
||||
Entry point for processing vote equivocation.
|
||||
Triggered once handle vote is successfully.
|
||||
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
|
||||
*/
|
||||
func (f *Forensics) ProcessVoteEquivocation(chain consensus.ChainReader, engine *XDPoS_v2, incomingVote *types.Vote) error {
|
||||
log.Debug("Received a vote in forensics", "vote", incomingVote)
|
||||
|
|
|
|||
|
|
@ -27,9 +27,15 @@ func (x *XDPoS_v2) timeoutHandler(blockChainReader consensus.ChainReader, timeou
|
|||
numberOfTimeoutsInPool, pooledTimeouts := x.timeoutPool.Add(timeout)
|
||||
log.Debug("[timeoutHandler] collect timeout", "number", numberOfTimeoutsInPool)
|
||||
|
||||
epochInfo, err := x.getEpochSwitchInfo(blockChainReader, blockChainReader.CurrentHeader(), blockChainReader.CurrentHeader().Hash())
|
||||
if err != nil {
|
||||
log.Error("[timeoutHandler] Error when getting epoch switch Info", "error", err)
|
||||
return fmt.Errorf("fail on timeoutHandler due to failure in getting epoch switch info, %s", err)
|
||||
}
|
||||
|
||||
// Threshold reached
|
||||
certThreshold := x.config.V2.Config(uint64(x.currentRound)).CertThreshold
|
||||
isThresholdReached := numberOfTimeoutsInPool >= certThreshold
|
||||
isThresholdReached := float64(numberOfTimeoutsInPool) >= float64(epochInfo.MasternodesLen)*certThreshold
|
||||
if isThresholdReached {
|
||||
log.Info(fmt.Sprintf("Timeout pool threashold reached: %v, number of items in the pool: %v", isThresholdReached, numberOfTimeoutsInPool))
|
||||
err := x.onTimeoutPoolThresholdReached(blockChainReader, pooledTimeouts, timeout, timeout.GapNumber)
|
||||
|
|
@ -89,11 +95,11 @@ func (x *XDPoS_v2) verifyTC(chain consensus.ChainReader, timeoutCert *types.Time
|
|||
snap, err := x.getSnapshot(chain, timeoutCert.GapNumber, true)
|
||||
if err != nil {
|
||||
log.Error("[verifyTC] Fail to get snapshot when verifying TC!", "TCGapNumber", timeoutCert.GapNumber)
|
||||
return fmt.Errorf("[verifyTC] Unable to get snapshot")
|
||||
return fmt.Errorf("[verifyTC] Unable to get snapshot, %s", err)
|
||||
}
|
||||
if snap == nil || len(snap.NextEpochMasterNodes) == 0 {
|
||||
log.Error("[verifyTC] Something wrong with the snapshot from gapNumber", "messageGapNumber", timeoutCert.GapNumber, "snapshot", snap)
|
||||
return fmt.Errorf("Empty master node lists from snapshot")
|
||||
return fmt.Errorf("empty master node lists from snapshot")
|
||||
}
|
||||
|
||||
signatures, duplicates := UniqueSignatures(timeoutCert.Signatures)
|
||||
|
|
@ -103,9 +109,15 @@ func (x *XDPoS_v2) verifyTC(chain consensus.ChainReader, timeoutCert *types.Time
|
|||
}
|
||||
}
|
||||
|
||||
epochInfo, err := x.getEpochSwitchInfo(chain, chain.CurrentHeader(), chain.CurrentHeader().Hash())
|
||||
if err != nil {
|
||||
log.Error("[verifyTC] Error when getting epoch switch Info", "error", err)
|
||||
return fmt.Errorf("fail on verifyTC due to failure in getting epoch switch info, %s", err)
|
||||
}
|
||||
|
||||
certThreshold := x.config.V2.Config(uint64(timeoutCert.Round)).CertThreshold
|
||||
if len(signatures) < certThreshold {
|
||||
log.Warn("[verifyTC] Invalid TC Signature is nil or empty", "timeoutCert.Round", timeoutCert.Round, "timeoutCert.GapNumber", timeoutCert.GapNumber, "Signatures len", len(timeoutCert.Signatures), "CertThreshold", certThreshold)
|
||||
if float64(len(signatures)) < float64(epochInfo.MasternodesLen)*certThreshold {
|
||||
log.Warn("[verifyTC] Invalid TC Signature is nil or empty", "timeoutCert.Round", timeoutCert.Round, "timeoutCert.GapNumber", timeoutCert.GapNumber, "Signatures len", len(timeoutCert.Signatures), "CertThreshold", float64(epochInfo.MasternodesLen)*certThreshold)
|
||||
return utils.ErrInvalidTCSignatures
|
||||
}
|
||||
|
||||
|
|
@ -124,12 +136,12 @@ func (x *XDPoS_v2) verifyTC(chain consensus.ChainReader, timeoutCert *types.Time
|
|||
verified, _, err := x.verifyMsgSignature(signedTimeoutObj, sig, snap.NextEpochMasterNodes)
|
||||
if err != nil {
|
||||
log.Error("[verifyTC] Error while verfying TC message signatures", "timeoutCert.Round", timeoutCert.Round, "timeoutCert.GapNumber", timeoutCert.GapNumber, "Signatures len", len(signatures), "Error", err)
|
||||
haveError = fmt.Errorf("Error while verfying TC message signatures")
|
||||
haveError = fmt.Errorf("error while verfying TC message signatures, %s", err)
|
||||
return
|
||||
}
|
||||
if !verified {
|
||||
log.Warn("[verifyTC] Signature not verified doing TC verification", "timeoutCert.Round", timeoutCert.Round, "timeoutCert.GapNumber", timeoutCert.GapNumber, "Signatures len", len(signatures))
|
||||
haveError = fmt.Errorf("Fail to verify TC due to signature mis-match")
|
||||
haveError = fmt.Errorf("fail to verify TC due to signature mis-match")
|
||||
return
|
||||
}
|
||||
}(signature)
|
||||
|
|
|
|||
|
|
@ -161,7 +161,6 @@ func (x *XDPoS_v2) verifyHeader(chain consensus.ChainReader, header *types.Heade
|
|||
return err
|
||||
}
|
||||
|
||||
// Check its validator
|
||||
verified, validatorAddress, err := x.verifyMsgSignature(sigHash(header), header.Validator, masterNodes)
|
||||
if err != nil {
|
||||
for index, mn := range masterNodes {
|
||||
|
|
@ -171,11 +170,11 @@ func (x *XDPoS_v2) verifyHeader(chain consensus.ChainReader, header *types.Heade
|
|||
return err
|
||||
}
|
||||
if !verified {
|
||||
log.Warn("[verifyHeader] Fail to verify the block validator as the validator address not within the masternode list", header.Number, "Hash", header.Hash().Hex(), "validatorAddress", validatorAddress.Hex())
|
||||
log.Warn("[verifyHeader] Fail to verify the block validator as the validator address not within the masternode list", "BlockNumber", header.Number, "Hash", header.Hash().Hex(), "validatorAddress", validatorAddress.Hex())
|
||||
return utils.ErrValidatorNotWithinMasternodes
|
||||
}
|
||||
if validatorAddress != header.Coinbase {
|
||||
log.Warn("[verifyHeader] Header validator and coinbase address not match", header.Number, "Hash", header.Hash().Hex(), "validatorAddress", validatorAddress.Hex(), "coinbase", header.Coinbase.Hex())
|
||||
log.Warn("[verifyHeader] Header validator and coinbase address not match", "BlockNumber", header.Number, "Hash", header.Hash().Hex(), "validatorAddress", validatorAddress.Hex(), "coinbase", header.Coinbase.Hex())
|
||||
return utils.ErrCoinbaseAndValidatorMismatch
|
||||
}
|
||||
// Check the proposer is the leader
|
||||
|
|
|
|||
|
|
@ -75,8 +75,14 @@ func (x *XDPoS_v2) voteHandler(chain consensus.ChainReader, voteMsg *types.Vote)
|
|||
go x.ForensicsProcessor.DetectEquivocationInVotePool(voteMsg, x.votePool)
|
||||
go x.ForensicsProcessor.ProcessVoteEquivocation(chain, x, voteMsg)
|
||||
|
||||
epochInfo, err := x.getEpochSwitchInfo(chain, chain.CurrentHeader(), chain.CurrentHeader().Hash())
|
||||
if err != nil {
|
||||
log.Error("[voteHandler] Error when getting epoch switch Info", "error", err)
|
||||
return fmt.Errorf("Fail on voteHandler due to failure in getting epoch switch info")
|
||||
}
|
||||
|
||||
certThreshold := x.config.V2.Config(uint64(voteMsg.ProposedBlockInfo.Round)).CertThreshold
|
||||
thresholdReached := numberOfVotesInPool >= certThreshold
|
||||
thresholdReached := float64(numberOfVotesInPool) >= float64(epochInfo.MasternodesLen)*certThreshold
|
||||
if thresholdReached {
|
||||
log.Info(fmt.Sprintf("[voteHandler] Vote pool threashold reached: %v, number of items in the pool: %v", thresholdReached, numberOfVotesInPool))
|
||||
|
||||
|
|
@ -156,9 +162,15 @@ func (x *XDPoS_v2) onVotePoolThresholdReached(chain consensus.ChainReader, poole
|
|||
}
|
||||
}
|
||||
|
||||
epochInfo, err := x.getEpochSwitchInfo(chain, chain.CurrentHeader(), chain.CurrentHeader().Hash())
|
||||
if err != nil {
|
||||
log.Error("[voteHandler] Error when getting epoch switch Info", "error", err)
|
||||
return fmt.Errorf("Fail on voteHandler due to failure in getting epoch switch info")
|
||||
}
|
||||
|
||||
// Skip and wait for the next vote to process again if valid votes is less than what we required
|
||||
certThreshold := x.config.V2.Config(uint64(currentVoteMsg.(*types.Vote).ProposedBlockInfo.Round)).CertThreshold
|
||||
if len(validSignatures) < certThreshold {
|
||||
if float64(len(validSignatures)) < float64(epochInfo.MasternodesLen)*certThreshold {
|
||||
log.Warn("[onVotePoolThresholdReached] Not enough valid signatures to generate QC", "VotesSignaturesAfterFilter", validSignatures, "NumberOfValidVotes", len(validSignatures), "NumberOfVotes", len(pooledVotes))
|
||||
return nil
|
||||
}
|
||||
|
|
@ -168,7 +180,7 @@ func (x *XDPoS_v2) onVotePoolThresholdReached(chain consensus.ChainReader, poole
|
|||
Signatures: validSignatures,
|
||||
GapNumber: currentVoteMsg.(*types.Vote).GapNumber,
|
||||
}
|
||||
err := x.processQC(chain, quorumCert)
|
||||
err = x.processQC(chain, quorumCert)
|
||||
if err != nil {
|
||||
log.Error("Error while processing QC in the Vote handler after reaching pool threshold, ", err)
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -92,8 +92,8 @@ var (
|
|||
ErrInvalidTCSignatures = errors.New("Invalid TC Signatures")
|
||||
ErrEmptyBlockInfoHash = errors.New("BlockInfo hash is empty")
|
||||
ErrInvalidFieldInNonEpochSwitch = errors.New("Invalid field exist in a non-epoch swtich block")
|
||||
ErrValidatorNotWithinMasternodes = errors.New("Validaotor address is not in the master node list")
|
||||
ErrCoinbaseAndValidatorMismatch = errors.New("Validaotor and coinbase address in header does not match")
|
||||
ErrValidatorNotWithinMasternodes = errors.New("Validator address is not in the master node list")
|
||||
ErrCoinbaseAndValidatorMismatch = errors.New("Validator and coinbase address in header does not match")
|
||||
ErrNotItsTurn = errors.New("Not validator's turn to mine this block")
|
||||
|
||||
ErrRoundInvalid = errors.New("Invalid Round, it shall be bigger than QC round")
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ func TestProcessQcShallSetForensicsCommittedQc(t *testing.T) {
|
|||
|
||||
// Set round to 5
|
||||
engineV2.SetNewRoundFaker(blockchain, types.Round(5), false)
|
||||
// Create two vote messages which will not reach vote pool threshold
|
||||
// Create three vote messages which will not reach vote pool threshold
|
||||
signedHash, err := signFn(accounts.Account{Address: signer}, voteSigningHash.Bytes())
|
||||
assert.Nil(t, err)
|
||||
voteMsg := &types.Vote{
|
||||
|
|
@ -42,9 +42,9 @@ func TestProcessQcShallSetForensicsCommittedQc(t *testing.T) {
|
|||
Signature: signedHash,
|
||||
GapNumber: 450,
|
||||
}
|
||||
|
||||
err = engineV2.VoteHandler(blockchain, voteMsg)
|
||||
assert.Nil(t, err)
|
||||
|
||||
signedHash = SignHashByPK(acc1Key, voteSigningHash.Bytes())
|
||||
voteMsg = &types.Vote{
|
||||
ProposedBlockInfo: blockInfo,
|
||||
|
|
@ -54,6 +54,15 @@ func TestProcessQcShallSetForensicsCommittedQc(t *testing.T) {
|
|||
err = engineV2.VoteHandler(blockchain, voteMsg)
|
||||
assert.Nil(t, err)
|
||||
|
||||
signedHash = SignHashByPK(acc2Key, voteSigningHash.Bytes())
|
||||
voteMsg = &types.Vote{
|
||||
ProposedBlockInfo: blockInfo,
|
||||
Signature: signedHash,
|
||||
GapNumber: 450,
|
||||
}
|
||||
err = engineV2.VoteHandler(blockchain, voteMsg)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// Create another vote which is signed by someone not from the master node list
|
||||
randomSigner, randomSignFn, err := backends.SimulateWalletAddressAndSignFn()
|
||||
assert.Nil(t, err)
|
||||
|
|
|
|||
|
|
@ -140,15 +140,14 @@ func TestTimeoutPeriodAndThreadholdConfigChange(t *testing.T) {
|
|||
|
||||
// Timeout handler
|
||||
func TestTimeoutMessageHandlerSuccessfullyGenerateTCandSyncInfo(t *testing.T) {
|
||||
params.TestXDPoSMockChainConfig.XDPoS.V2.CurrentConfig = params.UnitTestV2Configs[0]
|
||||
blockchain, _, _, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 11, params.TestXDPoSMockChainConfig, nil)
|
||||
blockchain, _, _, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 905, params.TestXDPoSMockChainConfig, nil)
|
||||
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2
|
||||
|
||||
// Set round to 1
|
||||
engineV2.SetNewRoundFaker(blockchain, types.Round(1), false)
|
||||
engineV2.SetNewRoundFaker(blockchain, types.Round(5), false)
|
||||
// Create two timeout message which will not reach timeout pool threshold
|
||||
timeoutMsg := &types.Timeout{
|
||||
Round: types.Round(1),
|
||||
Round: types.Round(5),
|
||||
Signature: []byte{1},
|
||||
GapNumber: 450,
|
||||
}
|
||||
|
|
@ -156,32 +155,39 @@ func TestTimeoutMessageHandlerSuccessfullyGenerateTCandSyncInfo(t *testing.T) {
|
|||
err := engineV2.TimeoutHandler(blockchain, timeoutMsg)
|
||||
assert.Nil(t, err)
|
||||
currentRound, _, _, _, _, _ := engineV2.GetPropertiesFaker()
|
||||
assert.Equal(t, types.Round(1), currentRound)
|
||||
assert.Equal(t, types.Round(5), currentRound)
|
||||
timeoutMsg = &types.Timeout{
|
||||
Round: types.Round(1),
|
||||
Round: types.Round(5),
|
||||
Signature: []byte{2},
|
||||
GapNumber: 450,
|
||||
}
|
||||
err = engineV2.TimeoutHandler(blockchain, timeoutMsg)
|
||||
assert.Nil(t, err)
|
||||
timeoutMsg = &types.Timeout{
|
||||
Round: types.Round(5),
|
||||
Signature: []byte{3},
|
||||
GapNumber: 450,
|
||||
}
|
||||
err = engineV2.TimeoutHandler(blockchain, timeoutMsg)
|
||||
assert.Nil(t, err)
|
||||
currentRound, _, _, _, _, _ = engineV2.GetPropertiesFaker()
|
||||
assert.Equal(t, types.Round(1), currentRound)
|
||||
assert.Equal(t, types.Round(5), currentRound)
|
||||
|
||||
// Send a timeout with different gap number, it shall not trigger timeout pool hook
|
||||
timeoutMsg = &types.Timeout{
|
||||
Round: types.Round(1),
|
||||
Signature: []byte{3},
|
||||
Round: types.Round(5),
|
||||
Signature: []byte{4},
|
||||
GapNumber: 1350,
|
||||
}
|
||||
err = engineV2.TimeoutHandler(blockchain, timeoutMsg)
|
||||
assert.Nil(t, err)
|
||||
currentRound, _, _, _, _, _ = engineV2.GetPropertiesFaker()
|
||||
assert.Equal(t, types.Round(1), currentRound)
|
||||
assert.Equal(t, types.Round(5), currentRound)
|
||||
|
||||
// Create a timeout message that should trigger timeout pool hook
|
||||
timeoutMsg = &types.Timeout{
|
||||
Round: types.Round(1),
|
||||
Signature: []byte{4},
|
||||
Round: types.Round(5),
|
||||
Signature: []byte{5},
|
||||
GapNumber: 450,
|
||||
}
|
||||
|
||||
|
|
@ -200,12 +206,12 @@ func TestTimeoutMessageHandlerSuccessfullyGenerateTCandSyncInfo(t *testing.T) {
|
|||
|
||||
tc := syncInfoMsg.(*types.SyncInfo).HighestTimeoutCert
|
||||
assert.NotNil(t, tc)
|
||||
assert.Equal(t, tc.Round, types.Round(1))
|
||||
assert.Equal(t, tc.Round, types.Round(5))
|
||||
assert.Equal(t, uint64(450), tc.GapNumber)
|
||||
// The signatures shall not include the byte{3} from a different gap number
|
||||
sigatures := []types.Signature{[]byte{1}, []byte{2}, []byte{4}}
|
||||
sigatures := []types.Signature{[]byte{1}, []byte{2}, []byte{3}, []byte{5}}
|
||||
assert.ElementsMatch(t, tc.Signatures, sigatures)
|
||||
assert.Equal(t, types.Round(2), currentRound)
|
||||
assert.Equal(t, types.Round(6), currentRound)
|
||||
}
|
||||
|
||||
func TestThrowErrorIfTimeoutMsgRoundNotEqualToCurrentRound(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -235,9 +235,10 @@ func TestConfigSwitchOnDifferentCertThreshold(t *testing.T) {
|
|||
acc1SignedHash = SignHashByPK(acc1Key, types.VoteSigHash(voteForSign).Bytes())
|
||||
acc2SignedHash = SignHashByPK(acc2Key, types.VoteSigHash(voteForSign).Bytes())
|
||||
acc3SignedHash = SignHashByPK(acc3Key, types.VoteSigHash(voteForSign).Bytes())
|
||||
voteSignedHash := SignHashByPK(voterKey, types.VoteSigHash(voteForSign).Bytes())
|
||||
|
||||
var signaturesThr []types.Signature
|
||||
signaturesThr = append(signaturesThr, acc1SignedHash, acc2SignedHash, acc3SignedHash)
|
||||
signaturesThr = append(signaturesThr, acc1SignedHash, acc2SignedHash, acc3SignedHash, voteSignedHash)
|
||||
quorumCert = &types.QuorumCert{
|
||||
ProposedBlockInfo: proposedBlockInfo,
|
||||
Signatures: signaturesThr,
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ func TestVoteMessageHandlerSuccessfullyGeneratedAndProcessQCForFistV2Round(t *te
|
|||
|
||||
// Set round to 1
|
||||
engineV2.SetNewRoundFaker(blockchain, types.Round(1), false)
|
||||
// Create two vote messages which will not reach vote pool threshold
|
||||
// Create three vote messages which will not reach vote pool threshold
|
||||
signedHash, err := signFn(accounts.Account{Address: signer}, voteSigningHash.Bytes())
|
||||
assert.Nil(t, err)
|
||||
voteMsg := &types.Vote{
|
||||
|
|
@ -52,8 +52,16 @@ func TestVoteMessageHandlerSuccessfullyGeneratedAndProcessQCForFistV2Round(t *te
|
|||
assert.Equal(t, types.Round(0), highestQuorumCert.ProposedBlockInfo.Round)
|
||||
assert.Equal(t, types.Round(1), currentRound)
|
||||
|
||||
signedHash = SignHashByPK(acc2Key, voteSigningHash.Bytes())
|
||||
signedHash = SignHashByPK(acc1Key, voteSigningHash.Bytes())
|
||||
voteMsg = &types.Vote{
|
||||
ProposedBlockInfo: blockInfo,
|
||||
Signature: signedHash,
|
||||
GapNumber: 450,
|
||||
}
|
||||
err = engineV2.VoteHandler(blockchain, voteMsg)
|
||||
assert.Nil(t, err)
|
||||
|
||||
signedHash = SignHashByPK(acc2Key, voteSigningHash.Bytes())
|
||||
voteMsg = &types.Vote{
|
||||
ProposedBlockInfo: blockInfo,
|
||||
Signature: signedHash,
|
||||
|
|
@ -104,7 +112,7 @@ func TestVoteMessageHandlerSuccessfullyGeneratedAndProcessQC(t *testing.T) {
|
|||
|
||||
// Set round to 5
|
||||
engineV2.SetNewRoundFaker(blockchain, types.Round(5), false)
|
||||
// Create two vote messages which will not reach vote pool threshold
|
||||
// Create three vote messages which will not reach vote pool threshold
|
||||
signedHash, err := signFn(accounts.Account{Address: signer}, voteSigningHash.Bytes())
|
||||
assert.Nil(t, err)
|
||||
voteMsg := &types.Vote{
|
||||
|
|
@ -128,6 +136,15 @@ func TestVoteMessageHandlerSuccessfullyGeneratedAndProcessQC(t *testing.T) {
|
|||
}
|
||||
err = engineV2.VoteHandler(blockchain, voteMsg)
|
||||
assert.Nil(t, err)
|
||||
|
||||
signedHash = SignHashByPK(acc2Key, voteSigningHash.Bytes())
|
||||
voteMsg = &types.Vote{
|
||||
ProposedBlockInfo: blockInfo,
|
||||
Signature: signedHash,
|
||||
GapNumber: 450,
|
||||
}
|
||||
err = engineV2.VoteHandler(blockchain, voteMsg)
|
||||
assert.Nil(t, err)
|
||||
currentRound, lockQuorumCert, highestQuorumCert, _, _, _ = engineV2.GetPropertiesFaker()
|
||||
// Still using the initlised value because we did not yet go to the next round
|
||||
assert.Nil(t, lockQuorumCert)
|
||||
|
|
@ -213,7 +230,7 @@ func TestThrowErrorIfVoteMsgRoundIsMoreThanOneRoundAwayFromCurrentRound(t *testi
|
|||
}
|
||||
|
||||
func TestProcessVoteMsgThenTimeoutMsg(t *testing.T) {
|
||||
blockchain, _, currentBlock, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 905, params.TestXDPoSMockChainConfig, nil)
|
||||
blockchain, _, currentBlock, signer, signFn, _ := PrepareXDCTestBlockChainForV2Engine(t, 905, params.TestXDPoSMockChainConfig, nil)
|
||||
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2
|
||||
|
||||
// Set round to 5
|
||||
|
|
@ -230,15 +247,27 @@ func TestProcessVoteMsgThenTimeoutMsg(t *testing.T) {
|
|||
GapNumber: 450,
|
||||
}
|
||||
voteSigningHash := types.VoteSigHash(voteForSign)
|
||||
// Create two vote message which will not reach vote pool threshold
|
||||
signedHash := SignHashByPK(acc1Key, voteSigningHash.Bytes())
|
||||
|
||||
// Create three vote message which will not reach vote pool threshold
|
||||
signedHash, err := signFn(accounts.Account{Address: signer}, voteSigningHash.Bytes())
|
||||
assert.Nil(t, err)
|
||||
voteMsg := &types.Vote{
|
||||
ProposedBlockInfo: blockInfo,
|
||||
Signature: signedHash,
|
||||
GapNumber: 450,
|
||||
}
|
||||
|
||||
err := engineV2.VoteHandler(blockchain, voteMsg)
|
||||
err = engineV2.VoteHandler(blockchain, voteMsg)
|
||||
assert.Nil(t, err)
|
||||
|
||||
signedHash = SignHashByPK(acc1Key, voteSigningHash.Bytes())
|
||||
voteMsg = &types.Vote{
|
||||
ProposedBlockInfo: blockInfo,
|
||||
Signature: signedHash,
|
||||
GapNumber: 450,
|
||||
}
|
||||
|
||||
err = engineV2.VoteHandler(blockchain, voteMsg)
|
||||
assert.Nil(t, err)
|
||||
currentRound, lockQuorumCert, highestQuorumCert, _, _, _ := engineV2.GetPropertiesFaker()
|
||||
// initialised with nil and 0 round
|
||||
|
|
@ -302,13 +331,19 @@ func TestProcessVoteMsgThenTimeoutMsg(t *testing.T) {
|
|||
}
|
||||
err = engineV2.TimeoutHandler(blockchain, timeoutMsg)
|
||||
assert.Nil(t, err)
|
||||
timeoutMsg = &types.Timeout{
|
||||
Round: types.Round(6),
|
||||
Signature: []byte{3},
|
||||
}
|
||||
err = engineV2.TimeoutHandler(blockchain, timeoutMsg)
|
||||
assert.Nil(t, err)
|
||||
currentRound, _, _, _, _, _ = engineV2.GetPropertiesFaker()
|
||||
assert.Equal(t, types.Round(6), currentRound)
|
||||
|
||||
// Create a timeout message that should trigger timeout pool hook
|
||||
timeoutMsg = &types.Timeout{
|
||||
Round: types.Round(6),
|
||||
Signature: []byte{3},
|
||||
Signature: []byte{4},
|
||||
}
|
||||
|
||||
err = engineV2.TimeoutHandler(blockchain, timeoutMsg)
|
||||
|
|
@ -325,7 +360,7 @@ func TestProcessVoteMsgThenTimeoutMsg(t *testing.T) {
|
|||
tc := syncInfoMsg.(*types.SyncInfo).HighestTimeoutCert
|
||||
assert.NotNil(t, tc)
|
||||
assert.Equal(t, types.Round(6), tc.Round)
|
||||
sigatures := []types.Signature{[]byte{1}, []byte{2}, []byte{3}}
|
||||
sigatures := []types.Signature{[]byte{1}, []byte{2}, []byte{3}, []byte{4}}
|
||||
assert.ElementsMatch(t, tc.Signatures, sigatures)
|
||||
// Round shall be +1 now
|
||||
currentRound, _, _, _, _, _ = engineV2.GetPropertiesFaker()
|
||||
|
|
@ -430,7 +465,7 @@ func TestProcessVoteMsgFailIfVerifyBlockInfoFail(t *testing.T) {
|
|||
GapNumber: 450,
|
||||
}
|
||||
voteSigningHash := types.VoteSigHash(voteForSign)
|
||||
// Create two vote message which will not reach vote pool threshold
|
||||
// Create three vote message which will not reach vote pool threshold
|
||||
signedHash := SignHashByPK(acc1Key, voteSigningHash.Bytes())
|
||||
voteMsg := &types.Vote{
|
||||
ProposedBlockInfo: blockInfo,
|
||||
|
|
@ -453,13 +488,20 @@ func TestProcessVoteMsgFailIfVerifyBlockInfoFail(t *testing.T) {
|
|||
}
|
||||
err = engineV2.VoteHandler(blockchain, voteMsg)
|
||||
assert.Nil(t, err)
|
||||
voteMsg = &types.Vote{
|
||||
ProposedBlockInfo: blockInfo,
|
||||
Signature: SignHashByPK(acc3Key, voteSigningHash.Bytes()),
|
||||
GapNumber: 450,
|
||||
}
|
||||
err = engineV2.VoteHandler(blockchain, voteMsg)
|
||||
assert.Nil(t, err)
|
||||
currentRound, _, _, _, _, _ = engineV2.GetPropertiesFaker()
|
||||
assert.Equal(t, types.Round(5), currentRound)
|
||||
|
||||
// Create a vote message that should trigger vote pool hook
|
||||
voteMsg = &types.Vote{
|
||||
ProposedBlockInfo: blockInfo,
|
||||
Signature: SignHashByPK(acc3Key, voteSigningHash.Bytes()),
|
||||
Signature: SignHashByPK(voterKey, voteSigningHash.Bytes()),
|
||||
GapNumber: 450,
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -114,6 +114,7 @@ type EpochSwitchInfo struct {
|
|||
Penalties []common.Address
|
||||
Standbynodes []common.Address
|
||||
Masternodes []common.Address
|
||||
MasternodesLen int
|
||||
EpochSwitchBlockInfo *BlockInfo
|
||||
EpochSwitchParentBlockInfo *BlockInfo
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ var (
|
|||
MainnetV2Configs = map[uint64]*V2Config{
|
||||
Default: {
|
||||
SwitchRound: 0,
|
||||
CertThreshold: 73, // based on masternode is 108
|
||||
CertThreshold: 0.667,
|
||||
TimeoutSyncThreshold: 3,
|
||||
TimeoutPeriod: 60,
|
||||
MinePeriod: 2,
|
||||
|
|
@ -52,7 +52,7 @@ var (
|
|||
TestnetV2Configs = map[uint64]*V2Config{
|
||||
Default: {
|
||||
SwitchRound: 0,
|
||||
CertThreshold: 7, //based on masternode is 10
|
||||
CertThreshold: 0.667,
|
||||
TimeoutSyncThreshold: 3,
|
||||
TimeoutPeriod: 60,
|
||||
MinePeriod: 2,
|
||||
|
|
@ -62,7 +62,7 @@ var (
|
|||
DevnetV2Configs = map[uint64]*V2Config{
|
||||
Default: {
|
||||
SwitchRound: 0,
|
||||
CertThreshold: 73, // based on masternode is 108
|
||||
CertThreshold: 0.667,
|
||||
TimeoutSyncThreshold: 5,
|
||||
TimeoutPeriod: 10,
|
||||
MinePeriod: 2,
|
||||
|
|
@ -72,21 +72,21 @@ var (
|
|||
UnitTestV2Configs = map[uint64]*V2Config{
|
||||
Default: {
|
||||
SwitchRound: 0,
|
||||
CertThreshold: 3,
|
||||
CertThreshold: 0.667,
|
||||
TimeoutSyncThreshold: 2,
|
||||
TimeoutPeriod: 4,
|
||||
MinePeriod: 2,
|
||||
},
|
||||
10: {
|
||||
SwitchRound: 10,
|
||||
CertThreshold: 5,
|
||||
CertThreshold: 1,
|
||||
TimeoutSyncThreshold: 2,
|
||||
TimeoutPeriod: 4,
|
||||
MinePeriod: 3,
|
||||
},
|
||||
899: {
|
||||
SwitchRound: 899,
|
||||
CertThreshold: 5,
|
||||
CertThreshold: 1,
|
||||
TimeoutSyncThreshold: 4,
|
||||
TimeoutPeriod: 5,
|
||||
MinePeriod: 2,
|
||||
|
|
@ -325,11 +325,11 @@ type V2 struct {
|
|||
}
|
||||
|
||||
type V2Config struct {
|
||||
SwitchRound uint64 `json:"switchRound"` // v1 to v2 switch block number
|
||||
MinePeriod int `json:"minePeriod"` // Miner mine period to mine a block
|
||||
TimeoutSyncThreshold int `json:"timeoutSyncThreshold"` // send syncInfo after number of timeout
|
||||
TimeoutPeriod int `json:"timeoutPeriod"` // Duration in ms
|
||||
CertThreshold int `json:"certificateThreshold"` // Necessary number of messages from master nodes to form a certificate
|
||||
SwitchRound uint64 `json:"switchRound"` // v1 to v2 switch block number
|
||||
MinePeriod int `json:"minePeriod"` // Miner mine period to mine a block
|
||||
TimeoutSyncThreshold int `json:"timeoutSyncThreshold"` // send syncInfo after number of timeout
|
||||
TimeoutPeriod int `json:"timeoutPeriod"` // Duration in ms
|
||||
CertThreshold float64 `json:"certificateThreshold"` // Necessary number of messages from master nodes to form a certificate
|
||||
}
|
||||
|
||||
func (c *XDPoSConfig) String() string {
|
||||
|
|
|
|||
|
|
@ -85,11 +85,11 @@ func TestCheckCompatible(t *testing.T) {
|
|||
func TestUpdateV2Config(t *testing.T) {
|
||||
TestXDPoSMockChainConfig.XDPoS.V2.BuildConfigIndex()
|
||||
c := TestXDPoSMockChainConfig.XDPoS.V2.CurrentConfig
|
||||
assert.Equal(t, 3, c.CertThreshold)
|
||||
assert.Equal(t, 0.667, c.CertThreshold)
|
||||
|
||||
TestXDPoSMockChainConfig.XDPoS.V2.UpdateConfig(10)
|
||||
c = TestXDPoSMockChainConfig.XDPoS.V2.CurrentConfig
|
||||
assert.Equal(t, 5, c.CertThreshold)
|
||||
assert.Equal(t, float64(1), c.CertThreshold)
|
||||
|
||||
TestXDPoSMockChainConfig.XDPoS.V2.UpdateConfig(899)
|
||||
c = TestXDPoSMockChainConfig.XDPoS.V2.CurrentConfig
|
||||
|
|
@ -99,16 +99,16 @@ func TestUpdateV2Config(t *testing.T) {
|
|||
func TestV2Config(t *testing.T) {
|
||||
TestXDPoSMockChainConfig.XDPoS.V2.BuildConfigIndex()
|
||||
c := TestXDPoSMockChainConfig.XDPoS.V2.Config(1)
|
||||
assert.Equal(t, 3, c.CertThreshold)
|
||||
assert.Equal(t, 0.667, c.CertThreshold)
|
||||
|
||||
c = TestXDPoSMockChainConfig.XDPoS.V2.Config(5)
|
||||
assert.Equal(t, 3, c.CertThreshold)
|
||||
assert.Equal(t, 0.667, c.CertThreshold)
|
||||
|
||||
c = TestXDPoSMockChainConfig.XDPoS.V2.Config(10)
|
||||
assert.Equal(t, 3, c.CertThreshold)
|
||||
assert.Equal(t, 0.667, c.CertThreshold)
|
||||
|
||||
c = TestXDPoSMockChainConfig.XDPoS.V2.Config(11)
|
||||
assert.Equal(t, 5, c.CertThreshold)
|
||||
assert.Equal(t, float64(1), c.CertThreshold)
|
||||
}
|
||||
|
||||
func TestBuildConfigIndex(t *testing.T) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue