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"
12 const utxoPreFix = "UT:"
14 func calcUtxoKey(hash *bc.Hash) []byte {
15 return []byte(utxoPreFix + hash.String())
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) {
25 data := db.Get(calcUtxoKey(&prevout))
30 var utxo storage.UtxoEntry
31 if err := proto.Unmarshal(data, &utxo); err != nil {
32 return errors.Wrap(err, "unmarshaling utxo entry")
35 view.Entries[prevout] = &utxo
38 for _, prevout := range tx.MainchainOutputIDs {
39 if view.HasUtxo(&prevout) {
43 data := db.Get(calcUtxoKey(&prevout))
45 view.Entries[prevout] = storage.NewUtxoEntry(storage.CrosschainUTXOType, 0, false)
49 var utxo storage.UtxoEntry
50 if err := proto.Unmarshal(data, &utxo); err != nil {
51 return errors.Wrap(err, "unmarshaling mainchain ouput entry")
54 view.Entries[prevout] = &utxo
61 func getUtxo(db dbm.DB, hash *bc.Hash) (*storage.UtxoEntry, error) {
62 var utxo storage.UtxoEntry
63 data := db.Get(calcUtxoKey(hash))
65 return nil, errors.New("can't find utxo in db")
67 if err := proto.Unmarshal(data, &utxo); err != nil {
68 return nil, errors.Wrap(err, "unmarshaling utxo entry")
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))
80 if (entry.Type == storage.NormalUTXOType || entry.Type == storage.VoteUTXOType) && (entry.Spent) {
81 batch.Delete(calcUtxoKey(&key))
85 b, err := proto.Marshal(entry)
87 return errors.Wrap(err, "marshaling utxo entry")
89 batch.Set(calcUtxoKey(&key), b)
94 func SaveUtxoView(batch dbm.Batch, view *state.UtxoViewpoint) error {
95 return saveUtxoView(batch, view)