OSDN Git Service

Utxo storage (#196)
[bytom/bytom.git] / blockchain / txdb / mainchain.go
1 package txdb
2
3 import (
4         "bytes"
5
6         "github.com/golang/protobuf/proto"
7         dbm "github.com/tendermint/tmlibs/db"
8
9         "github.com/bytom/blockchain/txdb/storage"
10         "github.com/bytom/errors"
11         "github.com/bytom/protocol/bc"
12 )
13
14 const mainchainPreFix = "MC:"
15
16 func calcMainchainKey(hash *bc.Hash) []byte {
17         return []byte(mainchainPreFix + hash.String())
18 }
19
20 // DecodeMainchain decodes a Mainchain from bytes
21 func DecodeMainchain(data []byte) (map[uint64]*bc.Hash, error) {
22         var mainchainList storage.Mainchain
23         if err := proto.Unmarshal(data, &mainchainList); err != nil {
24                 return nil, errors.Wrap(err, "unmarshaling Mainchain proto")
25         }
26
27         mainchain := make(map[uint64]*bc.Hash)
28         for i, rawHash := range mainchainList.Hashs {
29                 var b32 [32]byte
30                 copy(b32[:], rawHash.Key)
31                 hash := bc.NewHash(b32)
32                 mainchain[uint64(i+1)] = &hash
33         }
34
35         return mainchain, nil
36 }
37
38 func saveMainchain(batch dbm.Batch, mainchain map[uint64]*bc.Hash, hash *bc.Hash) error {
39         var mainchainList storage.Mainchain
40         for i := 1; i <= len(mainchain); i++ {
41                 rawHash := &storage.Mainchain_Hash{Key: mainchain[uint64(i)].Bytes()}
42                 mainchainList.Hashs = append(mainchainList.Hashs, rawHash)
43         }
44
45         b, err := proto.Marshal(&mainchainList)
46         if err != nil {
47                 return errors.Wrap(err, "marshaling Mainchain")
48         }
49
50         batch.Set(calcMainchainKey(hash), b)
51         return nil
52 }
53
54 func getMainchain(db dbm.DB, hash *bc.Hash) (map[uint64]*bc.Hash, error) {
55         data := db.Get(calcMainchainKey(hash))
56         if data == nil {
57                 return nil, errors.New("no this Mainchain")
58         }
59
60         mainchain, err := DecodeMainchain(data)
61         if err != nil {
62                 return nil, errors.Wrap(err, "decoding Mainchain")
63         }
64         return mainchain, nil
65 }
66
67 func cleanMainchainDB(db dbm.DB, hash *bc.Hash) {
68         keepKey := calcMainchainKey(hash)
69
70         iter := db.IteratorPrefix([]byte(mainchainPreFix))
71         defer iter.Release()
72         for iter.Next() {
73                 if key := iter.Key(); !bytes.Equal(key, keepKey) {
74                         db.Delete(key)
75                 }
76         }
77         db.SetSync(nil, nil)
78 }