11 "github.com/equity/compiler"
15 packageName := flag.String("package", "main", "Go package name for generated file")
18 contracts, err := compiler.Compile(os.Stdin)
23 fmt.Printf("package %s\n\n", *packageName)
25 imports := map[string]bool{
29 "github.com/bytom/equity/compiler": true,
30 "github.com/bytom/protocol/vm": true,
33 buf := new(bytes.Buffer)
35 if len(contracts) == 1 {
36 fmt.Fprintf(buf, "var %s_body_bytes []byte\n\n", contracts[0].Name)
38 fmt.Fprintf(buf, "var (\n")
39 for _, contract := range contracts {
40 fmt.Fprintf(buf, "\t%s_body_bytes []byte\n", contract.Name)
42 fmt.Fprintf(buf, ")\n\n")
45 fmt.Fprintf(buf, "func init() {\n")
46 for _, contract := range contracts {
47 fmt.Fprintf(buf, "\t%s_body_bytes, _ = hex.DecodeString(\"%x\")\n", contract.Name, contract.Body)
49 fmt.Fprintf(buf, "}\n\n")
51 for _, contract := range contracts {
52 fmt.Fprintf(buf, "// contract %s(%s) locks %s\n", contract.Name, paramsStr(contract.Params), contract.Value)
53 fmt.Fprintf(buf, "//\n")
55 for _, step := range contract.Steps {
56 if len(step.Opcodes) > maxWidth {
57 maxWidth = len(step.Opcodes)
60 format := fmt.Sprintf("// %%-%d.%ds %%s\n", maxWidth, maxWidth)
61 for _, step := range contract.Steps {
62 fmt.Fprintf(buf, format, step.Opcodes, step.Stack)
64 fmt.Fprintf(buf, "\n")
66 fmt.Fprintf(buf, "// PayTo%s instantiates contract %s as a program with specific arguments.\n", contract.Name, contract.Name)
67 goParams, newImports := asGoParams(contract.Params)
68 for _, imp := range newImports {
71 fmt.Fprintf(buf, "func PayTo%s(%s) ([]byte, error) {\n", contract.Name, goParams)
72 fmt.Fprintf(buf, "\t_contractParams := []compiler.Param{\n")
73 for _, param := range contract.Params {
74 fmt.Fprintf(buf, "\t\t{Name: \"%s\", Type: \"%s\"},\n", param.Name, param.Type)
76 fmt.Fprintf(buf, "\t}\n")
77 fmt.Fprintf(buf, "\tvar _contractArgs []compiler.ContractArg\n")
78 for _, param := range contract.Params {
81 fmt.Fprintf(buf, "\t_%s := int64(%s)\n", param.Name, param.Name)
82 fmt.Fprintf(buf, "\t_contractArgs = append(_contractArgs, compiler.ContractArg{I: &_%s})\n", param.Name)
84 fmt.Fprintf(buf, "\t_%s := %s[:]\n", param.Name, param.Name)
85 fmt.Fprintf(buf, "\t_contractArgs = append(_contractArgs, compiler.ContractArg{S: &_%s})\n", param.Name)
86 case "Boolean", "Hash", "Program", "PublicKey", "Signature", "String":
87 fmt.Fprintf(buf, "\t_contractArgs = append(_contractArgs, compiler.ContractArg{S: &%s})\n", param.Name)
89 fmt.Fprintf(buf, "\t_contractArgs = append(_contractArgs, compiler.ContractArg{I: &%s})\n", param.Name)
92 fmt.Fprintf(buf, "\treturn compiler.Instantiate(_contractParams, %s_body_bytes, %v, _contractArgs)\n", contract.Name, contract.Recursive)
93 fmt.Fprintf(buf, "}\n\n")
95 fmt.Fprintf(buf, "// ParsePayTo%s parses the arguments out of an instantiation of contract %s.\n", contract.Name, contract.Name)
96 fmt.Fprintf(buf, "// If the input is not an instantiation of %s, returns an error.\n", contract.Name)
97 fmt.Fprintf(buf, "func ParsePayTo%s(prog []byte) ([][]byte, error) {\n", contract.Name)
98 fmt.Fprintf(buf, "\tvar result [][]byte\n")
99 fmt.Fprintf(buf, "\tinsts, err := vm.ParseProgram(prog)\n")
100 fmt.Fprintf(buf, "\tif err != nil {\n")
101 fmt.Fprintf(buf, "\t\treturn nil, err\n")
102 fmt.Fprintf(buf, "\t}\n")
103 fmt.Fprintf(buf, "\tfor i := 0; i < %d; i++ {\n", len(contract.Params))
104 fmt.Fprintf(buf, "\t\tif len(insts) == 0 {\n")
105 fmt.Fprintf(buf, "\t\t\treturn nil, fmt.Errorf(\"program too short\")\n")
106 fmt.Fprintf(buf, "\t\t}\n")
107 fmt.Fprintf(buf, "\t\tif !insts[0].IsPushdata() {\n")
108 fmt.Fprintf(buf, "\t\t\treturn nil, fmt.Errorf(\"too few arguments\")\n")
109 fmt.Fprintf(buf, "\t\t}\n")
110 fmt.Fprintf(buf, "\t\tresult = append(result, insts[0].Data)\n")
111 fmt.Fprintf(buf, "\t\tinsts = insts[1:]\n")
112 fmt.Fprintf(buf, "\t}\n")
113 if contract.Recursive {
114 // args... body DEPTH OVER 0 CHECKPREDICATE
115 fmt.Fprintf(buf, "\tif len(insts) == 0 {\n")
116 fmt.Fprintf(buf, "\t\treturn nil, fmt.Errorf(\"program too short\")\n")
117 fmt.Fprintf(buf, "\t}\n")
118 fmt.Fprintf(buf, "\tif !insts[0].IsPushdata() {\n")
119 fmt.Fprintf(buf, "\t\treturn nil, fmt.Errorf(\"too few arguments\")\n")
120 fmt.Fprintf(buf, "\t}\n")
121 fmt.Fprintf(buf, "\tif !bytes.Equal(%s_body_bytes, insts[0].Data) {\n", contract.Name)
122 fmt.Fprintf(buf, "\t\treturn nil, fmt.Errorf(\"body bytes do not match %s\")\n", contract.Name)
123 fmt.Fprintf(buf, "\t}\n")
124 fmt.Fprintf(buf, "\tinsts = insts[1:]\n")
125 } // else args ... DEPTH body 0 CHECKPREDICATE
126 fmt.Fprintf(buf, "\tif len(insts) != 4 {\n")
127 fmt.Fprintf(buf, "\t\treturn nil, fmt.Errorf(\"program too short\")\n")
128 fmt.Fprintf(buf, "\t}\n")
129 fmt.Fprintf(buf, "\tif insts[0].Op != vm.OP_DEPTH {\n")
130 fmt.Fprintf(buf, "\t\treturn nil, fmt.Errorf(\"wrong program format\")\n")
131 fmt.Fprintf(buf, "\t}\n")
132 if contract.Recursive {
133 fmt.Fprintf(buf, "\tif insts[1].Op != vm.OP_OVER {\n")
134 fmt.Fprintf(buf, "\t\treturn nil, fmt.Errorf(\"wrong program format\")\n")
135 fmt.Fprintf(buf, "\t}\n")
137 fmt.Fprintf(buf, "\tif !insts[1].IsPushdata() {\n")
138 fmt.Fprintf(buf, "\t\treturn nil, fmt.Errorf(\"wrong program format\")\n")
139 fmt.Fprintf(buf, "\t}\n")
140 fmt.Fprintf(buf, "\tif !bytes.Equal(%s_body_bytes, insts[1].Data) {\n", contract.Name)
141 fmt.Fprintf(buf, "\t\treturn nil, fmt.Errorf(\"body bytes do not match %s\")\n", contract.Name)
142 fmt.Fprintf(buf, "\t}\n")
144 fmt.Fprintf(buf, "\tif !insts[2].IsPushdata() {\n")
145 fmt.Fprintf(buf, "\t\treturn nil, fmt.Errorf(\"wrong program format\")\n")
146 fmt.Fprintf(buf, "\t}\n")
147 fmt.Fprintf(buf, "\tv, err := vm.AsInt64(insts[2].Data)\n")
148 fmt.Fprintf(buf, "\tif err != nil {\n")
149 fmt.Fprintf(buf, "\t\treturn nil, err\n")
150 fmt.Fprintf(buf, "\t}\n")
151 fmt.Fprintf(buf, "\tif v != 0 {\n")
152 fmt.Fprintf(buf, "\t\treturn nil, fmt.Errorf(\"wrong program format\")\n")
153 fmt.Fprintf(buf, "\t}\n")
154 fmt.Fprintf(buf, "\tif insts[3].Op != vm.OP_CHECKPREDICATE {\n")
155 fmt.Fprintf(buf, "\t\treturn nil, fmt.Errorf(\"wrong program format\")\n")
156 fmt.Fprintf(buf, "\t}\n")
157 fmt.Fprintf(buf, "\treturn result, nil\n")
158 fmt.Fprintf(buf, "}\n\n")
160 // TODO(bobg): RedeemFoo_Bar functions for marshaling the args to
161 // the Bar clause of contract Foo.
164 fmt.Printf("import (\n")
165 for imp := range imports {
166 fmt.Printf("\t\"%s\"\n", imp)
170 os.Stdout.Write(buf.Bytes())
173 func paramsStr(params []*compiler.Param) string {
175 for _, p := range params {
176 strs = append(strs, fmt.Sprintf("%s: %s", p.Name, p.Type))
178 return strings.Join(strs, ", ")
181 func asGoParams(params []*compiler.Param) (goParams string, imports []string) {
183 for _, p := range params {
190 imports = append(imports, "github.com/bytom/protocol/bc")
200 typ = "ed25519.PublicKey"
201 imports = append(imports, "github.com/bytom/crypto/ed25519")
207 strs = append(strs, fmt.Sprintf("%s %s", p.Name, typ))
209 return strings.Join(strs, ", "), imports