add getalltxs, dup checks

Start of double spend detection for mempool and reorgs
This commit is contained in:
Tadge Dryja 2016-02-05 01:59:40 -08:00
parent 25d90f5345
commit 63b5926e01
3 changed files with 77 additions and 1 deletions

View File

@ -144,11 +144,29 @@ func Shellparse(cmdslice []string) error {
}
return nil
}
if cmd == "txs" {
err = Txs(args)
if err != nil {
fmt.Printf("txs error: %s\n", err)
}
return nil
}
fmt.Printf("Command not recognized. type help for command list.\n")
return nil
}
func Txs(args []string) error {
alltx, err := SCon.TS.GetAllTxs()
if err != nil {
return err
}
for i, tx := range alltx {
fmt.Printf("tx %d %s\n", i, uspv.TxToString(tx))
}
return nil
}
// Bal prints out your score.
func Bal(args []string) error {
if SCon.TS == nil {

View File

@ -100,9 +100,40 @@ func (t *TxStore) GimmeFilter() (*bloom.Filter, error) {
return f, nil
}
// GetDoubleSpends takes a transaction and compares it with
// all transactions in the db. It returns a slice of all txids in the db
// which are double spent by the received tx.
func GetDoubleSpends(
argTx *wire.MsgTx, txs []*wire.MsgTx) ([]*wire.ShaHash, error) {
var dubs []*wire.ShaHash // slice of all double-spent txs
argTxid := argTx.TxSha()
for _, compTx := range txs {
compTxid := compTx.TxSha()
// check if entire tx is dup
if argTxid.IsEqual(&compTxid) {
return nil, fmt.Errorf("tx %s is dup", argTxid.String())
}
// not dup, iterate through inputs of argTx
for _, argIn := range argTx.TxIn {
// iterate through inputs of compTx
for _, compIn := range compTx.TxIn {
if OutPointsEqual(
argIn.PreviousOutPoint, compIn.PreviousOutPoint) {
// found double spend
dubs = append(dubs, &compTxid)
break // back to argIn loop
}
}
}
}
return dubs, nil
}
// TxToString prints out some info about a transaction. for testing / debugging
func TxToString(tx *wire.MsgTx) string {
str := "\t\t\t - Tx - \n"
str := fmt.Sprintf("\t - Tx %s\n", tx.TxSha().String())
for i, in := range tx.TxIn {
str += fmt.Sprintf("Input %d: %s\n", i, in.PreviousOutPoint.String())
str += fmt.Sprintf("SigScript for input %d: %x\n", i, in.SignatureScript)

View File

@ -248,6 +248,33 @@ func (ts *TxStore) GetTx(txid *wire.ShaHash) (*wire.MsgTx, error) {
return rtx, nil
}
// GetTx takes a txid and returns the transaction. If we have it.
func (ts *TxStore) GetAllTxs() ([]*wire.MsgTx, error) {
var rtxs []*wire.MsgTx
err := ts.StateDB.View(func(btx *bolt.Tx) error {
txns := btx.Bucket(BKTTxns)
if txns == nil {
return fmt.Errorf("no transactions in db")
}
return txns.ForEach(func(k, v []byte) error {
tx := wire.NewMsgTx()
buf := bytes.NewBuffer(v)
err := tx.Deserialize(buf)
if err != nil {
return err
}
rtxs = append(rtxs, tx)
return nil
})
})
if err != nil {
return nil, err
}
return rtxs, nil
}
// GetPendingInv returns an inv message containing all txs known to the
// db which are at height 0 (not known to be confirmed).
// This can be useful on startup or to rebroadcast unconfirmed txs.