github.com/aergoio/aergo@v1.3.1/contract/name/name.go (about)

     1  package name
     2  
     3  import (
     4  	"encoding/binary"
     5  	"fmt"
     6  	"strings"
     7  
     8  	"github.com/aergoio/aergo/state"
     9  	"github.com/aergoio/aergo/types"
    10  )
    11  
    12  var prefix = []byte("name")
    13  
    14  type NameMap struct {
    15  	Version     byte
    16  	Owner       []byte
    17  	Destination []byte
    18  }
    19  
    20  // AccountStateReader is an interface for getting a name account state.
    21  type AccountStateReader interface {
    22  	GetNameAccountState() (*state.ContractState, error)
    23  }
    24  
    25  func CreateName(scs *state.ContractState, tx *types.TxBody, sender, receiver *state.V, name string) error {
    26  	amount := tx.GetAmountBigInt()
    27  	sender.SubBalance(amount)
    28  	receiver.AddBalance(amount)
    29  	return createName(scs, []byte(name), sender.ID())
    30  }
    31  
    32  func createName(scs *state.ContractState, name []byte, owner []byte) error {
    33  	//	return setAddress(scs, name, owner)
    34  	return registerOwner(scs, name, owner, owner)
    35  }
    36  
    37  //UpdateName is avaliable after bid implement
    38  func UpdateName(bs *state.BlockState, scs *state.ContractState, tx *types.TxBody,
    39  	sender, receiver *state.V, name, to string) error {
    40  	amount := tx.GetAmountBigInt()
    41  	if len(getAddress(scs, []byte(name))) <= types.NameLength {
    42  		return fmt.Errorf("%s is not created yet", string(name))
    43  	}
    44  	destination, _ := types.DecodeAddress(to)
    45  	destination = GetAddress(scs, destination)
    46  	sender.SubBalance(amount)
    47  	receiver.AddBalance(amount)
    48  	contract, err := bs.StateDB.OpenContractStateAccount(types.ToAccountID(destination))
    49  	if err != nil {
    50  		return types.ErrTxInvalidRecipient
    51  	}
    52  	creator, err := contract.GetData([]byte("Creator"))
    53  	if err != nil {
    54  		return err
    55  	}
    56  	ownerAddr := destination
    57  	if creator != nil {
    58  		ownerAddr, err = types.DecodeAddress(string(creator))
    59  		if err != nil {
    60  			return types.ErrTxInvalidRecipient
    61  		}
    62  	}
    63  	return updateName(scs, []byte(name), ownerAddr, destination)
    64  }
    65  
    66  func updateName(scs *state.ContractState, name []byte, owner []byte, to []byte) error {
    67  	//return setAddress(scs, name, to)
    68  	return registerOwner(scs, name, owner, to)
    69  }
    70  
    71  //Resolve is resolve name for chain
    72  func Resolve(bs *state.BlockState, name []byte) []byte {
    73  	if len(name) == types.AddressLength ||
    74  		strings.Contains(string(name), ".") {
    75  		return name
    76  	}
    77  	scs, err := openContract(bs)
    78  	if err != nil {
    79  		return name
    80  	}
    81  	return getAddress(scs, name)
    82  }
    83  
    84  func openContract(bs *state.BlockState) (*state.ContractState, error) {
    85  	v, err := bs.GetAccountStateV([]byte("aergo.name"))
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  	scs, err := bs.StateDB.OpenContractState(v.AccountID(), v.State())
    90  	if err != nil {
    91  		return nil, err
    92  	}
    93  	return scs, nil
    94  }
    95  
    96  //GetAddress is resolve name for mempool
    97  func GetAddress(scs *state.ContractState, name []byte) []byte {
    98  	if len(name) == types.AddressLength ||
    99  		strings.Contains(string(name), ".") {
   100  		return name
   101  	}
   102  	return getAddress(scs, name)
   103  }
   104  
   105  func getAddress(scs *state.ContractState, name []byte) []byte {
   106  	nameMap := getNameMap(scs, name, true)
   107  	if nameMap != nil {
   108  		return nameMap.Destination
   109  	}
   110  	return nil
   111  }
   112  
   113  func GetOwner(scs *state.ContractState, name []byte) []byte {
   114  	return getOwner(scs, name, true)
   115  }
   116  
   117  func getOwner(scs *state.ContractState, name []byte, useInitial bool) []byte {
   118  	nameMap := getNameMap(scs, name, useInitial)
   119  	if nameMap != nil {
   120  		return nameMap.Owner
   121  	}
   122  	return nil
   123  }
   124  
   125  func getNameMap(scs *state.ContractState, name []byte, useInitial bool) *NameMap {
   126  	lowerCaseName := strings.ToLower(string(name))
   127  	key := append(prefix, lowerCaseName...)
   128  	var err error
   129  	var ownerdata []byte
   130  	if useInitial {
   131  		ownerdata, err = scs.GetInitialData(key)
   132  	} else {
   133  		ownerdata, err = scs.GetData(key)
   134  	}
   135  	if err != nil {
   136  		return nil
   137  	}
   138  	return deserializeNameMap(ownerdata)
   139  }
   140  
   141  func GetNameInfo(r AccountStateReader, name string) (*types.NameInfo, error) {
   142  	scs, err := r.GetNameAccountState()
   143  	if err != nil {
   144  		return nil, err
   145  	}
   146  	owner := getOwner(scs, []byte(name), true)
   147  	return &types.NameInfo{Name: &types.Name{Name: string(name)}, Owner: owner, Destination: GetAddress(scs, []byte(name))}, err
   148  }
   149  
   150  func registerOwner(scs *state.ContractState, name, owner, destination []byte) error {
   151  	nameMap := &NameMap{Version: 1, Owner: owner, Destination: destination}
   152  	return setNameMap(scs, name, nameMap)
   153  }
   154  
   155  func setNameMap(scs *state.ContractState, name []byte, n *NameMap) error {
   156  	lowerCaseName := strings.ToLower(string(name))
   157  	key := append(prefix, lowerCaseName...)
   158  	return scs.SetData(key, serializeNameMap(n))
   159  }
   160  
   161  func serializeNameMap(n *NameMap) []byte {
   162  	var ret []byte
   163  	if n != nil {
   164  		ret = append(ret, n.Version)
   165  		buf := make([]byte, 8)
   166  		binary.LittleEndian.PutUint64(buf, uint64(len(n.Owner)))
   167  		ret = append(ret, buf...)
   168  		ret = append(ret, n.Owner...)
   169  		binary.LittleEndian.PutUint64(buf, uint64(len(n.Destination)))
   170  		ret = append(ret, buf...)
   171  		ret = append(ret, n.Destination...)
   172  	}
   173  	return ret
   174  }
   175  
   176  func deserializeNameMap(data []byte) *NameMap {
   177  	if data != nil {
   178  		version := data[0]
   179  		if version != 1 {
   180  			panic("could not deserializeOwner, not supported version")
   181  		}
   182  		offset := 1
   183  		next := offset + 8
   184  		sizeOfAddr := binary.LittleEndian.Uint64(data[offset:next])
   185  
   186  		offset = next
   187  		next = offset + int(sizeOfAddr)
   188  		owner := data[offset:next]
   189  
   190  		offset = next
   191  		next = offset + 8
   192  		sizeOfDest := binary.LittleEndian.Uint64(data[offset:next])
   193  
   194  		offset = next
   195  		next = offset + int(sizeOfDest)
   196  		destination := data[offset:next]
   197  		return &NameMap{
   198  			Version:     version,
   199  			Owner:       owner,
   200  			Destination: destination,
   201  		}
   202  	}
   203  	return nil
   204  }