github.com/aergoio/aergo@v1.3.1/account/accountservice.go (about) 1 package account 2 3 import ( 4 "sync" 5 6 "github.com/aergoio/aergo-actor/actor" 7 "github.com/aergoio/aergo-lib/log" 8 "github.com/aergoio/aergo/account/key" 9 cfg "github.com/aergoio/aergo/config" 10 "github.com/aergoio/aergo/contract/name" 11 "github.com/aergoio/aergo/message" 12 "github.com/aergoio/aergo/pkg/component" 13 "github.com/aergoio/aergo/state" 14 "github.com/aergoio/aergo/types" 15 ) 16 17 type AccountService struct { 18 *component.BaseComponent 19 cfg *cfg.Config 20 sdb *state.ChainStateDB 21 ks *key.Store 22 accountLock sync.RWMutex 23 accounts []*types.Account 24 testConfig bool 25 } 26 27 //NewAccountService create account service 28 func NewAccountService(cfg *cfg.Config, sdb *state.ChainStateDB) *AccountService { 29 actor := &AccountService{ 30 cfg: cfg, 31 sdb: sdb, 32 } 33 actor.BaseComponent = component.NewBaseComponent(message.AccountsSvc, actor, log.NewLogger("account")) 34 35 return actor 36 } 37 38 func (as *AccountService) BeforeStart() { 39 as.ks = key.NewStore(as.cfg.DataDir, as.cfg.Account.UnlockTimeout) 40 41 as.accounts = []*types.Account{} 42 addresses, err := as.ks.GetAddresses() 43 if err != nil { 44 as.Logger.Error().Err(err).Msg("could not open addresses") 45 } 46 for _, v := range addresses { 47 as.accounts = append(as.accounts, &types.Account{Address: v}) 48 } 49 } 50 51 func (as *AccountService) AfterStart() {} 52 53 func (as *AccountService) BeforeStop() { 54 as.ks.CloseStore() 55 as.accounts = nil 56 } 57 58 func (as *AccountService) Statistics() *map[string]interface{} { 59 return &map[string]interface{}{ 60 "totalaccounts": len(as.accounts), 61 "personal": as.cfg.Personal, 62 "config": as.cfg.Account, 63 } 64 } 65 func (as *AccountService) resolveName(namedAddress []byte) ([]byte, error) { 66 scs, err := as.sdb.GetStateDB().OpenContractStateAccount(types.ToAccountID([]byte(types.AergoName))) 67 if err != nil { 68 return nil, err 69 } 70 return name.GetAddress(scs, namedAddress), nil 71 } 72 73 func (as *AccountService) Receive(context actor.Context) { 74 75 switch msg := context.Message().(type) { 76 case *message.GetAccounts: 77 accountList := as.getAccounts() 78 context.Respond(&message.GetAccountsRsp{Accounts: &types.AccountList{Accounts: accountList}}) 79 case *message.CreateAccount: 80 account, _ := as.createAccount(msg.Passphrase) 81 context.Respond(&message.CreateAccountRsp{Account: account}) 82 case *message.LockAccount: 83 actualAddress := msg.Account.Address 84 var err error 85 if len(actualAddress) == types.NameLength { 86 actualAddress, err = as.resolveName(actualAddress) 87 if err != nil { 88 context.Respond(&message.AccountRsp{ 89 Account: &types.Account{Address: actualAddress}, 90 Err: err, 91 }) 92 } 93 } 94 account, err := as.lockAccount(actualAddress, msg.Passphrase) 95 context.Respond(&message.AccountRsp{Account: account, Err: err}) 96 case *message.UnlockAccount: 97 actualAddress := msg.Account.Address 98 var err error 99 if len(actualAddress) == types.NameLength { 100 actualAddress, err = as.resolveName(actualAddress) 101 if err != nil { 102 context.Respond(&message.AccountRsp{ 103 Account: &types.Account{Address: actualAddress}, 104 Err: err, 105 }) 106 } 107 } 108 account, err := as.unlockAccount(actualAddress, msg.Passphrase) 109 context.Respond(&message.AccountRsp{Account: account, Err: err}) 110 case *message.ImportAccount: 111 account, err := as.importAccount(msg.Wif, msg.OldPass, msg.NewPass) 112 context.Respond(&message.ImportAccountRsp{Account: account, Err: err}) 113 case *message.ExportAccount: 114 wif, err := as.exportAccount(msg.Account.Address, msg.Pass) 115 context.Respond(&message.ExportAccountRsp{Wif: wif, Err: err}) 116 case *message.SignTx: 117 var err error 118 actualAddress := msg.Tx.GetBody().GetAccount() 119 if len(actualAddress) == types.NameLength { 120 actualAddress, err = as.resolveName(msg.Tx.GetBody().GetAccount()) 121 if err != nil { 122 context.Respond(&message.SignTxRsp{Tx: nil, Err: err}) 123 } 124 msg.Requester = actualAddress 125 } 126 err = as.signTx(context, msg) 127 if err != nil { 128 context.Respond(&message.SignTxRsp{Tx: nil, Err: err}) 129 } 130 case *message.VerifyTx: 131 err := as.verifyTx(msg.Tx) 132 if err != nil { 133 context.Respond(&message.VerifyTxRsp{Tx: nil, Err: err}) 134 } else { 135 context.Respond(&message.VerifyTxRsp{Tx: msg.Tx, Err: nil}) 136 } 137 } 138 } 139 140 func (as *AccountService) getAccounts() []*types.Account { 141 as.accountLock.RLock() 142 defer as.accountLock.RUnlock() 143 return as.accounts 144 } 145 146 func (as *AccountService) createAccount(passphrase string) (*types.Account, error) { 147 address, err := as.ks.CreateKey(passphrase) 148 if err != nil { 149 return nil, err 150 } 151 account := types.NewAccount(address) 152 153 //append list 154 as.accountLock.Lock() 155 //TODO: performance turning here 156 as.ks.SaveAddress(address) 157 as.accounts = append(as.accounts, account) 158 as.accountLock.Unlock() 159 return account, nil 160 } 161 162 func (as *AccountService) importAccount(wif []byte, old string, new string) (*types.Account, error) { 163 address, err := as.ks.ImportKey(wif, old, new) 164 if err != nil { 165 return nil, err 166 } 167 //append list 168 account := &types.Account{Address: address} 169 as.accountLock.Lock() 170 //TODO: performance turning here 171 as.ks.SaveAddress(address) 172 as.accounts = append(as.accounts, account) 173 as.accountLock.Unlock() 174 return account, nil 175 } 176 177 func (as *AccountService) exportAccount(address []byte, pass string) ([]byte, error) { 178 wif, err := as.ks.ExportKey(address, pass) 179 if err != nil { 180 return nil, err 181 } 182 return wif, nil 183 } 184 185 func (as *AccountService) unlockAccount(address []byte, passphrase string) (*types.Account, error) { 186 addr, err := as.ks.Unlock(address, passphrase) 187 if err != nil { 188 as.Warn().Err(err).Msg("could not find the key") 189 return nil, err 190 } 191 return &types.Account{Address: addr}, nil 192 } 193 194 func (as *AccountService) lockAccount(address []byte, passphrase string) (*types.Account, error) { 195 addr, err := as.ks.Lock(address, passphrase) 196 if err != nil { 197 as.Warn().Err(err).Msg("could not load the key") 198 return nil, err 199 } 200 return &types.Account{Address: addr}, nil 201 } 202 203 func (as *AccountService) signTx(c actor.Context, msg *message.SignTx) error { 204 //sign tx 205 prop := actor.FromInstance(NewSigner(as.ks)) 206 signer := c.Spawn(prop) 207 signer.Request(msg, c.Sender()) 208 return nil 209 } 210 211 func (as *AccountService) verifyTx(tx *types.Tx) error { 212 return as.ks.VerifyTx(tx) 213 }