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()
if mod := block.Height % state.BlocksOfEpoch; mod == 1 {
parent := checkpoint
checkpoint = &state.Checkpoint{
+ ParentHash: parent.Hash,
Parent: parent,
StartTimestamp: block.Timestamp,
Status: state.Growing,
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