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  }