OSDN Git Service

edit code while reviewing the code (#255)
[bytom/vapor.git] / database / utxo_view.go
1 package database
2
3 import (
4         "github.com/golang/protobuf/proto"
5         dbm "github.com/vapor/database/leveldb"
6         "github.com/vapor/database/storage"
7         "github.com/vapor/errors"
8         "github.com/vapor/protocol/bc"
9         "github.com/vapor/protocol/state"
10 )
11
12 const utxoPreFix = "UT:"
13
14 func calcUtxoKey(hash *bc.Hash) []byte {
15         return []byte(utxoPreFix + hash.String())
16 }
17
18 func getTransactionsUtxo(db dbm.DB, view *state.UtxoViewpoint, txs []*bc.Tx) error {
19         for _, tx := range txs {
20                 for _, prevout := range tx.SpentOutputIDs {
21                         if view.HasUtxo(&prevout) {
22                                 continue
23                         }
24
25                         data := db.Get(calcUtxoKey(&prevout))
26                         if data == nil {
27                                 continue
28                         }
29
30                         var utxo storage.UtxoEntry
31                         if err := proto.Unmarshal(data, &utxo); err != nil {
32                                 return errors.Wrap(err, "unmarshaling utxo entry")
33                         }
34
35                         view.Entries[prevout] = &utxo
36                 }
37
38                 for _, prevout := range tx.MainchainOutputIDs {
39                         if view.HasUtxo(&prevout) {
40                                 continue
41                         }
42
43                         data := db.Get(calcUtxoKey(&prevout))
44                         if data == nil {
45                                 view.Entries[prevout] = storage.NewUtxoEntry(storage.CrosschainUTXOType, 0, false)
46                                 continue
47                         }
48
49                         var utxo storage.UtxoEntry
50                         if err := proto.Unmarshal(data, &utxo); err != nil {
51                                 return errors.Wrap(err, "unmarshaling mainchain ouput entry")
52                         }
53
54                         view.Entries[prevout] = &utxo
55                 }
56         }
57
58         return nil
59 }
60
61 func getUtxo(db dbm.DB, hash *bc.Hash) (*storage.UtxoEntry, error) {
62         var utxo storage.UtxoEntry
63         data := db.Get(calcUtxoKey(hash))
64         if data == nil {
65                 return nil, errors.New("can't find utxo in db")
66         }
67         if err := proto.Unmarshal(data, &utxo); err != nil {
68                 return nil, errors.Wrap(err, "unmarshaling utxo entry")
69         }
70         return &utxo, nil
71 }
72
73 func saveUtxoView(batch dbm.Batch, view *state.UtxoViewpoint) error {
74         for key, entry := range view.Entries {
75                 if entry.Type == storage.CrosschainUTXOType && !entry.Spent {
76                         batch.Delete(calcUtxoKey(&key))
77                         continue
78                 }
79
80                 if entry.Type == storage.NormalUTXOType && entry.Spent {
81                         batch.Delete(calcUtxoKey(&key))
82                         continue
83                 }
84
85                 b, err := proto.Marshal(entry)
86                 if err != nil {
87                         return errors.Wrap(err, "marshaling utxo entry")
88                 }
89                 batch.Set(calcUtxoKey(&key), b)
90         }
91         return nil
92 }
93
94 func SaveUtxoView(batch dbm.Batch, view *state.UtxoViewpoint) error {
95         return saveUtxoView(batch, view)
96 }