OSDN Git Service

fix(bcrp): fix bcrp when apply block and detach block (#2081)
[bytom/bytom.git] / consensus / bcrp / bcrp.go
1 package bcrp
2
3 import (
4         "bytes"
5
6         "github.com/bytom/bytom/consensus"
7         "github.com/bytom/bytom/errors"
8         "github.com/bytom/bytom/protocol/vm"
9 )
10
11 const (
12         // BCRP bytom contract register protocol
13         BCRP = "bcrp"
14         // Version bcrp version
15         Version = 1
16 )
17
18 // IsBCRPScript checks if a control program is bytom contract register protocol
19 // BCRP script format: OP_FAIL + OP_DATA_4 + "bcrp" + OP_DATA_1 + "1" + {{dynamic_op}} + contract
20 // 0 < len(contract) <= 75       dynamic_op -> OP_DATA_N
21 // 75 <len(contract) < 256       dynamic_op -> OP_PUSHDATA1
22 // 256 <= len(contract) < 65536  dynamic_op -> OP_PUSHDATA2
23 // len(contract) >= 65536        dynamic_op -> OP_PUSHDATA4
24 func IsBCRPScript(prog []byte) bool {
25         inst, err := vm.ParseProgram(prog)
26         if err != nil {
27                 return false
28         }
29
30         if len(inst) != 4 {
31                 return false
32         }
33
34         if inst[0].Op != vm.OP_FAIL {
35                 return false
36         }
37
38         if inst[1].Op != vm.OP_DATA_4 || !bytes.Equal(inst[1].Data, []byte(BCRP)) {
39                 return false
40         }
41
42         if inst[2].Op != vm.OP_DATA_1 || !bytes.Equal(inst[2].Data, []byte{byte(Version)}) {
43                 return false
44         }
45
46         return len(inst[3].Data) > 0
47 }
48
49 // IsCallContractScript checks if a program is script call contract registered by BCRP
50 // call contract script format: OP_DATA_4 + "bcrp"+ OP_DATA_32 + SHA3-256(contract)
51 func IsCallContractScript(prog []byte) bool {
52         insts, err := vm.ParseProgram(prog)
53         if err != nil {
54                 return false
55         }
56
57         if len(insts) != 2 {
58                 return false
59         }
60
61         if insts[0].Op != vm.OP_DATA_4 || !bytes.Equal(insts[0].Data, []byte(BCRP)) {
62                 return false
63         }
64
65         return insts[1].Op == vm.OP_DATA_32 && len(insts[1].Data) == consensus.BCRPContractHashDataSize
66 }
67
68 // ParseContract parse contract from BCRP script
69 // BCRP script format: OP_FAIL + OP_DATA_4 + "bcrp" + OP_DATA_1 + "1" + {{dynamic_op}} + contract
70 func ParseContract(prog []byte) ([]byte, error) {
71         insts, err := vm.ParseProgram(prog)
72         if err != nil {
73                 return nil, err
74         }
75
76         if len(insts) != 4 {
77                 return nil, errors.New("unsupport program")
78         }
79
80         return insts[3].Data, nil
81 }
82
83 // ParseContractHash parse contract hash from call BCRP script
84 // call contract script format: OP_DATA_4 + "bcrp"+ OP_DATA_32 + SHA3-256(contract)
85 func ParseContractHash(prog []byte) ([32]byte, error) {
86         insts, err := vm.ParseProgram(prog)
87         if err != nil {
88                 return [32]byte{}, err
89         }
90
91         if len(insts) != 2 {
92                 return [32]byte{}, errors.New("unsupport program")
93         }
94
95         var hash [32]byte
96         copy(hash[:], insts[1].Data)
97
98         return hash, nil
99 }