mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 14:46:42 +00:00
apply validator id from validatorSet contract
This commit is contained in:
parent
3a3e619d4c
commit
72cbafbd16
4 changed files with 166 additions and 4 deletions
|
|
@ -620,7 +620,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash co
|
||||||
headers[i], headers[len(headers)-1-i] = headers[len(headers)-1-i], headers[i]
|
headers[i], headers[len(headers)-1-i] = headers[len(headers)-1-i], headers[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
snap, err := snap.apply(headers)
|
snap, err := snap.apply(headers, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,13 @@ type ChainSpanner struct {
|
||||||
validatorContractAddress common.Address
|
validatorContractAddress common.Address
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// validator response on ValidatorSet contract
|
||||||
|
type contractValidator struct {
|
||||||
|
Id *big.Int
|
||||||
|
Power *big.Int
|
||||||
|
Signer common.Address
|
||||||
|
}
|
||||||
|
|
||||||
func NewChainSpanner(ethAPI api.Caller, validatorSet abi.ABI, chainConfig *params.ChainConfig, validatorContractAddress common.Address) *ChainSpanner {
|
func NewChainSpanner(ethAPI api.Caller, validatorSet abi.ABI, chainConfig *params.ChainConfig, validatorContractAddress common.Address) *ChainSpanner {
|
||||||
return &ChainSpanner{
|
return &ChainSpanner{
|
||||||
ethAPI: ethAPI,
|
ethAPI: ethAPI,
|
||||||
|
|
@ -93,6 +100,141 @@ func (c *ChainSpanner) GetCurrentValidatorsByBlockNrOrHash(ctx context.Context,
|
||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
|
toAddress := c.validatorContractAddress
|
||||||
|
gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
|
||||||
|
|
||||||
|
valz, err := c.tryGetBorValidatorsWithId(ctx, blockNrOrHash, blockNumber, toAddress, gas)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return valz, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to get bor validators with Id from ValidatorSet contract by querying each element on mapping(uint256 => Validator[]) public producers
|
||||||
|
// If fails then returns GetBorValidators without id
|
||||||
|
func (c *ChainSpanner) tryGetBorValidatorsWithId(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash, blockNumber uint64, toAddress common.Address, gas hexutil.Uint64) ([]*valset.Validator, error) {
|
||||||
|
firstEndBlock, err := c.getFirstEndBlock(ctx, blockNrOrHash, toAddress, gas)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var spanNumber *big.Int
|
||||||
|
if big.NewInt(int64(blockNumber)).Cmp(firstEndBlock) <= 0 {
|
||||||
|
spanNumber = big.NewInt(0)
|
||||||
|
} else {
|
||||||
|
spanNumber, err = c.getSpanByBlock(ctx, blockNrOrHash, blockNumber, toAddress, gas)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
borValidatorsWithoutId, err := c.getBorValidatorsWithoutId(ctx, blockNrOrHash, blockNumber, toAddress, gas)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
producersCount := len(borValidatorsWithoutId)
|
||||||
|
|
||||||
|
valz := make([]*valset.Validator, producersCount)
|
||||||
|
|
||||||
|
for i := 0; i < producersCount; i++ {
|
||||||
|
p, err := c.getProducersBySpanAndIndexMethod(ctx, blockNrOrHash, blockNumber, toAddress, gas, spanNumber, i)
|
||||||
|
// if fails, return validators without id
|
||||||
|
if err != nil {
|
||||||
|
return borValidatorsWithoutId, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
valz[i] = &valset.Validator{
|
||||||
|
ID: p.Id.Uint64(),
|
||||||
|
Address: p.Signer,
|
||||||
|
VotingPower: p.Power.Int64(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return valz, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ChainSpanner) getSpanByBlock(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash, blockNumber uint64, toAddress common.Address, gas hexutil.Uint64) (*big.Int, error) {
|
||||||
|
const getSpanByBlockMethod = "getSpanByBlock"
|
||||||
|
spanData, err := c.validatorSet.Pack(getSpanByBlockMethod, big.NewInt(0).SetUint64(blockNumber))
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Unable to pack tx for getSpanByBlock", "error", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
spanMsgData := (hexutil.Bytes)(spanData)
|
||||||
|
|
||||||
|
spanResult, err := c.ethAPI.Call(ctx, ethapi.TransactionArgs{
|
||||||
|
Gas: &gas,
|
||||||
|
To: &toAddress,
|
||||||
|
Data: &spanMsgData,
|
||||||
|
}, &blockNrOrHash, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var spanNumber *big.Int
|
||||||
|
if err := c.validatorSet.UnpackIntoInterface(&spanNumber, getSpanByBlockMethod, spanResult); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return spanNumber, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ChainSpanner) getProducersBySpanAndIndexMethod(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash, blockNumber uint64, toAddress common.Address, gas hexutil.Uint64, spanNumber *big.Int, index int) (*contractValidator, error) {
|
||||||
|
const getProducersBySpanAndIndexMethod = "producers"
|
||||||
|
producerData, err := c.validatorSet.Pack(getProducersBySpanAndIndexMethod, spanNumber, big.NewInt(int64(index)))
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Unable to pack tx for producers", "error", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
producerMsgData := (hexutil.Bytes)(producerData)
|
||||||
|
|
||||||
|
result, err := c.ethAPI.Call(ctx, ethapi.TransactionArgs{
|
||||||
|
Gas: &gas,
|
||||||
|
To: &toAddress,
|
||||||
|
Data: &producerMsgData,
|
||||||
|
}, &blockNrOrHash, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var producer contractValidator
|
||||||
|
if err := c.validatorSet.UnpackIntoInterface(&producer, getProducersBySpanAndIndexMethod, result); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &producer, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ChainSpanner) getFirstEndBlock(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash, toAddress common.Address, gas hexutil.Uint64) (*big.Int, error) {
|
||||||
|
const getFirstEndBlockMethod = "FIRST_END_BLOCK"
|
||||||
|
firstEndBlockData, err := c.validatorSet.Pack(getFirstEndBlockMethod)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Unable to pack tx for getFirstEndBlock", "error", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
firstEndBlockMsgData := (hexutil.Bytes)(firstEndBlockData)
|
||||||
|
|
||||||
|
firstEndBlockResult, err := c.ethAPI.Call(ctx, ethapi.TransactionArgs{
|
||||||
|
Gas: &gas,
|
||||||
|
To: &toAddress,
|
||||||
|
Data: &firstEndBlockMsgData,
|
||||||
|
}, &blockNrOrHash, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var firstEndBlockNumber *big.Int
|
||||||
|
if err := c.validatorSet.UnpackIntoInterface(&firstEndBlockNumber, getFirstEndBlockMethod, firstEndBlockResult); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return firstEndBlockNumber, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ChainSpanner) getBorValidatorsWithoutId(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash, blockNumber uint64, toAddress common.Address, gas hexutil.Uint64) ([]*valset.Validator, error) {
|
||||||
|
|
||||||
// method
|
// method
|
||||||
const method = "getBorValidators"
|
const method = "getBorValidators"
|
||||||
|
|
||||||
|
|
@ -104,8 +246,6 @@ func (c *ChainSpanner) GetCurrentValidatorsByBlockNrOrHash(ctx context.Context,
|
||||||
|
|
||||||
// call
|
// call
|
||||||
msgData := (hexutil.Bytes)(data)
|
msgData := (hexutil.Bytes)(data)
|
||||||
toAddress := c.validatorContractAddress
|
|
||||||
gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
|
|
||||||
|
|
||||||
result, err := c.ethAPI.Call(ctx, ethapi.TransactionArgs{
|
result, err := c.ethAPI.Call(ctx, ethapi.TransactionArgs{
|
||||||
Gas: &gas,
|
Gas: &gas,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package bor
|
package bor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/consensus/bor/valset"
|
"github.com/ethereum/go-ethereum/consensus/bor/valset"
|
||||||
|
|
@ -100,7 +101,7 @@ func (s *Snapshot) copy() *Snapshot {
|
||||||
return cpy
|
return cpy
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
|
func (s *Snapshot) apply(headers []*types.Header, c *Bor) (*Snapshot, error) {
|
||||||
// Allow passing in no headers for cleaner code
|
// Allow passing in no headers for cleaner code
|
||||||
if len(headers) == 0 {
|
if len(headers) == 0 {
|
||||||
return s, nil
|
return s, nil
|
||||||
|
|
@ -157,6 +158,9 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
|
||||||
newVals, _ := valset.ParseValidators(validatorBytes)
|
newVals, _ := valset.ParseValidators(validatorBytes)
|
||||||
v := getUpdatedValidatorSet(snap.ValidatorSet.Copy(), newVals)
|
v := getUpdatedValidatorSet(snap.ValidatorSet.Copy(), newVals)
|
||||||
v.IncrementProposerPriority(1)
|
v.IncrementProposerPriority(1)
|
||||||
|
|
||||||
|
valsWithId, _ := c.spanner.GetCurrentValidatorsByHash(context.Background(), header.Hash(), header.Number.Uint64())
|
||||||
|
v.IncludeIds(valsWithId)
|
||||||
snap.ValidatorSet = v
|
snap.ValidatorSet = v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,24 @@ func (vals *ValidatorSet) IncrementProposerPriority(times int) {
|
||||||
vals.Proposer = proposer
|
vals.Proposer = proposer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IncludeIds include the proper Id of each validator by getting the id from
|
||||||
|
// validator queried on ValidatorSet contract
|
||||||
|
func (vals *ValidatorSet) IncludeIds(valsWithId []*Validator) {
|
||||||
|
if vals.IsNilOrEmpty() {
|
||||||
|
panic("empty validator set")
|
||||||
|
}
|
||||||
|
|
||||||
|
addressToId := make(map[common.Address]uint64)
|
||||||
|
|
||||||
|
for _, val := range valsWithId {
|
||||||
|
addressToId[val.Address] = val.ID
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, val := range vals.Validators {
|
||||||
|
val.ID = addressToId[val.Address]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (vals *ValidatorSet) RescalePriorities(diffMax int64) {
|
func (vals *ValidatorSet) RescalePriorities(diffMax int64) {
|
||||||
if vals.IsNilOrEmpty() {
|
if vals.IsNilOrEmpty() {
|
||||||
panic("empty validator set")
|
panic("empty validator set")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue