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

     1  package name
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  
     9  	"github.com/aergoio/aergo/contract/system"
    10  	"github.com/aergoio/aergo/state"
    11  	"github.com/aergoio/aergo/types"
    12  )
    13  
    14  func ExecuteNameTx(bs *state.BlockState, scs *state.ContractState, txBody *types.TxBody,
    15  	sender, receiver *state.V, blockNo types.BlockNo) ([]*types.Event, error) {
    16  
    17  	systemContractState, err := bs.StateDB.OpenContractStateAccount(types.ToAccountID([]byte(types.AergoSystem)))
    18  
    19  	ci, err := ValidateNameTx(txBody, sender, scs, systemContractState)
    20  	if err != nil {
    21  		return nil, err
    22  	}
    23  	var events []*types.Event
    24  
    25  	var nameState *state.V
    26  	owner := getOwner(scs, []byte(types.AergoName), false)
    27  	if owner != nil {
    28  		if bytes.Equal(sender.ID(), owner) {
    29  			nameState = sender
    30  		} else {
    31  			nameState, err = bs.GetAccountStateV(owner)
    32  			if err != nil {
    33  				return nil, err
    34  			}
    35  		}
    36  	} else {
    37  		nameState = receiver
    38  	}
    39  	switch ci.Name {
    40  	case types.NameCreate:
    41  		if err = CreateName(scs, txBody, sender, nameState,
    42  			ci.Args[0].(string)); err != nil {
    43  			return nil, err
    44  		}
    45  		events = append(events, &types.Event{
    46  			ContractAddress: receiver.ID(),
    47  			EventIdx:        0,
    48  			EventName:       "create name",
    49  			JsonArgs:        `{"name":"` + ci.Args[0].(string) + `"}`,
    50  		})
    51  	case types.NameUpdate:
    52  		if err = UpdateName(bs, scs, txBody, sender, nameState,
    53  			ci.Args[0].(string), ci.Args[1].(string)); err != nil {
    54  			return nil, err
    55  		}
    56  		events = append(events, &types.Event{
    57  			ContractAddress: receiver.ID(),
    58  			EventIdx:        0,
    59  			EventName:       "update name",
    60  			JsonArgs: `{"name":"` + ci.Args[0].(string) +
    61  				`","to":"` + ci.Args[1].(string) + `"}`,
    62  		})
    63  	case types.SetContractOwner:
    64  		ownerState, err := SetContractOwner(bs, scs, ci.Args[0].(string), nameState)
    65  		if err != nil {
    66  			return nil, err
    67  		}
    68  		ownerState.PutState()
    69  	}
    70  	nameState.PutState()
    71  	return events, nil
    72  }
    73  
    74  func ValidateNameTx(tx *types.TxBody, sender *state.V,
    75  	scs, systemcs *state.ContractState) (*types.CallInfo, error) {
    76  	if sender != nil && sender.Balance().Cmp(tx.GetAmountBigInt()) < 0 {
    77  		return nil, types.ErrInsufficientBalance
    78  	}
    79  	var ci types.CallInfo
    80  	if err := json.Unmarshal(tx.Payload, &ci); err != nil {
    81  		return nil, err
    82  	}
    83  	name := ci.Args[0].(string)
    84  	switch ci.Name {
    85  	case types.NameCreate:
    86  		namePrice := system.GetNamePrice(systemcs)
    87  		if namePrice.Cmp(tx.GetAmountBigInt()) > 0 {
    88  			return nil, types.ErrTooSmallAmount
    89  		}
    90  		owner := getOwner(scs, []byte(name), false)
    91  		if owner != nil {
    92  			return nil, fmt.Errorf("aleady occupied %s", string(name))
    93  		}
    94  	case types.NameUpdate:
    95  		namePrice := system.GetNamePrice(systemcs)
    96  		if namePrice.Cmp(tx.GetAmountBigInt()) > 0 {
    97  			return nil, types.ErrTooSmallAmount
    98  		}
    99  		if (!bytes.Equal(tx.Account, []byte(name))) &&
   100  			(!bytes.Equal(tx.Account, getOwner(scs, []byte(name), false))) {
   101  			return nil, fmt.Errorf("owner not matched : %s", name)
   102  		}
   103  	case types.SetContractOwner:
   104  		owner := getOwner(scs, []byte(types.AergoName), false)
   105  		if owner != nil {
   106  			return nil, fmt.Errorf("owner aleady set to %s", types.EncodeAddress(owner))
   107  		}
   108  	default:
   109  		return nil, errors.New("could not execute unknown cmd")
   110  	}
   111  	return &ci, nil
   112  }
   113  
   114  func SetContractOwner(bs *state.BlockState, scs *state.ContractState,
   115  	address string, nameState *state.V) (*state.V, error) {
   116  	name := []byte(types.AergoName)
   117  	rawaddr, err := types.DecodeAddress(address)
   118  	if err != nil {
   119  		return nil, err
   120  	}
   121  	ownerState, err := bs.GetAccountStateV(rawaddr)
   122  	if err != nil {
   123  		return nil, err
   124  	}
   125  	ownerState.AddBalance(nameState.Balance())
   126  	nameState.SubBalance(nameState.Balance())
   127  	if err = registerOwner(scs, name, rawaddr, name); err != nil {
   128  		return nil, err
   129  	}
   130  	return ownerState, nil
   131  }