good enough storage of spent txs

This commit is contained in:
Tadge Dryja 2016-01-20 01:23:47 -08:00
parent 29d0c0cc6f
commit 1f40c7214e
2 changed files with 58 additions and 6 deletions

View File

@ -83,7 +83,7 @@ func (t *TxStore) IngestTx(tx *wire.MsgTx) error {
if err != nil { if err != nil {
return err return err
} }
err = t.ExpellTx(tx) err = t.ExpellTx(tx, height)
if err != nil { if err != nil {
return err return err
} }
@ -115,7 +115,10 @@ func (t *TxStore) AbsorbTx(tx *wire.MsgTx, height int32) error {
newop.Hash = tx.TxSha() newop.Hash = tx.TxSha()
newop.Index = uint32(i) newop.Index = uint32(i)
newu.Op = newop newu.Op = newop
err := newu.SaveToDB(t.StateDB)
if err != nil {
return err
}
t.Utxos = append(t.Utxos, newu) t.Utxos = append(t.Utxos, newu)
break break
} }
@ -127,7 +130,7 @@ func (t *TxStore) AbsorbTx(tx *wire.MsgTx, height int32) error {
} }
// Expell money from wallet due to a tx // Expell money from wallet due to a tx
func (t *TxStore) ExpellTx(tx *wire.MsgTx) error { func (t *TxStore) ExpellTx(tx *wire.MsgTx, height int32) error {
if tx == nil { if tx == nil {
return fmt.Errorf("Tried to add nil tx") return fmt.Errorf("Tried to add nil tx")
} }
@ -139,7 +142,11 @@ func (t *TxStore) ExpellTx(tx *wire.MsgTx) error {
if myutxo.Op == in.PreviousOutPoint { if myutxo.Op == in.PreviousOutPoint {
hits++ hits++
loss += myutxo.Txo.Value loss += myutxo.Txo.Value
// delete from my utxo set err := t.MarkSpent(&myutxo.Op, height, tx)
if err != nil {
return err
}
// delete from my in-ram utxo set
t.Utxos = append(t.Utxos[:i], t.Utxos[i+1:]...) t.Utxos = append(t.Utxos[:i], t.Utxos[i+1:]...)
} }
} }

View File

@ -5,6 +5,8 @@ import (
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"github.com/btcsuite/btcd/wire"
"github.com/boltdb/bolt" "github.com/boltdb/bolt"
) )
@ -26,8 +28,32 @@ func (u *Utxo) SaveToDB(dbx *bolt.DB) error {
}) })
} }
func (ts *TxStore) LoadUtxos() error { func (ts *TxStore) MarkSpent(op *wire.OutPoint, 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.
return ts.StateDB.Update(func(tx *bolt.Tx) error {
old := tx.Bucket(BKTOld)
opb, err := outPointToBytes(op)
if err != nil {
return err
}
var buf bytes.Buffer
err = binary.Write(&buf, binary.BigEndian, h)
if err != nil {
return err
}
sha := stx.TxSha()
err = old.Put(opb, sha.Bytes()) // write k:v outpoint:txid
if err != nil {
return err
}
return nil
})
}
func (ts *TxStore) LoadUtxos() error {
err := ts.StateDB.View(func(tx *bolt.Tx) error { err := ts.StateDB.View(func(tx *bolt.Tx) error {
duf := tx.Bucket(BKTUtxos) duf := tx.Bucket(BKTUtxos)
if duf == nil { if duf == nil {
@ -41,7 +67,8 @@ func (ts *TxStore) LoadUtxos() error {
duf.ForEach(func(k, v []byte) error { duf.ForEach(func(k, v []byte) error {
// have to copy these here, otherwise append will crash it. // have to copy these here, otherwise append will crash it.
// not quite sure why but append does weird stuff I guess. // not quite sure why but append does weird stuff I guess.
if spent.Get(k) == nil { // if it's not in the spent bucket stx := spent.Get(k)
if stx == nil { // if it's not in the spent bucket
// create a new utxo // create a new utxo
x := make([]byte, len(k)+len(v)) x := make([]byte, len(k)+len(v))
copy(x, k) copy(x, k)
@ -52,6 +79,9 @@ func (ts *TxStore) LoadUtxos() error {
} }
// and add it to ram // and add it to ram
ts.Utxos = append(ts.Utxos, newU) ts.Utxos = append(ts.Utxos, newU)
} else {
fmt.Printf("had utxo %x but spent by tx %x...\n",
k, stx[:8])
} }
return nil return nil
}) })
@ -63,6 +93,21 @@ func (ts *TxStore) LoadUtxos() error {
return nil 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. // ToBytes turns a Utxo into some bytes.
// note that the txid is the first 36 bytes and in our use cases will be stripped // 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 // off, but is left here for other applications