move ser/des from utxodb to txstore
This commit is contained in:
parent
f231113b90
commit
e56b1993fc
203
uspv/txstore.go
203
uspv/txstore.go
@ -1,6 +1,8 @@
|
||||
package uspv
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
@ -16,10 +18,8 @@ import (
|
||||
type TxStore struct {
|
||||
OKTxids map[wire.ShaHash]int32 // known good txids and their heights
|
||||
|
||||
Utxos []*Utxo // stacks on stacks
|
||||
Sum int64 // racks on racks
|
||||
Adrs []MyAdr // endeavouring to acquire capital
|
||||
LastIdx uint32 // should equal len(Adrs)
|
||||
StateDB *bolt.DB // place to write all this down
|
||||
// this is redundant with the SPVCon param... ugly and should be taken out
|
||||
Param *chaincfg.Params // network parameters (testnet3, testnetL)
|
||||
@ -100,15 +100,6 @@ func (t *TxStore) GimmeFilter() (*bloom.Filter, error) {
|
||||
return f, nil
|
||||
}
|
||||
|
||||
// need this because before I was comparing pointers maybe?
|
||||
// so they were the same outpoint but stored in 2 places so false negative?
|
||||
func OutPointsEqual(a, b wire.OutPoint) bool {
|
||||
if !a.Hash.IsEqual(&b.Hash) {
|
||||
return false
|
||||
}
|
||||
return a.Index == b.Index
|
||||
}
|
||||
|
||||
// TxToString prints out some info about a transaction. for testing / debugging
|
||||
func TxToString(tx *wire.MsgTx) string {
|
||||
str := "\t\t\t - Tx - \n"
|
||||
@ -126,3 +117,193 @@ func TxToString(tx *wire.MsgTx) string {
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
// need this because before I was comparing pointers maybe?
|
||||
// so they were the same outpoint but stored in 2 places so false negative?
|
||||
func OutPointsEqual(a, b wire.OutPoint) bool {
|
||||
if !a.Hash.IsEqual(&b.Hash) {
|
||||
return false
|
||||
}
|
||||
return a.Index == b.Index
|
||||
}
|
||||
|
||||
/*----- serialization for tx outputs ------- */
|
||||
|
||||
// outPointToBytes turns an outpoint into 36 bytes.
|
||||
func outPointToBytes(op *wire.OutPoint) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
_, err := buf.Write(op.Hash.Bytes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// write 4 byte outpoint index within the tx to spend
|
||||
err = binary.Write(&buf, binary.BigEndian, op.Index)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// ToBytes turns a Utxo into some bytes.
|
||||
// note that the txid is the first 36 bytes and in our use cases will be stripped
|
||||
// off, but is left here for other applications
|
||||
func (u *Utxo) ToBytes() ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
// write 32 byte txid of the utxo
|
||||
_, err := buf.Write(u.Op.Hash.Bytes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// write 4 byte outpoint index within the tx to spend
|
||||
err = binary.Write(&buf, binary.BigEndian, u.Op.Index)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// write 4 byte height of utxo
|
||||
err = binary.Write(&buf, binary.BigEndian, u.AtHeight)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// write 4 byte key index of utxo
|
||||
err = binary.Write(&buf, binary.BigEndian, u.KeyIdx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// write 8 byte amount of money at the utxo
|
||||
err = binary.Write(&buf, binary.BigEndian, u.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// UtxoFromBytes turns bytes into a Utxo. Note it wants the txid and outindex
|
||||
// in the first 36 bytes, which isn't stored that way in the boldDB,
|
||||
// but can be easily appended.
|
||||
func UtxoFromBytes(b []byte) (Utxo, error) {
|
||||
var u Utxo
|
||||
if b == nil {
|
||||
return u, fmt.Errorf("nil input slice")
|
||||
}
|
||||
buf := bytes.NewBuffer(b)
|
||||
if buf.Len() < 52 { // utxos are 52 bytes
|
||||
return u, fmt.Errorf("Got %d bytes for utxo, expect 52", buf.Len())
|
||||
}
|
||||
// read 32 byte txid
|
||||
err := u.Op.Hash.SetBytes(buf.Next(32))
|
||||
if err != nil {
|
||||
return u, err
|
||||
}
|
||||
// read 4 byte outpoint index within the tx to spend
|
||||
err = binary.Read(buf, binary.BigEndian, &u.Op.Index)
|
||||
if err != nil {
|
||||
return u, err
|
||||
}
|
||||
// read 4 byte height of utxo
|
||||
err = binary.Read(buf, binary.BigEndian, &u.AtHeight)
|
||||
if err != nil {
|
||||
return u, err
|
||||
}
|
||||
// read 4 byte key index of utxo
|
||||
err = binary.Read(buf, binary.BigEndian, &u.KeyIdx)
|
||||
if err != nil {
|
||||
return u, err
|
||||
}
|
||||
// read 8 byte amount of money at the utxo
|
||||
err = binary.Read(buf, binary.BigEndian, &u.Value)
|
||||
if err != nil {
|
||||
return u, err
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// ToBytes turns an Stxo into some bytes.
|
||||
// outpoint txid, outpoint idx, height, key idx, amt, spendheight, spendtxid
|
||||
func (s *Stxo) ToBytes() ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
// write 32 byte txid of the utxo
|
||||
_, err := buf.Write(s.Op.Hash.Bytes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// write 4 byte outpoint index within the tx to spend
|
||||
err = binary.Write(&buf, binary.BigEndian, s.Op.Index)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// write 4 byte height of utxo
|
||||
err = binary.Write(&buf, binary.BigEndian, s.AtHeight)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// write 4 byte key index of utxo
|
||||
err = binary.Write(&buf, binary.BigEndian, s.KeyIdx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// write 8 byte amount of money at the utxo
|
||||
err = binary.Write(&buf, binary.BigEndian, s.Value)
|
||||
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.Bytes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// StxoFromBytes turns bytes into a Stxo.
|
||||
func StxoFromBytes(b []byte) (Stxo, error) {
|
||||
var s Stxo
|
||||
if b == nil {
|
||||
return s, fmt.Errorf("nil input slice")
|
||||
}
|
||||
buf := bytes.NewBuffer(b)
|
||||
if buf.Len() < 88 { // stxos are 88 bytes
|
||||
return s, fmt.Errorf("Got %d bytes for stxo, expect 88", buf.Len())
|
||||
}
|
||||
// read 32 byte txid
|
||||
err := s.Op.Hash.SetBytes(buf.Next(32))
|
||||
if err != nil {
|
||||
return s, err
|
||||
}
|
||||
// read 4 byte outpoint index within the tx to spend
|
||||
err = binary.Read(buf, binary.BigEndian, &s.Op.Index)
|
||||
if err != nil {
|
||||
return s, err
|
||||
}
|
||||
// read 4 byte height of utxo
|
||||
err = binary.Read(buf, binary.BigEndian, &s.AtHeight)
|
||||
if err != nil {
|
||||
return s, err
|
||||
}
|
||||
// read 4 byte key index of utxo
|
||||
err = binary.Read(buf, binary.BigEndian, &s.KeyIdx)
|
||||
if err != nil {
|
||||
return s, err
|
||||
}
|
||||
// read 8 byte amount of money at the utxo
|
||||
err = binary.Read(buf, binary.BigEndian, &s.Value)
|
||||
if err != nil {
|
||||
return s, err
|
||||
}
|
||||
// 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
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
234
uspv/utxodb.go
234
uspv/utxodb.go
@ -290,7 +290,7 @@ func (ts *TxStore) Ingest(tx *wire.MsgTx) (uint32, error) {
|
||||
duf := btx.Bucket(BKTUtxos)
|
||||
// sta := btx.Bucket(BKTState)
|
||||
old := btx.Bucket(BKTStxos)
|
||||
// txns := btx.Bucket(BKTTxns)
|
||||
txns := btx.Bucket(BKTTxns)
|
||||
|
||||
// first see if we lose utxos
|
||||
// iterate through duffel bag and look for matches
|
||||
@ -326,6 +326,14 @@ func (ts *TxStore) Ingest(tx *wire.MsgTx) (uint32, error) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// store this relevant tx
|
||||
sha := tx.TxSha()
|
||||
var buf bytes.Buffer
|
||||
tx.Serialize(&buf)
|
||||
err = txns.Put(sha.Bytes(), buf.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil // matched utxo k, won't match another
|
||||
}
|
||||
@ -343,227 +351,3 @@ func (ts *TxStore) Ingest(tx *wire.MsgTx) (uint32, error) {
|
||||
})
|
||||
return hits, err
|
||||
}
|
||||
|
||||
func (ts *TxStore) MarkSpent(ut Utxo, h int32, stx *wire.MsgTx) error {
|
||||
// we write in key = outpoint (32 hash, 4 index)
|
||||
// value = spending txid
|
||||
// if we care about the spending tx we can store that in another bucket.
|
||||
|
||||
var st Stxo
|
||||
st.Utxo = ut
|
||||
st.SpendHeight = h
|
||||
st.SpendTxid = stx.TxSha()
|
||||
|
||||
return ts.StateDB.Update(func(btx *bolt.Tx) error {
|
||||
duf := btx.Bucket(BKTUtxos)
|
||||
old := btx.Bucket(BKTStxos)
|
||||
txns := btx.Bucket(BKTTxns)
|
||||
|
||||
opb, err := outPointToBytes(&st.Op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = duf.Delete(opb) // not utxo anymore
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stxb, err := st.ToBytes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = old.Put(opb, stxb) // write k:v outpoint:stxo bytes
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// store spending tx
|
||||
sha := stx.TxSha()
|
||||
var buf bytes.Buffer
|
||||
stx.Serialize(&buf)
|
||||
txns.Put(sha.Bytes(), buf.Bytes())
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// outPointToBytes turns an outpoint into 36 bytes.
|
||||
func outPointToBytes(op *wire.OutPoint) ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
_, err := buf.Write(op.Hash.Bytes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// write 4 byte outpoint index within the tx to spend
|
||||
err = binary.Write(&buf, binary.BigEndian, op.Index)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// ToBytes turns a Utxo into some bytes.
|
||||
// note that the txid is the first 36 bytes and in our use cases will be stripped
|
||||
// off, but is left here for other applications
|
||||
func (u *Utxo) ToBytes() ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
// write 32 byte txid of the utxo
|
||||
_, err := buf.Write(u.Op.Hash.Bytes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// write 4 byte outpoint index within the tx to spend
|
||||
err = binary.Write(&buf, binary.BigEndian, u.Op.Index)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// write 4 byte height of utxo
|
||||
err = binary.Write(&buf, binary.BigEndian, u.AtHeight)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// write 4 byte key index of utxo
|
||||
err = binary.Write(&buf, binary.BigEndian, u.KeyIdx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// write 8 byte amount of money at the utxo
|
||||
err = binary.Write(&buf, binary.BigEndian, u.Value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// UtxoFromBytes turns bytes into a Utxo. Note it wants the txid and outindex
|
||||
// in the first 36 bytes, which isn't stored that way in the boldDB,
|
||||
// but can be easily appended.
|
||||
func UtxoFromBytes(b []byte) (Utxo, error) {
|
||||
var u Utxo
|
||||
if b == nil {
|
||||
return u, fmt.Errorf("nil input slice")
|
||||
}
|
||||
buf := bytes.NewBuffer(b)
|
||||
if buf.Len() < 52 { // utxos are 52 bytes
|
||||
return u, fmt.Errorf("Got %d bytes for utxo, expect 52", buf.Len())
|
||||
}
|
||||
// read 32 byte txid
|
||||
err := u.Op.Hash.SetBytes(buf.Next(32))
|
||||
if err != nil {
|
||||
return u, err
|
||||
}
|
||||
// read 4 byte outpoint index within the tx to spend
|
||||
err = binary.Read(buf, binary.BigEndian, &u.Op.Index)
|
||||
if err != nil {
|
||||
return u, err
|
||||
}
|
||||
// read 4 byte height of utxo
|
||||
err = binary.Read(buf, binary.BigEndian, &u.AtHeight)
|
||||
if err != nil {
|
||||
return u, err
|
||||
}
|
||||
// read 4 byte key index of utxo
|
||||
err = binary.Read(buf, binary.BigEndian, &u.KeyIdx)
|
||||
if err != nil {
|
||||
return u, err
|
||||
}
|
||||
// read 8 byte amount of money at the utxo
|
||||
err = binary.Read(buf, binary.BigEndian, &u.Value)
|
||||
if err != nil {
|
||||
return u, err
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
||||
// ToBytes turns an Stxo into some bytes.
|
||||
// outpoint txid, outpoint idx, height, key idx, amt, spendheight, spendtxid
|
||||
func (s *Stxo) ToBytes() ([]byte, error) {
|
||||
var buf bytes.Buffer
|
||||
// write 32 byte txid of the utxo
|
||||
_, err := buf.Write(s.Op.Hash.Bytes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// write 4 byte outpoint index within the tx to spend
|
||||
err = binary.Write(&buf, binary.BigEndian, s.Op.Index)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// write 4 byte height of utxo
|
||||
err = binary.Write(&buf, binary.BigEndian, s.AtHeight)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// write 4 byte key index of utxo
|
||||
err = binary.Write(&buf, binary.BigEndian, s.KeyIdx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// write 8 byte amount of money at the utxo
|
||||
err = binary.Write(&buf, binary.BigEndian, s.Value)
|
||||
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.Bytes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
// StxoFromBytes turns bytes into a Stxo.
|
||||
func StxoFromBytes(b []byte) (Stxo, error) {
|
||||
var s Stxo
|
||||
if b == nil {
|
||||
return s, fmt.Errorf("nil input slice")
|
||||
}
|
||||
buf := bytes.NewBuffer(b)
|
||||
if buf.Len() < 88 { // stxos are 88 bytes
|
||||
return s, fmt.Errorf("Got %d bytes for stxo, expect 88", buf.Len())
|
||||
}
|
||||
// read 32 byte txid
|
||||
err := s.Op.Hash.SetBytes(buf.Next(32))
|
||||
if err != nil {
|
||||
return s, err
|
||||
}
|
||||
// read 4 byte outpoint index within the tx to spend
|
||||
err = binary.Read(buf, binary.BigEndian, &s.Op.Index)
|
||||
if err != nil {
|
||||
return s, err
|
||||
}
|
||||
// read 4 byte height of utxo
|
||||
err = binary.Read(buf, binary.BigEndian, &s.AtHeight)
|
||||
if err != nil {
|
||||
return s, err
|
||||
}
|
||||
// read 4 byte key index of utxo
|
||||
err = binary.Read(buf, binary.BigEndian, &s.KeyIdx)
|
||||
if err != nil {
|
||||
return s, err
|
||||
}
|
||||
// read 8 byte amount of money at the utxo
|
||||
err = binary.Read(buf, binary.BigEndian, &s.Value)
|
||||
if err != nil {
|
||||
return s, err
|
||||
}
|
||||
// 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
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user