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 }