6 "github.com/bytom/bytom/errors"
7 "github.com/bytom/bytom/math/checked"
8 "github.com/bytom/bytom/protocol"
9 "github.com/bytom/bytom/protocol/bc"
10 "github.com/bytom/bytom/protocol/bc/types"
11 "github.com/bytom/bytom/protocol/state"
14 // ApplyBlock used to receive a new block from upper layer, it provides idempotence
15 // and parse the vote and mortgage from the transactions, then save to the checkpoint
16 // the tree of checkpoint will grow with the arrival of new blocks
17 // it will return verification when an epoch is reached and the current node is the validator, otherwise return nil
18 // the chain module must broadcast the verification
19 func (c *Casper) ApplyBlock(block *types.Block) (*protocol.Verification, error) {
23 if _, err := c.tree.nodeByHash(block.Hash()); err == nil {
28 target, err := c.applyBlockToCheckpoint(block)
30 return nil, errors.Wrap(err, "apply block to checkpoint")
33 if err := c.applyTransactions(target, block.Transactions); err != nil {
37 validators, err := c.Validators(&target.Hash)
42 if err := c.applySupLinks(target, block.SupLinks, validators); err != nil {
46 if block.Height%state.BlocksOfEpoch == 0 {
47 c.newEpochCh <- block.Hash()
50 return c.myVerification(target, validators)
53 func (c *Casper) applyBlockToCheckpoint(block *types.Block) (*state.Checkpoint, error) {
54 node, err := c.tree.nodeByHash(block.PreviousBlockHash)
59 checkpoint := node.checkpoint
60 if mod := block.Height % state.BlocksOfEpoch; mod == 1 {
62 checkpoint = &state.Checkpoint{
63 ParentHash: parent.Hash,
65 StartTimestamp: block.Timestamp,
66 Status: state.Growing,
67 Votes: make(map[string]uint64),
68 Guaranties: make(map[string]uint64),
70 node.children = append(node.children, &treeNode{checkpoint: checkpoint})
72 checkpoint.Status = state.Unjustified
75 checkpoint.Height = block.Height
76 checkpoint.Hash = block.Hash()
77 return checkpoint, nil
80 func (c *Casper) applyTransactions(target *state.Checkpoint, transactions []*types.Tx) error {
81 for _, tx := range transactions {
82 for _, input := range tx.Inputs {
83 if vetoInput, ok := input.TypedInput.(*types.VetoInput); ok {
84 if err := processVeto(vetoInput, target); err != nil {
89 if isGuarantyProgram(input.ControlProgram()) {
90 if err := processWithdrawal(decodeGuarantyArgs(input.ControlProgram()), target); err != nil {
96 for _, output := range tx.Outputs {
97 if _, ok := output.TypedOutput.(*types.VoteOutput); ok {
98 if err := processVote(output, target); err != nil {
103 if isGuarantyProgram(output.ControlProgram) {
104 if err := processGuaranty(decodeGuarantyArgs(output.ControlProgram), target); err != nil {
113 // applySupLinks copy the block's supLink to the checkpoint
114 func (c *Casper) applySupLinks(target *state.Checkpoint, supLinks []*types.SupLink, validators []*state.Validator) error {
115 if target.Height%state.BlocksOfEpoch != 0 {
119 for _, supLink := range supLinks {
120 for _, verification := range supLinkToVerifications(supLink, validators, target.Hash, target.Height) {
121 if err := c.verifyVerification(verification, true); err == nil {
122 if err := c.addVerificationToCheckpoint(target, verification); err != nil {
131 func (c *Casper) myVerification(target *state.Checkpoint, validators []*state.Validator) (*protocol.Verification, error) {
132 pubKey := c.prvKey.XPub().String()
133 if !isValidator(pubKey, validators) {
137 source := c.lastJustifiedCheckpointOfBranch(target)
139 v := &protocol.Verification{
140 SourceHash: source.Hash,
141 TargetHash: target.Hash,
142 SourceHeight: source.Height,
143 TargetHeight: target.Height,
147 if err := v.Sign(c.prvKey); err != nil {
151 if err := c.verifyVerification(v, false); err != nil {
155 return v, c.addVerificationToCheckpoint(target, v)
160 type guarantyArgs struct {
165 func isGuarantyProgram(program []byte) bool {
169 func decodeGuarantyArgs(program []byte) *guarantyArgs {
173 func processWithdrawal(guarantyArgs *guarantyArgs, checkpoint *state.Checkpoint) error {
174 pubKey := hex.EncodeToString(guarantyArgs.PubKey)
175 guarantyNum := checkpoint.Guaranties[pubKey]
176 guarantyNum, ok := checked.SubUint64(guarantyNum, guarantyArgs.Amount)
181 checkpoint.Guaranties[pubKey] = guarantyNum
182 // TODO delete the evil validator when receive the confiscate transaction
186 func processGuaranty(guarantyArgs *guarantyArgs, checkpoint *state.Checkpoint) error {
187 if guarantyArgs.Amount < minGuaranty {
188 return errGuarantyLessThanMinimum
191 pubKey := hex.EncodeToString(guarantyArgs.PubKey)
192 guarantyNum := checkpoint.Guaranties[pubKey]
193 guarantyNum, ok := checked.AddUint64(guarantyNum, guarantyArgs.Amount)
198 checkpoint.Guaranties[pubKey] = guarantyNum
202 func processVeto(input *types.VetoInput, checkpoint *state.Checkpoint) error {
203 pubKey := hex.EncodeToString(input.Vote)
204 voteNum := checkpoint.Votes[pubKey]
205 voteNum, ok := checked.SubUint64(voteNum, input.Amount)
210 checkpoint.Votes[pubKey] = voteNum
214 func processVote(output *types.TxOutput, checkpoint *state.Checkpoint) error {
215 voteOutput := output.TypedOutput.(*types.VoteOutput)
216 pubKey := hex.EncodeToString(voteOutput.Vote)
217 if checkpoint.Guaranties[pubKey] < minGuaranty {
218 return errVoteToNonValidator
221 voteNum := checkpoint.Votes[pubKey]
222 voteNum, ok := checked.AddUint64(voteNum, output.Amount)
227 checkpoint.Votes[pubKey] = voteNum
231 func (c *Casper) lastJustifiedCheckpointOfBranch(branch *state.Checkpoint) *state.Checkpoint {
232 parent := branch.Parent
234 switch parent.Status {
235 case state.Finalized:
237 case state.Justified:
244 func supLinkToVerifications(supLink *types.SupLink, validators []*state.Validator, targetHash bc.Hash, targetHeight uint64) []*protocol.Verification {
245 var result []*protocol.Verification
246 for i, signature := range supLink.Signatures {
247 result = append(result, &protocol.Verification{
248 SourceHash: supLink.SourceHash,
249 TargetHash: targetHash,
250 SourceHeight: supLink.SourceHeight,
251 TargetHeight: targetHeight,
252 Signature: hex.EncodeToString(signature),
253 PubKey: validators[i].PubKey,