6 "github.com/sirupsen/logrus"
8 "github.com/bytom/bytom/config"
9 "github.com/bytom/bytom/errors"
10 "github.com/bytom/bytom/math/checked"
11 "github.com/bytom/bytom/protocol/bc"
12 "github.com/bytom/bytom/protocol/bc/types"
13 "github.com/bytom/bytom/protocol/state"
16 type applyBlockReply struct {
17 verification *Verification
22 // ApplyBlock used to receive a new block from upper layer, it provides idempotence
23 // and parse the vote and mortgage from the transactions, then save to the checkpoint
24 // the tree of checkpoint will grow with the arrival of new blocks
25 // it will return verification when an epoch is reached and the current node is the validator, otherwise return nil
26 // the chain module must broadcast the verification
27 func (c *Casper) ApplyBlock(block *types.Block) (*applyBlockReply, error) {
28 if block.Height%state.BlocksOfEpoch == 1 {
29 c.newEpochCh <- block.PreviousBlockHash
35 if _, err := c.tree.nodeByHash(block.Hash()); err == nil {
36 return nil, errAlreadyProcessedBlock
39 _, oldBestHash := c.bestChain()
40 target, err := c.applyBlockToCheckpoint(block)
42 return nil, errors.Wrap(err, "apply block to checkpoint")
45 if err := applyTransactions(target, block.Transactions); err != nil {
49 validators, err := c.Validators(&target.Hash)
54 verification, err := c.applyMyVerification(target, block, validators)
59 affectedCheckpoints, err := c.applySupLinks(target, block.SupLinks, validators)
64 reply := &applyBlockReply{verification: verification}
65 if c.isRollback(oldBestHash, block) {
66 reply.isRollback = true
67 reply.newBestHash = block.Hash()
69 return reply, c.saveCheckpoints(affectedCheckpoints)
72 func (c *Casper) applyBlockToCheckpoint(block *types.Block) (*state.Checkpoint, error) {
73 node, err := c.checkpointByHash(block.PreviousBlockHash)
78 checkpoint := node.checkpoint
79 if mod := block.Height % state.BlocksOfEpoch; mod == 1 {
81 checkpoint = &state.Checkpoint{
82 ParentHash: parent.Hash,
84 Status: state.Growing,
85 Votes: make(map[string]uint64),
86 Guaranties: make(map[string]uint64),
89 for pubKey, num := range parent.Votes {
90 checkpoint.Votes[pubKey] = num
92 for pubKey, num := range parent.Guaranties {
93 checkpoint.Guaranties[pubKey] = num
95 node.addChild(&treeNode{checkpoint: checkpoint})
97 checkpoint.Status = state.Unjustified
100 checkpoint.Height = block.Height
101 checkpoint.Hash = block.Hash()
102 checkpoint.Timestamp = block.Timestamp
103 return checkpoint, nil
106 func (c *Casper) checkpointByHash(blockHash bc.Hash) (*treeNode, error) {
107 node, err := c.tree.nodeByHash(blockHash)
109 logrus.WithField("err", err).Error("fail find checkpoint, start to reorganize checkpoint")
111 return c.reorganizeCheckpoint(blockHash)
117 func (c *Casper) isRollback(oldBestHash bc.Hash, block *types.Block) bool {
118 _, newBestHash := c.bestChain()
119 return block.Hash() == newBestHash && block.PreviousBlockHash != oldBestHash
122 func (c *Casper) reorganizeCheckpoint(hash bc.Hash) (*treeNode, error) {
124 var attachBlocks []*types.Block
126 prevBlock, err := c.store.GetBlock(&prevHash)
131 if prevBlock.Height%state.BlocksOfEpoch == 0 {
135 attachBlocks = append([]*types.Block{prevBlock}, attachBlocks...)
136 prevHash = prevBlock.PreviousBlockHash
139 parent, err := c.tree.nodeByHash(prevHash)
145 checkpoint: &state.Checkpoint{
146 ParentHash: parent.checkpoint.Hash,
147 Parent: parent.checkpoint,
148 Status: state.Growing,
149 Votes: make(map[string]uint64),
150 Guaranties: make(map[string]uint64),
154 parent.addChild(node)
155 for _, attachBlock := range attachBlocks {
156 if err := applyTransactions(node.checkpoint, attachBlock.Transactions); err != nil {
160 node.checkpoint.Hash = attachBlock.Hash()
161 node.checkpoint.Height = attachBlock.Height
162 node.checkpoint.Timestamp = attachBlock.Timestamp
167 func applyTransactions(target *state.Checkpoint, transactions []*types.Tx) error {
168 for _, tx := range transactions {
169 for _, input := range tx.Inputs {
170 if vetoInput, ok := input.TypedInput.(*types.VetoInput); ok {
171 if err := processVeto(vetoInput, target); err != nil {
176 if isGuarantyProgram(input.ControlProgram()) {
177 if err := processWithdrawal(decodeGuarantyArgs(input.ControlProgram()), target); err != nil {
183 for _, output := range tx.Outputs {
184 if _, ok := output.TypedOutput.(*types.VoteOutput); ok {
185 if err := processVote(output, target); err != nil {
190 if isGuarantyProgram(output.ControlProgram) {
191 if err := processGuaranty(decodeGuarantyArgs(output.ControlProgram), target); err != nil {
200 // applySupLinks copy the block's supLink to the checkpoint
201 func (c *Casper) applySupLinks(target *state.Checkpoint, supLinks []*types.SupLink, validators map[string]*state.Validator) ([]*state.Checkpoint, error) {
202 affectedCheckpoints := []*state.Checkpoint{target}
203 if target.Height%state.BlocksOfEpoch != 0 {
207 for _, supLink := range supLinks {
208 var validVerifications []*Verification
209 for _, v := range supLinkToVerifications(supLink, validators, target.Hash, target.Height) {
210 if validate(v) == nil && c.verifyVerification(v, validators[v.PubKey].Order, true) == nil {
211 validVerifications = append(validVerifications, v)
215 checkpoints, err := c.addVerificationToCheckpoint(target, validators, validVerifications...)
220 affectedCheckpoints = append(affectedCheckpoints, checkpoints...)
222 return affectedCheckpoints, nil
225 func (c *Casper) applyMyVerification(target *state.Checkpoint, block *types.Block, validators map[string]*state.Validator) (*Verification, error) {
226 v, err := c.myVerification(target, validators)
235 signature, err := hex.DecodeString(v.Signature)
240 block.SupLinks.AddSupLink(v.SourceHeight, v.SourceHash, signature, validators[v.PubKey].Order)
241 return v, c.store.SaveBlockHeader(&block.BlockHeader)
244 func (c *Casper) myVerification(target *state.Checkpoint, validators map[string]*state.Validator) (*Verification, error) {
245 if target.Height%state.BlocksOfEpoch != 0 {
249 pubKey := config.CommonConfig.PrivateKey().XPub().String()
250 if _, ok := validators[pubKey]; !ok {
254 validatorOrder := validators[pubKey].Order
255 if target.ContainsVerification(validatorOrder, nil) {
259 if source := c.lastJustifiedCheckpointOfBranch(target); source != nil {
261 SourceHash: source.Hash,
262 TargetHash: target.Hash,
263 SourceHeight: source.Height,
264 TargetHeight: target.Height,
268 prvKey := config.CommonConfig.PrivateKey()
269 if err := v.Sign(*prvKey); err != nil {
273 if err := c.verifyVerification(v, validatorOrder, false); err != nil {
282 type guarantyArgs struct {
287 func isGuarantyProgram(program []byte) bool {
291 func decodeGuarantyArgs(program []byte) *guarantyArgs {
295 func processWithdrawal(guarantyArgs *guarantyArgs, checkpoint *state.Checkpoint) error {
296 pubKey := hex.EncodeToString(guarantyArgs.PubKey)
297 guarantyNum := checkpoint.Guaranties[pubKey]
298 guarantyNum, ok := checked.SubUint64(guarantyNum, guarantyArgs.Amount)
303 checkpoint.Guaranties[pubKey] = guarantyNum
304 // TODO delete the evil validator when receive the confiscate transaction
308 func processGuaranty(guarantyArgs *guarantyArgs, checkpoint *state.Checkpoint) error {
309 if guarantyArgs.Amount < minGuaranty {
310 return errGuarantyLessThanMinimum
313 pubKey := hex.EncodeToString(guarantyArgs.PubKey)
314 guarantyNum := checkpoint.Guaranties[pubKey]
315 guarantyNum, ok := checked.AddUint64(guarantyNum, guarantyArgs.Amount)
320 checkpoint.Guaranties[pubKey] = guarantyNum
324 func processVeto(input *types.VetoInput, checkpoint *state.Checkpoint) error {
325 pubKey := hex.EncodeToString(input.Vote)
326 voteNum := checkpoint.Votes[pubKey]
327 voteNum, ok := checked.SubUint64(voteNum, input.Amount)
332 checkpoint.Votes[pubKey] = voteNum
336 func processVote(output *types.TxOutput, checkpoint *state.Checkpoint) error {
337 voteOutput := output.TypedOutput.(*types.VoteOutput)
338 pubKey := hex.EncodeToString(voteOutput.Vote)
339 if checkpoint.Guaranties[pubKey] < minGuaranty {
340 return errVoteToNonValidator
343 voteNum := checkpoint.Votes[pubKey]
344 voteNum, ok := checked.AddUint64(voteNum, output.Amount)
349 checkpoint.Votes[pubKey] = voteNum
353 func (c *Casper) lastJustifiedCheckpointOfBranch(branch *state.Checkpoint) *state.Checkpoint {
354 parent := branch.Parent
356 switch parent.Status {
357 case state.Finalized:
359 case state.Justified:
362 parent = parent.Parent
367 func (c *Casper) saveCheckpoints(checkpoints []*state.Checkpoint) error {
368 checkpointSet := make(map[bc.Hash]*state.Checkpoint)
369 for _, c := range checkpoints {
370 checkpointSet[c.Hash] = c
373 var result []*state.Checkpoint
374 for _, c := range checkpointSet {
375 result = append(result, c)
378 return c.store.SaveCheckpoints(result)
381 func supLinkToVerifications(supLink *types.SupLink, validators map[string]*state.Validator, targetHash bc.Hash, targetHeight uint64) []*Verification {
382 validatorList := make([]*state.Validator, len(validators))
383 for _, validator := range validators {
384 validatorList[validator.Order] = validator
387 var result []*Verification
388 for i := 0; i < len(validators); i++ {
389 signature := supLink.Signatures[i]
390 if len(signature) == 0 {
394 result = append(result, &Verification{
395 SourceHash: supLink.SourceHash,
396 TargetHash: targetHash,
397 SourceHeight: supLink.SourceHeight,
398 TargetHeight: targetHeight,
399 Signature: hex.EncodeToString(signature),
400 PubKey: validatorList[i].PubKey,