forked from OpenBazaar/spvwallet
-
Notifications
You must be signed in to change notification settings - Fork 0
/
txns.go
152 lines (144 loc) · 3.31 KB
/
txns.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
141
142
143
144
145
146
147
148
149
150
151
152
package db
import (
"bytes"
"database/sql"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
"github.com/scryinfo/wallet-interface"
"sync"
"time"
)
type TxnsDB struct {
db *sql.DB
lock *sync.RWMutex
}
func (t *TxnsDB) Put(txn []byte, txid string, value, height int, timestamp time.Time, watchOnly bool) error {
t.lock.Lock()
defer t.lock.Unlock()
tx, err := t.db.Begin()
if err != nil {
return err
}
stmt, err := tx.Prepare("insert or replace into txns(txid, value, height, timestamp, watchOnly, tx) values(?,?,?,?,?,?)")
defer stmt.Close()
if err != nil {
tx.Rollback()
return err
}
watchOnlyInt := 0
if watchOnly {
watchOnlyInt = 1
}
_, err = stmt.Exec(txid, value, height, int(timestamp.Unix()), watchOnlyInt, txn)
if err != nil {
tx.Rollback()
return err
}
tx.Commit()
return nil
}
func (t *TxnsDB) Get(txid chainhash.Hash) (wallet.Txn, error) {
t.lock.RLock()
defer t.lock.RUnlock()
var txn wallet.Txn
stmt, err := t.db.Prepare("select tx, value, height, timestamp, watchOnly from txns where txid=?")
if err != nil {
return txn, err
}
defer stmt.Close()
var ret []byte
var value int
var height int
var timestamp int
var watchOnlyInt int
err = stmt.QueryRow(txid.String()).Scan(&ret, &value, &height, ×tamp, &watchOnlyInt)
if err != nil {
return txn, err
}
r := bytes.NewReader(ret)
msgTx := wire.NewMsgTx(1)
msgTx.BtcDecode(r, 1, wire.WitnessEncoding)
watchOnly := false
if watchOnlyInt > 0 {
watchOnly = true
}
txn = wallet.Txn{
Txid: msgTx.TxHash().String(),
Value: int64(value),
Height: int32(height),
Timestamp: time.Unix(int64(timestamp), 0),
WatchOnly: watchOnly,
Bytes: ret,
}
return txn, nil
}
func (t *TxnsDB) GetAll(includeWatchOnly bool) ([]wallet.Txn, error) {
t.lock.RLock()
defer t.lock.RUnlock()
var ret []wallet.Txn
stm := "select tx, value, height, timestamp, watchOnly from txns"
rows, err := t.db.Query(stm)
if err != nil {
return ret, err
}
defer rows.Close()
for rows.Next() {
var tx []byte
var value int
var height int
var timestamp int
var watchOnlyInt int
if err := rows.Scan(&tx, &value, &height, ×tamp, &watchOnlyInt); err != nil {
continue
}
r := bytes.NewReader(tx)
msgTx := wire.NewMsgTx(1)
msgTx.BtcDecode(r, 1, wire.WitnessEncoding)
watchOnly := false
if watchOnlyInt > 0 {
if !includeWatchOnly {
continue
}
watchOnly = true
}
txn := wallet.Txn{
Txid: msgTx.TxHash().String(),
Value: int64(value),
Height: int32(height),
Timestamp: time.Unix(int64(timestamp), 0),
WatchOnly: watchOnly,
Bytes: tx,
}
ret = append(ret, txn)
}
return ret, nil
}
func (t *TxnsDB) Delete(txid *chainhash.Hash) error {
t.lock.Lock()
defer t.lock.Unlock()
_, err := t.db.Exec("delete from txns where txid=?", txid.String())
if err != nil {
return err
}
return nil
}
func (t *TxnsDB) UpdateHeight(txid chainhash.Hash, height int, timestamp time.Time) error {
t.lock.Lock()
defer t.lock.Unlock()
tx, err := t.db.Begin()
if err != nil {
return err
}
stmt, err := tx.Prepare("update txns set height=?, timestamp=? where txid=?")
if err != nil {
return err
}
defer stmt.Close()
_, err = stmt.Exec(height, int(timestamp.Unix()), txid.String())
if err != nil {
tx.Rollback()
return err
}
tx.Commit()
return nil
}