OSDN Git Service

Merge pull request #375 from Bytom/dev
[bytom/bytom-spv.git] / blockchain / txdb / utxo_view.go
1 package txdb
2
3 import (
4         dbm "github.com/tendermint/tmlibs/db"
5
6         "github.com/bytom/blockchain/txdb/storage"
7         "github.com/bytom/errors"
8         "github.com/bytom/protocol/bc"
9         "github.com/bytom/protocol/state"
10         "github.com/golang/protobuf/proto"
11 )
12
13 const utxoPreFix = "UT:"
14
15 func calcUtxoKey(hash *bc.Hash) []byte {
16         return []byte(utxoPreFix + hash.String())
17 }
18
19 func getTransactionsUtxo(db dbm.DB, view *state.UtxoViewpoint, txs []*bc.Tx) error {
20         for _, tx := range txs {
21                 for _, prevout := range tx.SpentOutputIDs {
22                         if view.HasUtxo(&prevout) {
23                                 continue
24                         }
25
26                         data := db.Get(calcUtxoKey(&prevout))
27                         if data == nil {
28                                 continue
29                         }
30
31                         var utxo storage.UtxoEntry
32                         if err := proto.Unmarshal(data, &utxo); err != nil {
33                                 return errors.Wrap(err, "unmarshaling utxo entry")
34                         }
35
36                         view.Entries[prevout] = &utxo
37                 }
38         }
39
40         return nil
41 }
42
43 func getUtxo(db dbm.DB, hash *bc.Hash) (*storage.UtxoEntry, error) {
44         var utxo storage.UtxoEntry
45         data := db.Get(calcUtxoKey(hash))
46         if data == nil {
47                 return nil, errors.New("can't find utxo in db")
48         }
49         if err := proto.Unmarshal(data, &utxo); err != nil {
50                 return nil, errors.Wrap(err, "unmarshaling utxo entry")
51         }
52         return &utxo, nil
53 }
54
55 func saveUtxoView(batch dbm.Batch, view *state.UtxoViewpoint) error {
56         for key, entry := range view.Entries {
57                 if entry.Spent && !entry.IsCoinBase {
58                         batch.Delete(calcUtxoKey(&key))
59                         continue
60                 }
61
62                 b, err := proto.Marshal(entry)
63                 if err != nil {
64                         return errors.Wrap(err, "marshaling utxo entry")
65                 }
66                 batch.Set(calcUtxoKey(&key), b)
67         }
68         return nil
69 }
70
71 func SaveUtxoView(batch dbm.Batch, view *state.UtxoViewpoint) error {
72         return saveUtxoView(batch, view)
73 }