github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/contract/contract.go (about) 1 package contract 2 3 import ( 4 "encoding/json" 5 "sync" 6 7 dbm "github.com/bytom/bytom/database/leveldb" 8 chainjson "github.com/bytom/bytom/encoding/json" 9 "github.com/bytom/bytom/errors" 10 ) 11 12 var ( 13 userContractPrefix = []byte("UC:") 14 ) 15 16 // pre-define errors for supporting bytom errorFormatter 17 var ( 18 ErrContractDuplicated = errors.New("contract is duplicated") 19 ErrContractNotFound = errors.New("contract not found") 20 ) 21 22 // userContractKey return user contract key 23 func userContractKey(hash chainjson.HexBytes) []byte { 24 return append(userContractPrefix, hash[:]...) 25 } 26 27 // Registry tracks and stores all user contract. 28 type Registry struct { 29 db dbm.DB 30 contractMu sync.Mutex 31 } 32 33 //NewRegistry create new registry 34 func NewRegistry(db dbm.DB) *Registry { 35 return &Registry{ 36 db: db, 37 } 38 } 39 40 //Contract describe user contract 41 type Contract struct { 42 Hash chainjson.HexBytes `json:"id"` 43 Alias string `json:"alias"` 44 Contract chainjson.HexBytes `json:"contract"` 45 CallProgram chainjson.HexBytes `json:"call_program"` 46 RegisterProgram chainjson.HexBytes `json:"register_program"` 47 } 48 49 // SaveContract save user contract 50 func (reg *Registry) SaveContract(contract *Contract) error { 51 reg.contractMu.Lock() 52 defer reg.contractMu.Unlock() 53 54 contractKey := userContractKey(contract.Hash) 55 if existContract := reg.db.Get(contractKey); existContract != nil { 56 return ErrContractDuplicated 57 } 58 59 rawContract, err := json.Marshal(contract) 60 if err != nil { 61 return err 62 } 63 64 reg.db.Set(contractKey, rawContract) 65 return nil 66 } 67 68 //UpdateContract updates user contract alias 69 func (reg *Registry) UpdateContract(hash chainjson.HexBytes, alias string) error { 70 reg.contractMu.Lock() 71 defer reg.contractMu.Unlock() 72 73 contract, err := reg.GetContract(hash) 74 if err != nil { 75 return err 76 } 77 78 contract.Alias = alias 79 rawContract, err := json.Marshal(contract) 80 if err != nil { 81 return err 82 } 83 84 reg.db.Set(userContractKey(hash), rawContract) 85 return nil 86 } 87 88 // GetContract get user contract 89 func (reg *Registry) GetContract(hash chainjson.HexBytes) (*Contract, error) { 90 contract := &Contract{} 91 if rawContract := reg.db.Get(userContractKey(hash)); rawContract != nil { 92 return contract, json.Unmarshal(rawContract, contract) 93 } 94 return nil, ErrContractNotFound 95 } 96 97 // ListContracts returns user contracts 98 func (reg *Registry) ListContracts() ([]*Contract, error) { 99 contracts := []*Contract{} 100 contractIter := reg.db.IteratorPrefix(userContractPrefix) 101 defer contractIter.Release() 102 103 for contractIter.Next() { 104 contract := &Contract{} 105 if err := json.Unmarshal(contractIter.Value(), contract); err != nil { 106 return nil, err 107 } 108 109 contracts = append(contracts, contract) 110 } 111 return contracts, nil 112 }