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 }