go-ethereum/consensus/XDPoS/engines/engine_v2/snapshot.go
Liam 6c5fe34615 v2 miner function implementation and happy path (#22)
* New struct in consensus/XDPoS/utils/types.go, util functions, and test. (#14)

* define vote, timeout, sync info, qc, tc, extra fields in types.go, add test in types_test.go

* add json tag in types.go, refine encoder decoder of extra fields

* refactor types.go utils.go

* re-write types, comments

* add Hash SigHash for types, and tests

* define Round type

* remove unnecessary logs

* add v2 engine functions placeholder

* typo fix on the consensus v2 function placeholders

* add countdown timer

* make initilised private to countdown

* add v2 specific config struct

* rename some config variables

* Implement BFT Message receiver (#13)

* fix or skip tests due to PR-136 changes

* add bft receiver functions

* add bft receiver functions

* rename tc to TimeoutCert

* implement more functions

* New struct in consensus/XDPoS/utils/types.go, util functions, and test. (#14)

* define vote, timeout, sync info, qc, tc, extra fields in types.go, add test in types_test.go

* add json tag in types.go, refine encoder decoder of extra fields

* refactor types.go utils.go

* re-write types, comments

* add Hash SigHash for types, and tests

* define Round type

* remove unnecessary logs

* add temp functions

* add v2 engine functions placeholder

* typo fix on the consensus v2 function placeholders

* add countdown timer

* make initilised private to countdown

* push verify function

* add test on receiving vote

* revert type change

* add async on broadcast function

* add quit initial

* fix test

Co-authored-by: Jianrong <wjrjerome@gmail.com>
Co-authored-by: wgr523 <wgr523@gmail.com>

* generate and verify timeout message

* Consensus V2 variable, timeout pool (#19)

* fill in XDPoS_v2 variables and processQC/TC

* add timeout pool, refine engine variables

* refactor type functions

* solve a small pointer bug

* create general pool and its test, refine engine

* refine pool, add xdpos v2 config cert threshold

* refine config

* vote and timeout handlers

* fix pool test

* bft miner preparation

* review comment improvement

* update

* relocate tests

* add and remove comment

* fix the syntax error

* update network layer and add handler functions (#23)

* update network layer and add handler functions

* fix test syntax error

* add ProcessQC implementation

* add ProcessQC tests

* add snapshot test

* add wait qc process

* remove testing files

* add route snapshot

* fix merge issue

* add default v2 behaviour (#24)

* add v2 ecrecover functions and refactor test

* fix all the tests

* put minimun lock variable

* debugging prepare and seal v2 blocks

* Trigger proposeBlockHandler after v2 block received and verified in fetcher

* skip snapshot apply related tests

* update test check

* rename bfter to bft handler and ignore normal behviour

* fix bugs during local 4 node run

* fix test

* fix sync info test

* fix bugs during local 4 node run

* rebase and fix bug

* remove hook validators function"

Co-authored-by: wgr523 <wgr523@gmail.com>
Co-authored-by: Jianrong <wjrjerome@gmail.com>
2021-12-30 11:45:18 +11:00

133 lines
3.9 KiB
Go

package engine_v2
import (
"encoding/json"
"sort"
"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/consensus/XDPoS/utils"
"github.com/XinFinOrg/XDPoSChain/core/types"
"github.com/XinFinOrg/XDPoSChain/ethdb"
lru "github.com/hashicorp/golang-lru"
)
// Snapshot is the state of the smart contract validator list
type SnapshotV2 struct {
sigcache *lru.ARCCache // Cache of recent block signatures to speed up ecrecover
Round utils.Round `json:"round"` // Round number
Number uint64 `json:"number"` // Block number where the snapshot was created
Hash common.Hash `json:"hash"` // Block hash where the snapshot was created
// MasterNodes will get assigned on updateM1
MasterNodes map[common.Address]struct{} `json:"masterNodes"` // Set of authorized master nodes at this moment
}
// 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(sigcache *lru.ARCCache, number uint64, hash common.Hash, round utils.Round, qc *utils.QuorumCert, masternodes []common.Address) *SnapshotV2 {
snap := &SnapshotV2{
sigcache: sigcache,
Round: round,
Number: number,
Hash: hash,
MasterNodes: make(map[common.Address]struct{}),
}
for _, signer := range masternodes {
snap.MasterNodes[signer] = struct{}{}
}
return snap
}
// loadSnapshot loads an existing snapshot from the database.
func loadSnapshot(sigcache *lru.ARCCache, db ethdb.Database, hash common.Hash) (*SnapshotV2, error) {
blob, err := db.Get(append([]byte("XDPoS-"), hash[:]...))
if err != nil {
return nil, err
}
snap := new(SnapshotV2)
if err := json.Unmarshal(blob, snap); err != nil {
return nil, err
}
snap.sigcache = sigcache
return snap, nil
}
// store inserts the SnapshotV2 into the database.
func storeSnapshot(s *SnapshotV2, db ethdb.Database) error {
blob, err := json.Marshal(s)
if err != nil {
return err
}
return db.Put(append([]byte("XDPoS-"), s.Hash[:]...), blob)
}
// copy creates a deep copy of the SnapshotV2, though not the individual votes.
func (s *SnapshotV2) copy() *SnapshotV2 {
cpy := &SnapshotV2{
sigcache: s.sigcache,
Round: s.Round,
Number: s.Number,
Hash: s.Hash,
MasterNodes: make(map[common.Address]struct{}),
}
for signer := range s.MasterNodes {
cpy.MasterNodes[signer] = struct{}{}
}
return cpy
}
// apply creates a new authorization SnapshotV2 by applying the given headers to
// the original one.
// TODO: XIN-100
func (s *SnapshotV2) apply(headers []*types.Header) (*SnapshotV2, error) {
return s, nil
// Allow passing in no headers for cleaner code
// if len(headers) == 0 {
// return s, nil
// }
// // 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, utils.ErrInvalidHeaderOrder
// }
// }
// if headers[0].Number.Uint64() != s.Number+1 {
// return nil, utils.ErrInvalidChild
// }
// // Iterate through the headers and create a new SnapshotV2
// snap := s.copy()
// lastHeader := headers[len(headers)-1]
// snap.Number += uint64(len(headers))
// snap.Hash = lastHeader.Hash()
// extraV2 := new(utils.ExtraFields_v2)
// err := utils.DecodeBytesExtraFields(lastHeader.Extra, &extraV2)
// if err != nil {
// return nil, err
// }
// snap.Round = extraV2.Round
// return snap, nil
}
// signers retrieves the list of authorized signers in ascending order, convert into strings then use native sort lib
func (s *SnapshotV2) GetMasterNodes() []common.Address {
nodes := make([]common.Address, 0, len(s.MasterNodes))
nodeStrs := make([]string, 0, len(s.MasterNodes))
for node := range s.MasterNodes {
nodeStrs = append(nodeStrs, node.Str())
}
sort.Strings(nodeStrs)
for _, str := range nodeStrs {
nodes = append(nodes, common.StringToAddress(str))
}
return nodes
}