From a175e098fa7f6d67cd9b9f822b3c0753d53f63ad Mon Sep 17 00:00:00 2001 From: Tadge Dryja Date: Wed, 17 Feb 2016 23:16:17 -0800 Subject: [PATCH] remove waitgroups from ingest block It doesn't work; can ingest out of order within a block, so if a block has gain then loss, you might read it as loss then gains, missing the loss. Also, tryna implement p2wpkh --- shell.go | 31 ++++++++++++++++++++++++------- uspv/hardmode.go | 37 ++++++++++++++----------------------- uspv/msghandler.go | 32 +++++++++++++++++++++++--------- uspv/sortsignsend.go | 14 +++++++++++++- 4 files changed, 74 insertions(+), 40 deletions(-) diff --git a/shell.go b/shell.go index bc255bb7..c820c740 100644 --- a/shell.go +++ b/shell.go @@ -61,7 +61,7 @@ func shell() { log.Fatal(err) } if tip == 0 { // DB has never been used, set to birthday - tip = 1234 // hardcoded; later base on keyfile date? + tip = 20000 // hardcoded; later base on keyfile date? err = SCon.TS.SetDBSyncHeight(tip) if err != nil { log.Fatal(err) @@ -254,7 +254,11 @@ func Send(args []string) error { } // need args, fail if len(args) < 2 { - return fmt.Errorf("need args: ssend amount(satoshis) address") + return fmt.Errorf("need args: ssend amount(satoshis) address wit?") + } + var wit bool // whether to send to p2wpkh + if len(args) > 2 { + wit = true } amt, err := strconv.ParseInt(args[0], 10, 64) if err != nil { @@ -270,7 +274,8 @@ func Send(args []string) error { } fmt.Printf("send %d to address: %s \n", amt, adr.String()) - err = SendCoins(SCon, adr, amt) + + err = SendCoins(SCon, adr, amt, wit) if err != nil { return err } @@ -278,7 +283,10 @@ func Send(args []string) error { } // SendCoins does send coins, but it's very rudimentary -func SendCoins(s uspv.SPVCon, adr btcutil.Address, sendAmt int64) error { +// wit makes it into p2wpkh. Which is not yet spendable. +func SendCoins( + s uspv.SPVCon, adr btcutil.Address, sendAmt int64, wit bool) error { + var err error var score int64 allUtxos, err := s.TS.GetAllUtxos() @@ -297,10 +305,19 @@ func SendCoins(s uspv.SPVCon, adr btcutil.Address, sendAmt int64) error { tx := wire.NewMsgTx() // make new tx // make address script 76a914...88ac - adrScript, err := txscript.PayToAddrScript(adr) - if err != nil { - return err + var adrScript []byte + if wit { + adrScript, err = uspv.P2wpkhScript(adr) + if err != nil { + return err + } + } else { // non-wit, use old p2pkh + adrScript, err = txscript.PayToAddrScript(adr) + if err != nil { + return err + } } + // make user specified txout and add to tx txout := wire.NewTxOut(sendAmt, adrScript) tx.AddTxOut(txout) diff --git a/uspv/hardmode.go b/uspv/hardmode.go index efa5a6aa..b54e8526 100644 --- a/uspv/hardmode.go +++ b/uspv/hardmode.go @@ -4,7 +4,6 @@ import ( "bytes" "fmt" "log" - "sync" "github.com/btcsuite/btcd/wire" ) @@ -123,13 +122,11 @@ func (s *SPVCon) IngestBlock(m *wire.MsgBlock) { // var buf bytes.Buffer // m.SerializeWitness(&buf) // fmt.Printf("block hex %x\n", buf.Bytes()) - for _, tx := range m.Transactions { - // if i > 0 { - fmt.Printf("wtxid: %s\n", tx.WTxSha()) - fmt.Printf(" txid: %s\n", tx.TxSha()) - // fmt.Printf("%d %s", i, TxToString(tx)) - // } - } + // for _, tx := range m.Transactions { + // fmt.Printf("wtxid: %s\n", tx.WTxSha()) + // fmt.Printf(" txid: %s\n", tx.TxSha()) + // fmt.Printf("%d %s", i, TxToString(tx)) + // } ok := BlockOK(*m) // check block self-consistency if !ok { fmt.Printf("block %s not OK!!11\n", m.BlockSha().String()) @@ -154,23 +151,17 @@ func (s *SPVCon) IngestBlock(m *wire.MsgBlock) { // iterate through all txs in the block, looking for matches. // this is slow and can be sped up by doing in-ram filters client side. // kindof a pain to implement though and it's fast enough for now. - var wg sync.WaitGroup - wg.Add(len(m.Transactions)) for i, tx := range m.Transactions { - go func() { - defer wg.Done() - hits, err := s.TS.Ingest(tx, hah.height) - if err != nil { - log.Printf("Incoming Tx error: %s\n", err.Error()) - return - } - if hits > 0 { - log.Printf("block %d tx %d %s ingested and matches %d utxo/adrs.", - hah.height, i, tx.TxSha().String(), hits) - } - }() + hits, err := s.TS.Ingest(tx, hah.height) + if err != nil { + log.Printf("Incoming Tx error: %s\n", err.Error()) + return + } + if hits > 0 { + log.Printf("block %d tx %d %s ingested and matches %d utxo/adrs.", + hah.height, i, tx.TxSha().String(), hits) + } } - wg.Wait() // write to db that we've sync'd to the height indicated in the // merkle block. This isn't QUITE true since we haven't actually gotten diff --git a/uspv/msghandler.go b/uspv/msghandler.go index c1ddf99f..ecb7c474 100644 --- a/uspv/msghandler.go +++ b/uspv/msghandler.go @@ -95,7 +95,6 @@ func (s *SPVCon) fPositiveHandler() { select { case x := <-s.fPositives: fpAccumulator += x - default: break finClear } @@ -181,17 +180,32 @@ func (s *SPVCon) GetDataHandler(m *wire.MsgGetData) { for i, thing := range m.InvList { log.Printf("\t%d)%s : %s", i, thing.Type.String(), thing.Hash.String()) - if thing.Type != wire.InvTypeTx { // refuse non-tx reqs - log.Printf("We only respond to tx requests, ignoring") + + // separate wittx and tx. needed / combine? + // does the same thing right now + if thing.Type == wire.InvTypeWitnessTx { + tx, err := s.TS.GetTx(&thing.Hash) + if err != nil { + log.Printf("error getting tx %s: %s", + thing.Hash.String(), err.Error()) + } + s.outMsgQueue <- tx + sent++ continue } - tx, err := s.TS.GetTx(&thing.Hash) - if err != nil { - log.Printf("error getting tx %s: %s", - thing.Hash.String(), err.Error()) + if thing.Type == wire.InvTypeTx { + tx, err := s.TS.GetTx(&thing.Hash) + if err != nil { + log.Printf("error getting tx %s: %s", + thing.Hash.String(), err.Error()) + } + s.outMsgQueue <- tx + sent++ + continue } - s.outMsgQueue <- tx - sent++ + // didn't match, so it's not something we're responding to + log.Printf("We only respond to tx requests, ignoring") + } log.Printf("sent %d of %d requested items", sent, len(m.InvList)) } diff --git a/uspv/sortsignsend.go b/uspv/sortsignsend.go index ec3e3ce0..d7b91610 100644 --- a/uspv/sortsignsend.go +++ b/uspv/sortsignsend.go @@ -7,6 +7,7 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" + "github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil/bloom" "github.com/btcsuite/btcutil/hdkeychain" "github.com/btcsuite/btcutil/txsort" @@ -41,6 +42,17 @@ func (s *SPVCon) Rebroadcast() { return } +func P2wpkhScript(adr btcutil.Address) ([]byte, error) { + switch adr := adr.(type) { + case *btcutil.AddressPubKeyHash: + sb := txscript.NewScriptBuilder() + sb.AddOp(txscript.OP_0) + sb.AddData(adr.ScriptAddress()) + return sb.Script() + } + return nil, fmt.Errorf("%s is not pkh address", adr.String()) +} + func (s *SPVCon) NewOutgoingTx(tx *wire.MsgTx) error { txid := tx.TxSha() // assign height of zero for txs we create @@ -53,7 +65,7 @@ func (s *SPVCon) NewOutgoingTx(tx *wire.MsgTx) error { return err } // make an inv message instead of a tx message to be polite - iv1 := wire.NewInvVect(wire.InvTypeTx, &txid) + iv1 := wire.NewInvVect(wire.InvTypeWitnessTx, &txid) invMsg := wire.NewMsgInv() err = invMsg.AddInvVect(iv1) if err != nil {