| 294 | } |
| 295 | |
| 296 | func (s *metaState) transferAccountToken(transfer *types.Transfer) (err error) { |
| 297 | if transfer.Signee == nil { |
| 298 | err = ErrInvalidSender |
| 299 | log.WithError(err).Warning("invalid signee in applyTransaction") |
| 300 | } |
| 301 | realSender, err := crypto.PubKeyHash(transfer.Signee) |
| 302 | if err != nil { |
| 303 | err = errors.Wrap(err, "applyTx failed") |
| 304 | return err |
| 305 | } |
| 306 | if realSender != transfer.Sender { |
| 307 | err = errors.Wrapf(ErrInvalidSender, |
| 308 | "applyTx failed: real sender %s, sender %s", realSender, transfer.Sender) |
| 309 | log.WithError(err).Warning("public key not match sender in applyTransaction") |
| 310 | return |
| 311 | } |
| 312 | |
| 313 | var ( |
| 314 | sender = transfer.Sender |
| 315 | receiver = transfer.Receiver |
| 316 | amount = transfer.Amount |
| 317 | tokenType = transfer.TokenType |
| 318 | ) |
| 319 | |
| 320 | if sender == receiver || amount == 0 { |
| 321 | return |
| 322 | } |
| 323 | |
| 324 | // Create empty receiver account if not found |
| 325 | s.loadOrStoreAccountObject(receiver, &types.Account{Address: receiver}) |
| 326 | |
| 327 | var ( |
| 328 | so, ro *types.Account |
| 329 | sd, rd, ok bool |
| 330 | ) |
| 331 | |
| 332 | // Load sender and receiver objects |
| 333 | if so, sd = s.dirty.accounts[sender]; !sd { |
| 334 | if so, ok = s.readonly.accounts[sender]; !ok { |
| 335 | err = ErrAccountNotFound |
| 336 | return |
| 337 | } |
| 338 | } |
| 339 | if ro, rd = s.dirty.accounts[receiver]; !rd { |
| 340 | if ro, ok = s.readonly.accounts[receiver]; !ok { |
| 341 | err = ErrAccountNotFound |
| 342 | return |
| 343 | } |
| 344 | } |
| 345 | |
| 346 | // Try transfer |
| 347 | var ( |
| 348 | sb = so.TokenBalance[tokenType] |
| 349 | rb = ro.TokenBalance[tokenType] |
| 350 | ) |
| 351 | if err = safeSub(&sb, &amount); err != nil { |
| 352 | return |
| 353 | } |