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 }