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

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