mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
refactor XDPoS to accommodate multiple consensus engine versions
This commit is contained in:
parent
a0046ff4be
commit
fcbc5a28e1
21 changed files with 1722 additions and 1389 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -48,3 +48,5 @@ profile.cov
|
|||
/dashboard/assets/package-lock.json
|
||||
|
||||
**/yarn-error.log
|
||||
coverage.txt
|
||||
go.sum
|
||||
|
|
@ -4,6 +4,10 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/XDCx"
|
||||
"github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate"
|
||||
"github.com/XinFinOrg/XDPoSChain/XDCxDAO"
|
||||
|
|
@ -12,9 +16,6 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/p2p"
|
||||
"gopkg.in/karalabe/cookiejar.v2/collections/prque"
|
||||
"math/big"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -6,6 +6,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
)
|
||||
|
|
@ -34,7 +35,7 @@ func TestGetM1M2FromCheckpointHeader(t *testing.T) {
|
|||
currentHeader := &types.Header{
|
||||
Number: big.NewInt(currentNumber),
|
||||
}
|
||||
m1m2, moveM2, err := getM1M2(masternodes, validators, currentHeader, config)
|
||||
m1m2, moveM2, err := utils.GetM1M2(masternodes, validators, currentHeader, config)
|
||||
if err != nil {
|
||||
t.Error("can't get m1m2", "err", err)
|
||||
}
|
||||
|
|
@ -66,19 +67,19 @@ func TestCompareSignersLists(t *testing.T) {
|
|||
common.StringToAddress("dddddddddddddddddddddddddddddddddddddddd"),
|
||||
common.StringToAddress("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"),
|
||||
}
|
||||
if !compareSignersLists(list1, list2) {
|
||||
if !utils.CompareSignersLists(list1, list2) {
|
||||
t.Error("list1 should be equal to list2", "list1", list1, "list2", list2)
|
||||
}
|
||||
if compareSignersLists(list1, list3) {
|
||||
if utils.CompareSignersLists(list1, list3) {
|
||||
t.Error("list1 and list3 should not be same", "list1", list1, "list3", list3)
|
||||
}
|
||||
if !compareSignersLists([]common.Address{}, []common.Address{}) {
|
||||
if !utils.CompareSignersLists([]common.Address{}, []common.Address{}) {
|
||||
t.Error("Failed with empty list")
|
||||
}
|
||||
if !compareSignersLists([]common.Address{common.StringToAddress("cccccccccccccccccccccccccccccccccccccccc")}, []common.Address{common.StringToAddress("cccccccccccccccccccccccccccccccccccccccc")}) {
|
||||
if !utils.CompareSignersLists([]common.Address{common.StringToAddress("cccccccccccccccccccccccccccccccccccccccc")}, []common.Address{common.StringToAddress("cccccccccccccccccccccccccccccccccccccccc")}) {
|
||||
t.Error("Failed with list has only one signer")
|
||||
}
|
||||
if compareSignersLists([]common.Address{common.StringToAddress("aaaaaaaaaaaaaaaa")}, []common.Address{common.StringToAddress("cccccccccccccccccccccccccccccccccccccccc")}) {
|
||||
if utils.CompareSignersLists([]common.Address{common.StringToAddress("aaaaaaaaaaaaaaaa")}, []common.Address{common.StringToAddress("cccccccccccccccccccccccccccccccccccccccc")}) {
|
||||
t.Error("Failed with list has only one signer")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,11 +16,13 @@
|
|||
package XDPoS
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/rpc"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
// API is a user facing RPC API to allow controlling the signer and voting
|
||||
|
|
@ -39,7 +41,7 @@ type NetworkInformation struct {
|
|||
}
|
||||
|
||||
// GetSnapshot retrieves the state snapshot at a given block.
|
||||
func (api *API) GetSnapshot(number *rpc.BlockNumber) (*Snapshot, error) {
|
||||
func (api *API) GetSnapshot(number *rpc.BlockNumber) (*utils.PublicApiSnapshot, error) {
|
||||
// Retrieve the requested block number (or current if none requested)
|
||||
var header *types.Header
|
||||
if number == nil || *number == rpc.LatestBlockNumber {
|
||||
|
|
@ -49,18 +51,18 @@ func (api *API) GetSnapshot(number *rpc.BlockNumber) (*Snapshot, error) {
|
|||
}
|
||||
// Ensure we have an actually valid block and return its snapshot
|
||||
if header == nil {
|
||||
return nil, errUnknownBlock
|
||||
return nil, utils.ErrUnknownBlock
|
||||
}
|
||||
return api.XDPoS.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
|
||||
return api.XDPoS.GetSnapshot(api.chain, header)
|
||||
}
|
||||
|
||||
// GetSnapshotAtHash retrieves the state snapshot at a given block.
|
||||
func (api *API) GetSnapshotAtHash(hash common.Hash) (*Snapshot, error) {
|
||||
func (api *API) GetSnapshotAtHash(hash common.Hash) (*utils.PublicApiSnapshot, error) {
|
||||
header := api.chain.GetHeaderByHash(hash)
|
||||
if header == nil {
|
||||
return nil, errUnknownBlock
|
||||
return nil, utils.ErrUnknownBlock
|
||||
}
|
||||
return api.XDPoS.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
|
||||
return api.XDPoS.GetSnapshot(api.chain, header)
|
||||
}
|
||||
|
||||
// GetSigners retrieves the list of authorized signers at the specified block.
|
||||
|
|
@ -74,31 +76,22 @@ func (api *API) GetSigners(number *rpc.BlockNumber) ([]common.Address, error) {
|
|||
}
|
||||
// Ensure we have an actually valid block and return the signers from its snapshot
|
||||
if header == nil {
|
||||
return nil, errUnknownBlock
|
||||
return nil, utils.ErrUnknownBlock
|
||||
}
|
||||
snap, err := api.XDPoS.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return snap.GetSigners(), nil
|
||||
|
||||
return api.XDPoS.GetAuthorisedSignersFromSnapshot(api.chain, header)
|
||||
}
|
||||
|
||||
// GetSignersAtHash retrieves the state snapshot at a given block.
|
||||
func (api *API) GetSignersAtHash(hash common.Hash) ([]common.Address, error) {
|
||||
header := api.chain.GetHeaderByHash(hash)
|
||||
if header == nil {
|
||||
return nil, errUnknownBlock
|
||||
return nil, utils.ErrUnknownBlock
|
||||
}
|
||||
snap, err := api.XDPoS.snapshot(api.chain, header.Number.Uint64(), header.Hash(), nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return snap.GetSigners(), nil
|
||||
return api.XDPoS.GetAuthorisedSignersFromSnapshot(api.chain, header)
|
||||
}
|
||||
|
||||
func (api *API) NetworkInformation() NetworkInformation {
|
||||
api.XDPoS.lock.RLock()
|
||||
defer api.XDPoS.lock.RUnlock()
|
||||
info := NetworkInformation{}
|
||||
info.NetworkId = api.chain.Config().ChainId
|
||||
info.XDCValidatorAddress = common.HexToAddress(common.MasternodeVotingSMC)
|
||||
|
|
|
|||
1145
consensus/XDPoS/engines/engine_v1/engine.go
Normal file
1145
consensus/XDPoS/engines/engine_v1/engine.go
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1,25 +1,11 @@
|
|||
// Copyright (c) 2018 XDPoSChain
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package XDPoS
|
||||
package engine_v1
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/clique"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||
|
|
@ -44,7 +30,7 @@ import (
|
|||
//}
|
||||
|
||||
// Snapshot is the state of the authorization voting at a given point in time.
|
||||
type Snapshot struct {
|
||||
type SnapshotV1 struct {
|
||||
config *params.XDPoSConfig // Consensus engine parameters to fine tune behavior
|
||||
sigcache *lru.ARCCache // Cache of recent block signatures to speed up ecrecover
|
||||
|
||||
|
|
@ -59,8 +45,8 @@ type Snapshot struct {
|
|||
// newSnapshot creates a new snapshot with the specified startup parameters. This
|
||||
// method does not initialize the set of recent signers, so only ever use if for
|
||||
// the genesis block.
|
||||
func newSnapshot(config *params.XDPoSConfig, sigcache *lru.ARCCache, number uint64, hash common.Hash, signers []common.Address) *Snapshot {
|
||||
snap := &Snapshot{
|
||||
func newSnapshot(config *params.XDPoSConfig, sigcache *lru.ARCCache, number uint64, hash common.Hash, signers []common.Address) *SnapshotV1 {
|
||||
snap := &SnapshotV1{
|
||||
config: config,
|
||||
sigcache: sigcache,
|
||||
Number: number,
|
||||
|
|
@ -76,12 +62,12 @@ func newSnapshot(config *params.XDPoSConfig, sigcache *lru.ARCCache, number uint
|
|||
}
|
||||
|
||||
// loadSnapshot loads an existing snapshot from the database.
|
||||
func loadSnapshot(config *params.XDPoSConfig, sigcache *lru.ARCCache, db ethdb.Database, hash common.Hash) (*Snapshot, error) {
|
||||
func loadSnapshot(config *params.XDPoSConfig, sigcache *lru.ARCCache, db ethdb.Database, hash common.Hash) (*SnapshotV1, error) {
|
||||
blob, err := db.Get(append([]byte("XDPoS-"), hash[:]...))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
snap := new(Snapshot)
|
||||
snap := new(SnapshotV1)
|
||||
if err := json.Unmarshal(blob, snap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -91,8 +77,8 @@ func loadSnapshot(config *params.XDPoSConfig, sigcache *lru.ARCCache, db ethdb.D
|
|||
return snap, nil
|
||||
}
|
||||
|
||||
// store inserts the snapshot into the database.
|
||||
func (s *Snapshot) store(db ethdb.Database) error {
|
||||
// store inserts the SnapshotV1 into the database.
|
||||
func (s *SnapshotV1) store(db ethdb.Database) error {
|
||||
blob, err := json.Marshal(s)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -100,9 +86,9 @@ func (s *Snapshot) store(db ethdb.Database) error {
|
|||
return db.Put(append([]byte("XDPoS-"), s.Hash[:]...), blob)
|
||||
}
|
||||
|
||||
// copy creates a deep copy of the snapshot, though not the individual votes.
|
||||
func (s *Snapshot) copy() *Snapshot {
|
||||
cpy := &Snapshot{
|
||||
// copy creates a deep copy of the SnapshotV1, though not the individual votes.
|
||||
func (s *SnapshotV1) copy() *SnapshotV1 {
|
||||
cpy := &SnapshotV1{
|
||||
config: s.config,
|
||||
sigcache: s.sigcache,
|
||||
Number: s.Number,
|
||||
|
|
@ -128,13 +114,13 @@ func (s *Snapshot) copy() *Snapshot {
|
|||
|
||||
// validVote returns whether it makes sense to cast the specified vote in the
|
||||
// given snapshot context (e.g. don't try to add an already authorized signer).
|
||||
func (s *Snapshot) validVote(address common.Address, authorize bool) bool {
|
||||
func (s *SnapshotV1) validVote(address common.Address, authorize bool) bool {
|
||||
_, signer := s.Signers[address]
|
||||
return (signer && !authorize) || (!signer && authorize)
|
||||
}
|
||||
|
||||
// cast adds a new vote into the tally.
|
||||
func (s *Snapshot) cast(address common.Address, authorize bool) bool {
|
||||
func (s *SnapshotV1) cast(address common.Address, authorize bool) bool {
|
||||
// Ensure the vote is meaningful
|
||||
if !s.validVote(address, authorize) {
|
||||
return false
|
||||
|
|
@ -150,7 +136,7 @@ func (s *Snapshot) cast(address common.Address, authorize bool) bool {
|
|||
}
|
||||
|
||||
// uncast removes a previously cast vote from the tally.
|
||||
func (s *Snapshot) uncast(address common.Address, authorize bool) bool {
|
||||
func (s *SnapshotV1) uncast(address common.Address, authorize bool) bool {
|
||||
// If there's no tally, it's a dangling vote, just drop
|
||||
tally, ok := s.Tally[address]
|
||||
if !ok {
|
||||
|
|
@ -170,9 +156,9 @@ func (s *Snapshot) uncast(address common.Address, authorize bool) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// apply creates a new authorization snapshot by applying the given headers to
|
||||
// apply creates a new authorization SnapshotV1 by applying the given headers to
|
||||
// the original one.
|
||||
func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
|
||||
func (s *SnapshotV1) apply(headers []*types.Header) (*SnapshotV1, error) {
|
||||
// Allow passing in no headers for cleaner code
|
||||
if len(headers) == 0 {
|
||||
return s, nil
|
||||
|
|
@ -180,13 +166,13 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
|
|||
// Sanity check that the headers can be applied
|
||||
for i := 0; i < len(headers)-1; i++ {
|
||||
if headers[i+1].Number.Uint64() != headers[i].Number.Uint64()+1 {
|
||||
return nil, errInvalidVotingChain
|
||||
return nil, utils.ErrInvalidVotingChain
|
||||
}
|
||||
}
|
||||
if headers[0].Number.Uint64() != s.Number+1 {
|
||||
return nil, errInvalidVotingChain
|
||||
return nil, utils.ErrInvalidVotingChain
|
||||
}
|
||||
// Iterate through the headers and create a new snapshot
|
||||
// Iterate through the headers and create a new SnapshotV1
|
||||
snap := s.copy()
|
||||
|
||||
for _, header := range headers {
|
||||
|
|
@ -230,12 +216,12 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
|
|||
// Tally up the new vote from the signer
|
||||
var authorize bool
|
||||
switch {
|
||||
case bytes.Equal(header.Nonce[:], nonceAuthVote):
|
||||
case bytes.Equal(header.Nonce[:], utils.NonceAuthVote):
|
||||
authorize = true
|
||||
case bytes.Equal(header.Nonce[:], nonceDropVote):
|
||||
case bytes.Equal(header.Nonce[:], utils.NonceDropVote):
|
||||
authorize = false
|
||||
default:
|
||||
return nil, errInvalidVote
|
||||
return nil, utils.ErrInvalidVote
|
||||
}
|
||||
if snap.cast(header.Coinbase, authorize) {
|
||||
snap.Votes = append(snap.Votes, &clique.Vote{
|
||||
|
|
@ -286,7 +272,7 @@ func (s *Snapshot) apply(headers []*types.Header) (*Snapshot, error) {
|
|||
}
|
||||
|
||||
// signers retrieves the list of authorized signers in ascending order.
|
||||
func (s *Snapshot) GetSigners() []common.Address {
|
||||
func (s *SnapshotV1) GetSigners() []common.Address {
|
||||
signers := make([]common.Address, 0, len(s.Signers))
|
||||
for signer := range s.Signers {
|
||||
signers = append(signers, signer)
|
||||
|
|
@ -300,12 +286,3 @@ func (s *Snapshot) GetSigners() []common.Address {
|
|||
}
|
||||
return signers
|
||||
}
|
||||
|
||||
// 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.GetSigners(), 0
|
||||
for offset < len(signers) && signers[offset] != signer {
|
||||
offset++
|
||||
}
|
||||
return (number % uint64(len(signers))) == uint64(offset)
|
||||
}
|
||||
1
consensus/XDPoS/engines/engine_v2/engine.go
Normal file
1
consensus/XDPoS/engines/engine_v2/engine.go
Normal file
|
|
@ -0,0 +1 @@
|
|||
package engine_v2
|
||||
1
consensus/XDPoS/engines/engine_v2/snapshot.go
Normal file
1
consensus/XDPoS/engines/engine_v2/snapshot.go
Normal file
|
|
@ -0,0 +1 @@
|
|||
package engine_v2
|
||||
25
consensus/XDPoS/utils/constants.go
Normal file
25
consensus/XDPoS/utils/constants.go
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"github.com/XinFinOrg/XDPoSChain/common/hexutil"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
)
|
||||
|
||||
// XDPoS delegated-proof-of-stake protocol constants.
|
||||
var (
|
||||
EpochLength = uint64(900) // Default number of blocks after which to checkpoint and reset the pending votes
|
||||
|
||||
ExtraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity
|
||||
ExtraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal
|
||||
|
||||
NonceAuthVote = hexutil.MustDecode("0xffffffffffffffff") // Magic nonce number to vote on adding a new signer
|
||||
NonceDropVote = hexutil.MustDecode("0x0000000000000000") // Magic nonce number to vote on removing a signer.
|
||||
|
||||
UncleHash = types.CalcUncleHash(nil) // Always Keccak256(RLP([])) as uncles are meaningless outside of PoW.
|
||||
)
|
||||
|
||||
const (
|
||||
InmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory
|
||||
BlockSignersCacheLimit = 9000
|
||||
M2ByteLength = 4
|
||||
)
|
||||
74
consensus/XDPoS/utils/errors.go
Normal file
74
consensus/XDPoS/utils/errors.go
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
package utils
|
||||
|
||||
import "errors"
|
||||
|
||||
// Various error messages to mark blocks invalid. These should be private to
|
||||
// prevent engine specific errors from being referenced in the remainder of the
|
||||
// codebase, inherently breaking if the engine is swapped out. Please put common
|
||||
// error types into the consensus package.
|
||||
var (
|
||||
// errUnknownBlock is returned when the list of signers is requested for a block
|
||||
// that is not part of the local blockchain.
|
||||
ErrUnknownBlock = errors.New("unknown block")
|
||||
|
||||
// errInvalidCheckpointBeneficiary is returned if a checkpoint/epoch transition
|
||||
// block has a beneficiary set to non-zeroes.
|
||||
ErrInvalidCheckpointBeneficiary = errors.New("beneficiary in checkpoint block non-zero")
|
||||
|
||||
// errInvalidVote is returned if a nonce value is something else that the two
|
||||
// allowed constants of 0x00..0 or 0xff..f.
|
||||
ErrInvalidVote = errors.New("vote nonce not 0x00..0 or 0xff..f")
|
||||
|
||||
// errInvalidCheckpointVote is returned if a checkpoint/epoch transition block
|
||||
// has a vote nonce set to non-zeroes.
|
||||
ErrInvalidCheckpointVote = errors.New("vote nonce in checkpoint block non-zero")
|
||||
|
||||
// errMissingVanity is returned if a block's extra-data section is shorter than
|
||||
// 32 bytes, which is required to store the signer vanity.
|
||||
ErrMissingVanity = errors.New("extra-data 32 byte vanity prefix missing")
|
||||
|
||||
// errMissingSignature is returned if a block's extra-data section doesn't seem
|
||||
// to contain a 65 byte secp256k1 signature.
|
||||
ErrMissingSignature = errors.New("extra-data 65 byte suffix signature missing")
|
||||
|
||||
// errExtraSigners is returned if non-checkpoint block contain signer data in
|
||||
// their extra-data fields.
|
||||
ErrExtraSigners = errors.New("non-checkpoint block contains extra signer list")
|
||||
|
||||
// errInvalidCheckpointSigners is returned if a checkpoint block contains an
|
||||
// invalid list of signers (i.e. non divisible by 20 bytes, or not the correct
|
||||
// ones).
|
||||
ErrInvalidCheckpointSigners = errors.New("invalid signer list on checkpoint block")
|
||||
|
||||
ErrInvalidCheckpointPenalties = errors.New("invalid penalty list on checkpoint block")
|
||||
|
||||
// errInvalidMixDigest is returned if a block's mix digest is non-zero.
|
||||
ErrInvalidMixDigest = errors.New("non-zero mix digest")
|
||||
|
||||
// errInvalidUncleHash is returned if a block contains an non-empty uncle list.
|
||||
ErrInvalidUncleHash = errors.New("non empty uncle hash")
|
||||
|
||||
// errInvalidDifficulty is returned if the difficulty of a block is not either
|
||||
// of 1 or 2, or if the value does not match the turn of the signer.
|
||||
ErrInvalidDifficulty = errors.New("invalid difficulty")
|
||||
|
||||
// ErrInvalidTimestamp is returned if the timestamp of a block is lower than
|
||||
// the previous block's timestamp + the minimum block period.
|
||||
ErrInvalidTimestamp = errors.New("invalid timestamp")
|
||||
|
||||
// errInvalidVotingChain is returned if an authorization list is attempted to
|
||||
// be modified via out-of-range or non-contiguous headers.
|
||||
ErrInvalidVotingChain = errors.New("invalid voting chain")
|
||||
|
||||
// errUnauthorized is returned if a header is signed by a non-authorized entity.
|
||||
ErrUnauthorized = errors.New("unauthorized")
|
||||
|
||||
ErrFailedDoubleValidation = errors.New("wrong pair of creator-validator in double validation")
|
||||
|
||||
// errWaitTransactions is returned if an empty block is attempted to be sealed
|
||||
// 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")
|
||||
)
|
||||
58
consensus/XDPoS/utils/types.go
Normal file
58
consensus/XDPoS/utils/types.go
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/XDCx/tradingstate"
|
||||
"github.com/XinFinOrg/XDPoSChain/XDCxlending/lendingstate"
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/clique"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"gopkg.in/karalabe/cookiejar.v2/collections/prque"
|
||||
)
|
||||
|
||||
type Masternode struct {
|
||||
Address common.Address
|
||||
Stake *big.Int
|
||||
}
|
||||
|
||||
type TradingService interface {
|
||||
GetTradingStateRoot(block *types.Block, author common.Address) (common.Hash, error)
|
||||
GetTradingState(block *types.Block, author common.Address) (*tradingstate.TradingStateDB, error)
|
||||
HasTradingState(block *types.Block, author common.Address) bool
|
||||
GetStateCache() tradingstate.Database
|
||||
GetTriegc() *prque.Prque
|
||||
ApplyOrder(header *types.Header, coinbase common.Address, chain consensus.ChainContext, statedb *state.StateDB, XDCXstatedb *tradingstate.TradingStateDB, orderBook common.Hash, order *tradingstate.OrderItem) ([]map[string]string, []*tradingstate.OrderItem, error)
|
||||
UpdateMediumPriceBeforeEpoch(epochNumber uint64, tradingStateDB *tradingstate.TradingStateDB, statedb *state.StateDB) error
|
||||
IsSDKNode() bool
|
||||
SyncDataToSDKNode(takerOrder *tradingstate.OrderItem, txHash common.Hash, txMatchTime time.Time, statedb *state.StateDB, trades []map[string]string, rejectedOrders []*tradingstate.OrderItem, dirtyOrderCount *uint64) error
|
||||
RollbackReorgTxMatch(txhash common.Hash) error
|
||||
GetTokenDecimal(chain consensus.ChainContext, statedb *state.StateDB, tokenAddr common.Address) (*big.Int, error)
|
||||
}
|
||||
|
||||
type LendingService interface {
|
||||
GetLendingStateRoot(block *types.Block, author common.Address) (common.Hash, error)
|
||||
GetLendingState(block *types.Block, author common.Address) (*lendingstate.LendingStateDB, error)
|
||||
HasLendingState(block *types.Block, author common.Address) bool
|
||||
GetStateCache() lendingstate.Database
|
||||
GetTriegc() *prque.Prque
|
||||
ApplyOrder(header *types.Header, coinbase common.Address, chain consensus.ChainContext, statedb *state.StateDB, lendingStateDB *lendingstate.LendingStateDB, tradingStateDb *tradingstate.TradingStateDB, lendingOrderBook common.Hash, order *lendingstate.LendingItem) ([]*lendingstate.LendingTrade, []*lendingstate.LendingItem, error)
|
||||
GetCollateralPrices(header *types.Header, chain consensus.ChainContext, statedb *state.StateDB, tradingStateDb *tradingstate.TradingStateDB, collateralToken common.Address, lendingToken common.Address) (*big.Int, *big.Int, error)
|
||||
GetMediumTradePriceBeforeEpoch(chain consensus.ChainContext, statedb *state.StateDB, tradingStateDb *tradingstate.TradingStateDB, baseToken common.Address, quoteToken common.Address) (*big.Int, error)
|
||||
ProcessLiquidationData(header *types.Header, chain consensus.ChainContext, statedb *state.StateDB, tradingState *tradingstate.TradingStateDB, lendingState *lendingstate.LendingStateDB) (updatedTrades map[common.Hash]*lendingstate.LendingTrade, liquidatedTrades, autoRepayTrades, autoTopUpTrades, autoRecallTrades []*lendingstate.LendingTrade, err error)
|
||||
SyncDataToSDKNode(chain consensus.ChainContext, state *state.StateDB, block *types.Block, takerOrderInTx *lendingstate.LendingItem, txHash common.Hash, txMatchTime time.Time, trades []*lendingstate.LendingTrade, rejectedOrders []*lendingstate.LendingItem, dirtyOrderCount *uint64) error
|
||||
UpdateLiquidatedTrade(blockTime uint64, result lendingstate.FinalizedResult, trades map[common.Hash]*lendingstate.LendingTrade) error
|
||||
RollbackLendingData(txhash common.Hash) error
|
||||
}
|
||||
|
||||
type PublicApiSnapshot struct {
|
||||
Number uint64 `json:"number"` // Block number where the snapshot was created
|
||||
Hash common.Hash `json:"hash"` // Block hash where the snapshot was created
|
||||
Signers map[common.Address]struct{} `json:"signers"` // Set of authorized signers at this moment
|
||||
Recents map[uint64]common.Address `json:"recents"` // Set of recent signers for spam protections
|
||||
Votes []*clique.Vote `json:"votes"` // List of votes cast in chronological order
|
||||
Tally map[common.Address]clique.Tally `json:"tally"` // Current vote tally to avoid recalculating
|
||||
}
|
||||
111
consensus/XDPoS/utils/utils.go
Normal file
111
consensus/XDPoS/utils/utils.go
Normal file
|
|
@ -0,0 +1,111 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
"github.com/XinFinOrg/XDPoSChain/log"
|
||||
"github.com/XinFinOrg/XDPoSChain/params"
|
||||
)
|
||||
|
||||
func Position(list []common.Address, x common.Address) int {
|
||||
for i, item := range list {
|
||||
if item == x {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func Hop(len, pre, cur int) int {
|
||||
switch {
|
||||
case pre < cur:
|
||||
return cur - (pre + 1)
|
||||
case pre > cur:
|
||||
return (len - pre) + (cur - 1)
|
||||
default:
|
||||
return len - 1
|
||||
}
|
||||
}
|
||||
|
||||
// Extract validators from byte array.
|
||||
func ExtractValidatorsFromBytes(byteValidators []byte) []int64 {
|
||||
lenValidator := len(byteValidators) / M2ByteLength
|
||||
var validators []int64
|
||||
for i := 0; i < lenValidator; i++ {
|
||||
trimByte := bytes.Trim(byteValidators[i*M2ByteLength:(i+1)*M2ByteLength], "\x00")
|
||||
intNumber, err := strconv.Atoi(string(trimByte))
|
||||
if err != nil {
|
||||
log.Error("Can not convert string to integer", "error", err)
|
||||
return []int64{}
|
||||
}
|
||||
validators = append(validators, int64(intNumber))
|
||||
}
|
||||
|
||||
return validators
|
||||
}
|
||||
|
||||
// Get masternodes address from checkpoint Header.
|
||||
func GetMasternodesFromCheckpointHeader(checkpointHeader *types.Header) []common.Address {
|
||||
masternodes := make([]common.Address, (len(checkpointHeader.Extra)-ExtraVanity-ExtraSeal)/common.AddressLength)
|
||||
for i := 0; i < len(masternodes); i++ {
|
||||
copy(masternodes[i][:], checkpointHeader.Extra[ExtraVanity+i*common.AddressLength:])
|
||||
}
|
||||
return masternodes
|
||||
}
|
||||
|
||||
// Get m2 list from checkpoint block.
|
||||
func GetM1M2FromCheckpointHeader(checkpointHeader *types.Header, currentHeader *types.Header, config *params.ChainConfig) (map[common.Address]common.Address, error) {
|
||||
if checkpointHeader.Number.Uint64()%common.EpocBlockRandomize != 0 {
|
||||
return nil, errors.New("This block is not checkpoint block epoc.")
|
||||
}
|
||||
// Get signers from this block.
|
||||
masternodes := GetMasternodesFromCheckpointHeader(checkpointHeader)
|
||||
validators := ExtractValidatorsFromBytes(checkpointHeader.Validators)
|
||||
m1m2, _, err := GetM1M2(masternodes, validators, currentHeader, config)
|
||||
if err != nil {
|
||||
return map[common.Address]common.Address{}, err
|
||||
}
|
||||
return m1m2, nil
|
||||
}
|
||||
|
||||
func GetM1M2(masternodes []common.Address, validators []int64, currentHeader *types.Header, config *params.ChainConfig) (map[common.Address]common.Address, uint64, error) {
|
||||
m1m2 := map[common.Address]common.Address{}
|
||||
maxMNs := len(masternodes)
|
||||
moveM2 := uint64(0)
|
||||
if len(validators) < maxMNs {
|
||||
return nil, moveM2, errors.New("len(m2) is less than len(m1)")
|
||||
}
|
||||
if maxMNs > 0 {
|
||||
isForked := config.IsTIPRandomize(currentHeader.Number)
|
||||
if isForked {
|
||||
moveM2 = ((currentHeader.Number.Uint64() % config.XDPoS.Epoch) / uint64(maxMNs)) % uint64(maxMNs)
|
||||
}
|
||||
for i, m1 := range masternodes {
|
||||
m2Index := uint64(validators[i] % int64(maxMNs))
|
||||
m2Index = (m2Index + moveM2) % uint64(maxMNs)
|
||||
m1m2[m1] = masternodes[m2Index]
|
||||
}
|
||||
}
|
||||
return m1m2, moveM2, nil
|
||||
}
|
||||
|
||||
// compare 2 signers lists
|
||||
// return true if they are same elements, otherwise return false
|
||||
func CompareSignersLists(list1 []common.Address, list2 []common.Address) bool {
|
||||
if len(list1) == 0 && len(list2) == 0 {
|
||||
return true
|
||||
}
|
||||
sort.Slice(list1, func(i, j int) bool {
|
||||
return list1[i].String() <= list1[j].String()
|
||||
})
|
||||
sort.Slice(list2, func(i, j int) bool {
|
||||
return list2[i].String() <= list2[j].String()
|
||||
})
|
||||
return reflect.DeepEqual(list1, list2)
|
||||
}
|
||||
|
|
@ -35,7 +35,9 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/common/hexutil"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
|
||||
"github.com/XinFinOrg/XDPoSChain/contracts/blocksigner/contract"
|
||||
randomizeContract "github.com/XinFinOrg/XDPoSChain/contracts/randomize/contract"
|
||||
"github.com/XinFinOrg/XDPoSChain/core"
|
||||
|
|
@ -278,7 +280,7 @@ func BuildValidatorFromM2(listM2 []int64) []byte {
|
|||
var validatorBytes []byte
|
||||
for _, numberM2 := range listM2 {
|
||||
// Convert number to byte.
|
||||
m2Byte := common.LeftPadBytes([]byte(fmt.Sprintf("%d", numberM2)), XDPoS.M2ByteLength)
|
||||
m2Byte := common.LeftPadBytes([]byte(fmt.Sprintf("%d", numberM2)), utils.M2ByteLength)
|
||||
validatorBytes = append(validatorBytes, m2Byte...)
|
||||
}
|
||||
|
||||
|
|
@ -292,7 +294,7 @@ func DecodeValidatorsHexData(validatorsStr string) ([]int64, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
return XDPoS.ExtractValidatorsFromBytes(validatorsByte), nil
|
||||
return utils.ExtractValidatorsFromBytes(validatorsByte), nil
|
||||
}
|
||||
|
||||
// Decrypt randomize from secrets and opening.
|
||||
|
|
@ -350,7 +352,7 @@ func GetRewardForCheckpoint(c *XDPoS.XDPoS, chain consensus.ChainReader, header
|
|||
}
|
||||
}
|
||||
header = chain.GetHeader(header.ParentHash, prevCheckpoint)
|
||||
masternodes := XDPoS.GetMasternodesFromCheckpointHeader(header)
|
||||
masternodes := utils.GetMasternodesFromCheckpointHeader(header)
|
||||
|
||||
for i := startBlockNumber; i <= endBlockNumber; i++ {
|
||||
if i%common.MergeSignRange == 0 || !chain.Config().IsTIP2019(big.NewInt(int64(i))) {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/accounts/abi/bind"
|
||||
"github.com/XinFinOrg/XDPoSChain/accounts/abi/bind/backends"
|
||||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
|
||||
"github.com/XinFinOrg/XDPoSChain/contracts/blocksigner"
|
||||
"github.com/XinFinOrg/XDPoSChain/core"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
|
|
@ -191,7 +191,7 @@ func TestGenM2FromRandomize(t *testing.T) {
|
|||
func TestBuildValidatorFromM2(t *testing.T) {
|
||||
a := []int64{84, 58, 27, 96, 127, 60, 136, 20, 121, 31, 87, 85, 40, 120, 149, 109, 141, 145, 11, 110, 147, 35, 76, 46, 34, 108, 72, 103, 102, 12, 23, 47, 70, 86, 125, 112, 128, 13, 130, 98, 126, 62, 132, 111, 134, 6, 106, 67, 24, 91, 101, 50, 94, 43, 77, 73, 129, 71, 51, 10, 92, 29, 80, 95, 33, 100, 124, 75, 38, 133, 79, 83, 61, 36, 122, 99, 16, 28, 18, 116, 140, 97, 119, 82, 148, 48, 56, 32, 93, 107, 69, 68, 123, 81, 22, 137, 25, 115, 44, 8, 42, 131, 143, 17, 55, 89, 9, 15, 19, 59, 146, 54, 5, 30, 41, 144, 117, 1, 104, 49, 105, 45, 88, 78, 74, 135, 0, 21, 57, 3, 66, 52, 63, 138, 4, 114, 37, 118, 14, 2, 26, 7, 65, 139, 39, 64, 90, 142, 53, 113}
|
||||
b := BuildValidatorFromM2(a)
|
||||
c := XDPoS.ExtractValidatorsFromBytes(b)
|
||||
c := utils.ExtractValidatorsFromBytes(b)
|
||||
if !isArrayEqual([][]int64{a}, [][]int64{c}) {
|
||||
t.Errorf("Fail to get m2 result %v", b)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/common/mclock"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
|
||||
contractValidator "github.com/XinFinOrg/XDPoSChain/contracts/validator/contract"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/state"
|
||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||
|
|
@ -877,8 +878,8 @@ func (bc *BlockChain) SaveData() {
|
|||
var lendingTriedb *trie.Database
|
||||
engine, _ := bc.Engine().(*XDPoS.XDPoS)
|
||||
triedb := bc.stateCache.TrieDB()
|
||||
var tradingService XDPoS.TradingService
|
||||
var lendingService XDPoS.LendingService
|
||||
var tradingService utils.TradingService
|
||||
var lendingService utils.LendingService
|
||||
if bc.Config().IsTIPXDCX(bc.CurrentBlock().Number()) && bc.chainConfig.XDPoS != nil && bc.CurrentBlock().NumberU64() > bc.chainConfig.XDPoS.Epoch && engine != nil {
|
||||
tradingService = engine.GetXDCXService()
|
||||
if tradingService != nil && tradingService.GetStateCache() != nil {
|
||||
|
|
@ -1201,9 +1202,9 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types.
|
|||
}
|
||||
engine, _ := bc.Engine().(*XDPoS.XDPoS)
|
||||
var tradingTrieDb *trie.Database
|
||||
var tradingService XDPoS.TradingService
|
||||
var tradingService utils.TradingService
|
||||
var lendingTrieDb *trie.Database
|
||||
var lendingService XDPoS.LendingService
|
||||
var lendingService utils.LendingService
|
||||
if bc.Config().IsTIPXDCX(block.Number()) && bc.chainConfig.XDPoS != nil && block.NumberU64() > bc.chainConfig.XDPoS.Epoch && engine != nil {
|
||||
tradingService = engine.GetXDCXService()
|
||||
if tradingService != nil {
|
||||
|
|
@ -1541,8 +1542,8 @@ func (bc *BlockChain) insertChain(chain types.Blocks) (int, []interface{}, []*ty
|
|||
// clear the previous dry-run cache
|
||||
var tradingState *tradingstate.TradingStateDB
|
||||
var lendingState *lendingstate.LendingStateDB
|
||||
var tradingService XDPoS.TradingService
|
||||
var lendingService XDPoS.LendingService
|
||||
var tradingService utils.TradingService
|
||||
var lendingService utils.LendingService
|
||||
isSDKNode := false
|
||||
if bc.Config().IsTIPXDCX(block.Number()) && bc.chainConfig.XDPoS != nil && engine != nil && block.NumberU64() > bc.chainConfig.XDPoS.Epoch {
|
||||
tradingService = engine.GetXDCXService()
|
||||
|
|
@ -1827,8 +1828,8 @@ func (bc *BlockChain) getResultBlock(block *types.Block, verifiedM2 bool) (*Resu
|
|||
|
||||
var tradingState *tradingstate.TradingStateDB
|
||||
var lendingState *lendingstate.LendingStateDB
|
||||
var tradingService XDPoS.TradingService
|
||||
var lendingService XDPoS.LendingService
|
||||
var tradingService utils.TradingService
|
||||
var lendingService utils.LendingService
|
||||
isSDKNode := false
|
||||
if bc.Config().IsTIPXDCX(block.Number()) && bc.chainConfig.XDPoS != nil && engine != nil && block.NumberU64() > bc.chainConfig.XDPoS.Epoch {
|
||||
tradingService = engine.GetXDCXService()
|
||||
|
|
@ -2481,7 +2482,7 @@ func (bc *BlockChain) UpdateM1() error {
|
|||
return err
|
||||
}
|
||||
|
||||
var ms []XDPoS.Masternode
|
||||
var ms []utils.Masternode
|
||||
for _, candidate := range candidates {
|
||||
v, err := validator.GetCandidateCap(opts, candidate)
|
||||
if err != nil {
|
||||
|
|
@ -2489,7 +2490,7 @@ func (bc *BlockChain) UpdateM1() error {
|
|||
}
|
||||
//TODO: smart contract shouldn't return "0x0000000000000000000000000000000000000000"
|
||||
if candidate.String() != "xdc0000000000000000000000000000000000000000" {
|
||||
ms = append(ms, XDPoS.Masternode{Address: candidate, Stake: v})
|
||||
ms = append(ms, utils.Masternode{Address: candidate, Stake: v})
|
||||
}
|
||||
}
|
||||
if len(ms) == 0 {
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/ethash"
|
||||
"github.com/XinFinOrg/XDPoSChain/contracts"
|
||||
contractValidator "github.com/XinFinOrg/XDPoSChain/contracts/validator/contract"
|
||||
|
|
@ -172,10 +173,10 @@ func New(ctx *node.ServiceContext, config *Config, XDCXServ *XDCx.XDCX, lendingS
|
|||
)
|
||||
if eth.chainConfig.XDPoS != nil {
|
||||
c := eth.engine.(*XDPoS.XDPoS)
|
||||
c.GetXDCXService = func() XDPoS.TradingService {
|
||||
c.GetXDCXService = func() utils.TradingService {
|
||||
return eth.XDCX
|
||||
}
|
||||
c.GetLendingService = func() XDPoS.LendingService {
|
||||
c.GetLendingService = func() utils.LendingService {
|
||||
return eth.Lending
|
||||
}
|
||||
}
|
||||
|
|
@ -471,7 +472,7 @@ func New(ctx *node.ServiceContext, config *Config, XDCXServ *XDCx.XDCX, lendingS
|
|||
opts := new(bind.CallOpts)
|
||||
var (
|
||||
candidateAddresses []common.Address
|
||||
candidates []XDPoS.Masternode
|
||||
candidates []utils.Masternode
|
||||
)
|
||||
|
||||
stateDB, err := eth.blockchain.StateAt(eth.blockchain.GetBlockByHash(block).Root())
|
||||
|
|
@ -486,7 +487,7 @@ func New(ctx *node.ServiceContext, config *Config, XDCXServ *XDCx.XDCX, lendingS
|
|||
return nil, err
|
||||
}
|
||||
if address.String() != "0x0000000000000000000000000000000000000000" {
|
||||
candidates = append(candidates, XDPoS.Masternode{Address: address, Stake: v})
|
||||
candidates = append(candidates, utils.Masternode{Address: address, Stake: v})
|
||||
}
|
||||
}
|
||||
// sort candidates by stake descending
|
||||
|
|
@ -565,7 +566,7 @@ func New(ctx *node.ServiceContext, config *Config, XDCXServ *XDCx.XDCX, lendingS
|
|||
return err
|
||||
}
|
||||
if !bytes.Equal(header.Validators, validators) {
|
||||
return XDPoS.ErrInvalidCheckpointValidators
|
||||
return utils.ErrInvalidCheckpointValidators
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
@ -581,15 +582,7 @@ func New(ctx *node.ServiceContext, config *Config, XDCXServ *XDCx.XDCX, lendingS
|
|||
// not genesis block
|
||||
header = parentHeader
|
||||
}
|
||||
snap, err := c.GetSnapshot(eth.blockchain, header)
|
||||
if err != nil {
|
||||
log.Error("Can't get snapshot with at ", "number", header.Number, "hash", header.Hash().Hex(), "err", err)
|
||||
return false
|
||||
}
|
||||
if _, ok := snap.Signers[address]; ok {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
return c.IsAuthorisedAddress(header, eth.blockchain, address)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -756,11 +749,9 @@ func (s *Ethereum) ValidateMasternode() (bool, error) {
|
|||
if s.chainConfig.XDPoS != nil {
|
||||
//check if miner's wallet is in set of validators
|
||||
c := s.engine.(*XDPoS.XDPoS)
|
||||
snap, err := c.GetSnapshot(s.blockchain, s.blockchain.CurrentHeader())
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("Can't verify masternode permission: %v", err)
|
||||
}
|
||||
if _, authorized := snap.Signers[eb]; !authorized {
|
||||
|
||||
authorized := c.IsAuthorisedAddress(s.blockchain.CurrentHeader(), s.blockchain, eb)
|
||||
if !authorized {
|
||||
//This miner doesn't belong to set of validators
|
||||
return false, nil
|
||||
}
|
||||
|
|
|
|||
3
go.sum
3
go.sum
|
|
@ -210,6 +210,7 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
|||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||
|
|
@ -250,6 +251,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
|||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d h1:gZZadD8H+fF+n9CmNhYL1Y0dJB+kLOmKd7FbPJLeGHs=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA=
|
||||
|
|
@ -334,6 +336,7 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWD
|
|||
gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0=
|
||||
gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/common/hexutil"
|
||||
"github.com/XinFinOrg/XDPoSChain/common/math"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/ethash"
|
||||
contractValidator "github.com/XinFinOrg/XDPoSChain/contracts/validator/contract"
|
||||
"github.com/XinFinOrg/XDPoSChain/core"
|
||||
|
|
@ -713,7 +714,7 @@ func (s *PublicBlockChainAPI) GetCandidateStatus(ctx context.Context, coinbaseAd
|
|||
checkpointNumber rpc.BlockNumber
|
||||
epochNumber rpc.EpochNumber // if epoch == "latest", print the latest epoch number to epochNumber
|
||||
masternodes, penaltyList []common.Address
|
||||
candidates []XDPoS.Masternode
|
||||
candidates []utils.Masternode
|
||||
penalties []byte
|
||||
err error
|
||||
)
|
||||
|
|
@ -755,7 +756,7 @@ func (s *PublicBlockChainAPI) GetCandidateStatus(ctx context.Context, coinbaseAd
|
|||
for _, address := range candidatesAddresses {
|
||||
v := state.GetCandidateCap(statedb, address)
|
||||
if address.String() != "0x0000000000000000000000000000000000000000" {
|
||||
candidates = append(candidates, XDPoS.Masternode{Address: address, Stake: v})
|
||||
candidates = append(candidates, utils.Masternode{Address: address, Stake: v})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -843,7 +844,7 @@ func (s *PublicBlockChainAPI) GetCandidates(ctx context.Context, epoch rpc.Epoch
|
|||
epochNumber rpc.EpochNumber
|
||||
masternodes []common.Address
|
||||
penaltyList []common.Address
|
||||
candidates []XDPoS.Masternode
|
||||
candidates []utils.Masternode
|
||||
penalties []byte
|
||||
err error
|
||||
)
|
||||
|
|
@ -881,7 +882,7 @@ func (s *PublicBlockChainAPI) GetCandidates(ctx context.Context, epoch rpc.Epoch
|
|||
for _, address := range candidatesAddresses {
|
||||
v := state.GetCandidateCap(statedb, address)
|
||||
if address.String() != "0x0000000000000000000000000000000000000000" {
|
||||
candidates = append(candidates, XDPoS.Masternode{Address: address, Stake: v})
|
||||
candidates = append(candidates, utils.Masternode{Address: address, Stake: v})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -939,7 +940,7 @@ func (s *PublicBlockChainAPI) GetCandidates(ctx context.Context, epoch rpc.Epoch
|
|||
}
|
||||
penaltyList = common.ExtractAddressFromBytes(penalties)
|
||||
|
||||
var topCandidates []XDPoS.Masternode
|
||||
var topCandidates []utils.Masternode
|
||||
if len(candidates) > common.MaxMasternodes {
|
||||
topCandidates = candidates[:common.MaxMasternodes]
|
||||
} else {
|
||||
|
|
@ -984,33 +985,33 @@ func (s *PublicBlockChainAPI) GetPreviousCheckpointFromEpoch(ctx context.Context
|
|||
}
|
||||
|
||||
// getCandidatesFromSmartContract returns all candidates with their capacities at the current time
|
||||
func (s *PublicBlockChainAPI) getCandidatesFromSmartContract() ([]XDPoS.Masternode, error) {
|
||||
func (s *PublicBlockChainAPI) getCandidatesFromSmartContract() ([]utils.Masternode, error) {
|
||||
client, err := s.b.GetIPCClient()
|
||||
if err != nil {
|
||||
return []XDPoS.Masternode{}, err
|
||||
return []utils.Masternode{}, err
|
||||
}
|
||||
|
||||
addr := common.HexToAddress(common.MasternodeVotingSMC)
|
||||
validator, err := contractValidator.NewXDCValidator(addr, client)
|
||||
if err != nil {
|
||||
return []XDPoS.Masternode{}, err
|
||||
return []utils.Masternode{}, err
|
||||
}
|
||||
|
||||
opts := new(bind.CallOpts)
|
||||
candidates, err := validator.GetCandidates(opts)
|
||||
if err != nil {
|
||||
return []XDPoS.Masternode{}, err
|
||||
return []utils.Masternode{}, err
|
||||
}
|
||||
|
||||
var candidatesWithStakeInfo []XDPoS.Masternode
|
||||
var candidatesWithStakeInfo []utils.Masternode
|
||||
|
||||
for _, candidate := range candidates {
|
||||
v, err := validator.GetCandidateCap(opts, candidate)
|
||||
if err != nil {
|
||||
return []XDPoS.Masternode{}, err
|
||||
return []utils.Masternode{}, err
|
||||
}
|
||||
if candidate.String() != "0x0000000000000000000000000000000000000000" {
|
||||
candidatesWithStakeInfo = append(candidatesWithStakeInfo, XDPoS.Masternode{Address: candidate, Stake: v})
|
||||
candidatesWithStakeInfo = append(candidatesWithStakeInfo, utils.Masternode{Address: candidate, Stake: v})
|
||||
}
|
||||
|
||||
if len(candidatesWithStakeInfo) > 0 {
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import (
|
|||
"github.com/XinFinOrg/XDPoSChain/common"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
|
||||
"github.com/XinFinOrg/XDPoSChain/consensus/misc"
|
||||
"github.com/XinFinOrg/XDPoSChain/contracts"
|
||||
"github.com/XinFinOrg/XDPoSChain/core"
|
||||
|
|
@ -396,12 +397,9 @@ func (self *worker) wait() {
|
|||
|
||||
if self.config.XDPoS != nil {
|
||||
c := self.engine.(*XDPoS.XDPoS)
|
||||
snap, err := c.GetSnapshot(self.chain, block.Header())
|
||||
if err != nil {
|
||||
log.Error("Fail to get snapshot for sign tx signer.")
|
||||
return
|
||||
}
|
||||
if _, authorized := snap.Signers[self.coinbase]; !authorized {
|
||||
|
||||
authorized := c.IsAuthorisedAddress(block.Header(), self.chain, self.coinbase)
|
||||
if !authorized {
|
||||
valid := false
|
||||
masternodes := c.GetMasternodes(self.chain, block.Header())
|
||||
for _, m := range masternodes {
|
||||
|
|
@ -542,7 +540,7 @@ func (self *worker) commitNewWork() {
|
|||
// you're not allowed to create this block
|
||||
return
|
||||
}
|
||||
h := XDPoS.Hop(len, preIndex, curIndex)
|
||||
h := utils.Hop(len, preIndex, curIndex)
|
||||
gap := waitPeriod * int64(h)
|
||||
// Check nearest checkpoint block in hop range.
|
||||
nearest := self.config.XDPoS.Epoch - (parent.Header().Number.Uint64() % self.config.XDPoS.Epoch)
|
||||
|
|
|
|||
|
|
@ -183,6 +183,14 @@ func (c *XDPoSConfig) String() string {
|
|||
return "XDPoS"
|
||||
}
|
||||
|
||||
/**
|
||||
ConsensusVersion will return the consensus version to use for the provided block number. The returned int represent its version
|
||||
TODO: It's a dummy value for now until the 2.0 consensus engine is fully implemented.
|
||||
*/
|
||||
func BlockConsensusVersion(num *big.Int) int {
|
||||
return 1
|
||||
}
|
||||
|
||||
// String implements the fmt.Stringer interface.
|
||||
func (c *ChainConfig) String() string {
|
||||
var engine interface{}
|
||||
|
|
|
|||
Loading…
Reference in a new issue