github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/api/contract.go (about)

     1  package api
     2  
     3  import (
     4  	"context"
     5  	"strings"
     6  
     7  	"github.com/bytom/bytom/contract"
     8  	"github.com/bytom/bytom/crypto/sha3pool"
     9  	chainjson "github.com/bytom/bytom/encoding/json"
    10  	"github.com/bytom/bytom/errors"
    11  	"github.com/bytom/bytom/protocol/bc"
    12  	"github.com/bytom/bytom/protocol/vm/vmutil"
    13  )
    14  
    15  // pre-define errors for supporting bytom errorFormatter
    16  var (
    17  	ErrNullContract      = errors.New("contract is empty")
    18  	ErrNullContractID    = errors.New("contract id is empty")
    19  	ErrNullContractAlias = errors.New("contract alias is empty")
    20  )
    21  
    22  // POST /create-asset
    23  func (a *API) createContract(_ context.Context, ins struct {
    24  	Alias    string             `json:"alias"`
    25  	Contract chainjson.HexBytes `json:"contract"`
    26  }) Response {
    27  	ins.Alias = strings.TrimSpace(ins.Alias)
    28  	if ins.Alias == "" {
    29  		return NewErrorResponse(ErrNullContractAlias)
    30  	}
    31  
    32  	if ins.Contract == nil {
    33  		return NewErrorResponse(ErrNullContract)
    34  	}
    35  
    36  	var hash [32]byte
    37  	sha3pool.Sum256(hash[:], ins.Contract)
    38  
    39  	registerProgram, err := vmutil.RegisterProgram(ins.Contract)
    40  	if err != nil {
    41  		return NewErrorResponse(err)
    42  	}
    43  
    44  	callProgram, err := vmutil.CallContractProgram(hash[:])
    45  	if err != nil {
    46  		return NewErrorResponse(err)
    47  	}
    48  
    49  	c := &contract.Contract{
    50  		Hash:            hash[:],
    51  		Alias:           ins.Alias,
    52  		Contract:        ins.Contract,
    53  		CallProgram:     callProgram,
    54  		RegisterProgram: registerProgram,
    55  	}
    56  	if err := a.wallet.ContractReg.SaveContract(c); err != nil {
    57  		return NewErrorResponse(err)
    58  	}
    59  
    60  	return NewSuccessResponse(c)
    61  }
    62  
    63  // POST /update-contract-alias
    64  func (a *API) updateContractAlias(_ context.Context, ins struct {
    65  	ID    chainjson.HexBytes `json:"id"`
    66  	Alias string             `json:"alias"`
    67  }) Response {
    68  	if ins.ID == nil {
    69  		return NewErrorResponse(ErrNullContractID)
    70  	}
    71  
    72  	ins.Alias = strings.TrimSpace(ins.Alias)
    73  	if ins.Alias == "" {
    74  		return NewErrorResponse(ErrNullContractAlias)
    75  	}
    76  
    77  	if err := a.wallet.ContractReg.UpdateContract(ins.ID, ins.Alias); err != nil {
    78  		return NewErrorResponse(err)
    79  	}
    80  
    81  	return NewSuccessResponse(nil)
    82  }
    83  
    84  // POST /get-contract
    85  func (a *API) getContract(_ context.Context, ins struct {
    86  	ID chainjson.HexBytes `json:"id"`
    87  }) Response {
    88  	if ins.ID == nil {
    89  		return NewErrorResponse(ErrNullContractID)
    90  	}
    91  
    92  	c, err := a.wallet.ContractReg.GetContract(ins.ID)
    93  	if err != nil {
    94  		return NewErrorResponse(err)
    95  	}
    96  
    97  	return NewSuccessResponse(c)
    98  }
    99  
   100  // POST /list-contracts
   101  func (a *API) listContracts(_ context.Context) Response {
   102  	cs, err := a.wallet.ContractReg.ListContracts()
   103  	if err != nil {
   104  		return NewErrorResponse(err)
   105  	}
   106  
   107  	return NewSuccessResponse(cs)
   108  }
   109  
   110  type ContractInstance struct {
   111  	UTXOs       []*contract.UTXO     `json:"utxos"`
   112  	TxHash      *bc.Hash             `json:"tx_hash"`
   113  	Status      contract.Status      `json:"status"`
   114  	Unconfirmed []*contract.TreeNode `json:"unconfirmed"`
   115  }
   116  
   117  func (a *API) getContractInstance(_ context.Context, ins struct {
   118  	TraceID string `json:"trace_id"`
   119  }) Response {
   120  	instance, err := a.contractTracer.GetInstance(ins.TraceID)
   121  	if err != nil {
   122  		return NewErrorResponse(err)
   123  	}
   124  
   125  	return NewSuccessResponse(&ContractInstance{
   126  		UTXOs:       instance.UTXOs,
   127  		TxHash:      instance.TxHash,
   128  		Status:      instance.Status,
   129  		Unconfirmed: instance.Unconfirmed,
   130  	})
   131  }
   132  
   133  func (a *API) createContractInstance(_ context.Context, ins struct {
   134  	TxHash    chainjson.HexBytes `json:"tx_hash"`
   135  	BlockHash chainjson.HexBytes `json:"block_hash"`
   136  }) Response {
   137  	var txHash, blockHash [32]byte
   138  	copy(txHash[:], ins.TxHash)
   139  	copy(blockHash[:], ins.BlockHash)
   140  
   141  	traceIDs, err := a.contractTracer.CreateInstance(bc.NewHash(txHash), bc.NewHash(blockHash))
   142  	if err != nil {
   143  		return NewErrorResponse(err)
   144  	}
   145  
   146  	return NewSuccessResponse(traceIDs)
   147  }
   148  
   149  func (a *API) removeContractInstance(_ context.Context, ins struct {
   150  	TraceID string `json:"trace_id"`
   151  }) Response {
   152  	if err := a.contractTracer.RemoveInstance(ins.TraceID); err != nil {
   153  		return NewErrorResponse(err)
   154  	}
   155  
   156  	return NewSuccessResponse(nil)
   157  }