github.com/Bytom/bytom@v1.1.2-0.20210127130405-ae40204c0b09/api/compile.go (about) 1 package api 2 3 import ( 4 "strings" 5 6 chainjson "github.com/bytom/bytom/encoding/json" 7 "github.com/bytom/bytom/equity/compiler" 8 "github.com/bytom/bytom/errors" 9 "github.com/bytom/bytom/protocol/vm" 10 ) 11 12 // pre-define contract error types 13 var ( 14 ErrCompileContract = errors.New("compile contract failed") 15 ErrInstContract = errors.New("instantiate contract failed") 16 ) 17 18 type ( 19 compileReq struct { 20 Contract string `json:"contract"` 21 Args []compiler.ContractArg `json:"args"` 22 } 23 24 compileResp struct { 25 Name string `json:"name"` 26 Source string `json:"source"` 27 Program chainjson.HexBytes `json:"program"` 28 Params []*compiler.Param `json:"params"` 29 Value string `json:"value"` 30 Clauses []*compiler.Clause `json:"clause_info"` 31 Opcodes string `json:"opcodes"` 32 Error string `json:"error"` 33 } 34 ) 35 36 func compileEquity(req compileReq) (*compileResp, error) { 37 compiled, err := compiler.Compile(strings.NewReader(req.Contract)) 38 if err != nil { 39 return nil, errors.WithDetail(ErrCompileContract, err.Error()) 40 } 41 42 // if source contract maybe contain import statement, multiple contract objects will be generated 43 // after the compilation, and the last object is what we need. 44 contract := compiled[len(compiled)-1] 45 resp := &compileResp{ 46 Name: contract.Name, 47 Source: req.Contract, 48 Program: contract.Body, 49 Value: contract.Value.Amount + " of " + contract.Value.Asset, 50 Clauses: contract.Clauses, 51 Opcodes: contract.Opcodes, 52 } 53 54 if req.Args != nil { 55 resp.Program, err = compiler.Instantiate(contract.Body, contract.Params, contract.Recursive, req.Args) 56 if err != nil { 57 return nil, errors.WithDetail(ErrInstContract, err.Error()) 58 } 59 60 resp.Opcodes, err = vm.Disassemble(resp.Program) 61 if err != nil { 62 return nil, err 63 } 64 } 65 66 for _, param := range contract.Params { 67 if param.InferredType != "" { 68 param.Type = param.InferredType 69 param.InferredType = "" 70 } 71 resp.Params = append(resp.Params, param) 72 } 73 74 return resp, nil 75 } 76 77 func (a *API) compileEquity(req compileReq) Response { 78 resp, err := compileEquity(req) 79 if err != nil { 80 return NewErrorResponse(err) 81 } 82 return NewSuccessResponse(&resp) 83 }