forked from mit-dci/lit
-
Notifications
You must be signed in to change notification settings - Fork 0
/
wallit.go
164 lines (139 loc) · 4.09 KB
/
wallit.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
153
154
155
156
157
158
159
160
161
162
163
164
package wallit
import (
"bytes"
"encoding/binary"
"fmt"
"log"
"sync"
"github.com/adiabat/btcd/blockchain"
"github.com/adiabat/btcd/chaincfg/chainhash"
"github.com/adiabat/btcd/wire"
"github.com/adiabat/btcutil"
"github.com/adiabat/btcutil/hdkeychain"
"github.com/boltdb/bolt"
"github.com/mit-dci/lit/coinparam"
"github.com/mit-dci/lit/lnutil"
"github.com/mit-dci/lit/portxo"
"github.com/mit-dci/lit/uspv"
)
// The Wallit is lit's main wallet struct. It's got the root key, the dbs, and
// contains the SPVhooks into the network.
type Wallit struct {
// could get rid of adr slice, it's just an in-ram cache...
StateDB *bolt.DB // place to write all this down
// Set of frozen utxos not to use... they point to the tx using em
FreezeSet map[wire.OutPoint]*FrozenTx
FreezeMutex sync.Mutex
// OPEventChan sends events to the LN wallet.
// Gets initialized and activates when called by qln
OPEventChan chan lnutil.OutPointEvent
// Params live here...
Param *coinparam.Params // network parameters (testnet3, segnet, etc)
// Hook is the connection to a blockchain.
// imports the uspv interface. Could put that somewhere else.
// like an interfaces library, ... lnutil?
Hook uspv.ChainHook
// current fee per byte
FeeRate int64
// From here, comes everything. It's a secret to everybody.
rootPrivKey *hdkeychain.ExtendedKey
}
type FrozenTx struct {
Ins []*portxo.PorTxo
Outs []*wire.TxOut
ChangeOut *wire.TxOut
Nlock uint32
Txid chainhash.Hash
}
// Stxo is a utxo that has moved on.
type Stxo struct {
portxo.PorTxo // when it used to be a utxo
SpendHeight int32 // height at which it met its demise
SpendTxid chainhash.Hash // the tx that consumed it
}
// TxToString prints out some info about a transaction. for testing / debugging
func TxToString(tx *wire.MsgTx) string {
utx := btcutil.NewTx(tx)
str := fmt.Sprintf("size %d vsize %d wsize %d locktime %d wit: %t txid %s\n",
tx.SerializeSizeStripped(), blockchain.GetTxVirtualSize(utx),
tx.SerializeSize(), tx.LockTime, tx.HasWitness(), tx.TxHash().String())
for i, in := range tx.TxIn {
str += fmt.Sprintf("Input %d spends %s seq %d\n",
i, in.PreviousOutPoint.String(), in.Sequence)
str += fmt.Sprintf("\tSigScript: %x\n", in.SignatureScript)
for j, wit := range in.Witness {
str += fmt.Sprintf("\twitness %d: %x\n", j, wit)
}
}
for i, out := range tx.TxOut {
if out != nil {
str += fmt.Sprintf("output %d script: %x amt: %d\n",
i, out.PkScript, out.Value)
} else {
str += fmt.Sprintf("output %d nil (WARNING)\n", i)
}
}
return str
}
/*----- serialization for stxos ------- */
/* Stxo serialization:
bytelength desc at offset
53 portxo 0
4 sheight 53
32 stxid 57
end len 89
*/
// ToBytes turns an Stxo into some bytes.
// prevUtxo serialization, then spendheight [4], spendtxid [32]
func (s *Stxo) ToBytes() ([]byte, error) {
var buf bytes.Buffer
// serialize the utxo part
uBytes, err := s.PorTxo.Bytes()
if err != nil {
return nil, err
}
// write that into the buffer
_, err = buf.Write(uBytes)
if err != nil {
return nil, err
}
// write 4 byte height where the txo was spent
err = binary.Write(&buf, binary.BigEndian, s.SpendHeight)
if err != nil {
return nil, err
}
// write 32 byte txid of the spending transaction
_, err = buf.Write(s.SpendTxid.CloneBytes())
if err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// StxoFromBytes turns bytes into a Stxo.
// it's a portxo with a spendHeight and spendTxid at the end.
func StxoFromBytes(b []byte) (Stxo, error) {
var s Stxo
l := len(b)
if l < 96 {
return s, fmt.Errorf("Got %d bytes for stxo, expect a bunch", len(b))
}
// last 36 bytes are height & spend txid.
u, err := portxo.PorTxoFromBytes(b[:l-36])
if err != nil {
log.Printf(" eof? ")
return s, err
}
buf := bytes.NewBuffer(b[l-36:])
// read 4 byte spend height
err = binary.Read(buf, binary.BigEndian, &s.SpendHeight)
if err != nil {
return s, err
}
// read 32 byte txid
err = s.SpendTxid.SetBytes(buf.Next(32))
if err != nil {
return s, err
}
s.PorTxo = *u // assign the utxo
return s, nil
}