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

     1  package storages
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/binary"
     6  	"fmt"
     7  	"io"
     8  
     9  	"github.com/sixexorg/magnetic-ring/common/sink"
    10  
    11  	"math/big"
    12  
    13  	"github.com/sixexorg/magnetic-ring/common"
    14  	"github.com/sixexorg/magnetic-ring/common/serialization"
    15  	"github.com/sixexorg/magnetic-ring/core/orgchain/types"
    16  	"github.com/sixexorg/magnetic-ring/errors"
    17  	"github.com/sixexorg/magnetic-ring/store/db"
    18  	scom "github.com/sixexorg/magnetic-ring/store/orgchain/common"
    19  )
    20  
    21  type BlockStore struct {
    22  	enableCache bool
    23  	dbDir       string
    24  	cache       *BlockCache
    25  	store       *db.LevelDBStore
    26  }
    27  
    28  type TXWithHeight struct {
    29  	Tx     *types.Transaction
    30  	Height uint64
    31  }
    32  
    33  func NewBlockStore(dbDir string, enableCache bool) (*BlockStore, error) {
    34  	var err error
    35  	store, err := db.NewLevelDBStore(dbDir)
    36  	if err != nil {
    37  		return nil, err
    38  	}
    39  	blockStore := &BlockStore{
    40  		dbDir: dbDir,
    41  		store: store,
    42  	}
    43  	return blockStore, nil
    44  }
    45  
    46  //NewBatch start a commit batch
    47  func (this *BlockStore) NewBatch() {
    48  	this.store.NewBatch()
    49  }
    50  
    51  //SaveBlock persist block to store
    52  func (this *BlockStore) SaveBlock(block *types.Block) error {
    53  	if this.enableCache {
    54  		this.cache.AddBlock(block)
    55  	}
    56  	blockHeight := block.Header.Height
    57  	err := this.SaveHeader(block)
    58  	if err != nil {
    59  		return fmt.Errorf("SaveHeader error %s", err)
    60  	}
    61  	for _, tx := range block.Transactions {
    62  		err = this.SaveTransaction(tx, blockHeight)
    63  		if err != nil {
    64  			txHash := tx.Hash()
    65  			return fmt.Errorf("SaveTransaction block height %d tx %s err %s", blockHeight, txHash.String(), err)
    66  		}
    67  	}
    68  	return nil
    69  }
    70  func (this *BlockStore) GetTransactions(txHashes []common.Hash) ([]*TXWithHeight, error) {
    71  	rxwhs := make([]*TXWithHeight, 0, len(txHashes))
    72  	for _, v := range txHashes {
    73  		tx, height, err := this.loadTransaction(v)
    74  		if err == nil {
    75  			txwh := &TXWithHeight{
    76  				Tx:     tx,
    77  				Height: height,
    78  			}
    79  			rxwhs = append(rxwhs, txwh)
    80  		} else {
    81  			return nil, errors.ERR_DB_NOT_FOUND
    82  		}
    83  	}
    84  	return rxwhs, nil
    85  }
    86  
    87  /*func (this *BlockStore) CorrectBlock(block *types.Block, capture, escape types.Transactions) error {
    88  	this.SaveBlockHash(block.Header.Height, block.Hash())
    89  	err := this.SaveHeader(block)
    90  	if err != nil {
    91  		return err
    92  	}
    93  	err = this.correctTransactions(block.Header.Height, capture, escape)
    94  	return err
    95  }
    96  func (this *BlockStore) correctTransactions(height uint64, capture, escape types.Transactions) error {
    97  	for _, tx := range capture {
    98  		err := this.SaveTransaction(tx, height)
    99  		if err != nil {
   100  			txHash := tx.Hash()
   101  			return fmt.Errorf("SaveTransaction block height %d tx %s err %s", height, txHash.String(), err)
   102  		}
   103  	}
   104  	for _, tx := range escape {
   105  		err := this.SaveTransaction(tx, 0)
   106  		if err != nil {
   107  			txHash := tx.Hash()
   108  			return fmt.Errorf("SaveTransaction block height %d tx %s err %s", height, txHash.String(), err)
   109  		}
   110  	}
   111  	return nil
   112  }*/
   113  
   114  //ContainBlock return the block specified by block hash save in store
   115  func (this *BlockStore) ContainBlock(blockHash common.Hash) (bool, error) {
   116  	if this.enableCache {
   117  		if this.cache.ContainBlock(blockHash) {
   118  			return true, nil
   119  		}
   120  	}
   121  	key := this.getHeaderKey(blockHash)
   122  	_, err := this.store.Get(key)
   123  	if err != nil {
   124  		if err == errors.ERR_DB_NOT_FOUND {
   125  			return false, nil
   126  		}
   127  		return false, err
   128  	}
   129  	return true, nil
   130  }
   131  
   132  //GetBlock return block by block hash
   133  func (this *BlockStore) GetBlock(blockHash common.Hash) (*types.Block, error) {
   134  	var block *types.Block
   135  	if this.enableCache {
   136  		block = this.cache.GetBlock(blockHash)
   137  		if block != nil {
   138  			return block, nil
   139  		}
   140  	}
   141  	header, txHashes, err := this.loadHeaderWithTx(blockHash)
   142  	if err != nil {
   143  		return nil, err
   144  	}
   145  	txList := make([]*types.Transaction, 0, len(txHashes))
   146  	for _, txHash := range txHashes {
   147  		tx, _, err := this.GetTransaction(txHash)
   148  		if err != nil {
   149  			return nil, fmt.Errorf("GetTransaction %s error %s", txHash.String(), err)
   150  		}
   151  		if tx == nil {
   152  			return nil, fmt.Errorf("cannot get transaction %s", txHash.String())
   153  		}
   154  		txList = append(txList, tx)
   155  	}
   156  	block = &types.Block{
   157  		Header:       header,
   158  		Transactions: txList,
   159  	}
   160  	return block, nil
   161  }
   162  
   163  //GetBlock return block by block hash
   164  /*func (this *BlockStore) GetBlock2(blockHash common.Hash) (block *types.Block, diffHeightTxHash []common.Hash, err error) {
   165  	if this.enableCache {
   166  		block = this.cache.GetBlock(blockHash)
   167  		if block != nil {
   168  			return block, nil, nil
   169  		}
   170  	}
   171  	header, txHashes, err := this.loadHeaderWithTx(blockHash)
   172  	if err != nil {
   173  		return nil, nil, err
   174  	}
   175  	txList := make([]*types.Transaction, 0, len(txHashes))
   176  	diffHeightTxHash = make([]common.Hash, 0)
   177  	for k, txHash := range txHashes {
   178  		tx, height, err := this.GetTransaction(txHash)
   179  		if err != nil {
   180  			return nil, nil, fmt.Errorf("GetTransaction %s error %s", txHash.String(), err)
   181  		}
   182  		if tx == nil {
   183  			return nil, nil, fmt.Errorf("cannot get transaction %s", txHash.String())
   184  		}
   185  		if height != header.Height {
   186  			diffHeightTxHash = append(diffHeightTxHash, txHashes[k])
   187  		}
   188  		txList = append(txList, tx)
   189  	}
   190  	block = &types.Block{
   191  		Header:       header,
   192  		Transactions: txList,
   193  	}
   194  	return block, diffHeightTxHash, nil
   195  }*/
   196  
   197  func (this *BlockStore) loadHeaderWithTx(blockHash common.Hash) (*types.Header, []common.Hash, error) {
   198  	key := this.getHeaderKey(blockHash)
   199  	value, err := this.store.Get(key)
   200  	if err != nil {
   201  		return nil, nil, err
   202  	}
   203  	reader := bytes.NewBuffer(value)
   204  	header := new(types.Header)
   205  	err = header.Deserialize(reader)
   206  	if err != nil {
   207  		return nil, nil, err
   208  	}
   209  	txSize, err := serialization.ReadUint32(reader)
   210  	if err != nil {
   211  		return nil, nil, err
   212  	}
   213  	txHashes := make([]common.Hash, 0, int(txSize))
   214  	for i := uint32(0); i < txSize; i++ {
   215  		txHash := common.Hash{}
   216  		err = txHash.Deserialize(reader)
   217  		if err != nil {
   218  			return nil, nil, err
   219  		}
   220  		txHashes = append(txHashes, txHash)
   221  	}
   222  	return header, txHashes, nil
   223  }
   224  
   225  //SaveHeader persist block header to store
   226  func (this *BlockStore) SaveHeader(block *types.Block) error {
   227  	blockHash := block.Hash()
   228  
   229  	key := this.getHeaderKey(blockHash)
   230  	value := bytes.NewBuffer(nil)
   231  	block.Header.Serialize(value)
   232  	serialization.WriteUint32(value, uint32(len(block.Transactions)))
   233  	for _, tx := range block.Transactions {
   234  		txHash := tx.Hash()
   235  		err := txHash.Serialize(value)
   236  		if err != nil {
   237  			return err
   238  		}
   239  	}
   240  	this.store.BatchPut(key, value.Bytes())
   241  	return nil
   242  }
   243  func (this *BlockStore) RemoveHeader(blockHash common.Hash) error {
   244  	key := this.getHeaderKey(blockHash)
   245  	err := this.store.Delete(key)
   246  	return err
   247  }
   248  
   249  //GetHeader return the header specified by block hash
   250  func (this *BlockStore) GetHeader(blockHash common.Hash) (*types.Header, error) {
   251  	if this.enableCache {
   252  		block := this.cache.GetBlock(blockHash)
   253  		if block != nil {
   254  			return block.Header, nil
   255  		}
   256  	}
   257  	return this.loadHeader(blockHash)
   258  }
   259  func (this *BlockStore) GetDifficultyByBlockHash(blockHash common.Hash) (*big.Int, error) {
   260  	if this.enableCache {
   261  		block := this.cache.GetBlock(blockHash)
   262  		if block != nil {
   263  			return block.Header.Difficulty, nil
   264  		}
   265  	}
   266  	header, err := this.loadHeader(blockHash)
   267  	if err != nil {
   268  		return nil, err
   269  	}
   270  	return header.Difficulty, nil
   271  }
   272  func (this *BlockStore) loadHeader(blockHash common.Hash) (*types.Header, error) {
   273  	key := this.getHeaderKey(blockHash)
   274  	value, err := this.store.Get(key)
   275  	if err != nil {
   276  		return nil, err
   277  	}
   278  	reader := bytes.NewBuffer(value)
   279  	header := new(types.Header)
   280  	err = header.Deserialize(reader)
   281  	if err != nil {
   282  		return nil, err
   283  	}
   284  	return header, nil
   285  }
   286  
   287  //GetCurrentBlock return the current block hash and current block height
   288  func (this *BlockStore) GetCurrentBlock() (common.Hash, uint64, error) {
   289  	key := this.getCurrentBlockKey()
   290  	data, err := this.store.Get(key)
   291  	if err != nil {
   292  		return common.Hash{}, 0, err
   293  	}
   294  	reader := bytes.NewReader(data)
   295  	blockHash := common.Hash{}
   296  	err = blockHash.Deserialize(reader)
   297  	if err != nil {
   298  		return common.Hash{}, 0, err
   299  	}
   300  	height, err := serialization.ReadUint64(reader)
   301  	if err != nil {
   302  		return common.Hash{}, 0, err
   303  	}
   304  	return blockHash, height, nil
   305  }
   306  
   307  //SaveCurrentBlock persist the current block height and current block hash to store
   308  func (this *BlockStore) SaveCurrentBlock(height uint64, blockHash common.Hash) error {
   309  	key := this.getCurrentBlockKey()
   310  	value := bytes.NewBuffer(nil)
   311  	blockHash.Serialize(value)
   312  	serialization.WriteUint64(value, height)
   313  	this.store.BatchPut(key, value.Bytes())
   314  	return nil
   315  }
   316  
   317  //GetHeaderIndexList return the head index store in header index list
   318  func (this *BlockStore) GetHeaderIndexList() (map[uint64]common.Hash, error) {
   319  	result := make(map[uint64]common.Hash)
   320  	iter := this.store.NewIterator([]byte{byte(scom.IX_HEADER_HASH_LIST)})
   321  	defer iter.Release()
   322  	for iter.Next() {
   323  		startCount, err := this.getStartHeightByHeaderIndexKey(iter.Key())
   324  		if err != nil {
   325  			return nil, fmt.Errorf("getStartHeightByHeaderIndexKey error %s", err)
   326  		}
   327  		reader := bytes.NewReader(iter.Value())
   328  		count, err := serialization.ReadUint32(reader)
   329  		if err != nil {
   330  			return nil, fmt.Errorf("serialization.ReadUint32 count error %s", err)
   331  		}
   332  		for i := uint32(0); i < count; i++ {
   333  			height := startCount + uint64(i)
   334  			blockHash := common.Hash{}
   335  			err = blockHash.Deserialize(reader)
   336  			if err != nil {
   337  				return nil, fmt.Errorf("blockHash.Deserialize error %s", err)
   338  			}
   339  			result[height] = blockHash
   340  		}
   341  	}
   342  	return result, nil
   343  }
   344  
   345  //SaveHeaderIndexList persist header index list to store
   346  func (this *BlockStore) SaveHeaderIndexList(startIndex uint64, indexList []common.Hash) error {
   347  	indexKey := this.getHeaderIndexListKey(startIndex)
   348  	indexSize := uint32(len(indexList))
   349  	value := bytes.NewBuffer(nil)
   350  	serialization.WriteUint32(value, indexSize)
   351  	for _, hash := range indexList {
   352  		hash.Serialize(value)
   353  	}
   354  	this.store.BatchPut(indexKey, value.Bytes())
   355  	return nil
   356  }
   357  
   358  //GetBlockHash return block hash by block height
   359  func (this *BlockStore) GetBlockHash(height uint64) (common.Hash, error) {
   360  	key := this.getBlockHashKey(height)
   361  	value, err := this.store.Get(key)
   362  	if err != nil {
   363  		return common.Hash{}, err
   364  	}
   365  	blockHash, err := common.ParseHashFromBytes(value)
   366  	if err != nil {
   367  		return common.Hash{}, err
   368  	}
   369  	return blockHash, nil
   370  }
   371  
   372  //SaveBlockHash persist block height and block hash to store
   373  func (this *BlockStore) SaveBlockHash(height uint64, blockHash common.Hash) {
   374  	key := this.getBlockHashKey(height)
   375  	this.store.BatchPut(key, blockHash.ToBytes())
   376  }
   377  func (this *BlockStore) RemoveBlockHash(height uint64) {
   378  	key := this.getBlockHashKey(height)
   379  	this.store.BatchDelete(key)
   380  }
   381  
   382  //SaveTransaction persist transaction to store
   383  func (this *BlockStore) SaveTransaction(tx *types.Transaction, height uint64) error {
   384  	if this.enableCache {
   385  		this.cache.AddTransaction(tx, height)
   386  	}
   387  	return this.putTransaction(tx, height)
   388  }
   389  
   390  func (this *BlockStore) putTransaction(tx *types.Transaction, height uint64) error {
   391  	txHash := tx.Hash()
   392  	key := this.getTransactionKey(txHash)
   393  
   394  	value := bytes.NewBuffer(nil)
   395  	serialization.WriteUint64(value, height)
   396  	err := tx.Serialize(value)
   397  	if err != nil {
   398  		return err
   399  	}
   400  	this.store.BatchPut(key, value.Bytes())
   401  	return nil
   402  }
   403  func (this *BlockStore) RemoveTransaction(txHash common.Hash) {
   404  	key := this.getTransactionKey(txHash)
   405  	this.store.BatchDelete(key)
   406  }
   407  
   408  //GetTransaction return transaction by transaction hash
   409  func (this *BlockStore) GetTransaction(txHash common.Hash) (*types.Transaction, uint64, error) {
   410  	if this.enableCache {
   411  		tx, height := this.cache.GetTransaction(txHash)
   412  		if tx != nil {
   413  			return tx, height, nil
   414  		}
   415  	}
   416  	return this.loadTransaction(txHash)
   417  }
   418  
   419  func (this *BlockStore) loadTransaction(txHash common.Hash) (*types.Transaction, uint64, error) {
   420  	key := this.getTransactionKey(txHash)
   421  	var tx *types.Transaction
   422  	var height uint64
   423  	if this.enableCache {
   424  		tx, height = this.cache.GetTransaction(txHash)
   425  		if tx != nil {
   426  			return tx, height, nil
   427  		}
   428  	}
   429  	value, err := this.store.Get(key)
   430  	if err != nil {
   431  		return nil, 0, err
   432  	}
   433  	source := sink.NewZeroCopySource(value)
   434  	var eof bool
   435  	height, eof = source.NextUint64()
   436  	if eof {
   437  		return nil, 0, io.ErrUnexpectedEOF
   438  	}
   439  	tx = new(types.Transaction)
   440  	err = tx.Deserialization(source)
   441  	if err != nil {
   442  		return nil, 0, fmt.Errorf("transaction deserialize error %s", err)
   443  	}
   444  	return tx, height, nil
   445  }
   446  
   447  //IsContainTransaction return whether the transaction is in store
   448  func (this *BlockStore) ContainTransaction(txHash common.Hash) (bool, error) {
   449  	key := this.getTransactionKey(txHash)
   450  
   451  	if this.enableCache {
   452  		if this.cache.ContainTransaction(txHash) {
   453  			return true, nil
   454  		}
   455  	}
   456  	_, err := this.store.Get(key)
   457  	if err != nil {
   458  		if err == errors.ERR_DB_NOT_FOUND {
   459  			return false, nil
   460  		}
   461  		return false, err
   462  	}
   463  	return true, nil
   464  }
   465  
   466  //GetVersion return the version of store
   467  func (this *BlockStore) GetVersion() (byte, error) {
   468  	key := this.getVersionKey()
   469  	value, err := this.store.Get(key)
   470  	if err != nil {
   471  		return 0, err
   472  	}
   473  	reader := bytes.NewReader(value)
   474  	return reader.ReadByte()
   475  }
   476  
   477  //SaveVersion persist version to store
   478  func (this *BlockStore) SaveVersion(ver byte) error {
   479  	key := this.getVersionKey()
   480  	return this.store.Put(key, []byte{ver})
   481  }
   482  
   483  //ClearAll clear all the data of block store
   484  func (this *BlockStore) ClearAll() error {
   485  	this.NewBatch()
   486  	iter := this.store.NewIterator(nil)
   487  	for iter.Next() {
   488  		this.store.BatchDelete(iter.Key())
   489  	}
   490  	iter.Release()
   491  	return this.CommitTo()
   492  }
   493  
   494  //CommitTo commit the batch to store
   495  func (this *BlockStore) CommitTo() error {
   496  	return this.store.BatchCommit()
   497  }
   498  
   499  //Close block store
   500  func (this *BlockStore) Close() error {
   501  	return this.store.Close()
   502  }
   503  
   504  func (this *BlockStore) getTransactionKey(txHash common.Hash) []byte {
   505  	key := bytes.NewBuffer(nil)
   506  	key.WriteByte(byte(scom.DATA_TRANSACTION))
   507  	txHash.Serialize(key)
   508  	return key.Bytes()
   509  }
   510  
   511  func (this *BlockStore) getHeaderKey(blockHash common.Hash) []byte {
   512  	data := blockHash.ToBytes()
   513  	key := make([]byte, 1+len(data))
   514  	key[0] = byte(scom.DATA_HEADER)
   515  	copy(key[1:], data)
   516  	return key
   517  }
   518  
   519  func (this *BlockStore) getBlockHashKey(height uint64) []byte {
   520  	key := make([]byte, 9, 9)
   521  	key[0] = byte(scom.DATA_BLOCK)
   522  	binary.LittleEndian.PutUint64(key[1:], height)
   523  	return key
   524  }
   525  
   526  func (this *BlockStore) getCurrentBlockKey() []byte {
   527  	return []byte{byte(scom.SYS_CURRENT_BLOCK)}
   528  }
   529  
   530  func (this *BlockStore) getBlockMerkleTreeKey() []byte {
   531  	return []byte{byte(scom.SYS_BLOCK_MERKLE_TREE)}
   532  }
   533  
   534  func (this *BlockStore) getVersionKey() []byte {
   535  	return []byte{byte(scom.SYS_VERSION)}
   536  }
   537  
   538  func (this *BlockStore) getHeaderIndexListKey(startHeight uint64) []byte {
   539  	key := bytes.NewBuffer(nil)
   540  	key.WriteByte(byte(scom.IX_HEADER_HASH_LIST))
   541  	serialization.WriteUint64(key, startHeight)
   542  	return key.Bytes()
   543  }
   544  
   545  func (this *BlockStore) getStartHeightByHeaderIndexKey(key []byte) (uint64, error) {
   546  	reader := bytes.NewReader(key[1:])
   547  	height, err := serialization.ReadUint64(reader)
   548  	if err != nil {
   549  		return 0, err
   550  	}
   551  	return height, nil
   552  }