From 153f8d296d13aa737de1ac90118ea4858d01fef1 Mon Sep 17 00:00:00 2001 From: Liam Date: Tue, 16 May 2023 21:23:02 +1000 Subject: [PATCH] Fix API penalty bug and add more info in api (#262) * fix api bug * remove cmd --- consensus/XDPoS/api.go | 25 +++++++++++++------ consensus/XDPoS/api_test.go | 20 +++++++-------- consensus/XDPoS/engines/engine_v2/engine.go | 12 ++++++--- .../XDPoS/engines/engine_v2/epochSwitch.go | 3 +++ consensus/XDPoS/engines/engine_v2/utils.go | 1 + .../tests/engine_v2_tests/penalty_test.go | 15 +++++++++++ core/types/consensus_v2.go | 1 + 7 files changed, 57 insertions(+), 20 deletions(-) diff --git a/consensus/XDPoS/api.go b/consensus/XDPoS/api.go index f8aaa22359..4a9b23d298 100644 --- a/consensus/XDPoS/api.go +++ b/consensus/XDPoS/api.go @@ -60,11 +60,13 @@ type SignerTypes struct { } type MasternodesStatus struct { + Number uint64 + Round types.Round MasternodesLen int Masternodes []common.Address - - PenaltyLen int - Penalty []common.Address + PenaltyLen int + Penalty []common.Address + Error error } type MessageStatus map[string]map[string]SignerTypes @@ -130,13 +132,22 @@ func (api *API) GetMasternodesByNumber(number *rpc.BlockNumber) MasternodesStatu } else { header = api.chain.GetHeaderByNumber(uint64(number.Int64())) } - masternodes, penalties, err := api.XDPoS.EngineV2.CalcMasternodes(api.chain, header.Number, header.ParentHash) + + round, err := api.XDPoS.EngineV2.GetRoundNumber(header) if err != nil { - return MasternodesStatus{} + return MasternodesStatus{ + Error: err, + } } + + masterNodes := api.XDPoS.EngineV2.GetMasternodes(api.chain, header) + penalties := api.XDPoS.EngineV2.GetPenalties(api.chain, header) + info := MasternodesStatus{ - MasternodesLen: len(masternodes), - Masternodes: masternodes, + Number: header.Number.Uint64(), + Round: round, + MasternodesLen: len(masterNodes), + Masternodes: masterNodes, PenaltyLen: len(penalties), Penalty: penalties, } diff --git a/consensus/XDPoS/api_test.go b/consensus/XDPoS/api_test.go index 3d4cbcd3d4..923726c010 100644 --- a/consensus/XDPoS/api_test.go +++ b/consensus/XDPoS/api_test.go @@ -17,6 +17,7 @@ func TestCalculateSignersVote(t *testing.T) { masternodes := []common.Address{{1}, {2}, {3}} vote1 := types.Vote{ + Signature: types.Signature{1}, ProposedBlockInfo: &types.BlockInfo{ Hash: common.Hash{1}, Round: types.Round(10), @@ -27,10 +28,11 @@ func TestCalculateSignersVote(t *testing.T) { vote1.SetSigner(common.Address{1}) vote2 := types.Vote{ + Signature: types.Signature{2}, ProposedBlockInfo: &types.BlockInfo{ - Hash: common.Hash{2}, - Round: types.Round(11), - Number: big.NewInt(911), + Hash: common.Hash{1}, + Round: types.Round(10), + Number: big.NewInt(910), }, GapNumber: 450, } @@ -40,9 +42,7 @@ func TestCalculateSignersVote(t *testing.T) { votes.Add(&vote2) calculateSigners(info, votes.Get(), masternodes) - - //assert.Equal(t, info["xxx"].CurrentNumber, 2) - assert.Equal(t, 2, 2) + assert.Equal(t, info["10:450:910:0x0100000000000000000000000000000000000000000000000000000000000000"].CurrentNumber, 2) } func TestCalculateSignersTimeout(t *testing.T) { @@ -52,13 +52,15 @@ func TestCalculateSignersTimeout(t *testing.T) { masternodes := []common.Address{{1}, {2}, {3}} timeout1 := types.Timeout{ + Signature: types.Signature{1}, Round: types.Round(10), GapNumber: 450, } timeout1.SetSigner(common.Address{1}) timeout2 := types.Timeout{ - Round: types.Round(11), + Signature: types.Signature{2}, + Round: types.Round(10), GapNumber: 450, } timeout1.SetSigner(common.Address{2}) @@ -67,7 +69,5 @@ func TestCalculateSignersTimeout(t *testing.T) { timeouts.Add(&timeout2) calculateSigners(info, timeouts.Get(), masternodes) - - //assert.Equal(t, info["xxx"].CurrentNumber, 2) - assert.Equal(t, 2, 2) + assert.Equal(t, info["10:450"].CurrentNumber, 2) } diff --git a/consensus/XDPoS/engines/engine_v2/engine.go b/consensus/XDPoS/engines/engine_v2/engine.go index ef8dab5a86..c71e41c72f 100644 --- a/consensus/XDPoS/engines/engine_v2/engine.go +++ b/consensus/XDPoS/engines/engine_v2/engine.go @@ -972,14 +972,20 @@ func (x *XDPoS_v2) GetMasternodesFromEpochSwitchHeader(epochSwitchHeader *types. func (x *XDPoS_v2) GetMasternodes(chain consensus.ChainReader, header *types.Header) []common.Address { epochSwitchInfo, err := x.getEpochSwitchInfo(chain, header, header.Hash()) if err != nil { - log.Error("[GetMasternodes] Adaptor v2 getEpochSwitchInfo has error, potentially bug", "err", err) + log.Error("[GetMasternodes] Adaptor v2 getEpochSwitchInfo has error", "err", err) return []common.Address{} } return epochSwitchInfo.Masternodes } -func (x *XDPoS_v2) CalcMasternodes(chain consensus.ChainReader, blockNum *big.Int, parentHash common.Hash) ([]common.Address, []common.Address, error) { - return x.calcMasternodes(chain, blockNum, parentHash) +// Given header, get master node from the epoch switch block of that epoch +func (x *XDPoS_v2) GetPenalties(chain consensus.ChainReader, header *types.Header) []common.Address { + epochSwitchInfo, err := x.getEpochSwitchInfo(chain, header, header.Hash()) + if err != nil { + log.Error("[GetMasternodes] Adaptor v2 getEpochSwitchInfo has error", "err", err) + return []common.Address{} + } + return epochSwitchInfo.Penalties } func (x *XDPoS_v2) calcMasternodes(chain consensus.ChainReader, blockNum *big.Int, parentHash common.Hash) ([]common.Address, []common.Address, error) { diff --git a/consensus/XDPoS/engines/engine_v2/epochSwitch.go b/consensus/XDPoS/engines/engine_v2/epochSwitch.go index 66feda0617..3660c15f9b 100644 --- a/consensus/XDPoS/engines/engine_v2/epochSwitch.go +++ b/consensus/XDPoS/engines/engine_v2/epochSwitch.go @@ -53,9 +53,12 @@ func (x *XDPoS_v2) getEpochSwitchInfo(chain consensus.ChainReader, header *types log.Debug("[getEpochSwitchInfo] header is epoch switch", "hash", hash.Hex(), "number", h.Number.Uint64()) quorumCert, round, masternodes, err := x.getExtraFields(h) if err != nil { + log.Error("[getEpochSwitchInfo] get extra field", "err", err, "number", h.Number.Uint64()) return nil, err } + penalties := common.ExtractAddressFromBytes(h.Penalties) epochSwitchInfo := &types.EpochSwitchInfo{ + Penalties: penalties, Masternodes: masternodes, EpochSwitchBlockInfo: &types.BlockInfo{ Hash: hash, diff --git a/consensus/XDPoS/engines/engine_v2/utils.go b/consensus/XDPoS/engines/engine_v2/utils.go index a599b662f0..88f2f40b68 100644 --- a/consensus/XDPoS/engines/engine_v2/utils.go +++ b/consensus/XDPoS/engines/engine_v2/utils.go @@ -138,6 +138,7 @@ func (x *XDPoS_v2) getExtraFields(header *types.Header) (*types.QuorumCert, type var decodedExtraField types.ExtraFields_v2 err := utils.DecodeBytesExtraFields(header.Extra, &decodedExtraField) if err != nil { + log.Error("[getExtraFields] error on decode extra fields", "err", err, "extra", header.Extra) return nil, types.Round(0), masternodes, err } return decodedExtraField.QuorumCert, decodedExtraField.Round, masternodes, nil diff --git a/consensus/tests/engine_v2_tests/penalty_test.go b/consensus/tests/engine_v2_tests/penalty_test.go index 2d84cf9ece..3b4b6887ce 100644 --- a/consensus/tests/engine_v2_tests/penalty_test.go +++ b/consensus/tests/engine_v2_tests/penalty_test.go @@ -136,3 +136,18 @@ func TestHookPenaltyV2LessThen150Blocks(t *testing.T) { assert.Nil(t, err) assert.Equal(t, 2, len(penalty)) } + +func TestGetPenalties(t *testing.T) { + config := params.TestXDPoSMockChainConfig + blockchain, _, _, _, _ := PrepareXDCTestBlockChainWithPenaltyForV2Engine(t, int(config.XDPoS.Epoch)*3, config) + adaptor := blockchain.Engine().(*XDPoS.XDPoS) + + header2699 := blockchain.GetHeaderByNumber(2699) + header1801 := blockchain.GetHeaderByNumber(1801) + + penalty2699 := adaptor.EngineV2.GetPenalties(blockchain, header2699) + penalty1801 := adaptor.EngineV2.GetPenalties(blockchain, header1801) + + assert.Equal(t, 1, len(penalty2699)) + assert.Equal(t, 1, len(penalty1801)) +} diff --git a/core/types/consensus_v2.go b/core/types/consensus_v2.go index fd2c181112..ce3090487c 100644 --- a/core/types/consensus_v2.go +++ b/core/types/consensus_v2.go @@ -111,6 +111,7 @@ func (e *ExtraFields_v2) EncodeToBytes() ([]byte, error) { } type EpochSwitchInfo struct { + Penalties []common.Address Masternodes []common.Address EpochSwitchBlockInfo *BlockInfo EpochSwitchParentBlockInfo *BlockInfo