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  }