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