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

     1  package extstorages
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"sync"
     7  
     8  	"path"
     9  
    10  	"math/big"
    11  
    12  	"github.com/sixexorg/magnetic-ring/common"
    13  	"github.com/sixexorg/magnetic-ring/core/mainchain/types"
    14  	orgtypes "github.com/sixexorg/magnetic-ring/core/orgchain/types"
    15  	"github.com/sixexorg/magnetic-ring/errors"
    16  	scom "github.com/sixexorg/magnetic-ring/store/mainchain/common"
    17  	"github.com/sixexorg/magnetic-ring/store/mainchain/extstates"
    18  	"github.com/sixexorg/magnetic-ring/store/mainchain/storages"
    19  	orgStorages "github.com/sixexorg/magnetic-ring/store/orgchain/storages"
    20  	"github.com/sixexorg/magnetic-ring/store/storelaw"
    21  )
    22  
    23  var (
    24  	//Storage save path.
    25  	DBDirBlock          = "extblock"
    26  	DBDirState          = "extstates"
    27  	DBDirMainTx         = "extmain"
    28  	DBDirAccIdx         = "extaccidx"
    29  	DBDirVote           = "extvote"
    30  	DBDirFullTx         = "extfull"
    31  	DBDirUT             = "extut"
    32  	MerkleTreeStorePath = "extmerkle_tree.db"
    33  	//radarActor          *actor.PID
    34  )
    35  
    36  /*func initActor() {
    37  	if radarActor == nil {
    38  		actor, err := bactor.GetActorPid(bactor.MAINRADARACTOR)
    39  		if err != nil {
    40  			panic(fmt.Errorf("extstorages init radarActor failed,error: %s", err.Error()))
    41  		}
    42  		radarActor = actor
    43  	}
    44  }
    45  */
    46  //LedgerStoreImp is main store struct fo ledger
    47  type LedgerStoreImp struct {
    48  	blockStore      *ExternalLeagueBlock
    49  	accountStore    *ExternalLeague
    50  	mainTxUsedStore *MainTxUsed
    51  	acctIdxStore    *ExtAccIndexStore
    52  	voteStore       *orgStorages.VoteStore
    53  	fullTxStore     *ExtFullTXStore
    54  	utStore         *ExtUTStore
    55  
    56  	LightLedger     *storages.LightLedger
    57  	currBlockHeader map[common.Address]*orgtypes.Header //BlockHash => Header
    58  	savingBlock     bool                                //is saving block now
    59  
    60  	bonusCache    map[common.Address]map[uint64]uint64
    61  	destroyedEnergy map[common.Address]*big.Int
    62  	lock          sync.RWMutex
    63  }
    64  
    65  var ledgerStore *LedgerStoreImp
    66  
    67  func (this *LedgerStoreImp) NewBlockBatch() {
    68  	this.blockStore.NewBatch()
    69  }
    70  
    71  func (this *LedgerStoreImp) BlockBatchCommit() error {
    72  	err := this.blockStore.CommitTo()
    73  	if err != nil {
    74  		return err
    75  	}
    76  	return nil
    77  }
    78  func GetLedgerStoreInstance() *LedgerStoreImp {
    79  	return ledgerStore
    80  }
    81  
    82  //NewLedgerStore return LedgerStoreImp instance
    83  func NewLedgerStore(dataDir string) (*LedgerStoreImp, error) {
    84  	if ledgerStore != nil {
    85  		return ledgerStore, nil
    86  	}
    87  	ledgerStore = &LedgerStoreImp{
    88  		currBlockHeader: make(map[common.Address]*orgtypes.Header),
    89  		bonusCache:      make(map[common.Address]map[uint64]uint64),
    90  		destroyedEnergy:   make(map[common.Address]*big.Int),
    91  	}
    92  
    93  	accountStore, err := NewExternalLeague(path.Join(dataDir, DBDirState), false)
    94  	if err != nil {
    95  		fmt.Fprintf(os.Stderr, "NewExtAccoutStore error %s\n", err)
    96  		return nil, err
    97  	}
    98  
    99  	ledgerStore.accountStore = accountStore
   100  
   101  	blockStore, err := NewExternalLeagueBlock(path.Join(dataDir, DBDirBlock), true)
   102  	if err != nil {
   103  		return nil, fmt.Errorf("NewExtBlockStore error %s", err)
   104  	}
   105  	ledgerStore.blockStore = blockStore
   106  
   107  	mainTxUsed, err := NewMainTxUsed(path.Join(dataDir, DBDirMainTx))
   108  	if err != nil {
   109  		return nil, fmt.Errorf("NewExtMainTxUsedStore error %s", err)
   110  	}
   111  	ledgerStore.mainTxUsedStore = mainTxUsed
   112  
   113  	accIdxStore, err := NewExtAccIndexStore(path.Join(dataDir, DBDirAccIdx), false)
   114  	if err != nil {
   115  		return nil, fmt.Errorf("NewExtAccIndexStore error %s", err)
   116  	}
   117  	ledgerStore.acctIdxStore = accIdxStore
   118  
   119  	voteStore, err := orgStorages.NewVoteStore(path.Join(dataDir, DBDirVote), byte(scom.EXT_VOTE_STATE), byte(scom.EXT_VOTE_RECORD))
   120  	if err != nil {
   121  		return nil, fmt.Errorf("NewVoteStore error %s", err)
   122  	}
   123  	ledgerStore.voteStore = voteStore
   124  
   125  	utStore, err := NewExtUTStore(path.Join(dataDir, DBDirUT))
   126  	if err != nil {
   127  		return nil, fmt.Errorf("NewExtUTStore error %s", err)
   128  	}
   129  	ledgerStore.utStore = utStore
   130  
   131  	fullTxStore, err := NewExtFullTX(path.Join(dataDir, DBDirFullTx))
   132  	if err != nil {
   133  		return nil, fmt.Errorf("NewExtFullTX error %s", err)
   134  	}
   135  	ledgerStore.fullTxStore = fullTxStore
   136  
   137  	ledgerStore.LightLedger = storages.GetLightLedger()
   138  	return ledgerStore, nil
   139  }
   140  func (this *LedgerStoreImp) getCurrentBlockHeader(leagueId common.Address) *orgtypes.Header {
   141  	this.lock.RLock()
   142  	defer this.lock.RUnlock()
   143  	return this.currBlockHeader[leagueId]
   144  }
   145  
   146  func (this *LedgerStoreImp) MainTxUsedExist(txHash common.Hash) bool {
   147  	this.lock.RLock()
   148  	defer this.lock.RUnlock()
   149  	return this.mainTxUsedStore.Exist(txHash)
   150  }
   151  func (this *LedgerStoreImp) GetBlockHashSpan(leagueId common.Address, start, end uint64) (hashArr common.HashArray, gasUsedSum *big.Int, err error) {
   152  	this.lock.RLock()
   153  	defer this.lock.RUnlock()
   154  	return this.blockStore.GetBlockHashSpan(leagueId, start, end)
   155  
   156  }
   157  func (this *LedgerStoreImp) GetExtDataByHeight(leagueId common.Address, height uint64) (*extstates.ExtData, error) {
   158  	this.lock.RLock()
   159  	defer this.lock.RUnlock()
   160  	fmt.Printf("🚫 💿 GetExtDataByHeight part0 leagueId:%s,height:%d\n", leagueId.ToString(), height)
   161  	block, err := this.blockStore.GetBlock(leagueId, height)
   162  	if err != nil {
   163  		fmt.Printf("🚫 💿 GetExtDataByHeight part1 err:%s,leagueId:%s,height:%d\n", err, leagueId.ToString(), height)
   164  		return nil, err
   165  	}
   166  	addrs, hashes, err := this.acctIdxStore.Get(height, leagueId)
   167  	if err != nil {
   168  		fmt.Printf("🚫 💿 GetExtDataByHeight part2 err:%s,leagueId:%s,height:%d\n", err, leagueId.ToString(), height)
   169  		return nil, err
   170  	}
   171  	accountStates := make([]*extstates.EasyLeagueAccount, len(addrs))
   172  	if len(addrs) > 0 {
   173  		for _, acc := range addrs {
   174  			extAcc, err := this.accountStore.GetAccountByHeight(acc, leagueId, height)
   175  			if err != nil {
   176  				fmt.Printf("🚫 💿 GetExtDataByHeight part3 err:%s,leagueId:%s,height:%d,account:%s\n", err, leagueId.ToString(), height, acc.ToString())
   177  				return nil, err
   178  			}
   179  			accountStates = append(accountStates, &extstates.EasyLeagueAccount{acc, extAcc})
   180  		} //3
   181  	}
   182  	ed := new(extstates.ExtData)
   183  	ed.Height = height
   184  	ed.LeagueBlock = block
   185  	ed.MainTxUsed = hashes //2
   186  	ed.AccountStates = accountStates
   187  	return ed, nil
   188  }
   189  
   190  /*func (this *LedgerStoreImp) GetExtDataMapByHeight(leagueHeight map[common.Address]uint64) []*extstates.ExtData {
   191  	this.lock.RLock()
   192  	defer this.lock.RUnlock()
   193  	wg := new(sync.WaitGroup)
   194  	wg.Add(len(leagueHeight))
   195  	etdCh := make(chan *extstates.ExtData, 1)
   196  	etds := make([]*extstates.ExtData, 0, len(leagueHeight))
   197  	for k, v := range leagueHeight {
   198  		go func(league common.Address, height uint64) {
   199  			ed := new(extstates.ExtData)
   200  			ed.Height = height
   201  			block, err := this.blockStore.GetBlock(league, height)
   202  			if err != nil {
   203  				ed.Err = err
   204  				etdCh <- ed
   205  				return
   206  			}
   207  			ed.LeagueBlock = block //1
   208  			addrs, hashes, err := this.acctIdxStore.Get(height, league)
   209  			if err != nil {
   210  				etdCh <- ed
   211  				return
   212  			}
   213  			ed.MainTxUsed = hashes //2
   214  			ed.AccountStates = make(map[common.Address]*extstates.Account, len(addrs))
   215  			for _, acc := range addrs {
   216  				extAcc, err := this.accountStore.GetAccountByHeight(acc, league, height)
   217  				if err != nil {
   218  					ed.Err = err
   219  				}
   220  				ed.AccountStates[acc] = extAcc
   221  			} //3
   222  			etdCh <- ed
   223  			return
   224  		}(k, v)
   225  	}
   226  	go func() {
   227  		for ch := range etdCh {
   228  			etds = append(etds, ch)
   229  			wg.Done()
   230  		}
   231  	}()
   232  	close(etdCh)
   233  	return etds
   234  }*/
   235  func (this *LedgerStoreImp) SaveAll(blkInfo *storelaw.OrgBlockInfo, mainTxUsed common.HashArray) error {
   236  	if this.isSavingBlock() {
   237  		return nil
   238  	}
   239  	defer this.resetSavingBlock()
   240  	if blkInfo.Block == nil {
   241  		return errors.ERR_COMMON_REFERENCE_EMPTY
   242  	}
   243  	currentHeight := this.GetCurrentBlockHeight4V(blkInfo.Block.Header.LeagueId)
   244  	blockHeight := blkInfo.Block.Header.Height
   245  	if blockHeight <= currentHeight {
   246  		return nil
   247  	}
   248  	nextBlockHeight := currentHeight + 1
   249  	if blockHeight != nextBlockHeight {
   250  		return fmt.Errorf("block height %d not equal next block height %d", blockHeight, nextBlockHeight)
   251  	}
   252  
   253  	leagueBlock := extstates.Block2LeagueBlock(blkInfo.Block)
   254  	this.blockStore.NewBatch()
   255  	err := this.blockStore.Save(leagueBlock)
   256  	if err != nil {
   257  		return fmt.Errorf("saveBlock error %s", err)
   258  	}
   259  	err = this.blockStore.CommitTo()
   260  	if err != nil {
   261  		return fmt.Errorf("saveBlock error %s", err)
   262  	}
   263  	err = this.saveFullTxs(blkInfo.Block.Header.LeagueId, blkInfo.Block.Header.Height, blkInfo.Block.Transactions)
   264  	if err != nil {
   265  		return fmt.Errorf("saveFullTxs error %s", err)
   266  	}
   267  	err = this.acctIdxStore.Save(blockHeight, blkInfo.Block.Header.LeagueId, blkInfo.AccStates.GetAccounts(), mainTxUsed)
   268  	if err != nil {
   269  		return fmt.Errorf("saveAccIdx error %s", err)
   270  	}
   271  	this.accountStore.NewBatch()
   272  	if err = this.accountStore.BatchSave(blkInfo.AccStates); err != nil {
   273  		return fmt.Errorf("saveAccountState error %s", err)
   274  	}
   275  	if err = this.accountStore.CommitTo(); err != nil {
   276  		return fmt.Errorf("saveAccountState error %s", err)
   277  	}
   278  	this.mainTxUsedStore.NewBatch()
   279  	if err = this.mainTxUsedStore.BatchSave(mainTxUsed, blkInfo.Block.Header.Height); err != nil {
   280  		return err
   281  	}
   282  	if err = this.mainTxUsedStore.CommitTo(); err != nil {
   283  		return err
   284  	}
   285  	err = this.saveVotes(blkInfo.VoteStates, blkInfo.AccountVoteds, blkInfo.Block.Header.Height)
   286  	if err != nil {
   287  		return err
   288  	}
   289  	err = this.saveUT(blkInfo.UT, blkInfo.Block.Header.LeagueId, blkInfo.Block.Header.Height)
   290  	if err != nil {
   291  		return err
   292  	}
   293  	this.setCurrentBlock(blkInfo.Block.Header)
   294  	this.setDestroyedEnergy(blkInfo.Block.Header, blkInfo.FeeSum)
   295  	fmt.Printf("🚫 -----S---A---V---E----A---L---L---  Height:%d  TxLen:%d blockHash:%s bonus:%d \n",
   296  		blkInfo.Block.Header.Height,
   297  		blkInfo.Block.Transactions.Len(),
   298  		blkInfo.Block.Hash().String(),
   299  		blkInfo.Block.Header.Bonus,
   300  	)
   301  	return nil
   302  }
   303  func (this *LedgerStoreImp) saveVotes(voteStates []*storelaw.VoteState, AccountVoteds []*storelaw.AccountVoted, height uint64) error {
   304  	this.voteStore.NewBatch()
   305  	this.voteStore.SaveVotes(voteStates)
   306  	this.voteStore.SaveAccountVoted(AccountVoteds, height)
   307  	err := this.voteStore.CommitTo()
   308  	return err
   309  }
   310  func (this *LedgerStoreImp) saveUT(ut *big.Int, leagueId common.Address, height uint64) error {
   311  	fmt.Println("🚫  mainchain saveUT ", ut.Uint64(), leagueId.ToString(), height)
   312  	amount := this.utStore.GetUTByHeight(height, leagueId)
   313  	if amount.Cmp(ut) == 0 {
   314  		return nil
   315  	}
   316  	return this.utStore.Save(height, leagueId, ut)
   317  }
   318  func (this *LedgerStoreImp) saveFullTxs(leagueId common.Address, height uint64, txs orgtypes.Transactions) error {
   319  	voteSources := make(orgtypes.Transactions, 0)
   320  	for _, v := range txs {
   321  		if v.TxType == orgtypes.VoteIncreaseUT {
   322  			voteSources = append(voteSources, v)
   323  		}
   324  	}
   325  	if voteSources.Len() > 0 {
   326  		err := this.fullTxStore.SaveTxs(leagueId, height, voteSources)
   327  		return err
   328  	}
   329  	return nil
   330  }
   331  
   332  func (this *LedgerStoreImp) isSavingBlock() bool {
   333  	this.lock.Lock()
   334  	defer this.lock.Unlock()
   335  
   336  	if !this.savingBlock {
   337  		this.savingBlock = true
   338  		return false
   339  	}
   340  	return true
   341  }
   342  
   343  func (this *LedgerStoreImp) resetSavingBlock() {
   344  	this.lock.Lock()
   345  	defer this.lock.Unlock()
   346  	this.savingBlock = false
   347  }
   348  
   349  func (this *LedgerStoreImp) setCurrentBlock(header *orgtypes.Header) {
   350  	this.lock.Lock()
   351  	defer this.lock.Unlock()
   352  	this.currBlockHeader[header.LeagueId] = header
   353  	if header.Height%types.HWidth == 0 {
   354  		if this.bonusCache[header.LeagueId] == nil {
   355  			this.bonusCache[header.LeagueId] = make(map[uint64]uint64)
   356  		}
   357  		this.bonusCache[header.LeagueId][header.Height] = header.Bonus
   358  	}
   359  	return
   360  }
   361  
   362  func (this *LedgerStoreImp) setDestroyedEnergy(header *orgtypes.Header, feeSum *big.Int) {
   363  	this.lock.Lock()
   364  	defer this.lock.Unlock()
   365  	if header.Height%types.HWidth == 0 {
   366  		if this.destroyedEnergy[header.LeagueId] == nil {
   367  			this.destroyedEnergy[header.LeagueId] = big.NewInt(0)
   368  		}
   369  		this.destroyedEnergy[header.LeagueId].SetUint64(0)
   370  	}
   371  	rat := new(big.Rat).Set(orgtypes.BonusRate)
   372  	rat.Mul(rat, new(big.Rat).SetInt(feeSum))
   373  	rfTmp := big.NewFloat(0).SetRat(rat)
   374  	integer, _ := rfTmp.Uint64()
   375  	this.destroyedEnergy[header.LeagueId].Add(this.destroyedEnergy[header.LeagueId], big.NewInt(int64(integer)))
   376  }
   377  
   378  ////////////////////Ledger4Validation///////////////////
   379  func (this *LedgerStoreImp) GetBlockHashByHeight4V(leagueId common.Address, height uint64) (common.Hash, error) {
   380  	this.lock.RLock()
   381  	defer this.lock.RUnlock()
   382  	return this.blockStore.GetBlockHash(leagueId, height)
   383  }
   384  func (this *LedgerStoreImp) GetCurrentBlockHeight4V(leagueId common.Address) uint64 {
   385  	this.lock.RLock()
   386  	defer this.lock.RUnlock()
   387  	if this.currBlockHeader[leagueId] == nil {
   388  		return 0
   389  	}
   390  	return this.currBlockHeader[leagueId].Height
   391  }
   392  func (this *LedgerStoreImp) GetPrevAccount4V(height uint64, account, leagueId common.Address) (storelaw.AccountStater, error) {
   393  	this.lock.RLock()
   394  	defer this.lock.RUnlock()
   395  	return this.accountStore.GetPrev(height, account, leagueId)
   396  }
   397  
   398  func (this *LedgerStoreImp) GetCurrentHeaderHash4V(leagueId common.Address) common.Hash {
   399  	this.lock.RLock()
   400  	defer this.lock.RUnlock()
   401  	if this.currBlockHeader[leagueId] == nil {
   402  		return common.Hash{}
   403  	}
   404  	return this.currBlockHeader[leagueId].Hash()
   405  }
   406  func (this *LedgerStoreImp) ContainTx4V(txHash common.Hash) bool {
   407  	return true
   408  }
   409  
   410  func (this *LedgerStoreImp) GetVoteState(voteId common.Hash, height uint64) (*storelaw.VoteState, error) {
   411  	return this.voteStore.GetVoteState(voteId, height)
   412  }
   413  func (this *LedgerStoreImp) AlreadyVoted(voteId common.Hash, account common.Address) bool {
   414  	return this.voteStore.AlreadyVoted(voteId, account)
   415  }
   416  func (this *LedgerStoreImp) GetUTByHeight(height uint64, leagueId common.Address) *big.Int {
   417  	return this.utStore.GetUTByHeight(height, leagueId)
   418  	/*this.utStore.GetUTByHeight(height, leagueId)
   419  	fmt.Println("💗 💗 💗 💗 💗 💗 p1", height, leagueId.ToString())
   420  	ls, err := this.lightLedger.GetLeagueByHeight(height, leagueId)
   421  	fmt.Println("💗 💗 💗 💗 💗 💗 p1.5", ls, err)
   422  	rate := uint32(0)
   423  	if err != nil {
   424  		return big.NewInt(0)
   425  		fmt.Println("💗 💗 💗 💗 💗 💗 p2")
   426  	} else {
   427  		rate, _, _, err = this.lightLedger.GetMetaData(leagueId)
   428  		fmt.Println("💗 💗 💗 💗 💗 💗 p3", rate, err)
   429  	}
   430  	fmt.Printf("💗 💗 💗 💗 💗 💗 p4 %v", ls)
   431  	ut := big.NewInt(0)
   432  	ut.Mul(ls.Data.FrozenBox, big.NewInt(0).SetUint64(uint64(rate)))*/
   433  }
   434  func (this *LedgerStoreImp) GetBonus(leagueId common.Address) map[uint64]uint64 {
   435  	return this.bonusCache[leagueId]
   436  }
   437  func (this *LedgerStoreImp) GetTransaction(txHash common.Hash, leagueId common.Address) (*orgtypes.Transaction, uint64, error) {
   438  	return this.fullTxStore.GetTx(leagueId, txHash)
   439  }
   440  func (this *LedgerStoreImp) GetHeaderBonus(leagueId common.Address) *big.Int {
   441  	b := this.destroyedEnergy[leagueId]
   442  	if b == nil {
   443  		return big.NewInt(0)
   444  	}
   445  	return b
   446  }
   447  func (this *LedgerStoreImp) GetAccountRange(start, end uint64, account, leagueId common.Address) (storelaw.AccountStaters, error) {
   448  	return this.accountStore.GetAccountRange(start, end, account, leagueId)
   449  }
   450  
   451  ////////////////////Ledger4Validation///////////////////