Skip to content

Commit

Permalink
Merge pull request #778 from XinFinOrg/release-br-v2.4.6-beta1-dev-up…
Browse files Browse the repository at this point in the history
…grade

Release br v2.4.6 beta1 merge back to dev upgrade
  • Loading branch information
benjamin202410 authored Dec 28, 2024
2 parents 3a0d5b6 + 77f9cc5 commit 3e62a4c
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 22 deletions.
6 changes: 2 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,8 @@ jobs:
script: go run build/ci.go test -coverage $(go list ./... | grep "github.com/XinFinOrg/XDPoSChain/[d-i].*")
- name: J-N tests
script: go run build/ci.go test -coverage $(go list ./... | grep "github.com/XinFinOrg/XDPoSChain/[j-n].*")
- name: O-R tests
script: go run build/ci.go test -coverage $(go list ./... | grep "github.com/XinFinOrg/XDPoSChain/[o-r].*")
- name: S tests
script: go run build/ci.go test -coverage $(go list ./... | grep "github.com/XinFinOrg/XDPoSChain/s.*")
- name: O-S tests
script: go run build/ci.go test -coverage $(go list ./... | grep "github.com/XinFinOrg/XDPoSChain/[o-s].*")
- name: T-Z tests
script: go run build/ci.go test -coverage $(go list ./... | grep "github.com/XinFinOrg/XDPoSChain/[t-z].*")
steps:
Expand Down
3 changes: 1 addition & 2 deletions consensus/XDPoS/engines/engine_v2/epochSwitch.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ func (x *XDPoS_v2) getEpochSwitchInfo(chain consensus.ChainReader, header *types
log.Debug("[getEpochSwitchInfo] header doesn't provide, get header by hash", "hash", hash.Hex())
h = chain.GetHeaderByHash(hash)
if h == nil {
log.Warn("[getEpochSwitchInfo] can not find header from db", "hash", hash.Hex())
return nil, fmt.Errorf("[getEpochSwitchInfo] can not find header from db hash %v", hash.Hex())
}
}
Expand Down Expand Up @@ -152,7 +151,7 @@ func (x *XDPoS_v2) IsEpochSwitch(header *types.Header) (bool, uint64, error) {
log.Info("[IsEpochSwitch] true, parent equals V2.SwitchBlock", "round", round, "number", header.Number.Uint64(), "hash", header.Hash())
return true, epochNum, nil
}
log.Debug("[IsEpochSwitch]", "is", parentRound < epochStartRound, "parentRound", parentRound, "round", round, "number", header.Number.Uint64(), "epochNum", epochNum, "hash", header.Hash())
log.Debug("[IsEpochSwitch]", "is", parentRound < epochStartRound, "parentRound", parentRound, "round", round, "number", header.Number.Uint64(), "epochNum", epochNum, "hash", header.Hash().Hex())
// if isEpochSwitch, add to cache
if parentRound < epochStartRound {
x.round2epochBlockInfo.Add(round, &types.BlockInfo{
Expand Down
43 changes: 36 additions & 7 deletions consensus/XDPoS/engines/engine_v2/timeout.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ 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)
log.Error("[verifyTC] Fail to get snapshot when verifying TC!", "tcGapNumber", timeoutCert.GapNumber)
return fmt.Errorf("[verifyTC] Unable to get snapshot, %s", err)
}
if snap == nil || len(snap.NextEpochCandidates) == 0 {
Expand All @@ -110,15 +110,42 @@ func (x *XDPoS_v2) verifyTC(chain consensus.ChainReader, timeoutCert *types.Time
}
}

epochInfo, err := x.getEpochSwitchInfo(chain, chain.CurrentHeader(), chain.CurrentHeader().Hash())
epochSwitchInfo, err := x.getEpochSwitchInfo(chain, (chain.CurrentHeader()), (chain.CurrentHeader()).Hash())
if err != nil {
log.Error("[verifyTC] Error when getting epoch switch Info", "error", err)
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)
}

epochRound := epochSwitchInfo.EpochSwitchBlockInfo.Round
tempTCEpoch := x.config.V2.SwitchBlock.Uint64()/x.config.Epoch + uint64(epochRound)/x.config.Epoch

epochBlockInfo := &types.BlockInfo{
Hash: epochSwitchInfo.EpochSwitchBlockInfo.Hash,
Round: epochRound,
Number: epochSwitchInfo.EpochSwitchBlockInfo.Number,
}
log.Info("[verifyTC] Init epochInfo", "number", epochBlockInfo.Number, "round", epochRound, "tcRound", timeoutCert.Round, "tcEpoch", tempTCEpoch)
for epochBlockInfo.Round > timeoutCert.Round {
tempTCEpoch--
epochBlockInfo, err = x.GetBlockByEpochNumber(chain, tempTCEpoch)
if err != nil {
log.Error("[verifyTC] Error when getting epoch block info by tc round", "error", err)
return fmt.Errorf("fail on verifyTC due to failure in getting epoch block info tc round, %s", err)
}
log.Debug("[verifyTC] Loop to get right epochInfo", "number", epochBlockInfo.Number, "round", epochBlockInfo.Round, "tcRound", timeoutCert.Round, "tcEpoch", tempTCEpoch)
}
tcEpoch := tempTCEpoch
log.Info("[verifyTC] Final TC epochInfo", "number", epochBlockInfo.Number, "round", epochBlockInfo.Round, "tcRound", timeoutCert.Round, "tcEpoch", tcEpoch)

epochInfo, err := x.getEpochSwitchInfo(chain, nil, epochBlockInfo.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 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)
log.Warn("[verifyTC] Invalid TC Signature is less or empty", "tcRound", timeoutCert.Round, "tcGapNumber", timeoutCert.GapNumber, "tcSignLen", len(timeoutCert.Signatures), "certThreshold", float64(epochInfo.MasternodesLen)*certThreshold)
return utils.ErrInvalidTCSignatures
}

Expand All @@ -138,14 +165,14 @@ func (x *XDPoS_v2) verifyTC(chain consensus.ChainReader, timeoutCert *types.Time
defer wg.Done()
verified, _, err := x.verifyMsgSignature(signedTimeoutObj, sig, snap.NextEpochCandidates)
if err != nil || !verified {
log.Error("[verifyTC] Error or verification failure", "Signature", sig, "Error", err)
log.Error("[verifyTC] Error or verification failure", "signature", sig, "error", err)
mutex.Lock() // Lock before accessing haveError
if haveError == nil {
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)
log.Error("[verifyTC] Error while verfying TC message signatures", "tcRound", timeoutCert.Round, "tcGapNumber", timeoutCert.GapNumber, "tcSignLen", len(signatures), "error", err)
haveError = fmt.Errorf("error while verifying TC message signatures, %s", err)
} else {
log.Warn("[verifyTC] Signature not verified doing TC verification", "timeoutCert.Round", timeoutCert.Round, "timeoutCert.GapNumber", timeoutCert.GapNumber, "Signatures len", len(signatures))
log.Warn("[verifyTC] Signature not verified doing TC verification", "tcRound", timeoutCert.Round, "tcGapNumber", timeoutCert.GapNumber, "tcSignLen", len(signatures))
haveError = errors.New("fail to verify TC due to signature mis-match")
}
}
Expand Down Expand Up @@ -219,6 +246,8 @@ func (x *XDPoS_v2) sendTimeout(chain consensus.ChainReader) error {
Signature: signedHash,
GapNumber: gapNumber,
}

timeoutMsg.SetSigner(x.signer)
log.Warn("[sendTimeout] Timeout message generated, ready to send!", "timeoutMsgRound", timeoutMsg.Round, "timeoutMsgGapNumber", timeoutMsg.GapNumber, "whosTurn", x.whosTurn)
err = x.timeoutHandler(chain, timeoutMsg)
if err != nil {
Expand Down
175 changes: 175 additions & 0 deletions consensus/tests/engine_v2_tests/sync_info_test.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package engine_v2_tests

import (
"fmt"
"math/big"
"testing"

"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
"github.com/XinFinOrg/XDPoSChain/core/types"
Expand Down Expand Up @@ -100,3 +102,176 @@ func TestSkipVerifySyncInfoIfBothQcTcNotQualified(t *testing.T) {
assert.False(t, verified)
assert.Nil(t, err)
}

func TestVerifySyncInfoIfTCRoundIsAtNextEpoch(t *testing.T) {
blockchain, _, _, _, _, _ := PrepareXDCTestBlockChainForV2Engine(t, 905, params.TestXDPoSMockChainConfig, nil)
engineV2 := blockchain.Engine().(*XDPoS.XDPoS).EngineV2

// Make the Highest QC in syncInfo point to an old block to simulate it's no longer qualified
parentBlock := blockchain.GetBlockByNumber(903)
var extraField types.ExtraFields_v2
err := utils.DecodeBytesExtraFields(parentBlock.Extra(), &extraField)
if err != nil {
t.Fatal("Fail to decode extra data", err)
}

highestTC := &types.TimeoutCert{
Round: types.Round(899),
Signatures: []types.Signature{},
}

timeoutForSign := &types.TimeoutForSign{
Round: types.Round(900),
GapNumber: 450,
}

// Sign from acc 1, 2, 3 and voter
acc1SignedHash := SignHashByPK(acc1Key, types.TimeoutSigHash(timeoutForSign).Bytes())
acc2SignedHash := SignHashByPK(acc2Key, types.TimeoutSigHash(timeoutForSign).Bytes())
acc3SignedHash := SignHashByPK(acc3Key, types.TimeoutSigHash(timeoutForSign).Bytes())
voterSignedHash := SignHashByPK(voterKey, types.TimeoutSigHash(timeoutForSign).Bytes())

var signatures []types.Signature
signatures = append(signatures, acc1SignedHash, acc2SignedHash, acc3SignedHash, voterSignedHash)

syncInfoTC := &types.TimeoutCert{
Round: timeoutForSign.Round,
Signatures: signatures,
GapNumber: timeoutForSign.GapNumber,
}

syncInfoMsg := &types.SyncInfo{
HighestQuorumCert: extraField.QuorumCert,
HighestTimeoutCert: syncInfoTC,
}

engineV2.SetPropertiesFaker(syncInfoMsg.HighestQuorumCert, highestTC)

verified, err := engineV2.VerifySyncInfoMessage(blockchain, syncInfoMsg)
assert.True(t, verified)
assert.Nil(t, err)
}

func TestVerifySyncInfoIfTcUseDifferentEpoch(t *testing.T) {
config := params.TestXDPoSMockChainConfig
blockchain, _, currentBlock, signer, signFn, _ := PrepareXDCTestBlockChainForV2Engine(t, 1349, config, nil)
adaptor := blockchain.Engine().(*XDPoS.XDPoS)
x := adaptor.EngineV2

// Insert block 1350
t.Logf("Inserting block with propose at 1350...")
blockCoinbaseA := "0xaaa0000000000000000000000000000000001350"
// NOTE: voterAddr never exist in the Masternode list, but all acc1,2,3 already does
tx, err := voteTX(37117, 0, signer.String())
if err != nil {
t.Fatal(err)
}
//Get from block validator error message
merkleRoot := "8a355a8636d1aae24d5a63df0318534e09110891d6ab7bf20587da64725083be"
header := &types.Header{
Root: common.HexToHash(merkleRoot),
Number: big.NewInt(int64(1350)),
ParentHash: currentBlock.Hash(),
Coinbase: common.HexToAddress(blockCoinbaseA),
}

header.Extra = generateV2Extra(450, currentBlock, signer, signFn, nil)

parentBlock, err := createBlockFromHeader(blockchain, header, []*types.Transaction{tx}, signer, signFn, config)
assert.Nil(t, err)
err = blockchain.InsertBlock(parentBlock)
assert.Nil(t, err)
// 1350 is a gap block, need to update the snapshot
err = blockchain.UpdateM1()
assert.Nil(t, err)
t.Logf("Inserting block from 1351 to 1799...")
for i := 1351; i <= 1799; i++ {
blockCoinbase := fmt.Sprintf("0xaaa000000000000000000000000000000000%4d", i)
//Get from block validator error message
header = &types.Header{
Root: common.HexToHash(merkleRoot),
Number: big.NewInt(int64(i)),
ParentHash: parentBlock.Hash(),
Coinbase: common.HexToAddress(blockCoinbase),
}

header.Extra = generateV2Extra(int64(i)-900, parentBlock, signer, signFn, nil)

block, err := createBlockFromHeader(blockchain, header, nil, signer, signFn, config)
if err != nil {
t.Fatal(err)
}
err = blockchain.InsertBlock(block)
assert.Nil(t, err)
parentBlock = block
}
t.Logf("build epoch block with new set of masternodes")
blockCoinbase := fmt.Sprintf("0xaaa0000000000000000000000000000000001800")
//Get from block validator error message
header = &types.Header{
Root: common.HexToHash(merkleRoot),
Number: big.NewInt(int64(1800)),
ParentHash: parentBlock.Hash(),
Coinbase: common.HexToAddress(blockCoinbase),
}

header.Extra = generateV2Extra(900, parentBlock, signer, signFn, nil)
validators := []byte{}

snap, err := x.GetSnapshot(blockchain, parentBlock.Header())
assert.Nil(t, err)

for _, v := range snap.NextEpochCandidates {
validators = append(validators, v[:]...)
}
// set up 1 more masternode to make it difference
validators = append(validators, voterAddr[:]...)
header.Validators = validators
block, err := createBlockFromHeader(blockchain, header, nil, signer, signFn, config)
if err != nil {
t.Fatal(err)
}
err = blockchain.InsertBlock(block)
assert.Nil(t, err)
parentBlock = block

var extraField types.ExtraFields_v2
err = utils.DecodeBytesExtraFields(parentBlock.Extra(), &extraField)
if err != nil {
t.Fatal("Fail to decode extra data", err)
}

timeoutForSign := &types.TimeoutForSign{
Round: types.Round(899),
GapNumber: 450,
}

// Sign from acc 1, 2, 3 and voter
acc1SignedHash := SignHashByPK(acc1Key, types.TimeoutSigHash(timeoutForSign).Bytes())
acc2SignedHash := SignHashByPK(acc2Key, types.TimeoutSigHash(timeoutForSign).Bytes())
acc3SignedHash := SignHashByPK(acc3Key, types.TimeoutSigHash(timeoutForSign).Bytes())
voterSignedHash := SignHashByPK(voterKey, types.TimeoutSigHash(timeoutForSign).Bytes())

var signatures []types.Signature
signatures = append(signatures, acc1SignedHash, acc2SignedHash, acc3SignedHash, voterSignedHash)

newTC := &types.TimeoutCert{
Round: timeoutForSign.Round,
Signatures: signatures,
GapNumber: timeoutForSign.GapNumber,
}

syncInfoMsg := &types.SyncInfo{
HighestQuorumCert: extraField.QuorumCert,
HighestTimeoutCert: newTC,
}

x.SetPropertiesFaker(syncInfoMsg.HighestQuorumCert, &types.TimeoutCert{
Round: types.Round(898),
Signatures: []types.Signature{},
})

verified, err := x.VerifySyncInfoMessage(blockchain, syncInfoMsg)
assert.True(t, verified)
assert.Nil(t, err)
}
6 changes: 3 additions & 3 deletions core/types/consensus_v2.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type BlockInfo struct {

// Vote message in XDPoS 2.0
type Vote struct {
signer common.Address //field not exported
signer common.Address //field not exported
ProposedBlockInfo *BlockInfo `json:"proposedBlockInfo"`
Signature Signature `json:"signature"`
GapNumber uint64 `json:"gapNumber"`
Expand Down Expand Up @@ -81,9 +81,9 @@ func (s *SyncInfo) Hash() common.Hash {

// Quorum Certificate struct in XDPoS 2.0
type QuorumCert struct {
ProposedBlockInfo *BlockInfo `json:"proposedBlockInfo"`
ProposedBlockInfo *BlockInfo `json:"proposedBlockInfo"`
Signatures []Signature `json:"signatures"`
GapNumber uint64 `json:"gapNumber"`
GapNumber uint64 `json:"gapNumber"`
}

// Timeout Certificate struct in XDPoS 2.0
Expand Down
4 changes: 2 additions & 2 deletions params/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,15 @@ var (
SwitchRound: 0,
CertThreshold: 0.45,
TimeoutSyncThreshold: 3,
TimeoutPeriod: 20,
TimeoutPeriod: 60,
MinePeriod: 2,
},
900000: {
MaxMasternodes: 108,
SwitchRound: 900000,
CertThreshold: 0.667,
TimeoutSyncThreshold: 3,
TimeoutPeriod: 30,
TimeoutPeriod: 60,
MinePeriod: 2,
},
}
Expand Down
8 changes: 4 additions & 4 deletions params/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ import (
)

const (
VersionMajor = 2 // Major version component of the current release
VersionMinor = 3 // Minor 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
VersionMajor = 2 // Major version component of the current release
VersionMinor = 4 // Minor version component of the current release
VersionPatch = 6 // Patch version component of the current release
VersionMeta = "beta1" // Version metadata to append to the version string
)

// Version holds the textual version string.
Expand Down

0 comments on commit 3e62a4c

Please sign in to comment.