github.com/sixexorg/magnetic-ring@v0.0.0-20191119090307-31705a21e419/store/orgchain/storages/ledger_store.go (about)

     1  package storages
     2  
     3  import (
     4  	"fmt"
     5  	"sync"
     6  
     7  	"math/big"
     8  
     9  	"sort"
    10  
    11  	"path"
    12  
    13  	"github.com/sixexorg/magnetic-ring/bactor"
    14  	"github.com/sixexorg/magnetic-ring/common"
    15  	"github.com/sixexorg/magnetic-ring/core/orgchain/types"
    16  
    17  	"github.com/ontio/ontology-eventbus/actor"
    18  	"github.com/sixexorg/magnetic-ring/log"
    19  	p2pcommon "github.com/sixexorg/magnetic-ring/p2pserver/common"
    20  	scom "github.com/sixexorg/magnetic-ring/store/orgchain/common"
    21  	"github.com/sixexorg/magnetic-ring/store/orgchain/states"
    22  	"github.com/sixexorg/magnetic-ring/store/storelaw"
    23  )
    24  
    25  const (
    26  	SYSTEM_VERSION          = byte(1)      //Version of ledger store
    27  	HEADER_INDEX_BATCH_SIZE = uint64(2000) //Bath size of saving header index
    28  )
    29  
    30  var (
    31  	//Storage save path.
    32  	DBDirBlock          = "block"
    33  	DBDirState          = "states"
    34  	DBDirAccountState   = "account"
    35  	DBDirAccountRoot    = "aroot"
    36  	DBDirVote           = "vote"
    37  	DBDirUT             = "ut"
    38  	MerkleTreeStorePath = "merkle_tree.db"
    39  	p2pActor            *actor.PID
    40  )
    41  
    42  func initActor() error {
    43  	var err error
    44  	if p2pActor == nil {
    45  		p2pActor, err = bactor.GetActorPid(bactor.P2PACTOR)
    46  		if err != nil {
    47  			log.Error(err.Error())
    48  			return err
    49  		}
    50  	}
    51  	return nil
    52  }
    53  
    54  //LedgerStoreImp is main store struct fo ledger
    55  type LedgerStoreImp struct {
    56  	blockStore *BlockStore //BlockStore for saving block & transaction data
    57  	//stateStore       *StateStore //StateStore for saving state data, like balance, smart contract execution result, and so on.
    58  	accountStore     *AccountStore
    59  	accountRootStore *AccountRootStore
    60  	voteStore        *VoteStore
    61  	utStore          *UTStore
    62  
    63  	storedIndexCount uint64      //record the count of have saved block index
    64  	currBlockHeight  uint64      //Current block height
    65  	currBlockHash    common.Hash //Current block hash
    66  	currBlock        *types.Block
    67  	totalDifficulty  *big.Int
    68  	headerCache      map[common.Hash]*types.Header //BlockHash => Header
    69  	headerIndex      map[uint64]common.Hash        //Header index, Mapping header height => block hash
    70  	savingBlock      bool                          //is saving block now
    71  	destroyedEnergy    *big.Int
    72  	bonusCache       map[uint64]uint64
    73  	lock             sync.RWMutex
    74  }
    75  
    76  //NewLedgerStore return LedgerStoreImp instance
    77  func NewLedgerStore(dataDir string) (*LedgerStoreImp, error) {
    78  	ledgerStore := &LedgerStoreImp{
    79  		headerIndex:     make(map[uint64]common.Hash),
    80  		headerCache:     make(map[common.Hash]*types.Header, 0),
    81  		totalDifficulty: big.NewInt(0),
    82  		destroyedEnergy:   big.NewInt(0),
    83  		bonusCache:      make(map[uint64]uint64),
    84  	}
    85  
    86  	blockStore, err := NewBlockStore(path.Join(dataDir, DBDirBlock), true)
    87  	if err != nil {
    88  		return nil, fmt.Errorf("NewBlockStore error %s", err)
    89  	}
    90  	ledgerStore.blockStore = blockStore
    91  
    92  	accountState, err := NewAccountStore(path.Join(dataDir, DBDirAccountState))
    93  	if err != nil {
    94  		return nil, fmt.Errorf("NewAccountStateStore error %s", err)
    95  	}
    96  	ledgerStore.accountStore = accountState
    97  	accountRoot, err := NewAccountRootStore(path.Join(dataDir, DBDirAccountRoot))
    98  	if err != nil {
    99  		return nil, fmt.Errorf("NewAccountRootStore error %s", err)
   100  	}
   101  	ledgerStore.accountRootStore = accountRoot
   102  
   103  	voteStore, err := NewVoteStore(path.Join(dataDir, DBDirVote), byte(scom.ST_VOTE_STATE), byte(scom.ST_VOTE_RECORD))
   104  	if err != nil {
   105  		return nil, fmt.Errorf("NewVoteStore error %s", err)
   106  	}
   107  	ledgerStore.voteStore = voteStore
   108  
   109  	utStore, err := NewUTStore(path.Join(dataDir, DBDirUT))
   110  	if err != nil {
   111  		return nil, fmt.Errorf("NewUTStore error %s", err)
   112  	}
   113  	ledgerStore.utStore = utStore
   114  	/*
   115  		stateStore, err := NewStateStore(path.Join(dataDir, DBDirState), MerkleTreeStorePath)
   116  		if err != nil {
   117  			return nil, fmt.Errorf("NewStateStore error %s", err)
   118  		}
   119  
   120  		ledgerStore.stateStore = stateStore*/
   121  	return ledgerStore, nil
   122  }
   123  
   124  func (this *LedgerStoreImp) ContainBlock(blockHash common.Hash) (bool, error) {
   125  	return this.blockStore.ContainBlock(blockHash)
   126  
   127  }
   128  func (this *LedgerStoreImp) GetBlockByHash(blockHash common.Hash) (*types.Block, error) {
   129  	this.lock.RLock()
   130  	defer this.lock.RUnlock()
   131  	block, err := this.blockStore.GetBlock(blockHash)
   132  	if err != nil {
   133  		return nil, err
   134  	}
   135  	return block, nil
   136  }
   137  
   138  func (this *LedgerStoreImp) verifyHeader(header *types.Header) error {
   139  	if header.Height == 1 {
   140  		return nil
   141  	}
   142  	prevHeader, err := this.GetHeaderByHash(header.PrevBlockHash)
   143  	if err != nil {
   144  		return err
   145  	}
   146  	if prevHeader == nil {
   147  		return fmt.Errorf("cannot find pre header by blockHash %s", header.PrevBlockHash.String())
   148  	}
   149  	if prevHeader.Height+1 != header.Height {
   150  		return fmt.Errorf("block height is incorrect")
   151  	}
   152  	/*	if prevHeader.Timestamp >= header.Timestamp {
   153  		return fmt.Errorf("block timestamp is incorrect")
   154  	}*/
   155  	return nil
   156  }
   157  
   158  func (this *LedgerStoreImp) GetBlockHashByHeight(height uint64) (common.Hash, error) {
   159  	this.lock.RLock()
   160  	defer this.lock.RUnlock()
   161  	blockHash, err := this.blockStore.GetBlockHash(height)
   162  	if err != nil {
   163  		return common.Hash{}, err
   164  	}
   165  	return blockHash, err
   166  }
   167  func (this *LedgerStoreImp) GetBlockByHeight(height uint64) (*types.Block, error) {
   168  	this.lock.RLock()
   169  	defer this.lock.RUnlock()
   170  	blockHash, err := this.blockStore.GetBlockHash(height)
   171  	if err != nil {
   172  		return nil, err
   173  	}
   174  	return this.GetBlockByHash(blockHash)
   175  }
   176  
   177  func (this *LedgerStoreImp) setCurrentBlock(block *types.Block) {
   178  	this.lock.Lock()
   179  	defer this.lock.Unlock()
   180  	this.currBlockHash = block.Hash()
   181  	this.currBlockHeight = block.Header.Height
   182  	this.currBlock = block
   183  	if block.Header.Height%types.HWidth == 0 {
   184  		this.bonusCache[block.Header.Height] = block.Header.Bonus
   185  	}
   186  }
   187  func (this *LedgerStoreImp) setDestroyedEnergy(header *types.Header, feeSum *big.Int) {
   188  	this.lock.Lock()
   189  	defer this.lock.Unlock()
   190  	if header.Height%types.HWidth == 0 {
   191  		this.destroyedEnergy.SetUint64(0)
   192  	}
   193  	rat := new(big.Rat).Set(types.BonusRate)
   194  	rat.Mul(rat, new(big.Rat).SetInt(feeSum))
   195  	rfTmp := big.NewFloat(0).SetRat(rat)
   196  	integer, _ := rfTmp.Uint64()
   197  	this.destroyedEnergy.Add(this.destroyedEnergy, big.NewInt(int64(integer)))
   198  	fmt.Printf("⭕ leagueStore destoryEnergy:%d feeSu,:%d \n ", this.destroyedEnergy.Uint64(), feeSum.Uint64())
   199  }
   200  func (this *LedgerStoreImp) GetCurrentBlockInfo() *types.Block {
   201  	this.lock.RLock()
   202  	defer this.lock.RUnlock()
   203  	return this.currBlock
   204  }
   205  
   206  func (this *LedgerStoreImp) GetCurrentBlock() (uint64, common.Hash) {
   207  	this.lock.RLock()
   208  	defer this.lock.RUnlock()
   209  	return this.currBlockHeight, this.currBlockHash
   210  }
   211  
   212  //GetCurrentBlockHash return the current block hash
   213  func (this *LedgerStoreImp) GetCurrentBlockHash() common.Hash {
   214  	this.lock.RLock()
   215  	defer this.lock.RUnlock()
   216  	return this.currBlockHash
   217  }
   218  
   219  //GetCurrentBlockHeight return the current block height
   220  func (this *LedgerStoreImp) GetCurrentBlockHeight() uint64 {
   221  	this.lock.RLock()
   222  	defer this.lock.RUnlock()
   223  	return this.currBlockHeight
   224  }
   225  
   226  func (this *LedgerStoreImp) GetTransaction(txHash common.Hash, leagueId common.Address) (*types.Transaction, uint64, error) {
   227  	this.lock.RLock()
   228  	defer this.lock.RUnlock()
   229  	return this.blockStore.GetTransaction(txHash)
   230  }
   231  
   232  func (this *LedgerStoreImp) Restore()  {
   233  	
   234  }
   235  
   236  func (this *LedgerStoreImp) SaveAll(blockInfo *storelaw.OrgBlockInfo) error {
   237  	if this.isSavingBlock() {
   238  		//hash already saved or is saving
   239  		return nil
   240  	}
   241  	defer this.resetSavingBlock()
   242  
   243  	err := this.addStates(blockInfo.AccStates, blockInfo.Block.Header.Height)
   244  	if err != nil {
   245  		return err
   246  	}
   247  	err = this.addBlock(blockInfo.Block)
   248  	if err != nil {
   249  		return err
   250  	}
   251  	err = this.saveVotes(blockInfo.VoteStates, blockInfo.AccountVoteds, blockInfo.Block.Header.Height)
   252  	if err != nil {
   253  		return err
   254  	}
   255  	err = this.saveUT(blockInfo.UT, blockInfo.Block.Header.Height)
   256  	if err != nil {
   257  		return err
   258  	}
   259  	this.delHeaderCache(blockInfo.Block.Hash())
   260  	if this.currBlockHeight > 0 {
   261  		prevBlock := &types.Block{}
   262  		common.DeepCopy(prevBlock, this.currBlock)
   263  
   264  		/*	if actor.ConsensusPid != nil {
   265  			actor.ConsensusPid.Tell(blockInfo.Block)
   266  		}*/
   267  		err := initActor()
   268  		if err == nil {
   269  			p2pActor.Tell(&p2pcommon.OrgPendingData{
   270  				BANodeSrc: true,                            // true:ANode send staller false:staller send staller
   271  				OrgId:     blockInfo.Block.Header.LeagueId, // orgid
   272  				Block:     prevBlock,                       // tx
   273  			})
   274  			fmt.Println("!!!!!")
   275  		}
   276  		/*	fmt.Printf("⭕️ send to main radar the difficulty is %d the hash is %s \n", prevBlock.Header.Difficulty.Uint64(), prevBlock.Hash().String())
   277  			fmt.Println("⭕️ send to  🚫 ",
   278  				prevBlock.Header.Version,
   279  				prevBlock.Header.PrevBlockHash.String(),
   280  				prevBlock.Header.BlockRoot.String(),
   281  				prevBlock.Header.LeagueId.ToString(),
   282  				prevBlock.Header.TxRoot.String(),
   283  				prevBlock.Header.StateRoot.String(),
   284  				prevBlock.Header.ReceiptsRoot.String(),
   285  				prevBlock.Header.Timestamp,
   286  				prevBlock.Header.Height,
   287  				prevBlock.Header.Difficulty.Uint64(),
   288  				prevBlock.Header.Coinbase.ToString(),
   289  				prevBlock.Header.Extra,
   290  			)*/
   291  	}
   292  	this.setCurrentBlock(blockInfo.Block)
   293  	this.setDestroyedEnergy(blockInfo.Block.Header, blockInfo.FeeSum)
   294  	fmt.Printf("⭕ -----S---A---V---E----A---L---L---  Height:%d TxLen:%d blockHash:%s difficulty:%d bonus:%d bonusCache:%d \n",
   295  		blockInfo.Block.Header.Height,
   296  		blockInfo.Block.Transactions.Len(),
   297  		blockInfo.Block.Hash().String(),
   298  		blockInfo.Block.Header.Difficulty.Uint64(),
   299  		blockInfo.Block.Header.Bonus,
   300  		this.bonusCache[blockInfo.Height()],
   301  	)
   302  	return nil
   303  }
   304  func (this *LedgerStoreImp) saveUT(ut *big.Int, height uint64) error {
   305  	amount := this.utStore.GetUTByHeight(height)
   306  	if amount.Cmp(ut) == 0 {
   307  		return nil
   308  	}
   309  	return this.utStore.Save(height, ut)
   310  }
   311  func (this *LedgerStoreImp) addStates(accountStates storelaw.AccountStaters, height uint64) error {
   312  	if accountStates == nil {
   313  		return nil
   314  	}
   315  	this.accountStore.NewBatch()
   316  	err := this.accountStore.BatchSave(accountStates)
   317  	if err != nil {
   318  		return err
   319  	}
   320  	if err = this.accountStore.CommitTo(); err != nil {
   321  		return err
   322  	}
   323  	sort.Sort(accountStates)
   324  	hashes := []common.Address{}
   325  	for _, v := range accountStates {
   326  		hashes = append(hashes, v.Account())
   327  	}
   328  	asr := states.NewAccountStateRoot(height, hashes)
   329  	err = this.accountRootStore.Save(asr)
   330  	if err != nil {
   331  		return err
   332  	}
   333  	return nil
   334  }
   335  func (this *LedgerStoreImp) addBlock(block *types.Block) error {
   336  	currentHeight := this.GetCurrentBlockHeight()
   337  	blockHeight := block.Header.Height
   338  	if blockHeight <= currentHeight {
   339  		return nil
   340  	}
   341  	if blockHeight != currentHeight+1 {
   342  		return fmt.Errorf("block height %d not equal next block height %d", blockHeight, currentHeight+1)
   343  	}
   344  	err := this.saveBlock(block)
   345  	if err != nil {
   346  		return err
   347  	}
   348  	return nil
   349  }
   350  func (this *LedgerStoreImp) saveBlock(block *types.Block) error {
   351  	blockHash := block.Hash()
   352  	blockHeight := block.Header.Height
   353  	this.blockStore.NewBatch()
   354  	err := this.saveHeaderIndexList()
   355  	if err != nil {
   356  		return fmt.Errorf("saveHeaderIndexList error %s", err)
   357  	}
   358  
   359  	this.blockStore.SaveBlockHash(blockHeight, blockHash)
   360  	err = this.blockStore.SaveBlock(block)
   361  	if err != nil {
   362  		return fmt.Errorf("SaveBlock height %d hash %s error %s", blockHeight, blockHash.String(), err)
   363  	}
   364  	err = this.blockStore.CommitTo()
   365  	if err != nil {
   366  		return err
   367  	}
   368  	this.setHeaderIndex(blockHeight, blockHash)
   369  	//log.Info("this.totalDifficulty","difficulty",this.totalDifficulty,"block.Header.Difficulty",block.Header.Difficulty)
   370  	this.totalDifficulty.Add(this.totalDifficulty, block.Header.Difficulty)
   371  	return nil
   372  }
   373  func (this *LedgerStoreImp) saveVotes(voteStates []*storelaw.VoteState, AccountVoteds []*storelaw.AccountVoted, height uint64) error {
   374  	this.voteStore.NewBatch()
   375  	this.voteStore.SaveVotes(voteStates)
   376  	this.voteStore.SaveAccountVoted(AccountVoteds, height)
   377  	err := this.voteStore.CommitTo()
   378  	return err
   379  }
   380  func (this *LedgerStoreImp) RollbackToHeight(height uint64) error {
   381  	this.lock.RLock()
   382  	defer this.lock.RUnlock()
   383  	//accountState
   384  	asts, err := this.accountRootStore.GetRange(height, this.currBlockHeight)
   385  	if err != nil {
   386  		return err
   387  	}
   388  	//accountRoot
   389  	this.accountStore.NewBatch()
   390  	heights := []uint64{}
   391  	for k, v := range asts {
   392  		this.accountStore.BatchRemove(v.Height, v.Accounts)
   393  		heights = append(heights, asts[k].Height)
   394  	}
   395  	err = this.accountStore.CommitTo()
   396  	if err != nil {
   397  		return err
   398  	}
   399  	this.accountRootStore.NewBatch()
   400  	this.accountRootStore.BatchRemove(heights)
   401  	err = this.accountRootStore.CommitTo()
   402  	if err != nil {
   403  		return err
   404  	}
   405  
   406  	//block
   407  	this.blockStore.NewBatch()
   408  	for i := this.currBlockHeight; i > height; i-- {
   409  		hash, err := this.blockStore.GetBlockHash(i)
   410  		if err != nil {
   411  			return err
   412  		}
   413  		block, err := this.blockStore.GetBlock(hash)
   414  		if err != nil {
   415  			return err
   416  		}
   417  
   418  		delete(this.headerCache, hash)
   419  		delete(this.headerIndex, i)
   420  		this.currBlockHash = block.Header.PrevBlockHash
   421  		this.totalDifficulty.Sub(this.totalDifficulty, block.Header.Difficulty)
   422  
   423  		this.blockStore.RemoveBlockHash(i)
   424  		this.blockStore.RemoveHeader(hash)
   425  		for _, v := range block.Transactions {
   426  			this.blockStore.RemoveTransaction(v.Hash())
   427  		}
   428  	}
   429  	err = this.blockStore.CommitTo()
   430  
   431  	block, err := this.GetBlockByHeight(height)
   432  	if err != nil {
   433  		return err
   434  	}
   435  	this.setCurrentBlock(block)
   436  	return nil
   437  }
   438  func (this *LedgerStoreImp) TotalDifficulty() *big.Int {
   439  	this.lock.RLock()
   440  	defer this.lock.RUnlock()
   441  	return this.totalDifficulty
   442  }
   443  func (this *LedgerStoreImp) GetDifficultyByBlockHash(hash common.Hash) (*big.Int, error) {
   444  	return this.blockStore.GetDifficultyByBlockHash(hash)
   445  }
   446  func (this *LedgerStoreImp) SaveAccount(state storelaw.AccountStater) error {
   447  	this.lock.Lock()
   448  	defer this.lock.Unlock()
   449  	return this.accountStore.Save(state)
   450  }
   451  func (this *LedgerStoreImp) isSavingBlock() bool {
   452  	this.lock.Lock()
   453  	defer this.lock.Unlock()
   454  
   455  	if !this.savingBlock {
   456  		this.savingBlock = true
   457  		return false
   458  	}
   459  	return true
   460  }
   461  
   462  func (this *LedgerStoreImp) resetSavingBlock() {
   463  	this.lock.Lock()
   464  	defer this.lock.Unlock()
   465  	this.savingBlock = false
   466  }
   467  
   468  ////////////////////Ledger4Validation///////////////////
   469  func (this *LedgerStoreImp) GetCurrentBlockHeight4V(leagueId common.Address) uint64 {
   470  	return this.GetCurrentBlockHeight()
   471  }
   472  func (this *LedgerStoreImp) GetCurrentHeaderHash4V(leagueId common.Address) common.Hash {
   473  	return this.GetCurrentHeaderHash()
   474  }
   475  func (this *LedgerStoreImp) GetBlockHashByHeight4V(leagueId common.Address, height uint64) (common.Hash, error) {
   476  	return this.GetBlockHashByHeight(height)
   477  }
   478  
   479  func (this *LedgerStoreImp) GetPrevAccount4V(height uint64, account, leagueId common.Address) (storelaw.AccountStater, error) {
   480  	this.lock.RLock()
   481  	defer this.lock.RUnlock()
   482  	return this.accountStore.GetPrev(height, account, leagueId)
   483  }
   484  func (this *LedgerStoreImp) ContainTx4V(txHash common.Hash) bool {
   485  	bool, err := this.blockStore.ContainTransaction(txHash)
   486  	if err != nil {
   487  		return false
   488  	}
   489  	return bool
   490  }
   491  func (this *LedgerStoreImp) GetVoteState(voteId common.Hash, height uint64) (*storelaw.VoteState, error) {
   492  	return this.voteStore.GetVoteState(voteId, height)
   493  }
   494  func (this *LedgerStoreImp) AlreadyVoted(voteId common.Hash, account common.Address) bool {
   495  	return this.voteStore.AlreadyVoted(voteId, account)
   496  }
   497  func (this *LedgerStoreImp) GetUTByHeight(height uint64, leagueId common.Address) *big.Int {
   498  	return this.utStore.GetUTByHeight(height)
   499  }
   500  func (this *LedgerStoreImp) GetHeaderBonus(leagueId common.Address) *big.Int {
   501  	return this.destroyedEnergy
   502  }
   503  func (this *LedgerStoreImp) GetAccountRange(start, end uint64, account, leagueId common.Address) (storelaw.AccountStaters, error) {
   504  	return this.accountStore.GetAccountRange(start, end, account)
   505  }
   506  func (this *LedgerStoreImp) GetBonus(leagueId common.Address) map[uint64]uint64 {
   507  	return this.bonusCache
   508  }
   509  
   510  ////////////////////Ledger4Validation///////////////////