Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sweep: prepare for sweeper #1978

Merged
merged 6 commits into from
Oct 17, 2018
Merged

Conversation

joostjager
Copy link
Contributor

@joostjager joostjager commented Sep 26, 2018

This PR makes changes that prepare for the new Sweeper struct.

  • Create new subsystem for sweeping
  • Move sweep tx generation code to sweep subsystem.
  • Clean up SpendableOutput and CsvSpendableOutput structs.
  • Make Cltv expiry part of a sweep input.
  • Remove duplicated sweep tx generation code from Success and Commit resolvers

A follow PR is #1960, which builds the sweeper around the sweep tx generation and uses that from utxonursery.

@joostjager joostjager force-pushed the sweeper-prep branch 3 times, most recently from 49685bf to b569192 Compare September 26, 2018 16:58
@joostjager joostjager changed the title Sweeper prep [DO NOT REVIEW] sweep: prepare for sweeper [DO NOT REVIEW] Sep 26, 2018
@joostjager joostjager force-pushed the sweeper-prep branch 11 times, most recently from 9c1cca0 to 158b97a Compare September 27, 2018 01:00
@joostjager joostjager changed the title sweep: prepare for sweeper [DO NOT REVIEW] sweep: prepare for sweeper Sep 27, 2018
@joostjager joostjager force-pushed the sweeper-prep branch 3 times, most recently from a168546 to 58c8813 Compare September 28, 2018 11:23
Copy link
Member

@Roasbeef Roasbeef left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Solid PR! The commit structure makes the set of changes very easy to review. The only comment re the commits, is that we typically like to add additional context to the commits themselves using the message body provided. We find that this helps to make the git history more detailed as each commit has a small body that explains the changes/rationale within it, and may also extend to the commits proceeding it as well (assuming we always work to retain commit order).

@@ -849,10 +849,6 @@ func (bo *breachedOutput) BuildWitness(signer lnwallet.Signer, txn *wire.MsgTx,
return bo.witnessFunc(txn, hashCache, txinIdx)
}

// Add compile-time constraint ensuring breachedOutput implements
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the rationale behind this change? Seems better from the PoV of unit tests, that we can feed in this interface into various methods in his file. After all, we may eventually extract this into the contractcourt package.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the interface because it was not used anywhere. But indeed, I can also see the breacharbiter use an (its own) instance of the sweeper. Converted to Input types.

sweep/sweeper.go Outdated
Signer lnwallet.Signer
}

// NewSweeper returns a new Sweeper instance.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can instead be sweep.New as it's the primary external facing struct within the package (atm).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed. Not completely sure if I like it, because it'll be another rename when we found out we need another important external facing struct.

sweep/sweeper.go Outdated Show resolved Hide resolved
sweep/sweeper.go Outdated
cfg *SweeperConfig
}

// SweeperConfig contains dependencies of Sweeper
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing a period at the end of the sentence.

utxonursery.go Outdated
// Store provides access to and modification of the persistent state
// maintained about the utxo nursery's incubating outputs.
Store NurseryStore

// Sweeper manages the sweeping of unlocked outputs for nursery.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well at this point it actually just constructs the sweeping transactions.

return nil, err
}

log.Debugf("%T(%v): using %v sat/kw for sweep tx", c,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this change, we've lost the debug logging here. Also just realized that we don't have a way currently to signal to the sweeper what conf timing, or fee rate that we'd like when sweeping.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved logging to sweeper.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added TODO for configurable fee rate.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before we merge we should be able to specify the fee rate. In distinct areas in the codebase, we use 3 or 6 depending on how quickly we want the transaction to enter the chain. Some cases (CLTV timeouts) are more time sensitive than others.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added

return nil, err
}

log.Debugf("%T(%x): using %v sat/kw to sweep htlc"+
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar comment here re losing the debug logging.

sweep/input.go Outdated
// BaseInput contains all the information needed to sweep a output.
type BaseInput struct {
// InputKit contains the base information needed to sweep an output.
type InputKit struct {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be public seeing as it's mostly used as a mix-in struct (via composition) now?

sweep/input.go Outdated
@@ -72,28 +70,61 @@ func MakeBaseInput(outpoint *wire.OutPoint,
}

// Amount returns the number of satoshis contained in the breached output.
func (bi *BaseInput) Amount() btcutil.Amount {
func (bi *InputKit) Amount() btcutil.Amount {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this might cause vet on Go 1.11 to complain re the name of the method target...

sweep/input.go Outdated
return &bi.signDesc
}

// AbsoluteMaturity returns the absolute timelock.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do the absolute and relative maturity need to be a part of this struct? With the changes in this commit, it now serves more or less as the base class (via composition tho), and most "base" inputs don't require a CSV or CLTV semantics at all. Also if we go with my suggestion to always use non-final sequence locks inputs (or even randomize them as eventually we can make all transactions look like commitment transactions being broadcast) and use the next block height as the lock time value.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So you propose:

  • Always set tx locktime to current height + 1
  • Remove AbsoluteMaturity() from the interface completely, as it is no longer needed on the input level
  • Remove relativeMaturity from BaseInput
  • Implement BlockToMaturity of BaseInput as always returning 0
  • Create a new struct CsvInput that allows setting the relative lock time
    ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove them only on this new baseInput struct. Yes to the rest!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, got it. Didn't create CsvInput yet, as it is not needed in this PR.

@joostjager joostjager force-pushed the sweeper-prep branch 9 times, most recently from 22e8545 to d42c27a Compare October 3, 2018 08:26
@joostjager
Copy link
Contributor Author

Commit message bodies added

Copy link
Contributor Author

@joostjager joostjager left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.

sweep/input.go Outdated

// SpendableOutput an interface which can be used by the breach arbiter to
// construct a transaction spending from outputs we control.
type SpendableOutput interface {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice commit structure 👍

breacharbiter.go Outdated Show resolved Hide resolved
server.go Show resolved Hide resolved
server.go Outdated Show resolved Hide resolved
sweep/log.go Outdated Show resolved Hide resolved
sweep/input.go Outdated
// MakeBaseInput assembles a new BaseInput that can be used to construct a
// sweep transaction.
func MakeBaseInput(outpoint *wire.OutPoint,
func makeInputKit(outpoint *wire.OutPoint,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can remove makeInputKit and just populate the struct manually where needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First I didn't like the suggestion, because I'd need to duplicate the amount assignment in makeInputKit. But then I realized that whole field is redundant. Removed it completely.

breacharbiter.go Show resolved Hide resolved
breacharbiter.go Show resolved Hide resolved
// spends from them. This method also makes an accurate fee estimate before
// generating the required witnesses.
//
// The value of currentBlockHeight argument will be set as the tx locktime. This
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should the parameter be called locktime instead? Since we are currently not passing the correct block height.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The expected value is currentBlockHeight, otherwise the comments would not be valid. Because we are currently not passing the block height in the contract resolvers, I added todo comments there.

sweep/sweeper.go Outdated
sweepTx.AddTxIn(&wire.TxIn{
PreviousOutPoint: *input.OutPoint(),
Sequence: input.BlocksToMaturity(),
})
}
for _, input := range cltvInputs {
sweepTx.AddTxIn(&wire.TxIn{
PreviousOutPoint: *input.OutPoint(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is only set FF if NewTxIn is used, so I don't think this will change the existing behavior.

@joostjager joostjager force-pushed the sweeper-prep branch 2 times, most recently from d0aebc4 to 121d030 Compare October 11, 2018 17:29
@joostjager
Copy link
Contributor Author

Comments addressed.

sweep/input.go Show resolved Hide resolved
sweep/input.go Show resolved Hide resolved
sweep/sweeper.go Outdated
return nil, err
}

log.Debugf("Using %v sat/kw for sweep tx", int64(feePerKw))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we consider making this info?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a commit that restructures the functions in a imo more logical way and unites the log statements.

This commit moves the output structs to a new package as a
preparation for moving more logic into that package.
Sweep txes are currently generated in multiple locations. Moving
the sweep tx generation into a shared package will allow us to
reuse that logic.
This commit introduces a common interface for sweep
inputs. It eliminates the type checking from UtxoSweeper.

Also the formerly present Amount() getter is removed. It was redundant
because this value is present in SignDesc().Output.Value as well.
Removes duplicate sweep tx code from commit resolver
and delegates generation to UtxoSweeper in the sweep
package.
@joostjager
Copy link
Contributor Author

Comments addressed

Copy link
Member

@Roasbeef Roasbeef left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🦎

@Roasbeef Roasbeef merged commit c9e42a6 into lightningnetwork:master Oct 17, 2018
)

default:
log.Warnf("kindergarten output in nursery store "+
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think this is consistent with the current behavior, but currently we won't add any weight estimate for unknown witness types

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i take that back, the prior version would properly filter unknown output types and not include them in the transaction. the new version will include them

weightEstimate.AddWitnessInput(
lnwallet.OfferedHtlcSuccessWitnessSize,
)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing cltvCount++

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah wait, this is a new type that wasn't included before, nvm

}

log.Infof("Creating sweep transaction for %v inputs (%v CSV, %v CLTV) "+
"using %v sat/kw", len(inputs), csvCount, cltvCount,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

first argument should be len(inputs)-csvCount-cltvCount, or len(inputs)-len(csvInputs)-len(cltvOutputs) if getWeightEstimate is modified to return slices of filtered inputs.

@cfromknecht
Copy link
Contributor

Added a small commit to restore prior behavior that filters unknown witness types #2062

@joostjager
Copy link
Contributor Author

Oh, good catch. I introduced that already in a commit before that last refactor commit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants