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