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  }