11 "github.com/equity/compiler"
15 // generateInstPath is the directory (need to combine with GOPATH) for store generated contract instance
16 generateInstPath = "/src/github.com/equity/instance/"
20 if len(os.Args) != 2 {
21 fmt.Println("command args: [command] [contract file_path]")
25 filename := os.Args[1]
26 inputFile, inputError := os.Open(filename)
27 if inputError != nil {
28 fmt.Printf("An error occurred on opening the inputfile\n" +
29 "Does the file exist?\n" +
30 "Have you got acces to it?\n")
33 defer inputFile.Close()
35 inputReader := bufio.NewReader(inputFile)
36 contracts, err := compiler.Compile(inputReader)
41 var packageName *string
45 //change the windows path into unix path
46 filename = strings.Replace(filename, "\\", "/", -1)
47 if strings.Contains(filename, "/") == true {
48 outstr = strings.Split(filename, "/")
49 midstr = outstr[len(outstr)-1]
54 //check whether the filename contains point flag
55 if strings.Contains(midstr, ".") == true {
56 outstr = strings.Split(midstr, ".")
57 packageName = &outstr[0]
62 header := new(bytes.Buffer)
63 fmt.Fprintf(header, "package instance\n\n")
65 imports := map[string]bool{
69 "github.com/equity/compiler": true,
70 "github.com/bytom/protocol/vm": true,
73 buf := new(bytes.Buffer)
75 if len(contracts) == 1 {
76 fmt.Fprintf(buf, "// %sBodyBytes refer to contract's body\n", contracts[0].Name)
77 fmt.Fprintf(buf, "var %sBodyBytes []byte\n\n", contracts[0].Name)
79 fmt.Fprintf(buf, "var (\n")
80 for _, contract := range contracts {
81 fmt.Fprintf(buf, "\t%sBodyBytes []byte\n", contract.Name)
83 fmt.Fprintf(buf, ")\n\n")
86 fmt.Fprintf(buf, "func init() {\n")
87 for _, contract := range contracts {
88 fmt.Fprintf(buf, "\t%sBodyBytes, _ = hex.DecodeString(\"%x\")\n", contract.Name, contract.Body)
90 fmt.Fprintf(buf, "}\n\n")
92 for _, contract := range contracts {
93 fmt.Fprintf(buf, "// contract %s(%s) locks %s\n", contract.Name, paramsStr(contract.Params), contract.Value)
94 fmt.Fprintf(buf, "//\n")
96 for _, step := range contract.Steps {
97 if len(step.Opcodes) > maxWidth {
98 maxWidth = len(step.Opcodes)
101 format := fmt.Sprintf("// %%-%d.%ds %%s\n", maxWidth, maxWidth)
102 for _, step := range contract.Steps {
103 fmt.Fprintf(buf, format, step.Opcodes, step.Stack)
105 fmt.Fprintf(buf, "\n")
107 fmt.Fprintf(buf, "// PayTo%s instantiates contract %s as a program with specific arguments.\n", contract.Name, contract.Name)
108 goParams, newImports := asGoParams(contract.Params)
109 for _, imp := range newImports {
112 fmt.Fprintf(buf, "func PayTo%s(%s) ([]byte, error) {\n", contract.Name, goParams)
113 fmt.Fprintf(buf, "\t_contractParams := []*compiler.Param{\n")
114 for _, param := range contract.Params {
115 fmt.Fprintf(buf, "\t\t{Name: \"%s\", Type: \"%s\"},\n", param.Name, param.Type)
117 fmt.Fprintf(buf, "\t}\n")
118 fmt.Fprintf(buf, "\tvar _contractArgs []compiler.ContractArg\n")
119 for _, param := range contract.Params {
122 fmt.Fprintf(buf, "\t_%s := int64(%s)\n", param.Name, param.Name)
123 fmt.Fprintf(buf, "\t_contractArgs = append(_contractArgs, compiler.ContractArg{I: &_%s})\n", param.Name)
125 fmt.Fprintf(buf, "\t_%s := %s.Bytes()\n", param.Name, param.Name)
126 fmt.Fprintf(buf, "\t_contractArgs = append(_contractArgs, compiler.ContractArg{S: (*json.HexBytes)(&_%s)})\n", param.Name)
128 fmt.Fprintf(buf, "\t_contractArgs = append(_contractArgs, compiler.ContractArg{B: &%s})\n", param.Name)
130 fmt.Fprintf(buf, "\t_contractArgs = append(_contractArgs, compiler.ContractArg{I: &%s})\n", param.Name)
131 case "Hash", "Program", "PublicKey", "Signature", "Sign", "String":
132 fmt.Fprintf(buf, "\t_contractArgs = append(_contractArgs, compiler.ContractArg{S: (*json.HexBytes)(&%s)})\n", param.Name)
135 fmt.Fprintf(buf, "\treturn compiler.Instantiate(%sBodyBytes, _contractParams, %v, _contractArgs)\n", contract.Name, contract.Recursive)
136 fmt.Fprintf(buf, "}\n\n")
138 fmt.Fprintf(buf, "// ParsePayTo%s parses the arguments out of an instantiation of contract %s.\n", contract.Name, contract.Name)
139 fmt.Fprintf(buf, "// If the input is not an instantiation of %s, returns an error.\n", contract.Name)
140 fmt.Fprintf(buf, "func ParsePayTo%s(prog []byte) ([][]byte, error) {\n", contract.Name)
141 fmt.Fprintf(buf, "\tvar result [][]byte\n")
142 fmt.Fprintf(buf, "\tinsts, err := vm.ParseProgram(prog)\n")
143 fmt.Fprintf(buf, "\tif err != nil {\n")
144 fmt.Fprintf(buf, "\t\treturn nil, err\n")
145 fmt.Fprintf(buf, "\t}\n")
146 fmt.Fprintf(buf, "\tfor i := 0; i < %d; i++ {\n", len(contract.Params))
147 fmt.Fprintf(buf, "\t\tif len(insts) == 0 {\n")
148 fmt.Fprintf(buf, "\t\t\treturn nil, fmt.Errorf(\"program too short\")\n")
149 fmt.Fprintf(buf, "\t\t}\n")
150 fmt.Fprintf(buf, "\t\tif !insts[0].IsPushdata() {\n")
151 fmt.Fprintf(buf, "\t\t\treturn nil, fmt.Errorf(\"too few arguments\")\n")
152 fmt.Fprintf(buf, "\t\t}\n")
153 fmt.Fprintf(buf, "\t\tresult = append(result, insts[0].Data)\n")
154 fmt.Fprintf(buf, "\t\tinsts = insts[1:]\n")
155 fmt.Fprintf(buf, "\t}\n")
156 if contract.Recursive {
157 // args... body DEPTH OVER 0 CHECKPREDICATE
158 fmt.Fprintf(buf, "\tif len(insts) == 0 {\n")
159 fmt.Fprintf(buf, "\t\treturn nil, fmt.Errorf(\"program too short\")\n")
160 fmt.Fprintf(buf, "\t}\n")
161 fmt.Fprintf(buf, "\tif !insts[0].IsPushdata() {\n")
162 fmt.Fprintf(buf, "\t\treturn nil, fmt.Errorf(\"too few arguments\")\n")
163 fmt.Fprintf(buf, "\t}\n")
164 fmt.Fprintf(buf, "\tif !bytes.Equal(%sBodyBytes, insts[0].Data) {\n", contract.Name)
165 fmt.Fprintf(buf, "\t\treturn nil, fmt.Errorf(\"body bytes do not match %s\")\n", contract.Name)
166 fmt.Fprintf(buf, "\t}\n")
167 fmt.Fprintf(buf, "\tinsts = insts[1:]\n")
168 } // else args ... DEPTH body 0 CHECKPREDICATE
169 fmt.Fprintf(buf, "\tif len(insts) != 4 {\n")
170 fmt.Fprintf(buf, "\t\treturn nil, fmt.Errorf(\"program too short\")\n")
171 fmt.Fprintf(buf, "\t}\n")
172 fmt.Fprintf(buf, "\tif insts[0].Op != vm.OP_DEPTH {\n")
173 fmt.Fprintf(buf, "\t\treturn nil, fmt.Errorf(\"wrong program format\")\n")
174 fmt.Fprintf(buf, "\t}\n")
175 if contract.Recursive {
176 fmt.Fprintf(buf, "\tif insts[1].Op != vm.OP_OVER {\n")
177 fmt.Fprintf(buf, "\t\treturn nil, fmt.Errorf(\"wrong program format\")\n")
178 fmt.Fprintf(buf, "\t}\n")
180 fmt.Fprintf(buf, "\tif !insts[1].IsPushdata() {\n")
181 fmt.Fprintf(buf, "\t\treturn nil, fmt.Errorf(\"wrong program format\")\n")
182 fmt.Fprintf(buf, "\t}\n")
183 fmt.Fprintf(buf, "\tif !bytes.Equal(%sBodyBytes, insts[1].Data) {\n", contract.Name)
184 fmt.Fprintf(buf, "\t\treturn nil, fmt.Errorf(\"body bytes do not match %s\")\n", contract.Name)
185 fmt.Fprintf(buf, "\t}\n")
187 fmt.Fprintf(buf, "\tif !insts[2].IsPushdata() {\n")
188 fmt.Fprintf(buf, "\t\treturn nil, fmt.Errorf(\"wrong program format\")\n")
189 fmt.Fprintf(buf, "\t}\n")
190 fmt.Fprintf(buf, "\tv, err := vm.AsInt64(insts[2].Data)\n")
191 fmt.Fprintf(buf, "\tif err != nil {\n")
192 fmt.Fprintf(buf, "\t\treturn nil, err\n")
193 fmt.Fprintf(buf, "\t}\n")
194 fmt.Fprintf(buf, "\tif v != 0 {\n")
195 fmt.Fprintf(buf, "\t\treturn nil, fmt.Errorf(\"wrong program format\")\n")
196 fmt.Fprintf(buf, "\t}\n")
197 fmt.Fprintf(buf, "\tif insts[3].Op != vm.OP_CHECKPREDICATE {\n")
198 fmt.Fprintf(buf, "\t\treturn nil, fmt.Errorf(\"wrong program format\")\n")
199 fmt.Fprintf(buf, "\t}\n")
200 fmt.Fprintf(buf, "\treturn result, nil\n")
201 fmt.Fprintf(buf, "}\n\n")
203 // TODO(bobg): RedeemFoo_Bar functions for marshaling the args to
204 // the Bar clause of contract Foo.
207 fmt.Fprintf(header, "import (\n")
208 for imp := range imports {
209 fmt.Fprintf(header, "\t\"%s\"\n", imp)
211 fmt.Fprintf(header, ")\n\n")
213 //get the Environment variables of GOPATH
214 gopath := os.Getenv("GOPATH")
215 path := gopath + generateInstPath
217 //if the directory is not exist, create it
218 _, err = os.Stat(path)
220 if os.IsNotExist(err) {
221 direrr := os.MkdirAll(path, os.ModePerm)
225 fmt.Println("the path is create success")
231 //store buf by create file
232 file, _ := os.Create(path + *packageName + ".go")
234 file.Write(header.Bytes())
235 file.Write(buf.Bytes())
236 fmt.Printf("create file [%s] success!\n", *packageName+".go")
239 func paramsStr(params []*compiler.Param) string {
241 for _, p := range params {
242 strs = append(strs, fmt.Sprintf("%s: %s", p.Name, p.Type))
244 return strings.Join(strs, ", ")
247 func asGoParams(params []*compiler.Param) (goParams string, imports []string) {
250 for _, p := range params {
257 imports = append(imports, "github.com/bytom/protocol/bc")
270 typ = "ed25519.PublicKey"
271 imports = append(imports, "github.com/bytom/crypto/ed25519")
283 strs = append(strs, fmt.Sprintf("%s %s", p.Name, typ))
287 imports = append(imports, "github.com/bytom/encoding/json")
289 return strings.Join(strs, ", "), imports