OSDN Git Service

new casper (#1918)
authorPoseidon <shenao.78@163.com>
Fri, 23 Apr 2021 12:16:14 +0000 (20:16 +0800)
committerGitHub <noreply@github.com>
Fri, 23 Apr 2021 12:16:14 +0000 (20:16 +0800)
* new casper

* modify comment

* add check first checkpoints

* bug fix

* fix golint

Co-authored-by: Paladz <yzhu101@uottawa.ca>
protocol/consensus/casper.go
protocol/consensus/tree_node.go
protocol/state/checkpoint.go

index 2994fb0..c010fc8 100644 (file)
@@ -48,6 +48,29 @@ type Casper struct {
        verificationCache *common.Cache
 }
 
+// NewCasper create a new instance of Casper
+// argument checkpoints load the checkpoints from leveldb
+// the first element of checkpoints must genesis checkpoint or the last finalized checkpoint in order to reduce memory space
+// the others must successors of first one
+func NewCasper(store protocol.Store, prvKey chainkd.XPrv, checkpoints []*state.Checkpoint) *Casper {
+       if checkpoints[0].Height != 0 && checkpoints[0].Status != state.Finalized {
+               log.Panic("first element of checkpoints must genesis or in finalized status")
+       }
+
+       casper := &Casper{
+               tree:                makeTree(checkpoints[0], checkpoints[1:]),
+               rollbackNotifyCh:    make(chan bc.Hash),
+               newEpochCh:          make(chan bc.Hash),
+               store:               store,
+               prvKey:              prvKey,
+               evilValidators:      make(map[string][]*Verification),
+               prevCheckpointCache: common.NewCache(1024),
+               verificationCache:   common.NewCache(1024),
+       }
+       go casper.authVerificationLoop()
+       return casper
+}
+
 // Best chain return the chain containing the justified checkpoint of the largest height
 func (c *Casper) BestChain() (uint64, bc.Hash) {
        c.mu.RLock()
@@ -439,6 +462,7 @@ func (c *Casper) applyBlockToCheckpoint(block *types.Block) (*state.Checkpoint,
        if mod := block.Height % state.BlocksOfEpoch; mod == 1 {
                parent := checkpoint
                checkpoint = &state.Checkpoint{
+                       ParentHash:     parent.Hash,
                        Parent:         parent,
                        StartTimestamp: block.Timestamp,
                        Status:         state.Growing,
index a8fe41c..d3b451f 100644 (file)
@@ -13,6 +13,26 @@ type treeNode struct {
        children   []*treeNode
 }
 
+func makeTree(root *state.Checkpoint, successors []*state.Checkpoint) *treeNode {
+       parentToSuccessors := make(map[bc.Hash][]*state.Checkpoint)
+       for _, successor := range successors {
+               parentToSuccessors[successor.ParentHash] = append(parentToSuccessors[successor.ParentHash], successor)
+       }
+
+       rootNode := &treeNode{checkpoint: root}
+       nodes := []*treeNode{rootNode}
+       for len(nodes) != 0 {
+               node := nodes[0]
+               for _, successor := range parentToSuccessors[node.checkpoint.Hash] {
+                       child := &treeNode{checkpoint: successor}
+                       node.children = append(node.children, child)
+                       nodes = append(nodes, child)
+               }
+               nodes = nodes[1:]
+       }
+       return rootNode
+}
+
 func (t *treeNode) nodeByHash(blockHash bc.Hash) (*treeNode, error) {
        if c := t.findOnlyOne(func(c *state.Checkpoint) bool {
                return c.Hash == blockHash
index ee4a03a..c79918e 100644 (file)
@@ -50,6 +50,8 @@ func (s *SupLink) IsMajority() bool {
 type Checkpoint struct {
        Height         uint64
        Hash           bc.Hash
+       ParentHash     bc.Hash
+       // only save in the memory, not be persisted
        Parent         *Checkpoint
        StartTimestamp uint64
        SupLinks       []*SupLink