mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 18:32:23 +00:00
verify validators info at checkpoint block
This commit is contained in:
parent
f7c2902315
commit
a7c149d76b
5 changed files with 78 additions and 39 deletions
|
|
@ -71,7 +71,7 @@ func (api *API) GetSigners(number *rpc.BlockNumber) ([]common.Address, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return snap.signers(), nil
|
||||
return snap.GetSigners(), nil
|
||||
}
|
||||
|
||||
// GetSignersAtHash retrieves the state snapshot at a given block.
|
||||
|
|
@ -84,7 +84,7 @@ func (api *API) GetSignersAtHash(hash common.Hash) ([]common.Address, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return snap.signers(), nil
|
||||
return snap.GetSigners(), nil
|
||||
}
|
||||
|
||||
// Proposals returns the current proposals the node tries to uphold and vote on.
|
||||
|
|
|
|||
|
|
@ -136,6 +136,8 @@ var (
|
|||
// on an instant chain (0 second period). It's important to refuse these as the
|
||||
// block reward is zero, so an empty block just bloats the chain... fast.
|
||||
errWaitTransactions = errors.New("waiting for transactions")
|
||||
|
||||
ErrInvalidCheckpointValidators = errors.New("invalid validators list on checkpoint block")
|
||||
)
|
||||
|
||||
// SignerFn is a signer callback function to request a hash to be signed by a
|
||||
|
|
@ -216,6 +218,7 @@ type Posv struct {
|
|||
HookReward func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) error
|
||||
HookPenalty func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error)
|
||||
HookPrepare func(header *types.Header, signers []common.Address) error
|
||||
VerifyValidators func(header *types.Header, signers []common.Address) error
|
||||
}
|
||||
|
||||
// New creates a Posv proof-of-stake-voting consensus engine with the initial
|
||||
|
|
@ -379,7 +382,7 @@ func (c *Posv) verifyCascadingFields(chain consensus.ChainReader, header *types.
|
|||
return errInvalidCheckpointPenalties
|
||||
}
|
||||
}
|
||||
signers := snap.signers()
|
||||
signers := snap.GetSigners()
|
||||
signers = common.RemoveItemFromArray(signers, penPenalties)
|
||||
for i := 1; i <= common.LimitPenaltyEpoch; i++ {
|
||||
if number > uint64(i)*c.config.Epoch {
|
||||
|
|
@ -391,6 +394,12 @@ func (c *Posv) verifyCascadingFields(chain consensus.ChainReader, header *types.
|
|||
if !bytes.Equal(header.Extra[extraVanity:extraSuffix], byteMasterNodes) {
|
||||
return errInvalidCheckpointSigners
|
||||
}
|
||||
if c.VerifyValidators != nil {
|
||||
err := c.VerifyValidators(header, signers)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
// All basic checks passed, verify the seal and return
|
||||
return c.verifySeal(chain, header, parents)
|
||||
|
|
@ -581,7 +590,7 @@ func (c *Posv) verifySeal(chain consensus.ChainReader, header *types.Header, par
|
|||
mstring = append(mstring, m.String())
|
||||
}
|
||||
nstring := []string{}
|
||||
for _, n := range snap.signers() {
|
||||
for _, n := range snap.GetSigners() {
|
||||
nstring = append(nstring, n.String())
|
||||
}
|
||||
if _, ok := snap.Signers[signer]; !ok {
|
||||
|
|
@ -656,7 +665,7 @@ func (c *Posv) Prepare(chain consensus.ChainReader, header *types.Header) error
|
|||
header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, extraVanity-len(header.Extra))...)
|
||||
}
|
||||
header.Extra = header.Extra[:extraVanity]
|
||||
signers := snap.signers()
|
||||
signers := snap.GetSigners()
|
||||
if number%c.config.Epoch == 0 {
|
||||
if c.HookPenalty != nil {
|
||||
penSigners, err := c.HookPenalty(chain, number)
|
||||
|
|
@ -698,6 +707,9 @@ func (c *Posv) Prepare(chain consensus.ChainReader, header *types.Header) error
|
|||
}
|
||||
if c.HookPrepare != nil {
|
||||
c.HookPrepare(header, signers)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -710,7 +722,7 @@ func (c *Posv) UpdateMasternodes(chain consensus.ChainReader, header *types.Head
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
currentSigners := snap.signers()
|
||||
currentSigners := snap.GetSigners()
|
||||
proposedSigners := make(map[common.Address]struct{})
|
||||
// count all addresses in ms to be masternode
|
||||
for _, m := range ms {
|
||||
|
|
@ -724,7 +736,7 @@ func (c *Posv) UpdateMasternodes(chain consensus.ChainReader, header *types.Head
|
|||
}
|
||||
}
|
||||
nm := []string{}
|
||||
newSigners := snap.signers()
|
||||
newSigners := snap.GetSigners()
|
||||
for _, n := range newSigners {
|
||||
nm = append(nm, n.String())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
|
|||
}
|
||||
|
||||
// signers retrieves the list of authorized signers in ascending order.
|
||||
func (s *Snapshot) signers() []common.Address {
|
||||
func (s *Snapshot) GetSigners() []common.Address {
|
||||
signers := make([]common.Address, 0, len(s.Signers))
|
||||
for signer := range s.Signers {
|
||||
signers = append(signers, signer)
|
||||
|
|
@ -303,7 +303,7 @@ func (s *Snapshot) signers() []common.Address {
|
|||
|
||||
// inturn returns if a signer at a given block height is in-turn or not.
|
||||
func (s *Snapshot) inturn(number uint64, signer common.Address) bool {
|
||||
signers, offset := s.signers(), 0
|
||||
signers, offset := s.GetSigners(), 0
|
||||
for offset < len(signers) && signers[offset] != signer {
|
||||
offset++
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,4 +34,6 @@ var (
|
|||
ErrNonceTooHigh = errors.New("nonce too high")
|
||||
|
||||
ErrNotPoSV = errors.New("Posv not found in config")
|
||||
|
||||
ErrNotFoundM1 = errors.New("list M1 not found ")
|
||||
)
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import (
|
|||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"bytes"
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
|
|
@ -211,36 +212,13 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||
|
||||
// Hook will process when preparing block.
|
||||
c.HookPrepare = func(header *types.Header, signers []common.Address) error {
|
||||
client, err := eth.blockchain.GetClient()
|
||||
if err != nil {
|
||||
log.Error("Fail to connect IPC client for penalty.", "error", err)
|
||||
}
|
||||
number := header.Number.Int64()
|
||||
// Check m2 exists on chaindb.
|
||||
// Get secrets and opening at epoc block checkpoint.
|
||||
if number > 0 && number%common.EpocBlockRandomize == 0 {
|
||||
var candidates []int64
|
||||
lenSigners := int64(len(signers))
|
||||
|
||||
if lenSigners > 0 {
|
||||
for _, addr := range signers {
|
||||
random, err := contracts.GetRandomizeFromContract(client, addr)
|
||||
validators, err := GetValidators(eth.blockchain, signers)
|
||||
if err != nil {
|
||||
log.Error("Fail to get random m2 from contract.", "error", err)
|
||||
}
|
||||
candidates = append(candidates, random)
|
||||
}
|
||||
|
||||
// Get randomize m2 list.
|
||||
m2, err := contracts.GenM2FromRandomize(candidates, lenSigners)
|
||||
if err != nil {
|
||||
log.Error("Can not get m2 from randomize SC", "error", err)
|
||||
}
|
||||
if len(m2) > 0 {
|
||||
header.Validators = contracts.BuildValidatorFromM2(m2)
|
||||
log.Debug("New set Validators", "m2", m2, "number", header.Number.Uint64())
|
||||
}
|
||||
return err
|
||||
}
|
||||
header.Validators = validators
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -330,6 +308,19 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||
|
||||
return nil
|
||||
}
|
||||
c.VerifyValidators = func(header *types.Header, signers []common.Address) error {
|
||||
number := header.Number.Int64()
|
||||
if number > 0 && number%common.EpocBlockRandomize == 0 {
|
||||
validators, err := GetValidators(eth.blockchain, signers)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !bytes.Equal(header.Validators, validators) {
|
||||
return posv.ErrInvalidCheckpointValidators
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return eth, nil
|
||||
|
|
@ -606,3 +597,37 @@ func (s *Ethereum) Stop() error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetValidators(bc *core.BlockChain, masternodes []common.Address) ([]byte, error) {
|
||||
if bc.Config().Posv == nil {
|
||||
return nil, core.ErrNotPoSV
|
||||
}
|
||||
client, err := bc.GetClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Check m2 exists on chaindb.
|
||||
// Get secrets and opening at epoc block checkpoint.
|
||||
|
||||
var candidates []int64
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lenSigners := int64(len(masternodes))
|
||||
if lenSigners > 0 {
|
||||
for _, addr := range masternodes {
|
||||
random, err := contracts.GetRandomizeFromContract(client, addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
candidates = append(candidates, random)
|
||||
}
|
||||
// Get randomize m2 list.
|
||||
m2, err := contracts.GenM2FromRandomize(candidates, lenSigners)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return contracts.BuildValidatorFromM2(m2), nil
|
||||
}
|
||||
return nil, core.ErrNotFoundM1
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue