Skip to content

Commit f6389ae

Browse files
committed
dbft: use Governance contract for validators calculations
A part of #14. Signed-off-by: Anna Shaleva <[email protected]>
1 parent eebf53e commit f6389ae

File tree

3 files changed

+706
-9
lines changed

3 files changed

+706
-9
lines changed

consensus/dbft/dbft.go

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"math"
2929
"math/big"
3030
"sort"
31+
"strings"
3132
"sync"
3233
"sync/atomic"
3334
"time"
@@ -243,6 +244,11 @@ func New(config *params.DBFTConfig, _ ethdb.Database) (*DBFT, error) {
243244
copy(conf.StandByValidators, config.StandByValidators)
244245
slices.SortFunc(conf.StandByValidators, common.Address.Cmp)
245246

247+
govABI, err := abi.JSON(strings.NewReader(systemcontracts.GovernanceABI))
248+
if err != nil {
249+
return nil, fmt.Errorf("failed to parse Governance contract ABI")
250+
}
251+
246252
c := &DBFT{
247253
config: &conf,
248254
blockQueue: newBlockQueue(),
@@ -253,6 +259,8 @@ func New(config *params.DBFTConfig, _ ethdb.Database) (*DBFT, error) {
253259

254260
quit: make(chan struct{}),
255261
finished: make(chan struct{}),
262+
263+
governanceABI: govABI,
256264
}
257265

258266
logger, _ := zap.NewDevelopment()
@@ -1375,6 +1383,7 @@ func payloadFromMessage(ep *dbftproto.Message) *Payload {
13751383

13761384
func (c *DBFT) validatePayload(p *Payload) bool {
13771385
h := c.chain.CurrentBlock()
1386+
// TODO: need validators cache at least for payloads verification, otherwise we'll end up in endless state-dependent computations.
13781387
validators, err := c.getNextBlockValidators(h.Hash(), h.Number.Uint64(), false)
13791388
if err != nil {
13801389
return false
@@ -1593,7 +1602,8 @@ func (c *DBFT) APIs(chain consensus.ChainHeaderReader) []rpc.API {
15931602
// to be sorted by bytes order (even if returned from governance contract).
15941603
func (c *DBFT) getNextBlockValidators(blockHash common.Hash, blockNum uint64, compute bool) ([]common.Address, error) {
15951604
// Currently we don't have governance contract, thus, always return standby set.
1596-
if true {
1605+
// TODO: to be removed.
1606+
if blockNum == 0 {
15971607
return c.config.StandByValidators, nil
15981608
}
15991609

@@ -1603,13 +1613,20 @@ func (c *DBFT) getNextBlockValidators(blockHash common.Hash, blockNum uint64, co
16031613

16041614
// Once we have governance contract, we don't need StandByValidators in the dBFT's
16051615
// config, governance contract will handle it internally.
1606-
blockNr := rpc.BlockNumberOrHashWithHash(blockHash, false)
1616+
blockNr := rpc.BlockNumberOrHashWithNumber(rpc.BlockNumber(blockNum))
16071617

16081618
// Different values depending on dBFT epoch.
1609-
method := "getNextBlockValidators" // current epoch validators
1610-
if compute {
1611-
method = "computeNextBlockValidators" // current epoch validators for the middle of dBFT epoch and next epoch validators for the last block in epoch
1612-
}
1619+
method := "getCurrentConsensus" // current epoch validators
1620+
/*if compute {
1621+
// TODO: given time-dependent `EPOCH_DURATION`, calculation of next consensus becomes complicated. We need
1622+
// `getNextConsensus` API to be presented in Governance contract since `getConsensus` is not enough.
1623+
// `getConsensus` calculates consensus based on the current state, even if epoch is not finished yet. What we need
1624+
// is `getNextConsensus` that returns current epoch validators for the middle of dBFT epoch and next epoch validators
1625+
// for the last block in the epoch. We can organize this at the code-level, but it complicates getNextBlockValidators call, so
1626+
// why not to move it to the contract level where it costs nothing.
1627+
// @roman-khimov, agree?
1628+
method = "getNextConsensus" // current epoch validators for the middle of dBFT epoch and next epoch validators for the last block in epoch
1629+
}*/
16131630

16141631
ctx, cancel := context.WithCancel(context.Background())
16151632
// Cancel when we are finished consuming integers
@@ -1621,7 +1638,7 @@ func (c *DBFT) getNextBlockValidators(blockHash common.Hash, blockNum uint64, co
16211638
}
16221639
// do smart contract call
16231640
msgData := (hexutil.Bytes)(data)
1624-
toAddress := common.HexToAddress(systemcontracts.GovernanceContract)
1641+
toAddress := common.HexToAddress(systemcontracts.GovernanceHash)
16251642
gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
16261643
result, err := c.ethAPI.Call(ctx, ethapi.TransactionArgs{
16271644
Gas: &gas,
@@ -1634,6 +1651,10 @@ func (c *DBFT) getNextBlockValidators(blockHash common.Hash, blockNum uint64, co
16341651

16351652
var valSet []common.Address
16361653
err = c.governanceABI.UnpackIntoInterface(&valSet, method, result)
1654+
1655+
// TODO: roman-khimov, we've agreed that validators are sorted using lexicographic order, but in contract they are
1656+
// sorted by votes. Need to come to some single solution.
1657+
slices.SortFunc(valSet, common.Address.Cmp)
16371658
return valSet, err
16381659
}
16391660

0 commit comments

Comments
 (0)