From 851d3533e587d49fdc7a6dc5a81b656a2971f55d Mon Sep 17 00:00:00 2001 From: Tadge Dryja Date: Fri, 22 Jan 2016 17:15:56 -0800 Subject: [PATCH] deals with incoming blocks and txs gets stuck on reorgs though, until program is restarted --- uspv/txstore.go | 43 ++++++++++++++++++++++++++++++++----------- uspv/utxodb.go | 22 ++++++++++++---------- 2 files changed, 44 insertions(+), 21 deletions(-) diff --git a/uspv/txstore.go b/uspv/txstore.go index d1aeb45f..afe3561e 100644 --- a/uspv/txstore.go +++ b/uspv/txstore.go @@ -19,7 +19,7 @@ import ( type TxStore struct { OKTxids map[wire.ShaHash]int32 // known good txids and their heights - Utxos []Utxo // stacks on stacks + Utxos []*Utxo // stacks on stacks Sum int64 // racks on racks Adrs []MyAdr // endeavouring to acquire capital LastIdx uint32 // should equal len(Adrs) @@ -118,16 +118,40 @@ func (t *TxStore) AbsorbTx(tx *wire.MsgTx, height int32) error { if tx == nil { return fmt.Errorf("Tried to add nil tx") } - var hits uint32 - var acq int64 + newTxid := tx.TxSha() + var hits uint32 // how many outputs of this tx are ours + var acq int64 // total acquirement from this tx // check if any of the tx's outputs match my adrs for i, out := range tx.TxOut { // in each output of tx + dup := false // start by assuming its new until found duplicate + newOp := wire.NewOutPoint(&newTxid, uint32(i)) + // first look for dupes -- already known outpoints. + // if we find a dupe here overwrite it to the DB. + for _, u := range t.Utxos { + dup = OutPointsEqual(*newOp, u.Op) // is this outpoint known? + if dup { // found dupe + fmt.Printf(" %s is dupe\t", newOp.String()) + u.AtHeight = height // ONLY difference is height + // save modified utxo to db, overwriting old one + err := u.SaveToDB(t.StateDB) + if err != nil { + return err + } + break // out of the t.Utxo range loop + } + } + if dup { + // if we found the outpoint to be a dup above, don't add it again + // when it matches an address, just go to the next outpoint + continue + } for _, a := range t.Adrs { // compare to each adr we have // check for full script to eliminate false positives aPKscript, err := txscript.PayToAddrScript(a.PkhAdr) if err != nil { return err } + // already checked for dupes, this must be a new outpoint if bytes.Equal(out.PkScript, aPKscript) { // hit var newu Utxo @@ -139,17 +163,14 @@ func (t *TxStore) AbsorbTx(tx *wire.MsgTx, height int32) error { newop.Hash = tx.TxSha() newop.Index = uint32(i) newu.Op = newop - dupe, err := newu.SaveToDB(t.StateDB) + err = newu.SaveToDB(t.StateDB) if err != nil { return err } - if !dupe { // only save to DB if new txid - t.Utxos = append(t.Utxos, newu) - acq += out.Value - hits++ - } else { - fmt.Printf("...dupe ") - } + + acq += out.Value + hits++ + t.Utxos = append(t.Utxos, &newu) // always add new utxo break } } diff --git a/uspv/utxodb.go b/uspv/utxodb.go index 4e701cfc..aee9d9ff 100644 --- a/uspv/utxodb.go +++ b/uspv/utxodb.go @@ -100,26 +100,28 @@ func (ts *TxStore) PopulateAdrs(lastKey uint32) error { return nil } -// SaveToDB write a utxo to disk, and returns true if it's a dupe -func (u *Utxo) SaveToDB(dbx *bolt.DB) (bool, error) { - var dupe bool +// SaveToDB write a utxo to disk, overwriting an old utxo of the same outpoint +func (u *Utxo) SaveToDB(dbx *bolt.DB) error { + err := dbx.Update(func(tx *bolt.Tx) error { duf := tx.Bucket(BKTUtxos) b, err := u.ToBytes() if err != nil { return err } - if duf.Get(b[:36]) != nil { // already have tx - dupe = true - return nil - } + // don't check for dupes here, check in AbsorbTx(). here overwrite. + // if duf.Get(b[:36]) != nil { // already have tx + // dupe = true + // return nil + // } + // key : val is txid:everything else return duf.Put(b[:36], b[36:]) }) if err != nil { - return false, err + return err } - return dupe, nil + return nil } func (ts *TxStore) MarkSpent(op *wire.OutPoint, h int32, stx *wire.MsgTx) error { @@ -196,7 +198,7 @@ func (ts *TxStore) LoadFromDB() error { return err } // and add it to ram - ts.Utxos = append(ts.Utxos, newU) + ts.Utxos = append(ts.Utxos, &newU) ts.Sum += newU.Value } else { fmt.Printf("had utxo %x but spent by tx %x...\n",