From 92711c4d320efcd153adbfc2db94fc46521b0095 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Wed, 13 Jun 2018 01:32:06 -0700 Subject: [PATCH 1/5] utxonursery: rebroadcast finalized kinder txns on startup Alters the utxonursery to rebroadcast finalized sweep txns that sweep kindergarten (CSV-delayed) outputs. Currently, we reregister for confirmation notifications, but we make no attempt to rebroadcast. The htlc-timeout transactions are rebroadcast correctly, so this changes make the handling of crib and kinder outputs symmetric on startup. --- utxonursery.go | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/utxonursery.go b/utxonursery.go index 2e2d1f2e0..59f2d25b4 100644 --- a/utxonursery.go +++ b/utxonursery.go @@ -736,7 +736,7 @@ func (u *utxoNursery) regraduateClass(classHeight uint32) error { utxnLog.Infof("Re-registering confirmation for kindergarten "+ "sweep transaction at height=%d ", classHeight) - err = u.registerSweepConf(finalTx, kgtnOutputs, classHeight) + err = u.sweepMatureOutputs(classHeight, finalTx, kgtnOutputs) if err != nil { utxnLog.Errorf("Failed to re-register for kindergarten "+ "sweep transaction at height=%d: %v", @@ -1124,7 +1124,8 @@ func (u *utxoNursery) sweepMatureOutputs(classHeight uint32, finalTx *wire.MsgTx // With the sweep transaction fully signed, broadcast the transaction // to the network. Additionally, we can stop tracking these outputs as // they've just been swept. - if err := u.cfg.PublishTransaction(finalTx); err != nil { + err := u.cfg.PublishTransaction(finalTx) + if err != nil && err != lnwallet.ErrDoubleSpend { utxnLog.Errorf("unable to broadcast sweep tx: %v, %v", err, spew.Sdump(finalTx)) return err @@ -1230,7 +1231,8 @@ func (u *utxoNursery) sweepCribOutput(classHeight uint32, baby *babyOutput) erro // We'll now broadcast the HTLC transaction, then wait for it to be // confirmed before transitioning it to kindergarten. - if err := u.cfg.PublishTransaction(baby.timeoutTx); err != nil { + err := u.cfg.PublishTransaction(baby.timeoutTx) + if err != nil && err != lnwallet.ErrDoubleSpend { utxnLog.Errorf("Unable to broadcast baby tx: "+ "%v, %v", err, spew.Sdump(baby.timeoutTx)) return err From d82ef412456ff1db0ed45a14fa28013023b07f06 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 14 Jun 2018 17:14:31 -0700 Subject: [PATCH 2/5] rpc: sort closed channels in order of ascending height --- rpcserver.go | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/rpcserver.go b/rpcserver.go index 3cac313c2..5be590006 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -9,6 +9,7 @@ import ( "fmt" "io" "math" + "sort" "strings" "time" @@ -1137,8 +1138,9 @@ func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest, // the htlc switch which will handle the negotiation and // broadcast details. feePerKw := feeRate.FeePerKWeight() - updateChan, errChan = r.server.htlcSwitch.CloseLink(chanPoint, - htlcswitch.CloseRegular, feePerKw) + updateChan, errChan = r.server.htlcSwitch.CloseLink( + chanPoint, htlcswitch.CloseRegular, feePerKw, + ) } out: for { @@ -1583,14 +1585,14 @@ func (r *rpcServer) PendingChannels(ctx context.Context, return resp, nil } -// ClosedChannels returns a list of all the channels have been closed. +// ClosedChannels returns a list of all the channels have been closed. // This does not include channels that are still in the process of closing. func (r *rpcServer) ClosedChannels(ctx context.Context, - in *lnrpc.ClosedChannelsRequest) (*lnrpc.ClosedChannelsResponse, + in *lnrpc.ClosedChannelsRequest) (*lnrpc.ClosedChannelsResponse, error) { // Show all channels when no filter flags are set. - filterResults := in.Cooperative || in.LocalForce || + filterResults := in.Cooperative || in.LocalForce || in.RemoteForce || in.Breach || in.FundingCanceled resp := &lnrpc.ClosedChannelsResponse{} @@ -1600,6 +1602,13 @@ func (r *rpcServer) ClosedChannels(ctx context.Context, return nil, err } + // In order to make the response easier to parse for clients, we'll + // sort the set of closed channels by their closing height before + // serializing the proto response. + sort.Slice(dbChannels, func(i, j int) bool { + return dbChannels[i].CloseHeight < dbChannels[j].CloseHeight + }) + for _, dbChannel := range dbChannels { if dbChannel.IsPending { continue From 7b37cbd2d9356399618969ebb791740206f4366e Mon Sep 17 00:00:00 2001 From: yohei okada Date: Tue, 29 May 2018 21:52:07 +0900 Subject: [PATCH 3/5] htlcswitch: add basic table driven tests for ExpectedFee --- htlcswitch/link.go | 1 - htlcswitch/link_test.go | 54 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 03ee9d5fe..9a933f046 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -94,7 +94,6 @@ type ForwardingPolicy struct { func ExpectedFee(f ForwardingPolicy, htlcAmt lnwire.MilliSatoshi) lnwire.MilliSatoshi { - // TODO(roasbeef): write some basic table driven tests return f.BaseFee + (htlcAmt*f.FeeRate)/1000000 } diff --git a/htlcswitch/link_test.go b/htlcswitch/link_test.go index d76090125..c6b2819ff 100644 --- a/htlcswitch/link_test.go +++ b/htlcswitch/link_test.go @@ -4473,3 +4473,57 @@ func TestChannelLinkFail(t *testing.T) { cleanUp() } } + +// TestExpectedFee tests calculation of ExpectedFee returns expected fee, given +// a baseFee, a feeRate, and an htlc amount. +func TestExpectedFee(t *testing.T) { + testCases := []struct { + baseFee lnwire.MilliSatoshi + feeRate lnwire.MilliSatoshi + htlcAmt lnwire.MilliSatoshi + expected lnwire.MilliSatoshi + }{ + { + lnwire.MilliSatoshi(0), + lnwire.MilliSatoshi(0), + lnwire.MilliSatoshi(0), + lnwire.MilliSatoshi(0), + }, + { + lnwire.MilliSatoshi(0), + lnwire.MilliSatoshi(1), + lnwire.MilliSatoshi(999999), + lnwire.MilliSatoshi(0), + }, + { + lnwire.MilliSatoshi(0), + lnwire.MilliSatoshi(1), + lnwire.MilliSatoshi(1000000), + lnwire.MilliSatoshi(1), + }, + { + lnwire.MilliSatoshi(0), + lnwire.MilliSatoshi(1), + lnwire.MilliSatoshi(1000001), + lnwire.MilliSatoshi(1), + }, + { + lnwire.MilliSatoshi(1), + lnwire.MilliSatoshi(1), + lnwire.MilliSatoshi(1000000), + lnwire.MilliSatoshi(2), + }, + } + + for _, test := range testCases { + f := ForwardingPolicy{ + BaseFee: test.baseFee, + FeeRate: test.feeRate, + } + fee := ExpectedFee(f, test.htlcAmt) + if fee != test.expected { + t.Errorf("expected fee to be (%v), instead got (%v)", test.expected, + fee) + } + } +} From b5d8cde6fc488d182349c54fd1a629bf6b980a8c Mon Sep 17 00:00:00 2001 From: Dan Bolser Date: Mon, 18 Jun 2018 13:58:24 +0100 Subject: [PATCH 4/5] README: update README to indicate tx index is no longer required for full node backends --- docs/INSTALL.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index b2d695ab0..d6ab5def9 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -114,7 +114,7 @@ make btcd Running the following command will create `rpc.cert` and default `btcd.conf`. ``` -btcd --testnet --txindex --rpcuser=REPLACEME --rpcpass=REPLACEME +btcd --testnet --rpcuser=REPLACEME --rpcpass=REPLACEME ``` If you want to use `lnd` on testnet, `btcd` needs to first fully sync the testnet blockchain. Depending on your hardware, this may take up to a few @@ -207,9 +207,7 @@ prefixed by `litecoind`. To configure your bitcoind backend for use with lnd, first complete and verify the following: -- The `bitcoind` instance must be configured with `--txindex` just like `btcd` - above -- Additionally, since `lnd` uses +- Since `lnd` uses [ZeroMQ](https://github.com/bitcoin/bitcoin/blob/master/doc/zmq.md) to interface with `bitcoind`, *your `bitcoind` installation must be compiled with ZMQ*. Note that if you installed `bitcoind` from source and ZMQ was not present, @@ -228,7 +226,6 @@ the following: Here's a sample `bitcoin.conf` for use with lnd: ``` testnet=1 -txindex=1 server=1 daemon=1 zmqpubrawblock=tcp://127.0.0.1:28332 From fc658dbf6043951f6ba8b8e86f4e67bc903cf6b7 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Mon, 18 Jun 2018 14:01:25 +0100 Subject: [PATCH 5/5] docs: further clarify --txindex usage for full nodes --- docs/INSTALL.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/INSTALL.md b/docs/INSTALL.md index d6ab5def9..9f6127650 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -99,7 +99,7 @@ make check ### Installing btcd -When using the `btcd` backend, `lnd` currently requires the +If one wishes to use the `btcd` backend, `lnd` currently requires the [roasbeef](https://github.com/roasbeef/btcd) fork of `btcd` due to neutrino additions that are not yet available in the master branch. To install, run the following commands: @@ -118,7 +118,9 @@ btcd --testnet --rpcuser=REPLACEME --rpcpass=REPLACEME ``` If you want to use `lnd` on testnet, `btcd` needs to first fully sync the testnet blockchain. Depending on your hardware, this may take up to a few -hours. +hours. Note that adding `--txindex` is optional, as it will take longer to sync +the node, but then `lnd` will generally operate faster as it can hit the index +directly, rather than scanning blocks or BIP 158 filters for relevant items. (NOTE: It may take several minutes to find segwit-enabled peers.) @@ -202,7 +204,10 @@ The configuration for bitcoind and litecoind are nearly identical, the following steps can be mirrored with loss of generality to enable a litecoind backend. Setup will be described in regards to `bitcoind`, but note that `lnd` uses a distinct `litecoin.node=litecoind` argument and analogous subconfigurations -prefixed by `litecoind`. +prefixed by `litecoind`. Note that adding `--txindex` is optional, as it will +take longer to sync the node, but then `lnd` will generally operate faster as +it can hit the index directly, rather than scanning blocks or BIP 158 filters +for relevant items. To configure your bitcoind backend for use with lnd, first complete and verify the following: