diff --git a/.github/workflows/deploy_rpc_image.yml b/.github/workflows/deploy_rpc_image.yml index ebac65d963a5..088d809aeee8 100644 --- a/.github/workflows/deploy_rpc_image.yml +++ b/.github/workflows/deploy_rpc_image.yml @@ -6,19 +6,19 @@ on: network: type: choice description: 'devnet, testnet, or mainnet' - options: + options: - devnet - testnet - mainnet rpc_image: description: 'full image name' - + jobs: ansible: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - + - name: Update RPC nodes image uses: dawidd6/action-ansible-playbook@v2 with: @@ -38,4 +38,3 @@ jobs: - name: Send deployment notification run: | curl --location --request POST "66.94.98.186:8080/deploy?environment=${{inputs.network}}&service=xdc_rpc&version=${{inputs.rpc_image}}" - \ No newline at end of file diff --git a/consensus/XDPoS/engines/engine_v2/epochSwitch.go b/consensus/XDPoS/engines/engine_v2/epochSwitch.go index 40a684e335e3..9928b88fb25a 100644 --- a/consensus/XDPoS/engines/engine_v2/epochSwitch.go +++ b/consensus/XDPoS/engines/engine_v2/epochSwitch.go @@ -98,7 +98,7 @@ func (x *XDPoS_v2) getEpochSwitchInfo(chain consensus.ChainReader, header *types // IsEpochSwitchAtRound() is used by miner to check whether it mines a block in the same epoch with parent func (x *XDPoS_v2) isEpochSwitchAtRound(round types.Round, parentHeader *types.Header) (bool, uint64, error) { - epochNum := x.config.V2.SwitchBlock.Uint64()/x.config.Epoch + uint64(round)/x.config.Epoch + epochNum := x.config.V2.SwitchEpoch + uint64(round)/x.config.Epoch // if parent is last v1 block and this is first v2 block, this is treated as epoch switch if parentHeader.Number.Cmp(x.config.V2.SwitchBlock) == 0 { return true, epochNum, nil @@ -127,7 +127,7 @@ func (x *XDPoS_v2) GetCurrentEpochSwitchBlock(chain consensus.ChainReader, block } currentCheckpointNumber := epochSwitchInfo.EpochSwitchBlockInfo.Number.Uint64() - epochNum := x.config.V2.SwitchBlock.Uint64()/x.config.Epoch + uint64(epochSwitchInfo.EpochSwitchBlockInfo.Round)/x.config.Epoch + epochNum := x.config.V2.SwitchEpoch + uint64(epochSwitchInfo.EpochSwitchBlockInfo.Round)/x.config.Epoch return currentCheckpointNumber, epochNum, nil } @@ -145,7 +145,7 @@ func (x *XDPoS_v2) IsEpochSwitch(header *types.Header) (bool, uint64, error) { } parentRound := quorumCert.ProposedBlockInfo.Round epochStartRound := round - round%types.Round(x.config.Epoch) - epochNum := x.config.V2.SwitchBlock.Uint64()/x.config.Epoch + uint64(round)/x.config.Epoch + epochNum := x.config.V2.SwitchEpoch + uint64(round)/x.config.Epoch // if parent is last v1 block and this is first v2 block, this is treated as epoch switch if quorumCert.ProposedBlockInfo.Number.Cmp(x.config.V2.SwitchBlock) == 0 { log.Info("[IsEpochSwitch] true, parent equals V2.SwitchBlock", "round", round, "number", header.Number.Uint64(), "hash", header.Hash()) diff --git a/consensus/XDPoS/engines/engine_v2/timeout.go b/consensus/XDPoS/engines/engine_v2/timeout.go index 875dd22c9c99..169e1db7bab0 100644 --- a/consensus/XDPoS/engines/engine_v2/timeout.go +++ b/consensus/XDPoS/engines/engine_v2/timeout.go @@ -79,6 +79,43 @@ func (x *XDPoS_v2) onTimeoutPoolThresholdReached(blockChainReader consensus.Chai return nil } +func (x *XDPoS_v2) getTCEpochInfo(chain consensus.ChainReader, timeoutCert *types.TimeoutCert) (*types.EpochSwitchInfo, error) { + + epochSwitchInfo, err := x.getEpochSwitchInfo(chain, (chain.CurrentHeader()), (chain.CurrentHeader()).Hash()) + if err != nil { + log.Error("[getTCEpochInfo] Error when getting epoch switch info", "error", err) + return nil, fmt.Errorf("fail on getTCEpochInfo due to failure in getting epoch switch info, %s", err) + } + + epochRound := epochSwitchInfo.EpochSwitchBlockInfo.Round + tempTCEpoch := x.config.V2.SwitchEpoch + uint64(epochRound)/x.config.Epoch + + epochBlockInfo := &types.BlockInfo{ + Hash: epochSwitchInfo.EpochSwitchBlockInfo.Hash, + Round: epochRound, + Number: epochSwitchInfo.EpochSwitchBlockInfo.Number, + } + log.Info("[getTCEpochInfo] 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("[getTCEpochInfo] Error when getting epoch block info by tc round", "error", err) + return nil, fmt.Errorf("fail on getTCEpochInfo due to failure in getting epoch block info tc round, %s", err) + } + log.Debug("[getTCEpochInfo] Loop to get right epochInfo", "number", epochBlockInfo.Number, "round", epochBlockInfo.Round, "tcRound", timeoutCert.Round, "tcEpoch", tempTCEpoch) + } + tcEpoch := tempTCEpoch + log.Info("[getTCEpochInfo] 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("[getTCEpochInfo] Error when getting epoch switch info", "error", err) + return nil, fmt.Errorf("fail on getTCEpochInfo due to failure in getting epoch switch info, %s", err) + } + return epochInfo, nil +} + func (x *XDPoS_v2) verifyTC(chain consensus.ChainReader, timeoutCert *types.TimeoutCert) error { /* 1. Get epoch master node list by gapNumber @@ -110,37 +147,9 @@ func (x *XDPoS_v2) verifyTC(chain consensus.ChainReader, timeoutCert *types.Time } } - epochSwitchInfo, err := x.getEpochSwitchInfo(chain, (chain.CurrentHeader()), (chain.CurrentHeader()).Hash()) + epochInfo, err := x.getTCEpochInfo(chain, timeoutCert) 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) - } - - 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) + return err } certThreshold := x.config.V2.Config(uint64(timeoutCert.Round)).CertThreshold diff --git a/consensus/XDPoS/engines/engine_v2/utils.go b/consensus/XDPoS/engines/engine_v2/utils.go index 49d79177e8c1..0a0f2ad7a68f 100644 --- a/consensus/XDPoS/engines/engine_v2/utils.go +++ b/consensus/XDPoS/engines/engine_v2/utils.go @@ -296,7 +296,7 @@ func (x *XDPoS_v2) GetBlockByEpochNumber(chain consensus.ChainReader, targetEpoc if err != nil { return nil, err } - epochNum := x.config.V2.SwitchBlock.Uint64()/x.config.Epoch + uint64(epochSwitchInfo.EpochSwitchBlockInfo.Round)/x.config.Epoch + epochNum := x.config.V2.SwitchEpoch + uint64(epochSwitchInfo.EpochSwitchBlockInfo.Round)/x.config.Epoch // if current epoch is this epoch, we early return the result if targetEpochNum == epochNum { return epochSwitchInfo.EpochSwitchBlockInfo, nil @@ -304,11 +304,11 @@ func (x *XDPoS_v2) GetBlockByEpochNumber(chain consensus.ChainReader, targetEpoc if targetEpochNum > epochNum { return nil, errors.New("input epoch number > current epoch number") } - if targetEpochNum < x.config.V2.SwitchBlock.Uint64()/x.config.Epoch { + if targetEpochNum < x.config.V2.SwitchEpoch { return nil, errors.New("input epoch number < v2 begin epoch number") } // the block's round should be in [estRound,estRound+Epoch-1] - estRound := types.Round((targetEpochNum - x.config.V2.SwitchBlock.Uint64()/x.config.Epoch) * x.config.Epoch) + estRound := types.Round((targetEpochNum - x.config.V2.SwitchEpoch) * x.config.Epoch) // check the round2epochBlockInfo cache blockInfo := x.getBlockByEpochNumberInCache(chain, estRound) if blockInfo != nil { @@ -330,7 +330,7 @@ func (x *XDPoS_v2) GetBlockByEpochNumber(chain consensus.ChainReader, targetEpoc return nil, err } for _, info := range epochSwitchInfos { - epochNum := x.config.V2.SwitchBlock.Uint64()/x.config.Epoch + uint64(info.EpochSwitchBlockInfo.Round)/x.config.Epoch + epochNum := x.config.V2.SwitchEpoch + uint64(info.EpochSwitchBlockInfo.Round)/x.config.Epoch if epochNum == targetEpochNum { return info.EpochSwitchBlockInfo, nil } diff --git a/params/config.go b/params/config.go index ba9b45212a7a..6630f9b197b6 100644 --- a/params/config.go +++ b/params/config.go @@ -180,6 +180,7 @@ var ( Gap: 450, FoudationWalletAddr: common.HexToAddress("xdc92a289fe95a85c53b8d0d113cbaef0c1ec98ac65"), V2: &V2{ + SwitchEpoch: common.TIPV2SwitchBlock.Uint64() / 900, SwitchBlock: common.TIPV2SwitchBlock, CurrentConfig: MainnetV2Configs[0], AllConfigs: MainnetV2Configs, @@ -222,6 +223,7 @@ var ( Gap: 450, FoudationWalletAddr: common.HexToAddress("xdc746249c61f5832c5eed53172776b460491bdcd5c"), V2: &V2{ + SwitchEpoch: common.TIPV2SwitchBlock.Uint64() / 900, SwitchBlock: common.TIPV2SwitchBlock, CurrentConfig: TestnetV2Configs[0], AllConfigs: TestnetV2Configs, @@ -246,6 +248,7 @@ var ( Gap: 450, FoudationWalletAddr: common.HexToAddress("0x746249c61f5832c5eed53172776b460491bdcd5c"), V2: &V2{ + SwitchEpoch: common.TIPV2SwitchBlock.Uint64() / 900, SwitchBlock: common.TIPV2SwitchBlock, CurrentConfig: DevnetV2Configs[0], AllConfigs: DevnetV2Configs, @@ -269,6 +272,7 @@ var ( Period: 15, Epoch: 900, V2: &V2{ + SwitchEpoch: 9999999999 / 900, SwitchBlock: big.NewInt(9999999999), CurrentConfig: MainnetV2Configs[0], AllConfigs: MainnetV2Configs, @@ -355,6 +359,7 @@ var ( FoudationWalletAddr: common.HexToAddress("0x0000000000000000000000000000000000000068"), Reward: 250, V2: &V2{ + SwitchEpoch: 1, SwitchBlock: big.NewInt(900), CurrentConfig: UnitTestV2Configs[0], AllConfigs: UnitTestV2Configs, @@ -451,6 +456,7 @@ type XDPoSConfig struct { type V2 struct { lock sync.RWMutex // Protects the signer fields + SwitchEpoch uint64 SwitchBlock *big.Int `json:"switchBlock"` CurrentConfig *V2Config `json:"config"` AllConfigs map[uint64]*V2Config `json:"allConfigs"` diff --git a/params/config_test.go b/params/config_test.go index 3b18db4b5977..bd4113e135f1 100644 --- a/params/config_test.go +++ b/params/config_test.go @@ -117,3 +117,22 @@ func TestBuildConfigIndex(t *testing.T) { expected := []uint64{900, 10, 0} assert.Equal(t, expected, index) } + +// Test switch epoch is switchblock divide into epoch per block +func TestSwitchEpoch(t *testing.T) { + config := XDCMainnetChainConfig.XDPoS + epoch := config.Epoch + assert.Equal(t, config.V2.SwitchEpoch, config.V2.SwitchBlock.Uint64()/epoch) + + config = TestnetChainConfig.XDPoS + epoch = config.Epoch + assert.Equal(t, config.V2.SwitchEpoch, config.V2.SwitchBlock.Uint64()/epoch) + + config = DevnetChainConfig.XDPoS + epoch = config.Epoch + assert.Equal(t, config.V2.SwitchEpoch, config.V2.SwitchBlock.Uint64()/epoch) + + config = TestXDPoSMockChainConfig.XDPoS + epoch = config.Epoch + assert.Equal(t, config.V2.SwitchEpoch, config.V2.SwitchBlock.Uint64()/epoch) +}