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