package txdb
import (
- "encoding/json"
"fmt"
"github.com/golang/protobuf/proto"
- . "github.com/tendermint/tmlibs/common"
dbm "github.com/tendermint/tmlibs/db"
"github.com/bytom/blockchain/txdb/internal/storage"
"github.com/bytom/protocol/bc"
)
-var latestMainChainStatus = []byte("latestMainChainStatus")
-
-type MainchainStatusJSON struct {
- Height uint64
- Hash *bc.Hash
-}
-
-func (bsj MainchainStatusJSON) Save(db dbm.DB) {
- bytes, err := json.Marshal(bsj)
- if err != nil {
- PanicSanity(Fmt("Could not marshal state bytes: %v", err))
- }
- db.SetSync(latestMainChainStatus, bytes)
-}
-
-func LoadMainchainStatusJSON(db dbm.DB) MainchainStatusJSON {
- bytes := db.Get(latestMainChainStatus)
- if bytes == nil {
- return MainchainStatusJSON{Height: 0}
- }
-
- bsj := MainchainStatusJSON{}
- if err := json.Unmarshal(bytes, &bsj); err != nil {
- PanicCrisis(Fmt("Could not unmarshal bytes: %X", bytes))
- }
- return bsj
-}
-
func calcMainchainKey(hash *bc.Hash) []byte {
return []byte(fmt.Sprintf("MC:%v", hash.String()))
}
return mainchain, nil
}
-func saveMainchain(db dbm.DB, mainchain map[uint64]*bc.Hash, height uint64, hash *bc.Hash) error {
+func saveMainchain(db dbm.DB, mainchain map[uint64]*bc.Hash, hash *bc.Hash) error {
var mainchainList storage.Mainchain
for i := 0; i < len(mainchain); i++ {
rawHash := &storage.Mainchain_Hash{Key: mainchain[uint64(i)].Bytes()}
return errors.Wrap(err, "marshaling Mainchain")
}
- // set new Mainchain.
db.Set(calcMainchainKey(hash), b)
- MainchainStatusJSON{Height: height, Hash: hash}.Save(db)
db.SetSync(nil, nil)
-
- //TODO: delete old Mainchain.
- return errors.Wrap(err, "deleting old Mainchains")
+ return nil
}
-func getMainchain(db dbm.DB) (map[uint64]*bc.Hash, MainchainStatusJSON, error) {
- mainchainStatus := LoadMainchainStatusJSON(db)
- data := db.Get(calcMainchainKey(mainchainStatus.Hash))
+func getMainchain(db dbm.DB, hash *bc.Hash) (map[uint64]*bc.Hash, error) {
+ data := db.Get(calcMainchainKey(hash))
if data == nil {
- return nil, mainchainStatus, errors.New("no this Mainchain.")
+ return nil, errors.New("no this Mainchain.")
}
mainchain, err := DecodeMainchain(data)
if err != nil {
- return nil, mainchainStatus, errors.Wrap(err, "decoding Mainchain")
+ return nil, errors.Wrap(err, "decoding Mainchain")
}
- return mainchain, mainchainStatus, nil
+ return mainchain, nil
}
package txdb
import (
- "encoding/json"
"fmt"
"github.com/golang/protobuf/proto"
- . "github.com/tendermint/tmlibs/common"
dbm "github.com/tendermint/tmlibs/db"
"github.com/bytom/blockchain/txdb/internal/storage"
"github.com/bytom/protocol/state"
)
-var latestSnapshotStatus = []byte("latestSnapshotStatus")
-
-type SnapshotStatusJSON struct {
- Height uint64
- Hash *bc.Hash
-}
-
-func (bsj SnapshotStatusJSON) Save(db dbm.DB) {
- bytes, err := json.Marshal(bsj)
- if err != nil {
- PanicSanity(Fmt("Could not marshal state bytes: %v", err))
- }
- db.SetSync(latestSnapshotStatus, bytes)
-}
-
-func LoadSnapshotStatusJSON(db dbm.DB) SnapshotStatusJSON {
- bytes := db.Get(latestSnapshotStatus)
- if bytes == nil {
- return SnapshotStatusJSON{Height: 0}
- }
-
- bsj := SnapshotStatusJSON{}
- if err := json.Unmarshal(bytes, &bsj); err != nil {
- PanicCrisis(Fmt("Could not unmarshal bytes: %X", bytes))
- }
- return bsj
-}
-
func calcSnapshotKey(hash *bc.Hash) []byte {
return []byte(fmt.Sprintf("S:%v", hash.String()))
}
}, nil
}
-func saveSnapshot(db dbm.DB, snapshot *state.Snapshot, height uint64, hash *bc.Hash) error {
+func saveSnapshot(db dbm.DB, snapshot *state.Snapshot, hash *bc.Hash) error {
var storedSnapshot storage.Snapshot
err := patricia.Walk(snapshot.Tree, func(key []byte) error {
n := &storage.Snapshot_StateTreeNode{Key: key}
storedSnapshot.Nonces = make([]*storage.Snapshot_Nonce, 0, len(snapshot.Nonces))
for k, v := range snapshot.Nonces {
- hash := k
storedSnapshot.Nonces = append(storedSnapshot.Nonces, &storage.Snapshot_Nonce{
- Hash: hash.Bytes(), // TODO(bobg): now that hash is a protobuf, use it directly in the snapshot protobuf?
+ Hash: k.Bytes(),
ExpiryMs: v,
})
}
return errors.Wrap(err, "marshaling state snapshot")
}
- // set new snapshot.
db.Set(calcSnapshotKey(hash), b)
- SnapshotStatusJSON{Height: height, Hash: hash}.Save(db)
db.SetSync(nil, nil)
-
- //TODO: delete old snapshot.
- return errors.Wrap(err, "deleting old snapshots")
+ return nil
}
-func getSnapshot(db dbm.DB) (*state.Snapshot, SnapshotStatusJSON, error) {
- snapshotStatus := LoadSnapshotStatusJSON(db)
- data := db.Get(calcSnapshotKey(snapshotStatus.Hash))
+func getSnapshot(db dbm.DB, hash *bc.Hash) (*state.Snapshot, error) {
+ data := db.Get(calcSnapshotKey(hash))
if data == nil {
- return nil, snapshotStatus, errors.New("no this snapshot.")
+ return nil, errors.New("no this snapshot.")
}
snapshot, err := DecodeSnapshot(data)
if err != nil {
- return nil, snapshotStatus, errors.Wrap(err, "decoding snapshot")
+ return nil, errors.Wrap(err, "decoding snapshot")
}
- return snapshot, snapshotStatus, nil
+ return snapshot, nil
}
return loadBlockStoreStateJSON(s.db)
}
-func (s *Store) GetMainchain() (map[uint64]*bc.Hash, MainchainStatusJSON, error) {
- return getMainchain(s.db)
+func (s *Store) GetMainchain(hash *bc.Hash) (map[uint64]*bc.Hash, error) {
+ return getMainchain(s.db, hash)
}
-func (s *Store) GetRawBlock(hash *bc.Hash) ([]byte, error) {
- bytez := s.db.Get(calcBlockKey(hash))
- if bytez == nil {
- return nil, errors.New("querying blocks from the db null")
- }
- return bytez, nil
-}
-
-func (s *Store) GetSnapshot() (*state.Snapshot, SnapshotStatusJSON, error) {
- return getSnapshot(s.db)
+func (s *Store) GetSnapshot(hash *bc.Hash) (*state.Snapshot, error) {
+ return getSnapshot(s.db, hash)
}
// SaveBlock persists a new block in the database.
return nil
}
-func (s *Store) SaveMainchain(mainchain map[uint64]*bc.Hash, height uint64, hash *bc.Hash) error {
- err := saveMainchain(s.db, mainchain, height, hash)
+func (s *Store) SaveMainchain(mainchain map[uint64]*bc.Hash, hash *bc.Hash) error {
+ err := saveMainchain(s.db, mainchain, hash)
return errors.Wrap(err, "saving mainchain")
}
// SaveSnapshot saves a state snapshot to the database.
-func (s *Store) SaveSnapshot(snapshot *state.Snapshot, height uint64, hash *bc.Hash) error {
- err := saveSnapshot(s.db, snapshot, height, hash)
+func (s *Store) SaveSnapshot(snapshot *state.Snapshot, hash *bc.Hash) error {
+ err := saveSnapshot(s.db, snapshot, hash)
return errors.Wrap(err, "saving state tree")
}
func (s *Store) SaveStoreStatus(height uint64, hash *bc.Hash) {
BlockStoreStateJSON{Height: height, Hash: hash}.Save(s.db)
+ //TODO: clean the old snapshot && mainchain
}
}
blockHash := block.Hash()
- if err := c.store.SaveSnapshot(newSnapshot, block.Height, &blockHash); err != nil {
+ if err := c.store.SaveSnapshot(newSnapshot, &blockHash); err != nil {
return err
}
c.state.mainChain[block.Height] = &blockHash
- if err := c.store.SaveMainchain(c.state.mainChain, block.Height, &blockHash); err != nil {
+ if err := c.store.SaveMainchain(c.state.mainChain, &blockHash); err != nil {
delete(c.state.mainChain, block.Height)
return err
}
}
blockHash := block.Hash()
- if err := c.store.SaveSnapshot(newSnapshot, block.Height, &blockHash); err != nil {
+ if err := c.store.SaveSnapshot(newSnapshot, &blockHash); err != nil {
return err
}
for _, attachBlock := range attachBlocks {
c.orphanManage.Delete(&attachBlockHash)
}
c.state.mainChain[block.Height] = &blockHash
- if err := c.store.SaveMainchain(c.state.mainChain, block.Height, &blockHash); err != nil {
+ if err := c.store.SaveMainchain(c.state.mainChain, &blockHash); err != nil {
delete(c.state.mainChain, block.Height)
return err
}
BlockExist(*bc.Hash) bool
GetBlock(*bc.Hash) (*legacy.Block, error)
- GetMainchain() (map[uint64]*bc.Hash, txdb.MainchainStatusJSON, error)
- GetRawBlock(*bc.Hash) ([]byte, error)
- GetSnapshot() (*state.Snapshot, txdb.SnapshotStatusJSON, error)
+ GetMainchain(*bc.Hash) (map[uint64]*bc.Hash, error)
+ GetSnapshot(*bc.Hash) (*state.Snapshot, error)
GetStoreStatus() txdb.BlockStoreStateJSON
SaveBlock(*legacy.Block) error
- SaveMainchain(map[uint64]*bc.Hash, uint64, *bc.Hash) error
- SaveSnapshot(*state.Snapshot, uint64, *bc.Hash) error
+ SaveMainchain(map[uint64]*bc.Hash, *bc.Hash) error
+ SaveSnapshot(*state.Snapshot, *bc.Hash) error
SaveStoreStatus(uint64, *bc.Hash)
}
//TODO: snapshot, mainChain version check
c.state.hash = storeStatus.Hash
c.state.block, _ = store.GetBlock(storeStatus.Hash)
- c.state.snapshot, _, _ = store.GetSnapshot()
- c.state.mainChain, _, _ = store.GetMainchain()
+ c.state.snapshot, _ = store.GetSnapshot(storeStatus.Hash)
+ c.state.mainChain, _ = store.GetMainchain(storeStatus.Hash)
}
return c, nil
}