github.com/annchain/OG@v0.0.9/arefactor_core/core/account_flow.go (about) 1 // Copyright © 2019 Annchain Authors <EMAIL ADDRESS> 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 package core 15 16 import ( 17 "container/heap" 18 "fmt" 19 og_types "github.com/annchain/OG/arefactor/og_interface" 20 "github.com/annchain/OG/arefactor/types" 21 "github.com/annchain/OG/arefactor_core/core/state" 22 "github.com/annchain/OG/common/math" 23 log "github.com/sirupsen/logrus" 24 "sort" 25 "sync" 26 ) 27 28 type AccountFlowSet struct { 29 afs map[og_types.AddressKey]*AccountFlow 30 31 ledger Ledger 32 mu sync.RWMutex 33 } 34 35 func NewAccountFlowSet(ledger Ledger) *AccountFlowSet { 36 return &AccountFlowSet{ 37 afs: make(map[og_types.AddressKey]*AccountFlow), 38 ledger: ledger, 39 } 40 } 41 42 func (a *AccountFlowSet) Add(baseSeqHash og_types.Hash, tx types.Txi) { 43 a.mu.Lock() 44 defer a.mu.Unlock() 45 46 if tx.GetType() == types.TxBaseTypeArchive { 47 return 48 } 49 50 af := a.afs[tx.Sender().AddressKey()] 51 if af == nil { 52 af = NewAccountFlow(state.NewBalanceSet()) 53 } 54 if tx.GetType() == types.TxBaseTypeNormal { 55 txn := tx.(*types.Tx) 56 if af.balances[txn.TokenId] == nil { 57 blc := a.ledger.GetBalance(baseSeqHash, txn.Sender(), txn.TokenId) 58 af.balances[txn.TokenId] = NewBalanceState(blc) 59 } 60 } 61 af.Add(tx) 62 a.afs[tx.Sender().AddressKey()] = af 63 } 64 65 func (a *AccountFlowSet) Get(addr og_types.Address) *AccountFlow { 66 a.mu.RLock() 67 defer a.mu.RUnlock() 68 69 return a.afs[addr.AddressKey()] 70 } 71 72 func (a *AccountFlowSet) GetBalanceState(addr og_types.Address, tokenID int32) *BalanceState { 73 a.mu.RLock() 74 defer a.mu.RUnlock() 75 76 af := a.Get(addr) 77 if af == nil { 78 return nil 79 } 80 bls := af.balances 81 if bls == nil { 82 return nil 83 } 84 return bls[tokenID] 85 } 86 87 func (a *AccountFlowSet) GetTxByNonce(addr og_types.Address, nonce uint64) types.Txi { 88 a.mu.RLock() 89 defer a.mu.RUnlock() 90 91 flow := a.afs[addr.AddressKey()] 92 if flow == nil { 93 return nil 94 } 95 return flow.GetTx(nonce) 96 } 97 98 func (a *AccountFlowSet) GetLatestNonce(addr og_types.Address) (uint64, error) { 99 a.mu.RLock() 100 defer a.mu.RUnlock() 101 102 flow := a.afs[addr.AddressKey()] 103 if flow == nil { 104 return 0, fmt.Errorf("no related tx in txlookup") 105 } 106 if !(flow.Len() > 0) { 107 return 0, fmt.Errorf("flow not long enough") 108 } 109 return flow.LatestNonce() 110 } 111 112 func (a *AccountFlowSet) ResetFlow(addr og_types.Address, originBalance state.BalanceSet) { 113 a.mu.Lock() 114 defer a.mu.Unlock() 115 116 a.afs[addr.AddressKey()] = NewAccountFlow(originBalance) 117 } 118 119 func (a *AccountFlowSet) MergeFlow(addr og_types.Address, af *AccountFlow) { 120 afOld := a.afs[addr.AddressKey()] 121 if afOld == nil { 122 a.afs[addr.AddressKey()] = afOld 123 return 124 } 125 126 afOld.MergeFlow(af) 127 a.afs[addr.AddressKey()] = afOld 128 } 129 130 func (a *AccountFlowSet) Remove(tx types.Txi) { 131 a.mu.Lock() 132 defer a.mu.Unlock() 133 134 flow := a.afs[tx.Sender().AddressKey()] 135 if flow == nil { 136 log.WithField("tx", tx).Warnf("remove tx from accountflows failed") 137 return 138 } 139 flow.Remove(tx) 140 // remove account flow if there is no txs sent by this address in pool 141 if flow.Len() == 0 { 142 delete(a.afs, tx.Sender().AddressKey()) 143 } 144 } 145 146 // AccountFlow stores the information about an address. It includes the 147 // balance state of the account among the txpool, 148 type AccountFlow struct { 149 balances map[int32]*BalanceState 150 txlist *TxList 151 } 152 153 func NewAccountFlow(originBalance state.BalanceSet) *AccountFlow { 154 bls := map[int32]*BalanceState{} 155 for k, v := range originBalance { 156 bls[k] = NewBalanceState(v) 157 } 158 159 return &AccountFlow{ 160 balances: bls, 161 txlist: NewTxList(), 162 } 163 } 164 165 func NewAccountFlowWithFullData(balanceStates map[int32]*BalanceState, txlist *TxList) *AccountFlow { 166 return &AccountFlow{ 167 balances: balanceStates, 168 txlist: txlist, 169 } 170 } 171 172 func (af *AccountFlow) BalanceState(tokenID int32) *BalanceState { 173 return af.balances[tokenID] 174 } 175 176 func (af *AccountFlow) TxList() *TxList { 177 return af.txlist 178 } 179 180 // return the count of txs sent by this account. 181 func (af *AccountFlow) Len() int { 182 return af.txlist.Len() 183 } 184 185 // GetTx get a tx from accountflow. 186 func (af *AccountFlow) GetTx(nonce uint64) types.Txi { 187 return af.txlist.Get(nonce) 188 } 189 190 // Add new tx into account flow. This function should 191 // 1. update account's balance state. 192 // 2. add tx into nonce sorted txlist. 193 func (af *AccountFlow) Add(tx types.Txi) error { 194 if af.txlist.get(tx.GetNonce()) != nil { 195 log.WithField("tx", tx).Errorf("add tx that has same nonce") 196 return fmt.Errorf("already exists") 197 } 198 if tx.GetType() != types.TxBaseTypeNormal { 199 af.txlist.Put(tx) 200 return nil 201 } 202 txnormal := tx.(*types.Tx) 203 if af.balances[txnormal.TokenId] == nil { 204 af.txlist.Put(tx) 205 return fmt.Errorf("accountflow not exists for addr: %s", tx.Sender().Hex()) 206 } 207 value := txnormal.GetValue() 208 err := af.balances[txnormal.TokenId].TryProcessTx(value) 209 if err != nil { 210 return err 211 } 212 af.txlist.Put(tx) 213 return nil 214 } 215 216 // Remove a tx from account flow, find tx by nonce first, then 217 // rolls back the balance and remove tx from txlist. 218 func (af *AccountFlow) Remove(txToRemove types.Txi) error { 219 tx := af.txlist.Get(txToRemove.GetNonce()) 220 if tx == nil { 221 return nil 222 } 223 if tx.GetTxHash().Cmp(txToRemove.GetTxHash()) != 0 { 224 return nil 225 } 226 nonce := tx.GetNonce() 227 if tx.GetType() != types.TxBaseTypeNormal { 228 af.txlist.Remove(nonce) 229 return nil 230 } 231 txnormal := tx.(*types.Tx) 232 if af.balances[txnormal.TokenId] == nil { 233 af.txlist.Remove(nonce) 234 return fmt.Errorf("accountflow not exists for addr: %s", tx.Sender().Hex()) 235 } 236 value := txnormal.GetValue() 237 err := af.balances[txnormal.TokenId].TryRemoveValue(value) 238 if err != nil { 239 return err 240 } 241 af.txlist.Remove(nonce) 242 return nil 243 } 244 245 // LatestNonce returns the largest nonce stored in txlist. 246 func (af *AccountFlow) LatestNonce() (uint64, error) { 247 tl := af.txlist 248 if tl == nil { 249 return 0, fmt.Errorf("txlist is nil") 250 } 251 if !(tl.Len() > 0) { 252 return 0, fmt.Errorf("txlist is empty") 253 } 254 keys := tl.keys 255 if keys == nil { 256 return 0, fmt.Errorf("txlist's keys field is nil") 257 } 258 return keys.Tail(), nil 259 } 260 261 func (af *AccountFlow) MergeFlow(afToMerge *AccountFlow) { 262 for tokenID, blc := range afToMerge.balances { 263 if af.balances[tokenID] == nil { 264 af.balances[tokenID] = blc 265 continue 266 } 267 blcOld := af.balances[tokenID] 268 blcOld.spent = blcOld.spent.Add(blc.spent) 269 af.balances[tokenID] = blcOld 270 } 271 for _, nonce := range *afToMerge.txlist.keys { 272 af.txlist.Put(afToMerge.GetTx(nonce)) 273 } 274 } 275 276 type BalanceState struct { 277 spent *math.BigInt 278 originBalance *math.BigInt 279 } 280 281 func NewBalanceState(balance *math.BigInt) *BalanceState { 282 return &BalanceState{ 283 spent: math.NewBigInt(0), 284 originBalance: balance, 285 } 286 } 287 288 func NewBalanceStateWithFullData(balance *math.BigInt, spent *math.BigInt) *BalanceState { 289 return &BalanceState{ 290 spent: spent, 291 originBalance: balance, 292 } 293 } 294 295 func (bs *BalanceState) Spent() *math.BigInt { 296 return bs.spent 297 } 298 func (bs *BalanceState) OriginBalance() *math.BigInt { 299 return bs.originBalance 300 } 301 302 //func (bs *BalanceState) isValid(spend *math.BigInt) error { 303 // 304 // // if tx's value is larger than its balance, return fatal. 305 // if spend.Value.Cmp(bs.originBalance.Value) > 0 { 306 // log.WithField("tx", tx).Tracef("fatal tx, tx's value larger than balance") 307 // return TxQualityIsFatal 308 // } 309 // // if ( the value that 'from' already spent ) 310 // // + ( the value that 'from' newly spent ) 311 // // > ( balance of 'from' in db ) 312 // totalspent := math.NewBigInt(0) 313 // if totalspent.Value.Add(stateFrom.spent.Value, tx.Value.Value).Cmp( 314 // stateFrom.originBalance.Value) > 0 { 315 // log.WithField("tx", tx).Tracef("bad tx, total spent larget than balance") 316 // return TxQualityIsBad 317 // } 318 //} 319 320 // TryProcessTx checks if origin balance is enough for total spent of 321 // txs in pool. It trys to add new spent "value" into total spent and 322 // compare total spent with origin balance. 323 func (bs *BalanceState) TryProcessTx(value *math.BigInt) error { 324 totalspent := math.NewBigInt(0) 325 totalspent.Value.Add(bs.spent.Value, value.Value) 326 // check if (already spent + new spent) > confirmed balance 327 if totalspent.Value.Cmp(bs.originBalance.Value) > 0 { 328 return fmt.Errorf("balance not enough") 329 } 330 bs.spent.Value = totalspent.Value 331 return nil 332 } 333 334 // TryRemoveValue is called when remove a tx from pool. It reduce the total spent 335 // by the value of removed tx. 336 func (bs *BalanceState) TryRemoveValue(txValue *math.BigInt) error { 337 // check if (already spent < tx's value) 338 if bs.spent.Value.Cmp(txValue.Value) < 0 { 339 return fmt.Errorf("tx's value is too much to remove, spent: %s, tx value: %s", bs.spent.String(), txValue.String()) 340 } 341 bs.spent.Value.Sub(bs.spent.Value, txValue.Value) 342 bs.originBalance.Value.Sub(bs.originBalance.Value, txValue.Value) 343 return nil 344 } 345 346 type nonceHeap []uint64 347 348 // TODO no need to use heap type to store the nonce 349 func (n nonceHeap) Tail() uint64 { 350 sort.Sort(n) 351 return n[n.Len()-1] 352 } 353 354 // for sort 355 func (n nonceHeap) Len() int { return len(n) } 356 func (n nonceHeap) Less(i, j int) bool { return n[i] < n[j] } 357 func (n nonceHeap) Swap(i, j int) { n[i], n[j] = n[j], n[i] } 358 359 // for heap 360 func (n *nonceHeap) Push(x interface{}) { 361 *n = append(*n, x.(uint64)) 362 } 363 func (n *nonceHeap) Pop() interface{} { 364 old := *n 365 length := len(old) 366 last := old[length-1] 367 *n = old[0 : length-1] 368 return last 369 } 370 371 type TxList struct { 372 keys *nonceHeap 373 txflow map[uint64]types.Txi 374 } 375 376 func NewTxList() *TxList { 377 return &TxList{ 378 keys: new(nonceHeap), 379 txflow: make(map[uint64]types.Txi), 380 } 381 } 382 383 func NewTxListByKeySet(txFlow map[uint64]types.Txi, multiKeys ...*nonceHeap) *TxList { 384 txList := &TxList{} 385 386 nonces := make(nonceHeap, 0) 387 for _, keys := range multiKeys { 388 for _, nonce := range *keys { 389 nonces.Push(nonce) 390 } 391 } 392 393 txList.keys = &nonces 394 txList.txflow = txFlow 395 return txList 396 } 397 398 func (t *TxList) Len() int { 399 return t.keys.Len() 400 } 401 402 func (t *TxList) Get(nonce uint64) types.Txi { 403 return t.get(nonce) 404 } 405 func (t *TxList) get(nonce uint64) types.Txi { 406 return t.txflow[nonce] 407 } 408 409 func (t *TxList) Put(txi types.Txi) { 410 t.put(txi) 411 } 412 func (t *TxList) put(txi types.Txi) { 413 nonce := txi.GetNonce() 414 if _, ok := t.txflow[nonce]; !ok { 415 heap.Push(t.keys, nonce) 416 t.txflow[nonce] = txi 417 } 418 } 419 420 func (t *TxList) Remove(nonce uint64) bool { 421 return t.remove(nonce) 422 } 423 func (t *TxList) remove(nonce uint64) bool { 424 _, ok := t.txflow[nonce] 425 if !ok { 426 return false 427 } 428 for i := 0; i < t.keys.Len(); i++ { 429 if (*t.keys)[i] == nonce { 430 heap.Remove(t.keys, i) 431 } 432 } 433 delete(t.txflow, nonce) 434 return true 435 }