github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/store/mainchain/extstorages/league_account_store.go (about)

     1  package extstorages
     2  
     3  import (
     4  	"bytes"
     5  
     6  	"math/big"
     7  
     8  	"encoding/binary"
     9  
    10  	"github.com/syndtr/goleveldb/leveldb/util"
    11  	"github.com/sixexorg/magnetic-ring/common"
    12  	"github.com/sixexorg/magnetic-ring/common/sink"
    13  	"github.com/sixexorg/magnetic-ring/errors"
    14  	"github.com/sixexorg/magnetic-ring/store/db"
    15  	mcom "github.com/sixexorg/magnetic-ring/store/mainchain/common"
    16  	"github.com/sixexorg/magnetic-ring/store/mainchain/extstates"
    17  	"github.com/sixexorg/magnetic-ring/store/storelaw"
    18  )
    19  
    20  //Redundancy of the leagues data
    21  type ExternalLeague struct {
    22  	enableCache bool
    23  	dbDir       string
    24  	store       *db.LevelDBStore
    25  }
    26  
    27  func NewExternalLeague(dbDir string, enableCache bool) (*ExternalLeague, error) {
    28  	store, err := db.NewLevelDBStore(dbDir)
    29  	if err != nil {
    30  		return nil, err
    31  	}
    32  	el := new(ExternalLeague)
    33  
    34  	el.enableCache = enableCache
    35  	el.dbDir = dbDir
    36  	el.store = store
    37  	return el, nil
    38  }
    39  
    40  //NewBatch start a commit batch
    41  func (this *ExternalLeague) NewBatch() {
    42  	this.store.NewBatch()
    43  }
    44  func (this *ExternalLeague) CommitTo() error {
    45  	return this.store.BatchCommit()
    46  }
    47  
    48  func (this *ExternalLeague) GetAccountByHeight(account, leagueId common.Address, height uint64) (*extstates.Account, error) {
    49  	key := this.getKey(leagueId, account, height)
    50  	//fmt.Println("🛢 🛢 🛢 🛢 🛢 🛢 get ", hex.EncodeToString(key))
    51  	val, err := this.store.Get(key)
    52  	if err != nil {
    53  		return nil, err
    54  	}
    55  	acc, err := this.deserializeAccount(val)
    56  	if err != nil {
    57  		return nil, err
    58  	}
    59  	return acc, nil
    60  }
    61  func (this *ExternalLeague) GetPrev(height uint64, account, leagueId common.Address) (storelaw.AccountStater, error) {
    62  	key := this.getKey(leagueId, account, height)
    63  	iter := this.store.NewIterator(nil)
    64  	buff := bytes.NewBuffer(nil)
    65  	flag := true
    66  	if iter.Seek(key) {
    67  		if bytes.Compare(iter.Key(), key) == 0 {
    68  			buff.Write(iter.Key())
    69  			buff.Write(iter.Value())
    70  			flag = false
    71  		}
    72  	}
    73  	if flag && iter.Prev() {
    74  		buff.Write(iter.Key())
    75  		buff.Write(iter.Value())
    76  	}
    77  	iter.Release()
    78  	err := iter.Error()
    79  	if err != nil {
    80  		return nil, err
    81  	}
    82  	if buff.Len() == 0 {
    83  		return &extstates.LeagueAccountState{
    84  			Address:  account,
    85  			LeagueId: leagueId,
    86  			Height:   height,
    87  			Data: &extstates.Account{
    88  				Balance:     big.NewInt(0),
    89  				EnergyBalance: big.NewInt(0),
    90  			},
    91  		}, nil
    92  	}
    93  	as := &extstates.LeagueAccountState{}
    94  	err = as.Deserialize(buff)
    95  	if err != nil {
    96  		return nil, err
    97  	}
    98  	if as.Address.Equals(account) && as.LeagueId.Equals(leagueId) {
    99  		return as, nil
   100  	}
   101  	return &extstates.LeagueAccountState{
   102  		Address:  account,
   103  		LeagueId: leagueId,
   104  		Height:   height,
   105  		Data: &extstates.Account{
   106  			Balance:     big.NewInt(0),
   107  			EnergyBalance: big.NewInt(0),
   108  		},
   109  	}, nil
   110  }
   111  func (this *ExternalLeague) GetAccountRange(start, end uint64, account, leagueId common.Address) (storelaw.AccountStaters, error) {
   112  	s := this.getKey(leagueId, account, start)
   113  	l := this.getKey(leagueId, account, end)
   114  	iter := this.store.NewSeniorIterator(&util.Range{Start: s, Limit: l})
   115  	ass := storelaw.AccountStaters{}
   116  	bf := bytes.NewBuffer(nil)
   117  	var err error
   118  	for iter.Next() {
   119  		bf.Write(iter.Key())
   120  		bf.Write(iter.Value())
   121  		as := &extstates.LeagueAccountState{}
   122  		err = as.Deserialize(bf)
   123  		if err != nil {
   124  			return nil, err
   125  		}
   126  		ass = append(ass, as)
   127  		bf.Reset()
   128  	}
   129  	iter.Release()
   130  	return ass, nil
   131  }
   132  
   133  //SaveBlock persist block to store
   134  func (this *ExternalLeague) Save(state storelaw.AccountStater) error {
   135  	key := state.GetKey()
   136  	buff := new(bytes.Buffer)
   137  	err := state.Serialize(buff)
   138  	if err != nil {
   139  		return err
   140  	}
   141  	err = this.store.Put(key, buff.Bytes())
   142  	if err != nil {
   143  		return err
   144  	}
   145  	return nil
   146  }
   147  func (this *ExternalLeague) BatchSave(states storelaw.AccountStaters) error {
   148  	for _, v := range states {
   149  		key := v.GetKey()
   150  		//fmt.Println("🛢 🛢 🛢 🛢 🛢 🛢 save ", hex.EncodeToString(key))
   151  		buff := new(bytes.Buffer)
   152  		err := v.Serialize(buff)
   153  		if err != nil {
   154  			return err
   155  		}
   156  		this.store.BatchPut(key, buff.Bytes())
   157  	}
   158  	return nil
   159  }
   160  
   161  func (this *ExternalLeague) getKey(leagueId, account common.Address, height uint64) []byte {
   162  	buff := make([]byte, 1+2*common.AddrLength+8)
   163  	buff[0] = byte(mcom.EXT_LEAGUE_ACCOUNT)
   164  	copy(buff[1:common.AddrLength+1], leagueId[:])
   165  	copy(buff[common.AddrLength+1:common.AddrLength*2+1], account[:])
   166  	binary.LittleEndian.PutUint64(buff[common.AddrLength*2+1:], height)
   167  	return buff
   168  }
   169  
   170  func (this *ExternalLeague) deserializeAccount(val []byte) (*extstates.Account, error) {
   171  	source := sink.NewZeroCopySource(val)
   172  	account := &extstates.Account{}
   173  	eof := false
   174  	var err error
   175  	account.Nonce, eof = source.NextUint64()
   176  	bal, eof := source.NextComplex()
   177  	account.Balance, err = bal.ComplexToBigInt()
   178  	if err != nil {
   179  		return nil, err
   180  	}
   181  	bbl, eof := source.NextComplex()
   182  	account.EnergyBalance, err = bbl.ComplexToBigInt()
   183  	if err != nil {
   184  		return nil, err
   185  	}
   186  	account.BonusHeight, eof = source.NextUint64()
   187  	if eof {
   188  		return nil, errors.ERR_TXRAW_EOF
   189  	}
   190  	return account, nil
   191  }