-
Notifications
You must be signed in to change notification settings - Fork 126
/
badger_snapshot.go
140 lines (126 loc) · 3.11 KB
/
badger_snapshot.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package storage
import (
"bytes"
"encoding/hex"
"fmt"
"github.com/MixinNetwork/mixin/common"
"github.com/MixinNetwork/mixin/crypto"
"github.com/dgraph-io/badger"
"github.com/vmihailenco/msgpack"
)
func (s *BadgerStore) ReadUTXO(hash crypto.Hash, index int) (*common.UTXO, error) {
txn := s.snapshotsDB.NewTransaction(false)
defer txn.Discard()
key := graphUtxoKey(hash, index)
item, err := txn.Get(key)
if err == badger.ErrKeyNotFound {
return nil, nil
}
if err != nil {
return nil, err
}
ival, err := item.ValueCopy(nil)
if err != nil {
return nil, err
}
var out common.UTXO
err = msgpack.Unmarshal(ival, &out)
return &out, err
}
func readDepositInput(txn *badger.Txn, deposit *common.DepositData) ([]byte, error) {
key := graphDepositKey(deposit)
item, err := txn.Get(key)
if err != nil {
return nil, err
}
return item.ValueCopy(nil)
}
func (s *BadgerStore) CheckDepositInput(deposit *common.DepositData, tx crypto.Hash) error {
txn := s.snapshotsDB.NewTransaction(false)
defer txn.Discard()
ival, err := readDepositInput(txn, deposit)
if err == badger.ErrKeyNotFound {
return nil
} else if err != nil {
return err
}
if bytes.Compare(ival, tx[:]) == 0 {
return nil
}
return fmt.Errorf("invalid lock %s %s", hex.EncodeToString(ival), hex.EncodeToString(tx[:]))
}
func (s *BadgerStore) LockDepositInput(deposit *common.DepositData, tx crypto.Hash, fork bool) error {
return s.snapshotsDB.Update(func(txn *badger.Txn) error {
key := graphDepositKey(deposit)
ival, err := readDepositInput(txn, deposit)
save := func() error {
return txn.Set(key, tx[:])
}
if err == badger.ErrKeyNotFound {
return save()
}
if err != nil {
return err
}
if bytes.Compare(ival, tx[:]) != 0 {
if !fork {
return fmt.Errorf("deposit locked for transaction %s", hex.EncodeToString(ival))
}
var hash crypto.Hash
copy(hash[:], ival)
err := pruneTransaction(txn, hash)
if err != nil {
return err
}
}
return save()
})
}
func (s *BadgerStore) LockUTXO(hash crypto.Hash, index int, tx crypto.Hash, fork bool) (*common.UTXO, error) {
var utxo *common.UTXO
err := s.snapshotsDB.Update(func(txn *badger.Txn) error {
key := graphUtxoKey(hash, index)
item, err := txn.Get(key)
if err == badger.ErrKeyNotFound {
return nil
}
if err != nil {
return err
}
ival, err := item.ValueCopy(nil)
if err != nil {
return err
}
var out common.UTXOWithLock
err = msgpack.Unmarshal(ival, &out)
if err != nil {
return err
}
if out.LockHash.HasValue() && out.LockHash != tx {
if !fork {
return fmt.Errorf("utxo locked for transaction %s", out.LockHash)
}
err := pruneTransaction(txn, out.LockHash)
if err != nil {
return err
}
}
out.LockHash = tx
err = txn.Set(key, common.MsgpackMarshalPanic(out))
utxo = &out.UTXO
return err
})
return utxo, err
}
func (s *BadgerStore) CheckGhost(key crypto.Key) (bool, error) {
txn := s.snapshotsDB.NewTransaction(false)
defer txn.Discard()
_, err := txn.Get(graphGhostKey(key))
if err == badger.ErrKeyNotFound {
return false, nil
}
if err != nil {
return false, err
}
return true, nil
}