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

     1  package storages
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"bytes"
     7  
     8  	"github.com/sixexorg/magnetic-ring/common"
     9  	"github.com/sixexorg/magnetic-ring/common/serialization"
    10  	"github.com/sixexorg/magnetic-ring/errors"
    11  	"github.com/sixexorg/magnetic-ring/merkle"
    12  	"github.com/sixexorg/magnetic-ring/store/db"
    13  	scom "github.com/sixexorg/magnetic-ring/store/mainchain/common"
    14  )
    15  
    16  //StateStore saving the data of ledger states. Like balance of account, and the execution result of smart contract
    17  type StateStore struct {
    18  	dbDir           string                    //Store file path
    19  	store           *db.LevelDBStore          //Store handler
    20  	merklePath      string                    //Merkle tree store path
    21  	merkleTree      *merkle.CompactMerkleTree //Merkle tree of block root
    22  	merkleHashStore merkle.HashStore
    23  }
    24  
    25  //NewStateStore return state store instance
    26  func NewStateStore(dbDir, merklePath string) (*StateStore, error) {
    27  	var err error
    28  	store, err := db.NewLevelDBStore(dbDir)
    29  	if err != nil {
    30  		return nil, err
    31  	}
    32  	stateStore := &StateStore{
    33  		dbDir:      dbDir,
    34  		store:      store,
    35  		merklePath: merklePath,
    36  	}
    37  	_, height, err := stateStore.GetCurrentBlock()
    38  	if err != nil && err != errors.ERR_DB_NOT_FOUND {
    39  		return nil, fmt.Errorf("GetCurrentBlock error %s", err)
    40  	}
    41  	err = stateStore.init(height)
    42  	if err != nil {
    43  		return nil, fmt.Errorf("init error %s", err)
    44  	}
    45  	return stateStore, nil
    46  }
    47  
    48  //NewBatch start new commit batch
    49  func (self *StateStore) NewBatch() {
    50  	self.store.NewBatch()
    51  }
    52  
    53  func (self *StateStore) init(currBlockHeight uint64) error {
    54  	treeSize, hashes, err := self.GetMerkleTree()
    55  	if err != nil && err != errors.ERR_DB_NOT_FOUND {
    56  		return err
    57  	}
    58  	if treeSize > 0 && treeSize != currBlockHeight+1 {
    59  		return fmt.Errorf("merkle tree size is inconsistent with blockheight: %d", currBlockHeight+1)
    60  	}
    61  	self.merkleHashStore, err = merkle.NewFileHashStore(self.merklePath, treeSize)
    62  	if err != nil {
    63  		return fmt.Errorf("merkle store is inconsistent with ChainStore. persistence will be disabled")
    64  	}
    65  	self.merkleTree = merkle.NewTree(treeSize, hashes, self.merkleHashStore)
    66  	return nil
    67  }
    68  
    69  //GetMerkleTree return merkle tree size an tree node
    70  func (self *StateStore) GetMerkleTree() (uint64, []common.Hash, error) {
    71  	key := self.getMerkleTreeKey()
    72  	data, err := self.store.Get(key)
    73  	if err != nil {
    74  		return 0, nil, err
    75  	}
    76  	value := bytes.NewBuffer(data)
    77  	treeSize, err := serialization.ReadUint64(value)
    78  	if err != nil {
    79  		return 0, nil, err
    80  	}
    81  	hashCount := (len(data) - 8) / common.HashLength
    82  	hashes := make([]common.Hash, 0, hashCount)
    83  	for i := 0; i < hashCount; i++ {
    84  		var hash = new(common.Hash)
    85  		err = hash.Deserialize(value)
    86  		if err != nil {
    87  			return 0, nil, err
    88  		}
    89  		hashes = append(hashes, *hash)
    90  	}
    91  	return treeSize, hashes, nil
    92  }
    93  
    94  //AddMerkleTreeRoot add a new tree root
    95  func (self *StateStore) AddMerkleTreeRoot(txRoot common.Hash) error {
    96  	key := self.getMerkleTreeKey()
    97  	self.merkleTree.AppendHash(txRoot)
    98  	err := self.merkleHashStore.Flush()
    99  	if err != nil {
   100  		return err
   101  	}
   102  	treeSize := self.merkleTree.TreeSize()
   103  	hashes := self.merkleTree.Hashes()
   104  	value := bytes.NewBuffer(make([]byte, 0, 8+len(hashes)*common.HashLength))
   105  	err = serialization.WriteUint64(value, treeSize)
   106  	if err != nil {
   107  		return err
   108  	}
   109  	for _, hash := range hashes {
   110  		err = hash.Serialize(value)
   111  		if err != nil {
   112  			return err
   113  		}
   114  	}
   115  	self.store.BatchPut(key, value.Bytes())
   116  	return nil
   117  }
   118  
   119  //GetMerkleProof return merkle proof of block
   120  func (self *StateStore) GetMerkleProof(proofHeight, rootHeight uint64) ([]common.Hash, error) {
   121  	return self.merkleTree.InclusionProof(proofHeight, rootHeight+1)
   122  }
   123  
   124  //CommitTo commit state batch to state store
   125  func (self *StateStore) CommitTo() error {
   126  	return self.store.BatchCommit()
   127  }
   128  
   129  //GetCurrentBlock return current block height and current hash in state store
   130  func (self *StateStore) GetCurrentBlock() (common.Hash, uint64, error) {
   131  	key := self.getCurrentBlockKey()
   132  	data, err := self.store.Get(key)
   133  	if err != nil {
   134  		return common.Hash{}, 0, err
   135  	}
   136  	reader := bytes.NewReader(data)
   137  	blockHash := common.Hash{}
   138  	err = blockHash.Deserialize(reader)
   139  	if err != nil {
   140  		return common.Hash{}, 0, err
   141  	}
   142  	height, err := serialization.ReadUint64(reader)
   143  	if err != nil {
   144  		return common.Hash{}, 0, err
   145  	}
   146  	return blockHash, height, nil
   147  }
   148  
   149  //SaveCurrentBlock persist current block to state store
   150  func (self *StateStore) SaveCurrentBlock(height uint64, blockHash common.Hash) error {
   151  	key := self.getCurrentBlockKey()
   152  	value := bytes.NewBuffer(nil)
   153  	blockHash.Serialize(value)
   154  	serialization.WriteUint64(value, height)
   155  	self.store.BatchPut(key, value.Bytes())
   156  	return nil
   157  }
   158  
   159  func (self *StateStore) getCurrentBlockKey() []byte {
   160  	return []byte{byte(scom.SYS_CURRENT_BLOCK)}
   161  }
   162  
   163  func (self *StateStore) GetBlockRootWithNewTxRoot(txRoot common.Hash) common.Hash {
   164  	return self.merkleTree.GetRootWithNewLeaf(txRoot)
   165  }
   166  
   167  func (self *StateStore) getMerkleTreeKey() []byte {
   168  	return []byte{byte(scom.SYS_BLOCK_MERKLE_TREE)}
   169  }
   170  
   171  //ClearAll clear all data in state store
   172  func (self *StateStore) ClearAll() error {
   173  	self.store.NewBatch()
   174  	iter := self.store.NewIterator(nil)
   175  	for iter.Next() {
   176  		self.store.BatchDelete(iter.Key())
   177  	}
   178  	iter.Release()
   179  	return self.store.BatchCommit()
   180  }
   181  
   182  //Close state store
   183  func (self *StateStore) Close() error {
   184  	return self.store.Close()
   185  }