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 }