Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions consensus/istanbul/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,6 @@ type Backend interface {
// HasPropsal checks if the combination of the given hash and height matches any existing blocks
HasPropsal(hash common.Hash, number *big.Int) bool

// GetProposer returns the proposer of the given block height
GetProposer(number uint64) common.Address

// HasBadProposal returns whether the proposal with the hash is a bad proposal
HasBadProposal(hash common.Hash) bool

Expand All @@ -80,12 +77,4 @@ type Backend interface {
SetCurrentView(view *View)

NodeType() common.ConnType

GetValidatorSet(num uint64) (*BlockValSet, error)

GetCommitteeState(num uint64) (*RoundCommitteeState, error)

GetCommitteeStateByRound(num uint64, round uint64) (*RoundCommitteeState, error)

GetProposerByRound(num uint64, round uint64) (common.Address, error)
}
72 changes: 25 additions & 47 deletions consensus/istanbul/backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ type backend struct {
nodetype common.ConnType

isRestoringSnapshots atomic.Bool

// Committee state provider
committeeStateProvider *consensus.CommitteeStateProvider
}

func (sb *backend) NodeType() common.ConnType {
Expand Down Expand Up @@ -236,7 +239,7 @@ func (sb *backend) getTargetReceivers() map[common.Address]bool {
return targets
}

// GossipSubPeer implements istanbul.Backend.Gossip
// GossipSubPeer implements istanbul.Backend.GossipSubPeer
func (sb *backend) GossipSubPeer(prevHash common.Hash, payload []byte) {
targets := sb.getTargetReceivers()
if targets == nil {
Expand Down Expand Up @@ -386,6 +389,7 @@ func (sb *backend) HasPropsal(hash common.Hash, number *big.Int) bool {
return sb.chain.GetHeader(hash, number.Uint64()) != nil
}

// LastProposal implements istanbul.Backend.LastProposal
func (sb *backend) LastProposal() (istanbul.Proposal, common.Address) {
block := sb.currentBlock()

Expand All @@ -403,74 +407,48 @@ func (sb *backend) LastProposal() (istanbul.Proposal, common.Address) {
return block, proposer
}

// HasBadProposal implements istanbul.Backend.HasBadProposal
func (sb *backend) HasBadProposal(hash common.Hash) bool {
if sb.hasBadBlock == nil {
return false
}
return sb.hasBadBlock(hash)
}

// GetValidatorSet returns the validator set for the given block number
func (sb *backend) GetValidatorSet(num uint64) (*istanbul.BlockValSet, error) {
council, err := sb.valsetModule.GetCouncil(num)
if err != nil {
return nil, err
}

demoted, err := sb.valsetModule.GetDemotedValidators(num)
if err != nil {
return nil, err
if sb.committeeStateProvider == nil {
return nil, errInternalError
}

return istanbul.NewBlockValSet(council, demoted), nil
}

func (sb *backend) GetCommitteeState(num uint64) (*istanbul.RoundCommitteeState, error) {
header := sb.chain.GetHeaderByNumber(num)
if header == nil {
return nil, errUnknownBlock
}

return sb.GetCommitteeStateByRound(num, uint64(header.Round()))
return sb.committeeStateProvider.GetValidatorSet(num)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How's about adding getQualifiedValidators at kaiax/valset module interface?

}

// GetCommitteeStateByRound returns the committee state for the given block number and round
func (sb *backend) GetCommitteeStateByRound(num uint64, round uint64) (*istanbul.RoundCommitteeState, error) {
blockValSet, err := sb.GetValidatorSet(num)
if err != nil {
return nil, err
if sb.committeeStateProvider == nil {
return nil, errInternalError
}

committee, err := sb.valsetModule.GetCommittee(num, round)
if err != nil {
return nil, err
}

proposer, err := sb.valsetModule.GetProposer(num, round)
if err != nil {
return nil, err
}

committeeSize := sb.govModule.GetParamSet(num).CommitteeSize
return istanbul.NewRoundCommitteeState(blockValSet, committeeSize, committee, proposer), nil
return sb.committeeStateProvider.GetCommitteeStateByRound(num, round)
}

// GetProposerByRound returns the proposer address for the given block number and round
func (sb *backend) GetProposerByRound(num uint64, round uint64) (common.Address, error) {
proposer, err := sb.valsetModule.GetProposer(num, round)
if err != nil {
return common.Address{}, err
if sb.committeeStateProvider == nil {
return common.Address{}, errInternalError
}
return proposer, nil
return sb.committeeStateProvider.GetProposerByRound(num, round)
}

// GetProposer implements istanbul.Backend.GetProposer
func (sb *backend) GetProposer(number uint64) common.Address {
if h := sb.chain.GetHeaderByNumber(number); h != nil {
a, _ := sb.Author(h)
return a
func (sb *backend) getCommitteeState(num uint64) (*istanbul.RoundCommitteeState, error) {
header := sb.chain.GetHeaderByNumber(num)
if header == nil {
return nil, errUnknownBlock
}
return common.Address{}

return sb.GetCommitteeStateByRound(num, uint64(header.Round()))
}

func (sb *backend) GetRewardAddress(num uint64, nodeId common.Address) common.Address {
func (sb *backend) getRewardAddress(num uint64, nodeId common.Address) common.Address {
sInfo, err := sb.stakingModule.GetStakingInfo(num)
if err != nil {
return common.Address{}
Expand Down
16 changes: 0 additions & 16 deletions consensus/istanbul/backend/backend_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,19 +269,3 @@ func TestCommit(t *testing.T) {
engine.Stop()
}
}

func TestGetProposer(t *testing.T) {
ctrl, mStaking := makeMockStakingManager(t, nil, 0)
defer ctrl.Finish()

configItems := []interface{}{mStaking}
configItems = append(configItems, lowerBoundBaseFee(2))
configItems = append(configItems, upperBoundBaseFee(10))
chain, engine := newBlockChain(1, configItems...)
defer engine.Stop()

block := makeBlockWithSeal(chain, engine, chain.Genesis())
_, err := chain.InsertChain(types.Blocks{block})
assert.NoError(t, err)
assert.Equal(t, engine.GetProposer(1), engine.Address())
}
8 changes: 6 additions & 2 deletions consensus/istanbul/backend/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@ func (sb *backend) Finalize(chain consensus.ChainReader, header *types.Header, s
// TODO-Kaia Let's redesign below logic and remove dependency between block reward and istanbul consensus.
var (
blockNum = header.Number.Uint64()
rewardAddress = sb.GetRewardAddress(blockNum, sb.address)
rewardAddress = sb.getRewardAddress(blockNum, sb.address)
)

valSet, err := sb.GetValidatorSet(blockNum)
Expand Down Expand Up @@ -706,6 +706,10 @@ func (sb *backend) RegisterKaiaxModules(mGov gov.GovModule, mStaking staking.Sta
sb.RegisterStakingModule(mStaking)
sb.valsetModule = mValset
sb.randaoModule = mRandao
// Initialize committee state provider with the registered modules
sb.committeeStateProvider = consensus.NewCommitteeStateProvider(mValset, mGov)
// Set the provider to the core
sb.core.SetCommitteeStateProvider(sb.committeeStateProvider)
}

func (sb *backend) RegisterStakingModule(module staking.StakingModule) {
Expand Down Expand Up @@ -797,7 +801,7 @@ func (sb *backend) GetConsensusInfo(block *types.Block) (consensus.ConsensusInfo

var currentCommittee []common.Address

currentRoundCState, err := sb.GetCommitteeState(block.NumberU64())
currentRoundCState, err := sb.getCommitteeState(block.NumberU64())
if err == nil {
currentCommittee = currentRoundCState.Committee().List()
}
Expand Down
14 changes: 9 additions & 5 deletions consensus/istanbul/core/commit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,23 @@ func TestCore_sendCommit(t *testing.T) {
{"invalid case - not committee", 2, false},
} {
{
mockBackend, mockCtrl := newMockBackend(t, validatorAddrs)
backend, mockCtrl := newMockBackend(t, validatorAddrs)
wrapper := backend.(*testBackendWrapper)
if tc.valid {
mockBackend.EXPECT().Sign(gomock.Any()).Return(nil, nil).AnyTimes()
mockBackend.EXPECT().Broadcast(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
wrapper.mockBackend.EXPECT().Sign(gomock.Any()).Return(nil, nil).AnyTimes()
wrapper.mockBackend.EXPECT().Broadcast(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
}

istConfig := istanbul.DefaultConfig.Copy()
istConfig.ProposerPolicy = istanbul.WeightedRandom

istCore := New(mockBackend, istConfig).(*core)
istCore := New(backend, istConfig).(*core)
// Set up test committee state provider
testProvider := &testCommitteeStateProvider{wrapper: wrapper}
istCore.committeeStateProvider = testProvider
assert.NoError(t, istCore.Start())

lastProposal, _ := mockBackend.LastProposal()
lastProposal, _ := backend.LastProposal()
proposal, err := genBlock(lastProposal.(*types.Block), validatorKeyMap[validatorAddrs[0]])
assert.NoError(t, err)

Expand Down
31 changes: 25 additions & 6 deletions consensus/istanbul/core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/kaiachain/kaia/blockchain/types"
"github.com/kaiachain/kaia/common"
"github.com/kaiachain/kaia/common/prque"
"github.com/kaiachain/kaia/consensus"
"github.com/kaiachain/kaia/consensus/istanbul"
"github.com/kaiachain/kaia/event"
"github.com/kaiachain/kaia/log"
Expand Down Expand Up @@ -111,6 +112,9 @@ type core struct {

councilSizeGauge metrics.Gauge
committeeSizeGauge metrics.Gauge

// Committee state provider
committeeStateProvider consensus.CommitteeStateProviderInterface
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second thought, i think it would be better to inject the valset and the govModule. What do you think?

}

func (c *core) finalizeMessage(msg *message) ([]byte, error) {
Expand Down Expand Up @@ -266,7 +270,12 @@ func (c *core) startNewRound(round *big.Int) {
}
}

c.currentCommittee, err = c.backend.GetCommitteeStateByRound(newView.Sequence.Uint64(), round.Uint64())
// Get committee state using committee state provider
if c.committeeStateProvider == nil {
logger.Error("Committee state provider is not set")
return
}
c.currentCommittee, err = c.committeeStateProvider.GetCommitteeStateByRound(newView.Sequence.Uint64(), round.Uint64())
if err != nil {
logger.Error("Failed to get current round's committee state", "err", err)
return
Expand Down Expand Up @@ -321,11 +330,16 @@ func (c *core) catchUpRound(view *istanbul.View) {
c.updateRoundState(view, c.currentCommittee, true)
c.roundChangeSet.Clear(view.Round)

newProposer, err := c.backend.GetProposerByRound(view.Sequence.Uint64(), view.Round.Uint64())
if err != nil {
logger.Warn("Failed to get proposer by round", "err", err)
// The newProposer is only for logging purpose, so we don't need to return here.
// If there's error, it'll be handled in the `startNewRound` anyway.
// Get proposer using committee state provider
var newProposer common.Address
var err error
if c.committeeStateProvider != nil {
newProposer, err = c.committeeStateProvider.GetProposerByRound(view.Sequence.Uint64(), view.Round.Uint64())
if err != nil {
logger.Warn("Failed to get proposer by round", "err", err)
// The newProposer is only for logging purpose, so we don't need to return here.
// If there's error, it'll be handled in the `startNewRound` anyway.
}
}

c.newRoundChangeTimer()
Expand Down Expand Up @@ -437,6 +451,11 @@ func (c *core) checkValidatorSignature(data []byte, sig []byte) (common.Address,
return c.currentCommittee.CheckValidatorSignature(data, sig)
}

// SetCommitteeStateProvider sets the committee state provider for the core
func (c *core) SetCommitteeStateProvider(provider consensus.CommitteeStateProviderInterface) {
c.committeeStateProvider = provider
}

// PrepareCommittedSeal returns a committed seal for the given hash
func PrepareCommittedSeal(hash common.Hash) []byte {
var buf bytes.Buffer
Expand Down
Loading