Merge pull request #2481 from joostjager/move-input
multi: move input to separate package
This commit is contained in:
commit
948646b58b
@ -19,8 +19,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/sweep"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -100,7 +100,7 @@ type BreachConfig struct {
|
|||||||
// Signer is used by the breach arbiter to generate sweep transactions,
|
// Signer is used by the breach arbiter to generate sweep transactions,
|
||||||
// which move coins from previously open channels back to the user's
|
// which move coins from previously open channels back to the user's
|
||||||
// wallet.
|
// wallet.
|
||||||
Signer lnwallet.Signer
|
Signer input.Signer
|
||||||
|
|
||||||
// Store is a persistent resource that maintains information regarding
|
// Store is a persistent resource that maintains information regarding
|
||||||
// breached channels. This is used in conjunction with DB to recover
|
// breached channels. This is used in conjunction with DB to recover
|
||||||
@ -282,7 +282,7 @@ func convertToSecondLevelRevoke(bo *breachedOutput, breachInfo *retributionInfo,
|
|||||||
|
|
||||||
// In this case, we'll modify the witness type of this output to
|
// In this case, we'll modify the witness type of this output to
|
||||||
// actually prepare for a second level revoke.
|
// actually prepare for a second level revoke.
|
||||||
bo.witnessType = lnwallet.HtlcSecondLevelRevoke
|
bo.witnessType = input.HtlcSecondLevelRevoke
|
||||||
|
|
||||||
// We'll also redirect the outpoint to this second level output, so the
|
// We'll also redirect the outpoint to this second level output, so the
|
||||||
// spending transaction updates it inputs accordingly.
|
// spending transaction updates it inputs accordingly.
|
||||||
@ -346,8 +346,8 @@ func (b *breachArbiter) waitForSpendEvent(breachInfo *retributionInfo,
|
|||||||
breachedOutput := &breachInfo.breachedOutputs[i]
|
breachedOutput := &breachInfo.breachedOutputs[i]
|
||||||
|
|
||||||
// If this isn't an HTLC output, then we can skip it.
|
// If this isn't an HTLC output, then we can skip it.
|
||||||
if breachedOutput.witnessType != lnwallet.HtlcAcceptedRevoke &&
|
if breachedOutput.witnessType != input.HtlcAcceptedRevoke &&
|
||||||
breachedOutput.witnessType != lnwallet.HtlcOfferedRevoke {
|
breachedOutput.witnessType != input.HtlcOfferedRevoke {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -581,18 +581,18 @@ justiceTxBroadcast:
|
|||||||
// Compute both the total value of funds being swept and the
|
// Compute both the total value of funds being swept and the
|
||||||
// amount of funds that were revoked from the counter party.
|
// amount of funds that were revoked from the counter party.
|
||||||
var totalFunds, revokedFunds btcutil.Amount
|
var totalFunds, revokedFunds btcutil.Amount
|
||||||
for _, input := range breachInfo.breachedOutputs {
|
for _, inp := range breachInfo.breachedOutputs {
|
||||||
totalFunds += input.Amount()
|
totalFunds += inp.Amount()
|
||||||
|
|
||||||
// If the output being revoked is the remote commitment
|
// If the output being revoked is the remote commitment
|
||||||
// output or an offered HTLC output, it's amount
|
// output or an offered HTLC output, it's amount
|
||||||
// contributes to the value of funds being revoked from
|
// contributes to the value of funds being revoked from
|
||||||
// the counter party.
|
// the counter party.
|
||||||
switch input.WitnessType() {
|
switch inp.WitnessType() {
|
||||||
case lnwallet.CommitmentRevoke:
|
case input.CommitmentRevoke:
|
||||||
revokedFunds += input.Amount()
|
revokedFunds += inp.Amount()
|
||||||
case lnwallet.HtlcOfferedRevoke:
|
case input.HtlcOfferedRevoke:
|
||||||
revokedFunds += input.Amount()
|
revokedFunds += inp.Amount()
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -755,21 +755,21 @@ func (b *breachArbiter) handleBreachHandoff(breachEvent *ContractBreachEvent) {
|
|||||||
type breachedOutput struct {
|
type breachedOutput struct {
|
||||||
amt btcutil.Amount
|
amt btcutil.Amount
|
||||||
outpoint wire.OutPoint
|
outpoint wire.OutPoint
|
||||||
witnessType lnwallet.WitnessType
|
witnessType input.WitnessType
|
||||||
signDesc lnwallet.SignDescriptor
|
signDesc input.SignDescriptor
|
||||||
confHeight uint32
|
confHeight uint32
|
||||||
|
|
||||||
secondLevelWitnessScript []byte
|
secondLevelWitnessScript []byte
|
||||||
|
|
||||||
witnessFunc lnwallet.WitnessGenerator
|
witnessFunc input.WitnessGenerator
|
||||||
}
|
}
|
||||||
|
|
||||||
// makeBreachedOutput assembles a new breachedOutput that can be used by the
|
// makeBreachedOutput assembles a new breachedOutput that can be used by the
|
||||||
// breach arbiter to construct a justice or sweep transaction.
|
// breach arbiter to construct a justice or sweep transaction.
|
||||||
func makeBreachedOutput(outpoint *wire.OutPoint,
|
func makeBreachedOutput(outpoint *wire.OutPoint,
|
||||||
witnessType lnwallet.WitnessType,
|
witnessType input.WitnessType,
|
||||||
secondLevelScript []byte,
|
secondLevelScript []byte,
|
||||||
signDescriptor *lnwallet.SignDescriptor,
|
signDescriptor *input.SignDescriptor,
|
||||||
confHeight uint32) breachedOutput {
|
confHeight uint32) breachedOutput {
|
||||||
|
|
||||||
amount := signDescriptor.Output.Value
|
amount := signDescriptor.Output.Value
|
||||||
@ -797,13 +797,13 @@ func (bo *breachedOutput) OutPoint() *wire.OutPoint {
|
|||||||
|
|
||||||
// WitnessType returns the type of witness that must be generated to spend the
|
// WitnessType returns the type of witness that must be generated to spend the
|
||||||
// breached output.
|
// breached output.
|
||||||
func (bo *breachedOutput) WitnessType() lnwallet.WitnessType {
|
func (bo *breachedOutput) WitnessType() input.WitnessType {
|
||||||
return bo.witnessType
|
return bo.witnessType
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignDesc returns the breached output's SignDescriptor, which is used during
|
// SignDesc returns the breached output's SignDescriptor, which is used during
|
||||||
// signing to compute the witness.
|
// signing to compute the witness.
|
||||||
func (bo *breachedOutput) SignDesc() *lnwallet.SignDescriptor {
|
func (bo *breachedOutput) SignDesc() *input.SignDescriptor {
|
||||||
return &bo.signDesc
|
return &bo.signDesc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -812,8 +812,8 @@ func (bo *breachedOutput) SignDesc() *lnwallet.SignDescriptor {
|
|||||||
// generation function, which parameterized primarily by the witness type and
|
// generation function, which parameterized primarily by the witness type and
|
||||||
// sign descriptor. The method then returns the witness computed by invoking
|
// sign descriptor. The method then returns the witness computed by invoking
|
||||||
// this function on the first and subsequent calls.
|
// this function on the first and subsequent calls.
|
||||||
func (bo *breachedOutput) CraftInputScript(signer lnwallet.Signer, txn *wire.MsgTx,
|
func (bo *breachedOutput) CraftInputScript(signer input.Signer, txn *wire.MsgTx,
|
||||||
hashCache *txscript.TxSigHashes, txinIdx int) (*lnwallet.InputScript, error) {
|
hashCache *txscript.TxSigHashes, txinIdx int) (*input.Script, error) {
|
||||||
|
|
||||||
// First, we ensure that the witness generation function has been
|
// First, we ensure that the witness generation function has been
|
||||||
// initialized for this breached output.
|
// initialized for this breached output.
|
||||||
@ -842,7 +842,7 @@ func (bo *breachedOutput) HeightHint() uint32 {
|
|||||||
|
|
||||||
// Add compile-time constraint ensuring breachedOutput implements the Input
|
// Add compile-time constraint ensuring breachedOutput implements the Input
|
||||||
// interface.
|
// interface.
|
||||||
var _ sweep.Input = (*breachedOutput)(nil)
|
var _ input.Input = (*breachedOutput)(nil)
|
||||||
|
|
||||||
// retributionInfo encapsulates all the data needed to sweep all the contested
|
// retributionInfo encapsulates all the data needed to sweep all the contested
|
||||||
// funds within a channel whose contract has been breached by the prior
|
// funds within a channel whose contract has been breached by the prior
|
||||||
@ -883,7 +883,7 @@ func newRetributionInfo(chanPoint *wire.OutPoint,
|
|||||||
if breachInfo.LocalOutputSignDesc != nil {
|
if breachInfo.LocalOutputSignDesc != nil {
|
||||||
localOutput := makeBreachedOutput(
|
localOutput := makeBreachedOutput(
|
||||||
&breachInfo.LocalOutpoint,
|
&breachInfo.LocalOutpoint,
|
||||||
lnwallet.CommitmentNoDelay,
|
input.CommitmentNoDelay,
|
||||||
// No second level script as this is a commitment
|
// No second level script as this is a commitment
|
||||||
// output.
|
// output.
|
||||||
nil,
|
nil,
|
||||||
@ -901,7 +901,7 @@ func newRetributionInfo(chanPoint *wire.OutPoint,
|
|||||||
if breachInfo.RemoteOutputSignDesc != nil {
|
if breachInfo.RemoteOutputSignDesc != nil {
|
||||||
remoteOutput := makeBreachedOutput(
|
remoteOutput := makeBreachedOutput(
|
||||||
&breachInfo.RemoteOutpoint,
|
&breachInfo.RemoteOutpoint,
|
||||||
lnwallet.CommitmentRevoke,
|
input.CommitmentRevoke,
|
||||||
// No second level script as this is a commitment
|
// No second level script as this is a commitment
|
||||||
// output.
|
// output.
|
||||||
nil,
|
nil,
|
||||||
@ -919,11 +919,11 @@ func newRetributionInfo(chanPoint *wire.OutPoint,
|
|||||||
// Using the breachedHtlc's incoming flag, determine the
|
// Using the breachedHtlc's incoming flag, determine the
|
||||||
// appropriate witness type that needs to be generated in order
|
// appropriate witness type that needs to be generated in order
|
||||||
// to sweep the HTLC output.
|
// to sweep the HTLC output.
|
||||||
var htlcWitnessType lnwallet.WitnessType
|
var htlcWitnessType input.WitnessType
|
||||||
if breachedHtlc.IsIncoming {
|
if breachedHtlc.IsIncoming {
|
||||||
htlcWitnessType = lnwallet.HtlcAcceptedRevoke
|
htlcWitnessType = input.HtlcAcceptedRevoke
|
||||||
} else {
|
} else {
|
||||||
htlcWitnessType = lnwallet.HtlcOfferedRevoke
|
htlcWitnessType = input.HtlcOfferedRevoke
|
||||||
}
|
}
|
||||||
|
|
||||||
htlcOutput := makeBreachedOutput(
|
htlcOutput := makeBreachedOutput(
|
||||||
@ -956,13 +956,13 @@ func (b *breachArbiter) createJusticeTx(
|
|||||||
// outputs, while simultaneously computing the estimated weight of the
|
// outputs, while simultaneously computing the estimated weight of the
|
||||||
// transaction.
|
// transaction.
|
||||||
var (
|
var (
|
||||||
spendableOutputs []sweep.Input
|
spendableOutputs []input.Input
|
||||||
weightEstimate lnwallet.TxWeightEstimator
|
weightEstimate input.TxWeightEstimator
|
||||||
)
|
)
|
||||||
|
|
||||||
// Allocate enough space to potentially hold each of the breached
|
// Allocate enough space to potentially hold each of the breached
|
||||||
// outputs in the retribution info.
|
// outputs in the retribution info.
|
||||||
spendableOutputs = make([]sweep.Input, 0, len(r.breachedOutputs))
|
spendableOutputs = make([]input.Input, 0, len(r.breachedOutputs))
|
||||||
|
|
||||||
// The justice transaction we construct will be a segwit transaction
|
// The justice transaction we construct will be a segwit transaction
|
||||||
// that pays to a p2wkh output. Components such as the version,
|
// that pays to a p2wkh output. Components such as the version,
|
||||||
@ -975,38 +975,38 @@ func (b *breachArbiter) createJusticeTx(
|
|||||||
// finally adding to our list of spendable outputs.
|
// finally adding to our list of spendable outputs.
|
||||||
for i := range r.breachedOutputs {
|
for i := range r.breachedOutputs {
|
||||||
// Grab locally scoped reference to breached output.
|
// Grab locally scoped reference to breached output.
|
||||||
input := &r.breachedOutputs[i]
|
inp := &r.breachedOutputs[i]
|
||||||
|
|
||||||
// First, select the appropriate estimated witness weight for
|
// First, select the appropriate estimated witness weight for
|
||||||
// the give witness type of this breached output. If the witness
|
// the give witness type of this breached output. If the witness
|
||||||
// type is unrecognized, we will omit it from the transaction.
|
// type is unrecognized, we will omit it from the transaction.
|
||||||
var witnessWeight int
|
var witnessWeight int
|
||||||
switch input.WitnessType() {
|
switch inp.WitnessType() {
|
||||||
case lnwallet.CommitmentNoDelay:
|
case input.CommitmentNoDelay:
|
||||||
witnessWeight = lnwallet.P2WKHWitnessSize
|
witnessWeight = input.P2WKHWitnessSize
|
||||||
|
|
||||||
case lnwallet.CommitmentRevoke:
|
case input.CommitmentRevoke:
|
||||||
witnessWeight = lnwallet.ToLocalPenaltyWitnessSize
|
witnessWeight = input.ToLocalPenaltyWitnessSize
|
||||||
|
|
||||||
case lnwallet.HtlcOfferedRevoke:
|
case input.HtlcOfferedRevoke:
|
||||||
witnessWeight = lnwallet.OfferedHtlcPenaltyWitnessSize
|
witnessWeight = input.OfferedHtlcPenaltyWitnessSize
|
||||||
|
|
||||||
case lnwallet.HtlcAcceptedRevoke:
|
case input.HtlcAcceptedRevoke:
|
||||||
witnessWeight = lnwallet.AcceptedHtlcPenaltyWitnessSize
|
witnessWeight = input.AcceptedHtlcPenaltyWitnessSize
|
||||||
|
|
||||||
case lnwallet.HtlcSecondLevelRevoke:
|
case input.HtlcSecondLevelRevoke:
|
||||||
witnessWeight = lnwallet.ToLocalPenaltyWitnessSize
|
witnessWeight = input.ToLocalPenaltyWitnessSize
|
||||||
|
|
||||||
default:
|
default:
|
||||||
brarLog.Warnf("breached output in retribution info "+
|
brarLog.Warnf("breached output in retribution info "+
|
||||||
"contains unexpected witness type: %v",
|
"contains unexpected witness type: %v",
|
||||||
input.WitnessType())
|
inp.WitnessType())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
weightEstimate.AddWitnessInput(witnessWeight)
|
weightEstimate.AddWitnessInput(witnessWeight)
|
||||||
|
|
||||||
// Finally, append this input to our list of spendable outputs.
|
// Finally, append this input to our list of spendable outputs.
|
||||||
spendableOutputs = append(spendableOutputs, input)
|
spendableOutputs = append(spendableOutputs, inp)
|
||||||
}
|
}
|
||||||
|
|
||||||
txWeight := int64(weightEstimate.Weight())
|
txWeight := int64(weightEstimate.Weight())
|
||||||
@ -1016,7 +1016,7 @@ func (b *breachArbiter) createJusticeTx(
|
|||||||
// sweepSpendableOutputsTxn creates a signed transaction from a sequence of
|
// sweepSpendableOutputsTxn creates a signed transaction from a sequence of
|
||||||
// spendable outputs by sweeping the funds into a single p2wkh output.
|
// spendable outputs by sweeping the funds into a single p2wkh output.
|
||||||
func (b *breachArbiter) sweepSpendableOutputsTxn(txWeight int64,
|
func (b *breachArbiter) sweepSpendableOutputsTxn(txWeight int64,
|
||||||
inputs ...sweep.Input) (*wire.MsgTx, error) {
|
inputs ...input.Input) (*wire.MsgTx, error) {
|
||||||
|
|
||||||
// First, we obtain a new public key script from the wallet which we'll
|
// First, we obtain a new public key script from the wallet which we'll
|
||||||
// sweep the funds to.
|
// sweep the funds to.
|
||||||
@ -1078,7 +1078,7 @@ func (b *breachArbiter) sweepSpendableOutputsTxn(txWeight int64,
|
|||||||
// witness, and attaching it to the transaction. This function accepts
|
// witness, and attaching it to the transaction. This function accepts
|
||||||
// an integer index representing the intended txin index, and the
|
// an integer index representing the intended txin index, and the
|
||||||
// breached output from which it will spend.
|
// breached output from which it will spend.
|
||||||
addWitness := func(idx int, so sweep.Input) error {
|
addWitness := func(idx int, so input.Input) error {
|
||||||
// First, we construct a valid witness for this outpoint and
|
// First, we construct a valid witness for this outpoint and
|
||||||
// transaction using the SpendableOutput's witness generation
|
// transaction using the SpendableOutput's witness generation
|
||||||
// function.
|
// function.
|
||||||
@ -1435,7 +1435,7 @@ func (bo *breachedOutput) Encode(w io.Writer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err := lnwallet.WriteSignDescriptor(w, &bo.signDesc)
|
err := input.WriteSignDescriptor(w, &bo.signDesc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1466,7 +1466,7 @@ func (bo *breachedOutput) Decode(r io.Reader) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := lnwallet.ReadSignDescriptor(r, &bo.signDesc); err != nil {
|
if err := input.ReadSignDescriptor(r, &bo.signDesc); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1479,7 +1479,7 @@ func (bo *breachedOutput) Decode(r io.Reader) error {
|
|||||||
if _, err := io.ReadFull(r, scratch[:2]); err != nil {
|
if _, err := io.ReadFull(r, scratch[:2]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
bo.witnessType = lnwallet.WitnessType(
|
bo.witnessType = input.WitnessType(
|
||||||
binary.BigEndian.Uint16(scratch[:2]),
|
binary.BigEndian.Uint16(scratch[:2]),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
@ -94,8 +95,8 @@ var (
|
|||||||
{
|
{
|
||||||
amt: btcutil.Amount(1e7),
|
amt: btcutil.Amount(1e7),
|
||||||
outpoint: breachOutPoints[0],
|
outpoint: breachOutPoints[0],
|
||||||
witnessType: lnwallet.CommitmentNoDelay,
|
witnessType: input.CommitmentNoDelay,
|
||||||
signDesc: lnwallet.SignDescriptor{
|
signDesc: input.SignDescriptor{
|
||||||
SingleTweak: []byte{
|
SingleTweak: []byte{
|
||||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||||
@ -138,8 +139,8 @@ var (
|
|||||||
{
|
{
|
||||||
amt: btcutil.Amount(2e9),
|
amt: btcutil.Amount(2e9),
|
||||||
outpoint: breachOutPoints[1],
|
outpoint: breachOutPoints[1],
|
||||||
witnessType: lnwallet.CommitmentRevoke,
|
witnessType: input.CommitmentRevoke,
|
||||||
signDesc: lnwallet.SignDescriptor{
|
signDesc: input.SignDescriptor{
|
||||||
SingleTweak: []byte{
|
SingleTweak: []byte{
|
||||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||||
@ -182,8 +183,8 @@ var (
|
|||||||
{
|
{
|
||||||
amt: btcutil.Amount(3e4),
|
amt: btcutil.Amount(3e4),
|
||||||
outpoint: breachOutPoints[2],
|
outpoint: breachOutPoints[2],
|
||||||
witnessType: lnwallet.CommitmentDelayOutput,
|
witnessType: input.CommitmentDelayOutput,
|
||||||
signDesc: lnwallet.SignDescriptor{
|
signDesc: input.SignDescriptor{
|
||||||
SingleTweak: []byte{
|
SingleTweak: []byte{
|
||||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||||
@ -1009,7 +1010,7 @@ func TestBreachHandoffSuccess(t *testing.T) {
|
|||||||
ProcessACK: make(chan error, 1),
|
ProcessACK: make(chan error, 1),
|
||||||
BreachRetribution: &lnwallet.BreachRetribution{
|
BreachRetribution: &lnwallet.BreachRetribution{
|
||||||
BreachTransaction: bobClose.CloseTx,
|
BreachTransaction: bobClose.CloseTx,
|
||||||
LocalOutputSignDesc: &lnwallet.SignDescriptor{
|
LocalOutputSignDesc: &input.SignDescriptor{
|
||||||
Output: &wire.TxOut{
|
Output: &wire.TxOut{
|
||||||
PkScript: breachKeys[0],
|
PkScript: breachKeys[0],
|
||||||
},
|
},
|
||||||
@ -1041,7 +1042,7 @@ func TestBreachHandoffSuccess(t *testing.T) {
|
|||||||
ProcessACK: make(chan error, 1),
|
ProcessACK: make(chan error, 1),
|
||||||
BreachRetribution: &lnwallet.BreachRetribution{
|
BreachRetribution: &lnwallet.BreachRetribution{
|
||||||
BreachTransaction: bobClose.CloseTx,
|
BreachTransaction: bobClose.CloseTx,
|
||||||
LocalOutputSignDesc: &lnwallet.SignDescriptor{
|
LocalOutputSignDesc: &input.SignDescriptor{
|
||||||
Output: &wire.TxOut{
|
Output: &wire.TxOut{
|
||||||
PkScript: breachKeys[0],
|
PkScript: breachKeys[0],
|
||||||
},
|
},
|
||||||
@ -1090,7 +1091,7 @@ func TestBreachHandoffFail(t *testing.T) {
|
|||||||
ProcessACK: make(chan error, 1),
|
ProcessACK: make(chan error, 1),
|
||||||
BreachRetribution: &lnwallet.BreachRetribution{
|
BreachRetribution: &lnwallet.BreachRetribution{
|
||||||
BreachTransaction: bobClose.CloseTx,
|
BreachTransaction: bobClose.CloseTx,
|
||||||
LocalOutputSignDesc: &lnwallet.SignDescriptor{
|
LocalOutputSignDesc: &input.SignDescriptor{
|
||||||
Output: &wire.TxOut{
|
Output: &wire.TxOut{
|
||||||
PkScript: breachKeys[0],
|
PkScript: breachKeys[0],
|
||||||
},
|
},
|
||||||
@ -1130,7 +1131,7 @@ func TestBreachHandoffFail(t *testing.T) {
|
|||||||
ProcessACK: make(chan error, 1),
|
ProcessACK: make(chan error, 1),
|
||||||
BreachRetribution: &lnwallet.BreachRetribution{
|
BreachRetribution: &lnwallet.BreachRetribution{
|
||||||
BreachTransaction: bobClose.CloseTx,
|
BreachTransaction: bobClose.CloseTx,
|
||||||
LocalOutputSignDesc: &lnwallet.SignDescriptor{
|
LocalOutputSignDesc: &input.SignDescriptor{
|
||||||
Output: &wire.TxOut{
|
Output: &wire.TxOut{
|
||||||
PkScript: breachKeys[0],
|
PkScript: breachKeys[0],
|
||||||
},
|
},
|
||||||
@ -1444,7 +1445,7 @@ func createInitChannels(revocationWindow int) (*lnwallet.LightningChannel, *lnwa
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
bobCommitPoint := lnwallet.ComputeCommitmentPoint(bobFirstRevoke[:])
|
bobCommitPoint := input.ComputeCommitmentPoint(bobFirstRevoke[:])
|
||||||
|
|
||||||
aliceRoot, err := chainhash.NewHash(aliceKeyPriv.Serialize())
|
aliceRoot, err := chainhash.NewHash(aliceKeyPriv.Serialize())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1455,7 +1456,7 @@ func createInitChannels(revocationWindow int) (*lnwallet.LightningChannel, *lnwa
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
aliceCommitPoint := lnwallet.ComputeCommitmentPoint(aliceFirstRevoke[:])
|
aliceCommitPoint := input.ComputeCommitmentPoint(aliceFirstRevoke[:])
|
||||||
|
|
||||||
aliceCommitTx, bobCommitTx, err := lnwallet.CreateCommitmentTxns(channelBal,
|
aliceCommitTx, bobCommitTx, err := lnwallet.CreateCommitmentTxns(channelBal,
|
||||||
channelBal, &aliceCfg, &bobCfg, aliceCommitPoint, bobCommitPoint,
|
channelBal, &aliceCfg, &bobCfg, aliceCommitPoint, bobCommitPoint,
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/chainntnfs/neutrinonotify"
|
"github.com/lightningnetwork/lnd/chainntnfs/neutrinonotify"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet/btcwallet"
|
"github.com/lightningnetwork/lnd/lnwallet/btcwallet"
|
||||||
@ -63,14 +64,14 @@ const (
|
|||||||
// TODO(halseth): make configurable at startup?
|
// TODO(halseth): make configurable at startup?
|
||||||
var defaultBtcChannelConstraints = channeldb.ChannelConstraints{
|
var defaultBtcChannelConstraints = channeldb.ChannelConstraints{
|
||||||
DustLimit: lnwallet.DefaultDustLimit(),
|
DustLimit: lnwallet.DefaultDustLimit(),
|
||||||
MaxAcceptedHtlcs: lnwallet.MaxHTLCNumber / 2,
|
MaxAcceptedHtlcs: input.MaxHTLCNumber / 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
// defaultLtcChannelConstraints is the default set of channel constraints that are
|
// defaultLtcChannelConstraints is the default set of channel constraints that are
|
||||||
// meant to be used when initially funding a Litecoin channel.
|
// meant to be used when initially funding a Litecoin channel.
|
||||||
var defaultLtcChannelConstraints = channeldb.ChannelConstraints{
|
var defaultLtcChannelConstraints = channeldb.ChannelConstraints{
|
||||||
DustLimit: defaultLitecoinDustLimit,
|
DustLimit: defaultLitecoinDustLimit,
|
||||||
MaxAcceptedHtlcs: lnwallet.MaxHTLCNumber / 2,
|
MaxAcceptedHtlcs: input.MaxHTLCNumber / 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
// chainCode is an enum-like structure for keeping track of the chains
|
// chainCode is an enum-like structure for keeping track of the chains
|
||||||
@ -105,7 +106,7 @@ type chainControl struct {
|
|||||||
|
|
||||||
feeEstimator lnwallet.FeeEstimator
|
feeEstimator lnwallet.FeeEstimator
|
||||||
|
|
||||||
signer lnwallet.Signer
|
signer input.Signer
|
||||||
|
|
||||||
keyRing keychain.KeyRing
|
keyRing keychain.KeyRing
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/coreos/bbolt"
|
"github.com/coreos/bbolt"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -908,7 +909,7 @@ func encodeIncomingResolution(w io.Writer, i *lnwallet.IncomingHtlcResolution) e
|
|||||||
if err := binary.Write(w, endian, i.ClaimOutpoint.Index); err != nil {
|
if err := binary.Write(w, endian, i.ClaimOutpoint.Index); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err := lnwallet.WriteSignDescriptor(w, &i.SweepSignDesc)
|
err := input.WriteSignDescriptor(w, &i.SweepSignDesc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -945,7 +946,7 @@ func decodeIncomingResolution(r io.Reader, h *lnwallet.IncomingHtlcResolution) e
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return lnwallet.ReadSignDescriptor(r, &h.SweepSignDesc)
|
return input.ReadSignDescriptor(r, &h.SweepSignDesc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeOutgoingResolution(w io.Writer, o *lnwallet.OutgoingHtlcResolution) error {
|
func encodeOutgoingResolution(w io.Writer, o *lnwallet.OutgoingHtlcResolution) error {
|
||||||
@ -977,7 +978,7 @@ func encodeOutgoingResolution(w io.Writer, o *lnwallet.OutgoingHtlcResolution) e
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return lnwallet.WriteSignDescriptor(w, &o.SweepSignDesc)
|
return input.WriteSignDescriptor(w, &o.SweepSignDesc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeOutgoingResolution(r io.Reader, o *lnwallet.OutgoingHtlcResolution) error {
|
func decodeOutgoingResolution(r io.Reader, o *lnwallet.OutgoingHtlcResolution) error {
|
||||||
@ -1010,7 +1011,7 @@ func decodeOutgoingResolution(r io.Reader, o *lnwallet.OutgoingHtlcResolution) e
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return lnwallet.ReadSignDescriptor(r, &o.SweepSignDesc)
|
return input.ReadSignDescriptor(r, &o.SweepSignDesc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeCommitResolution(w io.Writer,
|
func encodeCommitResolution(w io.Writer,
|
||||||
@ -1024,7 +1025,7 @@ func encodeCommitResolution(w io.Writer,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = lnwallet.WriteSignDescriptor(w, &c.SelfOutputSignDesc)
|
err = input.WriteSignDescriptor(w, &c.SelfOutputSignDesc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1044,7 +1045,7 @@ func decodeCommitResolution(r io.Reader,
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = lnwallet.ReadSignDescriptor(r, &c.SelfOutputSignDesc)
|
err = input.ReadSignDescriptor(r, &c.SelfOutputSignDesc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/coreos/bbolt"
|
"github.com/coreos/bbolt"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
)
|
)
|
||||||
@ -63,7 +64,7 @@ var (
|
|||||||
0xb4, 0x12, 0xa3,
|
0xb4, 0x12, 0xa3,
|
||||||
}
|
}
|
||||||
|
|
||||||
testSignDesc = lnwallet.SignDescriptor{
|
testSignDesc = input.SignDescriptor{
|
||||||
SingleTweak: []byte{
|
SingleTweak: []byte{
|
||||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/lightningnetwork/lnd/sweep"
|
"github.com/lightningnetwork/lnd/sweep"
|
||||||
@ -120,7 +121,7 @@ type ChainArbitratorConfig struct {
|
|||||||
// Signer is a signer backed by the active lnd node. This should be
|
// Signer is a signer backed by the active lnd node. This should be
|
||||||
// capable of producing a signature as specified by a valid
|
// capable of producing a signature as specified by a valid
|
||||||
// SignDescriptor.
|
// SignDescriptor.
|
||||||
Signer lnwallet.Signer
|
Signer input.Signer
|
||||||
|
|
||||||
// FeeEstimator will be used to return fee estimates.
|
// FeeEstimator will be used to return fee estimates.
|
||||||
FeeEstimator lnwallet.FeeEstimator
|
FeeEstimator lnwallet.FeeEstimator
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -93,7 +94,7 @@ type chainWatcherConfig struct {
|
|||||||
// signer is the main signer instances that will be responsible for
|
// signer is the main signer instances that will be responsible for
|
||||||
// signing any HTLC and commitment transaction generated by the state
|
// signing any HTLC and commitment transaction generated by the state
|
||||||
// machine.
|
// machine.
|
||||||
signer lnwallet.Signer
|
signer input.Signer
|
||||||
|
|
||||||
// contractBreach is a method that will be called by the watcher if it
|
// contractBreach is a method that will be called by the watcher if it
|
||||||
// detects that a contract breach transaction has been confirmed. Only
|
// detects that a contract breach transaction has been confirmed. Only
|
||||||
@ -191,13 +192,13 @@ func (c *chainWatcher) Start() error {
|
|||||||
|
|
||||||
localKey := chanState.LocalChanCfg.MultiSigKey.PubKey.SerializeCompressed()
|
localKey := chanState.LocalChanCfg.MultiSigKey.PubKey.SerializeCompressed()
|
||||||
remoteKey := chanState.RemoteChanCfg.MultiSigKey.PubKey.SerializeCompressed()
|
remoteKey := chanState.RemoteChanCfg.MultiSigKey.PubKey.SerializeCompressed()
|
||||||
multiSigScript, err := lnwallet.GenMultiSigScript(
|
multiSigScript, err := input.GenMultiSigScript(
|
||||||
localKey, remoteKey,
|
localKey, remoteKey,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
pkScript, err := lnwallet.WitnessScriptHash(multiSigScript)
|
pkScript, err := input.WitnessScriptHash(multiSigScript)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
)
|
)
|
||||||
@ -542,7 +543,7 @@ func TestChannelArbitratorLocalForceClosePendingHtlc(t *testing.T) {
|
|||||||
// our commitment transaction got confirmed.
|
// our commitment transaction got confirmed.
|
||||||
outgoingRes := lnwallet.OutgoingHtlcResolution{
|
outgoingRes := lnwallet.OutgoingHtlcResolution{
|
||||||
Expiry: 10,
|
Expiry: 10,
|
||||||
SweepSignDesc: lnwallet.SignDescriptor{
|
SweepSignDesc: input.SignDescriptor{
|
||||||
Output: &wire.TxOut{},
|
Output: &wire.TxOut{},
|
||||||
},
|
},
|
||||||
SignedTimeoutTx: &wire.MsgTx{
|
SignedTimeoutTx: &wire.MsgTx{
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
|
||||||
@ -100,9 +101,9 @@ func (c *commitSweepResolver) Resolve() (ContractResolver, error) {
|
|||||||
// we'll now craft an input with all the information required
|
// we'll now craft an input with all the information required
|
||||||
// to create a fully valid sweeping transaction to recover
|
// to create a fully valid sweeping transaction to recover
|
||||||
// these coins.
|
// these coins.
|
||||||
input := sweep.MakeBaseInput(
|
inp := input.MakeBaseInput(
|
||||||
&c.commitResolution.SelfOutPoint,
|
&c.commitResolution.SelfOutPoint,
|
||||||
lnwallet.CommitmentNoDelay,
|
input.CommitmentNoDelay,
|
||||||
&c.commitResolution.SelfOutputSignDesc,
|
&c.commitResolution.SelfOutputSignDesc,
|
||||||
c.broadcastHeight,
|
c.broadcastHeight,
|
||||||
)
|
)
|
||||||
@ -117,7 +118,7 @@ func (c *commitSweepResolver) Resolve() (ContractResolver, error) {
|
|||||||
//
|
//
|
||||||
// TODO: Use time-based sweeper and result chan.
|
// TODO: Use time-based sweeper and result chan.
|
||||||
c.sweepTx, err = c.Sweeper.CreateSweepTx(
|
c.sweepTx, err = c.Sweeper.CreateSweepTx(
|
||||||
[]sweep.Input{&input},
|
[]input.Input{&inp},
|
||||||
sweep.FeePreference{
|
sweep.FeePreference{
|
||||||
ConfTarget: sweepConfTarget,
|
ConfTarget: sweepConfTarget,
|
||||||
}, 0,
|
}, 0,
|
||||||
|
@ -2,12 +2,12 @@ package contractcourt
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// htlcOutgoingContestResolver is a ContractResolver that's able to resolve an
|
// htlcOutgoingContestResolver is a ContractResolver that's able to resolve an
|
||||||
@ -119,7 +119,7 @@ func (h *htlcOutgoingContestResolver) Resolve() (ContractResolver, error) {
|
|||||||
// re-construct the pkScipt we need to watch.
|
// re-construct the pkScipt we need to watch.
|
||||||
outPointToWatch = h.htlcResolution.SignedTimeoutTx.TxIn[0].PreviousOutPoint
|
outPointToWatch = h.htlcResolution.SignedTimeoutTx.TxIn[0].PreviousOutPoint
|
||||||
witness := h.htlcResolution.SignedTimeoutTx.TxIn[0].Witness
|
witness := h.htlcResolution.SignedTimeoutTx.TxIn[0].Witness
|
||||||
scriptToWatch, err = lnwallet.WitnessScriptHash(
|
scriptToWatch, err = input.WitnessScriptHash(
|
||||||
witness[len(witness)-1],
|
witness[len(witness)-1],
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -3,6 +3,7 @@ package contractcourt
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
@ -104,7 +105,7 @@ func (h *htlcSuccessResolver) Resolve() (ContractResolver, error) {
|
|||||||
// need to create an input which contains all the items
|
// need to create an input which contains all the items
|
||||||
// required to add this input to a sweeping transaction,
|
// required to add this input to a sweeping transaction,
|
||||||
// and generate a witness.
|
// and generate a witness.
|
||||||
input := sweep.MakeHtlcSucceedInput(
|
inp := input.MakeHtlcSucceedInput(
|
||||||
&h.htlcResolution.ClaimOutpoint,
|
&h.htlcResolution.ClaimOutpoint,
|
||||||
&h.htlcResolution.SweepSignDesc,
|
&h.htlcResolution.SweepSignDesc,
|
||||||
h.htlcResolution.Preimage[:],
|
h.htlcResolution.Preimage[:],
|
||||||
@ -122,7 +123,7 @@ func (h *htlcSuccessResolver) Resolve() (ContractResolver, error) {
|
|||||||
// TODO: Use time-based sweeper and result chan.
|
// TODO: Use time-based sweeper and result chan.
|
||||||
var err error
|
var err error
|
||||||
h.sweepTx, err = h.Sweeper.CreateSweepTx(
|
h.sweepTx, err = h.Sweeper.CreateSweepTx(
|
||||||
[]sweep.Input{&input},
|
[]input.Input{&inp},
|
||||||
sweep.FeePreference{
|
sweep.FeePreference{
|
||||||
ConfTarget: sweepConfTarget,
|
ConfTarget: sweepConfTarget,
|
||||||
}, 0,
|
}, 0,
|
||||||
|
@ -3,8 +3,9 @@ package wirefuzz
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Fuzz is used by go-fuzz to fuzz for potentially malicious input
|
// Fuzz is used by go-fuzz to fuzz for potentially malicious input
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
"github.com/lightningnetwork/lnd/lnpeer"
|
"github.com/lightningnetwork/lnd/lnpeer"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
@ -1847,12 +1848,12 @@ func makeFundingScript(channel *channeldb.OpenChannel) ([]byte, error) {
|
|||||||
localKey := channel.LocalChanCfg.MultiSigKey.PubKey.SerializeCompressed()
|
localKey := channel.LocalChanCfg.MultiSigKey.PubKey.SerializeCompressed()
|
||||||
remoteKey := channel.RemoteChanCfg.MultiSigKey.PubKey.SerializeCompressed()
|
remoteKey := channel.RemoteChanCfg.MultiSigKey.PubKey.SerializeCompressed()
|
||||||
|
|
||||||
multiSigScript, err := lnwallet.GenMultiSigScript(localKey, remoteKey)
|
multiSigScript, err := input.GenMultiSigScript(localKey, remoteKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return lnwallet.WitnessScriptHash(multiSigScript)
|
return input.WitnessScriptHash(multiSigScript)
|
||||||
}
|
}
|
||||||
|
|
||||||
// waitForFundingConfirmation handles the final stages of the channel funding
|
// waitForFundingConfirmation handles the final stages of the channel funding
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
"github.com/lightningnetwork/lnd/lnpeer"
|
"github.com/lightningnetwork/lnd/lnpeer"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
@ -202,7 +203,7 @@ func (n *testNode) AddNewChannel(channel *channeldb.OpenChannel,
|
|||||||
|
|
||||||
func createTestWallet(cdb *channeldb.DB, netParams *chaincfg.Params,
|
func createTestWallet(cdb *channeldb.DB, netParams *chaincfg.Params,
|
||||||
notifier chainntnfs.ChainNotifier, wc lnwallet.WalletController,
|
notifier chainntnfs.ChainNotifier, wc lnwallet.WalletController,
|
||||||
signer lnwallet.Signer, keyRing keychain.SecretKeyRing,
|
signer input.Signer, keyRing keychain.SecretKeyRing,
|
||||||
bio lnwallet.BlockChainIO,
|
bio lnwallet.BlockChainIO,
|
||||||
estimator lnwallet.FeeEstimator) (*lnwallet.LightningWallet, error) {
|
estimator lnwallet.FeeEstimator) (*lnwallet.LightningWallet, error) {
|
||||||
|
|
||||||
@ -340,7 +341,7 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey,
|
|||||||
return lnwire.NewMSatFromSatoshis(chanAmt) - reserve
|
return lnwire.NewMSatFromSatoshis(chanAmt) - reserve
|
||||||
},
|
},
|
||||||
RequiredRemoteMaxHTLCs: func(chanAmt btcutil.Amount) uint16 {
|
RequiredRemoteMaxHTLCs: func(chanAmt btcutil.Amount) uint16 {
|
||||||
return uint16(lnwallet.MaxHTLCNumber / 2)
|
return uint16(input.MaxHTLCNumber / 2)
|
||||||
},
|
},
|
||||||
WatchNewChannel: func(*channeldb.OpenChannel, *btcec.PublicKey) error {
|
WatchNewChannel: func(*channeldb.OpenChannel, *btcec.PublicKey) error {
|
||||||
return nil
|
return nil
|
||||||
|
@ -15,6 +15,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/contractcourt"
|
"github.com/lightningnetwork/lnd/contractcourt"
|
||||||
"github.com/lightningnetwork/lnd/htlcswitch/hodl"
|
"github.com/lightningnetwork/lnd/htlcswitch/hodl"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnpeer"
|
"github.com/lightningnetwork/lnd/lnpeer"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
@ -348,7 +349,7 @@ func NewChannelLink(cfg ChannelLinkConfig,
|
|||||||
shortChanID: channel.ShortChanID(),
|
shortChanID: channel.ShortChanID(),
|
||||||
// TODO(roasbeef): just do reserve here?
|
// TODO(roasbeef): just do reserve here?
|
||||||
logCommitTimer: time.NewTimer(300 * time.Millisecond),
|
logCommitTimer: time.NewTimer(300 * time.Millisecond),
|
||||||
overflowQueue: newPacketQueue(lnwallet.MaxHTLCNumber / 2),
|
overflowQueue: newPacketQueue(input.MaxHTLCNumber / 2),
|
||||||
htlcUpdates: make(chan []channeldb.HTLC),
|
htlcUpdates: make(chan []channeldb.HTLC),
|
||||||
quit: make(chan struct{}),
|
quit: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/contractcourt"
|
"github.com/lightningnetwork/lnd/contractcourt"
|
||||||
"github.com/lightningnetwork/lnd/htlcswitch/hodl"
|
"github.com/lightningnetwork/lnd/htlcswitch/hodl"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnpeer"
|
"github.com/lightningnetwork/lnd/lnpeer"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
@ -302,7 +303,7 @@ func TestChannelLinkBidirectionalOneHopPayments(t *testing.T) {
|
|||||||
|
|
||||||
// Send max available payment number in both sides, thereby testing
|
// Send max available payment number in both sides, thereby testing
|
||||||
// the property of channel link to cope with overflowing.
|
// the property of channel link to cope with overflowing.
|
||||||
count := 2 * lnwallet.MaxHTLCNumber
|
count := 2 * input.MaxHTLCNumber
|
||||||
resultChan := make(chan *result, count)
|
resultChan := make(chan *result, count)
|
||||||
for i := 0; i < count/2; i++ {
|
for i := 0; i < count/2; i++ {
|
||||||
go func(i int) {
|
go func(i int) {
|
||||||
@ -1802,7 +1803,7 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) {
|
|||||||
t.Fatalf("unable to query fee estimator: %v", err)
|
t.Fatalf("unable to query fee estimator: %v", err)
|
||||||
}
|
}
|
||||||
htlcFee := lnwire.NewMSatFromSatoshis(
|
htlcFee := lnwire.NewMSatFromSatoshis(
|
||||||
feePerKw.FeeForWeight(lnwallet.HtlcWeight),
|
feePerKw.FeeForWeight(input.HtlcWeight),
|
||||||
)
|
)
|
||||||
|
|
||||||
// The starting bandwidth of the channel should be exactly the amount
|
// The starting bandwidth of the channel should be exactly the amount
|
||||||
@ -2242,7 +2243,7 @@ func TestChannelLinkBandwidthConsistencyOverflow(t *testing.T) {
|
|||||||
// consistency along the way
|
// consistency along the way
|
||||||
htlcAmt := lnwire.NewMSatFromSatoshis(100000)
|
htlcAmt := lnwire.NewMSatFromSatoshis(100000)
|
||||||
totalHtlcAmt := lnwire.MilliSatoshi(0)
|
totalHtlcAmt := lnwire.MilliSatoshi(0)
|
||||||
const numHTLCs = lnwallet.MaxHTLCNumber / 2
|
const numHTLCs = input.MaxHTLCNumber / 2
|
||||||
var preImages [][32]byte
|
var preImages [][32]byte
|
||||||
for i := 0; i < numHTLCs; i++ {
|
for i := 0; i < numHTLCs; i++ {
|
||||||
preImage := addLinkHTLC(htlcID, htlcAmt)
|
preImage := addLinkHTLC(htlcID, htlcAmt)
|
||||||
@ -2280,7 +2281,7 @@ func TestChannelLinkBandwidthConsistencyOverflow(t *testing.T) {
|
|||||||
|
|
||||||
// TODO(roasbeef): increase sleep
|
// TODO(roasbeef): increase sleep
|
||||||
time.Sleep(time.Second * 1)
|
time.Sleep(time.Second * 1)
|
||||||
commitWeight := lnwallet.CommitWeight + lnwallet.HtlcWeight*numHTLCs
|
commitWeight := input.CommitWeight + input.HtlcWeight*numHTLCs
|
||||||
htlcFee := lnwire.NewMSatFromSatoshis(
|
htlcFee := lnwire.NewMSatFromSatoshis(
|
||||||
feePerKw.FeeForWeight(commitWeight),
|
feePerKw.FeeForWeight(commitWeight),
|
||||||
)
|
)
|
||||||
@ -2462,7 +2463,7 @@ func TestChannelLinkTrimCircuitsPending(t *testing.T) {
|
|||||||
|
|
||||||
defaultCommitFee := alice.channel.StateSnapshot().CommitFee
|
defaultCommitFee := alice.channel.StateSnapshot().CommitFee
|
||||||
htlcFee := lnwire.NewMSatFromSatoshis(
|
htlcFee := lnwire.NewMSatFromSatoshis(
|
||||||
feePerKw.FeeForWeight(lnwallet.HtlcWeight),
|
feePerKw.FeeForWeight(input.HtlcWeight),
|
||||||
)
|
)
|
||||||
|
|
||||||
// The starting bandwidth of the channel should be exactly the amount
|
// The starting bandwidth of the channel should be exactly the amount
|
||||||
@ -2740,7 +2741,7 @@ func TestChannelLinkTrimCircuitsNoCommit(t *testing.T) {
|
|||||||
|
|
||||||
defaultCommitFee := alice.channel.StateSnapshot().CommitFee
|
defaultCommitFee := alice.channel.StateSnapshot().CommitFee
|
||||||
htlcFee := lnwire.NewMSatFromSatoshis(
|
htlcFee := lnwire.NewMSatFromSatoshis(
|
||||||
feePerKw.FeeForWeight(lnwallet.HtlcWeight),
|
feePerKw.FeeForWeight(input.HtlcWeight),
|
||||||
)
|
)
|
||||||
|
|
||||||
// The starting bandwidth of the channel should be exactly the amount
|
// The starting bandwidth of the channel should be exactly the amount
|
||||||
@ -2996,7 +2997,7 @@ func TestChannelLinkBandwidthChanReserve(t *testing.T) {
|
|||||||
t.Fatalf("unable to query fee estimator: %v", err)
|
t.Fatalf("unable to query fee estimator: %v", err)
|
||||||
}
|
}
|
||||||
htlcFee := lnwire.NewMSatFromSatoshis(
|
htlcFee := lnwire.NewMSatFromSatoshis(
|
||||||
feePerKw.FeeForWeight(lnwallet.HtlcWeight),
|
feePerKw.FeeForWeight(input.HtlcWeight),
|
||||||
)
|
)
|
||||||
|
|
||||||
// The starting bandwidth of the channel should be exactly the amount
|
// The starting bandwidth of the channel should be exactly the amount
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/contractcourt"
|
"github.com/lightningnetwork/lnd/contractcourt"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnpeer"
|
"github.com/lightningnetwork/lnd/lnpeer"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
@ -747,7 +748,7 @@ type mockSigner struct {
|
|||||||
key *btcec.PrivateKey
|
key *btcec.PrivateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx, signDesc *lnwallet.SignDescriptor) ([]byte, error) {
|
func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx, signDesc *input.SignDescriptor) ([]byte, error) {
|
||||||
amt := signDesc.Output.Value
|
amt := signDesc.Output.Value
|
||||||
witnessScript := signDesc.WitnessScript
|
witnessScript := signDesc.WitnessScript
|
||||||
privKey := m.key
|
privKey := m.key
|
||||||
@ -758,10 +759,10 @@ func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx, signDesc *lnwallet.SignDescri
|
|||||||
|
|
||||||
switch {
|
switch {
|
||||||
case signDesc.SingleTweak != nil:
|
case signDesc.SingleTweak != nil:
|
||||||
privKey = lnwallet.TweakPrivKey(privKey,
|
privKey = input.TweakPrivKey(privKey,
|
||||||
signDesc.SingleTweak)
|
signDesc.SingleTweak)
|
||||||
case signDesc.DoubleTweak != nil:
|
case signDesc.DoubleTweak != nil:
|
||||||
privKey = lnwallet.DeriveRevocationPrivKey(privKey,
|
privKey = input.DeriveRevocationPrivKey(privKey,
|
||||||
signDesc.DoubleTweak)
|
signDesc.DoubleTweak)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -774,7 +775,7 @@ func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx, signDesc *lnwallet.SignDescri
|
|||||||
|
|
||||||
return sig[:len(sig)-1], nil
|
return sig[:len(sig)-1], nil
|
||||||
}
|
}
|
||||||
func (m *mockSigner) ComputeInputScript(tx *wire.MsgTx, signDesc *lnwallet.SignDescriptor) (*lnwallet.InputScript, error) {
|
func (m *mockSigner) ComputeInputScript(tx *wire.MsgTx, signDesc *input.SignDescriptor) (*input.Script, error) {
|
||||||
|
|
||||||
// TODO(roasbeef): expose tweaked signer from lnwallet so don't need to
|
// TODO(roasbeef): expose tweaked signer from lnwallet so don't need to
|
||||||
// duplicate this code?
|
// duplicate this code?
|
||||||
@ -783,10 +784,10 @@ func (m *mockSigner) ComputeInputScript(tx *wire.MsgTx, signDesc *lnwallet.SignD
|
|||||||
|
|
||||||
switch {
|
switch {
|
||||||
case signDesc.SingleTweak != nil:
|
case signDesc.SingleTweak != nil:
|
||||||
privKey = lnwallet.TweakPrivKey(privKey,
|
privKey = input.TweakPrivKey(privKey,
|
||||||
signDesc.SingleTweak)
|
signDesc.SingleTweak)
|
||||||
case signDesc.DoubleTweak != nil:
|
case signDesc.DoubleTweak != nil:
|
||||||
privKey = lnwallet.DeriveRevocationPrivKey(privKey,
|
privKey = input.DeriveRevocationPrivKey(privKey,
|
||||||
signDesc.DoubleTweak)
|
signDesc.DoubleTweak)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -797,7 +798,7 @@ func (m *mockSigner) ComputeInputScript(tx *wire.MsgTx, signDesc *lnwallet.SignD
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &lnwallet.InputScript{
|
return &input.Script{
|
||||||
Witness: witnessScript,
|
Witness: witnessScript,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/contractcourt"
|
"github.com/lightningnetwork/lnd/contractcourt"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
"github.com/lightningnetwork/lnd/lnpeer"
|
"github.com/lightningnetwork/lnd/lnpeer"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
@ -168,7 +169,7 @@ func createTestChannel(alicePrivKey, bobPrivKey []byte,
|
|||||||
channelCapacity),
|
channelCapacity),
|
||||||
ChanReserve: aliceReserve,
|
ChanReserve: aliceReserve,
|
||||||
MinHTLC: 0,
|
MinHTLC: 0,
|
||||||
MaxAcceptedHtlcs: lnwallet.MaxHTLCNumber / 2,
|
MaxAcceptedHtlcs: input.MaxHTLCNumber / 2,
|
||||||
CsvDelay: uint16(csvTimeoutAlice),
|
CsvDelay: uint16(csvTimeoutAlice),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,7 +179,7 @@ func createTestChannel(alicePrivKey, bobPrivKey []byte,
|
|||||||
channelCapacity),
|
channelCapacity),
|
||||||
ChanReserve: bobReserve,
|
ChanReserve: bobReserve,
|
||||||
MinHTLC: 0,
|
MinHTLC: 0,
|
||||||
MaxAcceptedHtlcs: lnwallet.MaxHTLCNumber / 2,
|
MaxAcceptedHtlcs: input.MaxHTLCNumber / 2,
|
||||||
CsvDelay: uint16(csvTimeoutBob),
|
CsvDelay: uint16(csvTimeoutBob),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,7 +242,7 @@ func createTestChannel(alicePrivKey, bobPrivKey []byte,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, err
|
return nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
bobCommitPoint := lnwallet.ComputeCommitmentPoint(bobFirstRevoke[:])
|
bobCommitPoint := input.ComputeCommitmentPoint(bobFirstRevoke[:])
|
||||||
|
|
||||||
aliceRoot, err := chainhash.NewHash(aliceKeyPriv.Serialize())
|
aliceRoot, err := chainhash.NewHash(aliceKeyPriv.Serialize())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -252,7 +253,7 @@ func createTestChannel(alicePrivKey, bobPrivKey []byte,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, err
|
return nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
aliceCommitPoint := lnwallet.ComputeCommitmentPoint(aliceFirstRevoke[:])
|
aliceCommitPoint := input.ComputeCommitmentPoint(aliceFirstRevoke[:])
|
||||||
|
|
||||||
aliceCommitTx, bobCommitTx, err := lnwallet.CreateCommitmentTxns(aliceAmount,
|
aliceCommitTx, bobCommitTx, err := lnwallet.CreateCommitmentTxns(aliceAmount,
|
||||||
bobAmount, &aliceCfg, &bobCfg, aliceCommitPoint, bobCommitPoint,
|
bobAmount, &aliceCfg, &bobCfg, aliceCommitPoint, bobCommitPoint,
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
package sweep
|
package input
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/btcsuite/btcd/txscript"
|
"github.com/btcsuite/btcd/txscript"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Input represents an abstract UTXO which is to be spent using a sweeping
|
// Input represents an abstract UTXO which is to be spent using a sweeping
|
||||||
@ -17,21 +16,21 @@ type Input interface {
|
|||||||
|
|
||||||
// WitnessType returns an enum specifying the type of witness that must
|
// WitnessType returns an enum specifying the type of witness that must
|
||||||
// be generated in order to spend this output.
|
// be generated in order to spend this output.
|
||||||
WitnessType() lnwallet.WitnessType
|
WitnessType() WitnessType
|
||||||
|
|
||||||
// SignDesc returns a reference to a spendable output's sign
|
// SignDesc returns a reference to a spendable output's sign
|
||||||
// descriptor, which is used during signing to compute a valid witness
|
// descriptor, which is used during signing to compute a valid witness
|
||||||
// that spends this output.
|
// that spends this output.
|
||||||
SignDesc() *lnwallet.SignDescriptor
|
SignDesc() *SignDescriptor
|
||||||
|
|
||||||
// CraftInputScript returns a valid set of input scripts allowing this
|
// CraftInputScript returns a valid set of input scripts allowing this
|
||||||
// output to be spent. The returns input scripts should target the
|
// output to be spent. The returns input scripts should target the
|
||||||
// input at location txIndex within the passed transaction. The input
|
// input at location txIndex within the passed transaction. The input
|
||||||
// scripts generated by this method support spending p2wkh, p2wsh, and
|
// scripts generated by this method support spending p2wkh, p2wsh, and
|
||||||
// also nested p2sh outputs.
|
// also nested p2sh outputs.
|
||||||
CraftInputScript(signer lnwallet.Signer, txn *wire.MsgTx,
|
CraftInputScript(signer Signer, txn *wire.MsgTx,
|
||||||
hashCache *txscript.TxSigHashes,
|
hashCache *txscript.TxSigHashes,
|
||||||
txinIdx int) (*lnwallet.InputScript, error)
|
txinIdx int) (*Script, error)
|
||||||
|
|
||||||
// BlocksToMaturity returns the relative timelock, as a number of
|
// BlocksToMaturity returns the relative timelock, as a number of
|
||||||
// blocks, that must be built on top of the confirmation height before
|
// blocks, that must be built on top of the confirmation height before
|
||||||
@ -46,8 +45,8 @@ type Input interface {
|
|||||||
|
|
||||||
type inputKit struct {
|
type inputKit struct {
|
||||||
outpoint wire.OutPoint
|
outpoint wire.OutPoint
|
||||||
witnessType lnwallet.WitnessType
|
witnessType WitnessType
|
||||||
signDesc lnwallet.SignDescriptor
|
signDesc SignDescriptor
|
||||||
heightHint uint32
|
heightHint uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,13 +58,13 @@ func (i *inputKit) OutPoint() *wire.OutPoint {
|
|||||||
|
|
||||||
// WitnessType returns the type of witness that must be generated to spend the
|
// WitnessType returns the type of witness that must be generated to spend the
|
||||||
// breached output.
|
// breached output.
|
||||||
func (i *inputKit) WitnessType() lnwallet.WitnessType {
|
func (i *inputKit) WitnessType() WitnessType {
|
||||||
return i.witnessType
|
return i.witnessType
|
||||||
}
|
}
|
||||||
|
|
||||||
// SignDesc returns the breached output's SignDescriptor, which is used during
|
// SignDesc returns the breached output's SignDescriptor, which is used during
|
||||||
// signing to compute the witness.
|
// signing to compute the witness.
|
||||||
func (i *inputKit) SignDesc() *lnwallet.SignDescriptor {
|
func (i *inputKit) SignDesc() *SignDescriptor {
|
||||||
return &i.signDesc
|
return &i.signDesc
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,8 +82,8 @@ type BaseInput struct {
|
|||||||
|
|
||||||
// MakeBaseInput assembles a new BaseInput that can be used to construct a
|
// MakeBaseInput assembles a new BaseInput that can be used to construct a
|
||||||
// sweep transaction.
|
// sweep transaction.
|
||||||
func MakeBaseInput(outpoint *wire.OutPoint, witnessType lnwallet.WitnessType,
|
func MakeBaseInput(outpoint *wire.OutPoint, witnessType WitnessType,
|
||||||
signDescriptor *lnwallet.SignDescriptor, heightHint uint32) BaseInput {
|
signDescriptor *SignDescriptor, heightHint uint32) BaseInput {
|
||||||
|
|
||||||
return BaseInput{
|
return BaseInput{
|
||||||
inputKit{
|
inputKit{
|
||||||
@ -100,8 +99,8 @@ func MakeBaseInput(outpoint *wire.OutPoint, witnessType lnwallet.WitnessType,
|
|||||||
// to be spent. The returns input scripts should target the input at location
|
// to be spent. The returns input scripts should target the input at location
|
||||||
// txIndex within the passed transaction. The input scripts generated by this
|
// txIndex within the passed transaction. The input scripts generated by this
|
||||||
// method support spending p2wkh, p2wsh, and also nested p2sh outputs.
|
// method support spending p2wkh, p2wsh, and also nested p2sh outputs.
|
||||||
func (bi *BaseInput) CraftInputScript(signer lnwallet.Signer, txn *wire.MsgTx,
|
func (bi *BaseInput) CraftInputScript(signer Signer, txn *wire.MsgTx,
|
||||||
hashCache *txscript.TxSigHashes, txinIdx int) (*lnwallet.InputScript, error) {
|
hashCache *txscript.TxSigHashes, txinIdx int) (*Script, error) {
|
||||||
|
|
||||||
witnessFunc := bi.witnessType.GenWitnessFunc(
|
witnessFunc := bi.witnessType.GenWitnessFunc(
|
||||||
signer, bi.SignDesc(),
|
signer, bi.SignDesc(),
|
||||||
@ -129,13 +128,13 @@ type HtlcSucceedInput struct {
|
|||||||
// MakeHtlcSucceedInput assembles a new redeem input that can be used to
|
// MakeHtlcSucceedInput assembles a new redeem input that can be used to
|
||||||
// construct a sweep transaction.
|
// construct a sweep transaction.
|
||||||
func MakeHtlcSucceedInput(outpoint *wire.OutPoint,
|
func MakeHtlcSucceedInput(outpoint *wire.OutPoint,
|
||||||
signDescriptor *lnwallet.SignDescriptor,
|
signDescriptor *SignDescriptor,
|
||||||
preimage []byte, heightHint uint32) HtlcSucceedInput {
|
preimage []byte, heightHint uint32) HtlcSucceedInput {
|
||||||
|
|
||||||
return HtlcSucceedInput{
|
return HtlcSucceedInput{
|
||||||
inputKit: inputKit{
|
inputKit: inputKit{
|
||||||
outpoint: *outpoint,
|
outpoint: *outpoint,
|
||||||
witnessType: lnwallet.HtlcAcceptedRemoteSuccess,
|
witnessType: HtlcAcceptedRemoteSuccess,
|
||||||
signDesc: *signDescriptor,
|
signDesc: *signDescriptor,
|
||||||
heightHint: heightHint,
|
heightHint: heightHint,
|
||||||
},
|
},
|
||||||
@ -147,21 +146,21 @@ func MakeHtlcSucceedInput(outpoint *wire.OutPoint,
|
|||||||
// to be spent. The returns input scripts should target the input at location
|
// to be spent. The returns input scripts should target the input at location
|
||||||
// txIndex within the passed transaction. The input scripts generated by this
|
// txIndex within the passed transaction. The input scripts generated by this
|
||||||
// method support spending p2wkh, p2wsh, and also nested p2sh outputs.
|
// method support spending p2wkh, p2wsh, and also nested p2sh outputs.
|
||||||
func (h *HtlcSucceedInput) CraftInputScript(signer lnwallet.Signer, txn *wire.MsgTx,
|
func (h *HtlcSucceedInput) CraftInputScript(signer Signer, txn *wire.MsgTx,
|
||||||
hashCache *txscript.TxSigHashes, txinIdx int) (*lnwallet.InputScript, error) {
|
hashCache *txscript.TxSigHashes, txinIdx int) (*Script, error) {
|
||||||
|
|
||||||
desc := h.signDesc
|
desc := h.signDesc
|
||||||
desc.SigHashes = hashCache
|
desc.SigHashes = hashCache
|
||||||
desc.InputIndex = txinIdx
|
desc.InputIndex = txinIdx
|
||||||
|
|
||||||
witness, err := lnwallet.SenderHtlcSpendRedeem(
|
witness, err := SenderHtlcSpendRedeem(
|
||||||
signer, &desc, txn, h.preimage,
|
signer, &desc, txn, h.preimage,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &lnwallet.InputScript{
|
return &Script{
|
||||||
Witness: witness,
|
Witness: witness,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
@ -1,9 +1,8 @@
|
|||||||
package lnwallet
|
package input
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
@ -22,28 +21,6 @@ var (
|
|||||||
// SequenceLockTimeSeconds is the 22nd bit which indicates the lock
|
// SequenceLockTimeSeconds is the 22nd bit which indicates the lock
|
||||||
// time is in seconds.
|
// time is in seconds.
|
||||||
SequenceLockTimeSeconds = uint32(1 << 22)
|
SequenceLockTimeSeconds = uint32(1 << 22)
|
||||||
|
|
||||||
// TimelockShift is used to make sure the commitment transaction is
|
|
||||||
// spendable by setting the locktime with it so that it is larger than
|
|
||||||
// 500,000,000, thus interpreting it as Unix epoch timestamp and not
|
|
||||||
// a block height. It is also smaller than the current timestamp which
|
|
||||||
// has bit (1 << 30) set, so there is no risk of having the commitment
|
|
||||||
// transaction be rejected. This way we can safely use the lower 24 bits
|
|
||||||
// of the locktime field for part of the obscured commitment transaction
|
|
||||||
// number.
|
|
||||||
TimelockShift = uint32(1 << 29)
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// StateHintSize is the total number of bytes used between the sequence
|
|
||||||
// number and locktime of the commitment transaction use to encode a hint
|
|
||||||
// to the state number of a particular commitment transaction.
|
|
||||||
StateHintSize = 6
|
|
||||||
|
|
||||||
// maxStateHint is the maximum state number we're able to encode using
|
|
||||||
// StateHintSize bytes amongst the sequence number and locktime fields
|
|
||||||
// of the commitment transaction.
|
|
||||||
maxStateHint uint64 = (1 << 48) - 1
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// WitnessScriptHash generates a pay-to-witness-script-hash public key script
|
// WitnessScriptHash generates a pay-to-witness-script-hash public key script
|
||||||
@ -162,7 +139,7 @@ func Ripemd160H(d []byte) []byte {
|
|||||||
return h.Sum(nil)
|
return h.Sum(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// senderHTLCScript constructs the public key script for an outgoing HTLC
|
// SenderHTLCScript constructs the public key script for an outgoing HTLC
|
||||||
// output payment for the sender's version of the commitment transaction. The
|
// output payment for the sender's version of the commitment transaction. The
|
||||||
// possible script paths from this output include:
|
// possible script paths from this output include:
|
||||||
//
|
//
|
||||||
@ -192,7 +169,7 @@ func Ripemd160H(d []byte) []byte {
|
|||||||
// OP_CHECKSIG
|
// OP_CHECKSIG
|
||||||
// OP_ENDIF
|
// OP_ENDIF
|
||||||
// OP_ENDIF
|
// OP_ENDIF
|
||||||
func senderHTLCScript(senderHtlcKey, receiverHtlcKey,
|
func SenderHTLCScript(senderHtlcKey, receiverHtlcKey,
|
||||||
revocationKey *btcec.PublicKey, paymentHash []byte) ([]byte, error) {
|
revocationKey *btcec.PublicKey, paymentHash []byte) ([]byte, error) {
|
||||||
|
|
||||||
builder := txscript.NewScriptBuilder()
|
builder := txscript.NewScriptBuilder()
|
||||||
@ -272,14 +249,14 @@ func senderHTLCScript(senderHtlcKey, receiverHtlcKey,
|
|||||||
return builder.Script()
|
return builder.Script()
|
||||||
}
|
}
|
||||||
|
|
||||||
// senderHtlcSpendRevoke constructs a valid witness allowing the receiver of an
|
// SenderHtlcSpendRevokeWithKey constructs a valid witness allowing the receiver of an
|
||||||
// HTLC to claim the output with knowledge of the revocation private key in the
|
// HTLC to claim the output with knowledge of the revocation private key in the
|
||||||
// scenario that the sender of the HTLC broadcasts a previously revoked
|
// scenario that the sender of the HTLC broadcasts a previously revoked
|
||||||
// commitment transaction. A valid spend requires knowledge of the private key
|
// commitment transaction. A valid spend requires knowledge of the private key
|
||||||
// that corresponds to their revocation base point and also the private key fro
|
// that corresponds to their revocation base point and also the private key fro
|
||||||
// the per commitment point, and a valid signature under the combined public
|
// the per commitment point, and a valid signature under the combined public
|
||||||
// key.
|
// key.
|
||||||
func senderHtlcSpendRevoke(signer Signer, signDesc *SignDescriptor,
|
func SenderHtlcSpendRevokeWithKey(signer Signer, signDesc *SignDescriptor,
|
||||||
revokeKey *btcec.PublicKey, sweepTx *wire.MsgTx) (wire.TxWitness, error) {
|
revokeKey *btcec.PublicKey, sweepTx *wire.MsgTx) (wire.TxWitness, error) {
|
||||||
|
|
||||||
sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
|
sweepSig, err := signer.SignOutputRaw(sweepTx, signDesc)
|
||||||
@ -322,7 +299,7 @@ func SenderHtlcSpendRevoke(signer Signer, signDesc *SignDescriptor,
|
|||||||
signDesc.DoubleTweak.PubKey(),
|
signDesc.DoubleTweak.PubKey(),
|
||||||
)
|
)
|
||||||
|
|
||||||
return senderHtlcSpendRevoke(signer, signDesc, revokeKey, sweepTx)
|
return SenderHtlcSpendRevokeWithKey(signer, signDesc, revokeKey, sweepTx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SenderHtlcSpendRedeem constructs a valid witness allowing the receiver of an
|
// SenderHtlcSpendRedeem constructs a valid witness allowing the receiver of an
|
||||||
@ -349,11 +326,11 @@ func SenderHtlcSpendRedeem(signer Signer, signDesc *SignDescriptor,
|
|||||||
return witnessStack, nil
|
return witnessStack, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// senderHtlcSpendTimeout constructs a valid witness allowing the sender of an
|
// SenderHtlcSpendTimeout constructs a valid witness allowing the sender of an
|
||||||
// HTLC to activate the time locked covenant clause of a soon to be expired
|
// HTLC to activate the time locked covenant clause of a soon to be expired
|
||||||
// HTLC. This script simply spends the multi-sig output using the
|
// HTLC. This script simply spends the multi-sig output using the
|
||||||
// pre-generated HTLC timeout transaction.
|
// pre-generated HTLC timeout transaction.
|
||||||
func senderHtlcSpendTimeout(receiverSig []byte, signer Signer,
|
func SenderHtlcSpendTimeout(receiverSig []byte, signer Signer,
|
||||||
signDesc *SignDescriptor, htlcTimeoutTx *wire.MsgTx) (wire.TxWitness, error) {
|
signDesc *SignDescriptor, htlcTimeoutTx *wire.MsgTx) (wire.TxWitness, error) {
|
||||||
|
|
||||||
sweepSig, err := signer.SignOutputRaw(htlcTimeoutTx, signDesc)
|
sweepSig, err := signer.SignOutputRaw(htlcTimeoutTx, signDesc)
|
||||||
@ -375,7 +352,7 @@ func senderHtlcSpendTimeout(receiverSig []byte, signer Signer,
|
|||||||
return witnessStack, nil
|
return witnessStack, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// receiverHTLCScript constructs the public key script for an incoming HTLC
|
// ReceiverHTLCScript constructs the public key script for an incoming HTLC
|
||||||
// output payment for the receiver's version of the commitment transaction. The
|
// output payment for the receiver's version of the commitment transaction. The
|
||||||
// possible execution paths from this script include:
|
// possible execution paths from this script include:
|
||||||
// * The receiver of the HTLC uses its second level HTLC transaction to
|
// * The receiver of the HTLC uses its second level HTLC transaction to
|
||||||
@ -405,7 +382,7 @@ func senderHtlcSpendTimeout(receiverSig []byte, signer Signer,
|
|||||||
// OP_CHECKSIG
|
// OP_CHECKSIG
|
||||||
// OP_ENDIF
|
// OP_ENDIF
|
||||||
// OP_ENDIF
|
// OP_ENDIF
|
||||||
func receiverHTLCScript(cltvExpiry uint32, senderHtlcKey,
|
func ReceiverHTLCScript(cltvExpiry uint32, senderHtlcKey,
|
||||||
receiverHtlcKey, revocationKey *btcec.PublicKey,
|
receiverHtlcKey, revocationKey *btcec.PublicKey,
|
||||||
paymentHash []byte) ([]byte, error) {
|
paymentHash []byte) ([]byte, error) {
|
||||||
|
|
||||||
@ -496,7 +473,7 @@ func receiverHTLCScript(cltvExpiry uint32, senderHtlcKey,
|
|||||||
return builder.Script()
|
return builder.Script()
|
||||||
}
|
}
|
||||||
|
|
||||||
// receiverHtlcSpendRedeem constructs a valid witness allowing the receiver of
|
// ReceiverHtlcSpendRedeem constructs a valid witness allowing the receiver of
|
||||||
// an HTLC to redeem the conditional payment in the event that their commitment
|
// an HTLC to redeem the conditional payment in the event that their commitment
|
||||||
// transaction is broadcast. This clause transitions the state of the HLTC
|
// transaction is broadcast. This clause transitions the state of the HLTC
|
||||||
// output into the delay+claim state by activating the off-chain covenant bound
|
// output into the delay+claim state by activating the off-chain covenant bound
|
||||||
@ -504,7 +481,7 @@ func receiverHTLCScript(cltvExpiry uint32, senderHtlcKey,
|
|||||||
// signed has a relative timelock delay enforced by its sequence number. This
|
// signed has a relative timelock delay enforced by its sequence number. This
|
||||||
// delay give the sender of the HTLC enough time to revoke the output if this
|
// delay give the sender of the HTLC enough time to revoke the output if this
|
||||||
// is a breach commitment transaction.
|
// is a breach commitment transaction.
|
||||||
func receiverHtlcSpendRedeem(senderSig, paymentPreimage []byte,
|
func ReceiverHtlcSpendRedeem(senderSig, paymentPreimage []byte,
|
||||||
signer Signer, signDesc *SignDescriptor,
|
signer Signer, signDesc *SignDescriptor,
|
||||||
htlcSuccessTx *wire.MsgTx) (wire.TxWitness, error) {
|
htlcSuccessTx *wire.MsgTx) (wire.TxWitness, error) {
|
||||||
|
|
||||||
@ -530,11 +507,11 @@ func receiverHtlcSpendRedeem(senderSig, paymentPreimage []byte,
|
|||||||
return witnessStack, nil
|
return witnessStack, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// receiverHtlcSpendRevoke constructs a valid witness allowing the sender of an
|
// ReceiverHtlcSpendRevokeWithKey constructs a valid witness allowing the sender of an
|
||||||
// HTLC within a previously revoked commitment transaction to re-claim the
|
// HTLC within a previously revoked commitment transaction to re-claim the
|
||||||
// pending funds in the case that the receiver broadcasts this revoked
|
// pending funds in the case that the receiver broadcasts this revoked
|
||||||
// commitment transaction.
|
// commitment transaction.
|
||||||
func receiverHtlcSpendRevoke(signer Signer, signDesc *SignDescriptor,
|
func ReceiverHtlcSpendRevokeWithKey(signer Signer, signDesc *SignDescriptor,
|
||||||
revokeKey *btcec.PublicKey, sweepTx *wire.MsgTx) (wire.TxWitness, error) {
|
revokeKey *btcec.PublicKey, sweepTx *wire.MsgTx) (wire.TxWitness, error) {
|
||||||
|
|
||||||
// First, we'll generate a signature for the sweep transaction. The
|
// First, we'll generate a signature for the sweep transaction. The
|
||||||
@ -579,10 +556,10 @@ func ReceiverHtlcSpendRevoke(signer Signer, signDesc *SignDescriptor,
|
|||||||
signDesc.DoubleTweak.PubKey(),
|
signDesc.DoubleTweak.PubKey(),
|
||||||
)
|
)
|
||||||
|
|
||||||
return receiverHtlcSpendRevoke(signer, signDesc, revokeKey, sweepTx)
|
return ReceiverHtlcSpendRevokeWithKey(signer, signDesc, revokeKey, sweepTx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// receiverHtlcSpendTimeout constructs a valid witness allowing the sender of
|
// ReceiverHtlcSpendTimeout constructs a valid witness allowing the sender of
|
||||||
// an HTLC to recover the pending funds after an absolute timeout in the
|
// an HTLC to recover the pending funds after an absolute timeout in the
|
||||||
// scenario that the receiver of the HTLC broadcasts their version of the
|
// scenario that the receiver of the HTLC broadcasts their version of the
|
||||||
// commitment transaction. If the caller has already set the lock time on the
|
// commitment transaction. If the caller has already set the lock time on the
|
||||||
@ -591,7 +568,7 @@ func ReceiverHtlcSpendRevoke(signer Signer, signDesc *SignDescriptor,
|
|||||||
//
|
//
|
||||||
// NOTE: The target input of the passed transaction MUST NOT have a final
|
// NOTE: The target input of the passed transaction MUST NOT have a final
|
||||||
// sequence number. Otherwise, the OP_CHECKLOCKTIMEVERIFY check will fail.
|
// sequence number. Otherwise, the OP_CHECKLOCKTIMEVERIFY check will fail.
|
||||||
func receiverHtlcSpendTimeout(signer Signer, signDesc *SignDescriptor,
|
func ReceiverHtlcSpendTimeout(signer Signer, signDesc *SignDescriptor,
|
||||||
sweepTx *wire.MsgTx, cltvExpiry int32) (wire.TxWitness, error) {
|
sweepTx *wire.MsgTx, cltvExpiry int32) (wire.TxWitness, error) {
|
||||||
|
|
||||||
// If the caller set a proper timeout value, then we'll apply it
|
// If the caller set a proper timeout value, then we'll apply it
|
||||||
@ -622,109 +599,7 @@ func receiverHtlcSpendTimeout(signer Signer, signDesc *SignDescriptor,
|
|||||||
return witnessStack, nil
|
return witnessStack, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// createHtlcTimeoutTx creates a transaction that spends the HTLC output on the
|
// SecondLevelHtlcScript is the uniform script that's used as the output for
|
||||||
// commitment transaction of the peer that created an HTLC (the sender). This
|
|
||||||
// transaction essentially acts as an off-chain covenant as it spends a 2-of-2
|
|
||||||
// multi-sig output. This output requires a signature from both the sender and
|
|
||||||
// receiver of the HTLC. By using a distinct transaction, we're able to
|
|
||||||
// uncouple the timeout and delay clauses of the HTLC contract. This
|
|
||||||
// transaction is locked with an absolute lock-time so the sender can only
|
|
||||||
// attempt to claim the output using it after the lock time has passed.
|
|
||||||
//
|
|
||||||
// In order to spend the HTLC output, the witness for the passed transaction
|
|
||||||
// should be:
|
|
||||||
// * <0> <sender sig> <receiver sig> <0>
|
|
||||||
//
|
|
||||||
// NOTE: The passed amount for the HTLC should take into account the required
|
|
||||||
// fee rate at the time the HTLC was created. The fee should be able to
|
|
||||||
// entirely pay for this (tiny: 1-in 1-out) transaction.
|
|
||||||
func createHtlcTimeoutTx(htlcOutput wire.OutPoint, htlcAmt btcutil.Amount,
|
|
||||||
cltvExpiry, csvDelay uint32,
|
|
||||||
revocationKey, delayKey *btcec.PublicKey) (*wire.MsgTx, error) {
|
|
||||||
|
|
||||||
// Create a version two transaction (as the success version of this
|
|
||||||
// spends an output with a CSV timeout), and set the lock-time to the
|
|
||||||
// specified absolute lock-time in blocks.
|
|
||||||
timeoutTx := wire.NewMsgTx(2)
|
|
||||||
timeoutTx.LockTime = cltvExpiry
|
|
||||||
|
|
||||||
// The input to the transaction is the outpoint that creates the
|
|
||||||
// original HTLC on the sender's commitment transaction.
|
|
||||||
timeoutTx.AddTxIn(&wire.TxIn{
|
|
||||||
PreviousOutPoint: htlcOutput,
|
|
||||||
})
|
|
||||||
|
|
||||||
// Next, we'll generate the script used as the output for all second
|
|
||||||
// level HTLC which forces a covenant w.r.t what can be done with all
|
|
||||||
// HTLC outputs.
|
|
||||||
witnessScript, err := secondLevelHtlcScript(revocationKey, delayKey,
|
|
||||||
csvDelay)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
pkScript, err := WitnessScriptHash(witnessScript)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, the output is simply the amount of the HTLC (minus the
|
|
||||||
// required fees), paying to the regular second level HTLC script.
|
|
||||||
timeoutTx.AddTxOut(&wire.TxOut{
|
|
||||||
Value: int64(htlcAmt),
|
|
||||||
PkScript: pkScript,
|
|
||||||
})
|
|
||||||
|
|
||||||
return timeoutTx, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// createHtlcSuccessTx creates a transaction that spends the output on the
|
|
||||||
// commitment transaction of the peer that receives an HTLC. This transaction
|
|
||||||
// essentially acts as an off-chain covenant as it's only permitted to spend
|
|
||||||
// the designated HTLC output, and also that spend can _only_ be used as a
|
|
||||||
// state transition to create another output which actually allows redemption
|
|
||||||
// or revocation of an HTLC.
|
|
||||||
//
|
|
||||||
// In order to spend the HTLC output, the witness for the passed transaction
|
|
||||||
// should be:
|
|
||||||
// * <0> <sender sig> <recvr sig> <preimage>
|
|
||||||
func createHtlcSuccessTx(htlcOutput wire.OutPoint, htlcAmt btcutil.Amount,
|
|
||||||
csvDelay uint32,
|
|
||||||
revocationKey, delayKey *btcec.PublicKey) (*wire.MsgTx, error) {
|
|
||||||
|
|
||||||
// Create a version two transaction (as the success version of this
|
|
||||||
// spends an output with a CSV timeout).
|
|
||||||
successTx := wire.NewMsgTx(2)
|
|
||||||
|
|
||||||
// The input to the transaction is the outpoint that creates the
|
|
||||||
// original HTLC on the sender's commitment transaction.
|
|
||||||
successTx.AddTxIn(&wire.TxIn{
|
|
||||||
PreviousOutPoint: htlcOutput,
|
|
||||||
})
|
|
||||||
|
|
||||||
// Next, we'll generate the script used as the output for all second
|
|
||||||
// level HTLC which forces a covenant w.r.t what can be done with all
|
|
||||||
// HTLC outputs.
|
|
||||||
witnessScript, err := secondLevelHtlcScript(revocationKey, delayKey,
|
|
||||||
csvDelay)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
pkScript, err := WitnessScriptHash(witnessScript)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, the output is simply the amount of the HTLC (minus the
|
|
||||||
// required fees), paying to the timeout script.
|
|
||||||
successTx.AddTxOut(&wire.TxOut{
|
|
||||||
Value: int64(htlcAmt),
|
|
||||||
PkScript: pkScript,
|
|
||||||
})
|
|
||||||
|
|
||||||
return successTx, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// secondLevelHtlcScript is the uniform script that's used as the output for
|
|
||||||
// the second-level HTLC transactions. The second level transaction act as a
|
// the second-level HTLC transactions. The second level transaction act as a
|
||||||
// sort of covenant, ensuring that a 2-of-2 multi-sig output can only be
|
// sort of covenant, ensuring that a 2-of-2 multi-sig output can only be
|
||||||
// spent in a particular way, and to a particular output.
|
// spent in a particular way, and to a particular output.
|
||||||
@ -750,7 +625,7 @@ func createHtlcSuccessTx(htlcOutput wire.OutPoint, htlcAmt btcutil.Amount,
|
|||||||
// TODO(roasbeef): possible renames for second-level
|
// TODO(roasbeef): possible renames for second-level
|
||||||
// * transition?
|
// * transition?
|
||||||
// * covenant output
|
// * covenant output
|
||||||
func secondLevelHtlcScript(revocationKey, delayKey *btcec.PublicKey,
|
func SecondLevelHtlcScript(revocationKey, delayKey *btcec.PublicKey,
|
||||||
csvDelay uint32) ([]byte, error) {
|
csvDelay uint32) ([]byte, error) {
|
||||||
|
|
||||||
builder := txscript.NewScriptBuilder()
|
builder := txscript.NewScriptBuilder()
|
||||||
@ -790,16 +665,16 @@ func secondLevelHtlcScript(revocationKey, delayKey *btcec.PublicKey,
|
|||||||
return builder.Script()
|
return builder.Script()
|
||||||
}
|
}
|
||||||
|
|
||||||
// htlcSpendSuccess spends a second-level HTLC output. This function is to be
|
// HtlcSpendSuccess spends a second-level HTLC output. This function is to be
|
||||||
// used by the sender of an HTLC to claim the output after a relative timeout
|
// used by the sender of an HTLC to claim the output after a relative timeout
|
||||||
// or the receiver of the HTLC to claim on-chain with the pre-image.
|
// or the receiver of the HTLC to claim on-chain with the pre-image.
|
||||||
func htlcSpendSuccess(signer Signer, signDesc *SignDescriptor,
|
func HtlcSpendSuccess(signer Signer, signDesc *SignDescriptor,
|
||||||
sweepTx *wire.MsgTx, csvDelay uint32) (wire.TxWitness, error) {
|
sweepTx *wire.MsgTx, csvDelay uint32) (wire.TxWitness, error) {
|
||||||
|
|
||||||
// We're required to wait a relative period of time before we can sweep
|
// We're required to wait a relative period of time before we can sweep
|
||||||
// the output in order to allow the other party to contest our claim of
|
// the output in order to allow the other party to contest our claim of
|
||||||
// validity to this version of the commitment transaction.
|
// validity to this version of the commitment transaction.
|
||||||
sweepTx.TxIn[0].Sequence = lockTimeToSequence(false, csvDelay)
|
sweepTx.TxIn[0].Sequence = LockTimeToSequence(false, csvDelay)
|
||||||
|
|
||||||
// Finally, OP_CSV requires that the version of the transaction
|
// Finally, OP_CSV requires that the version of the transaction
|
||||||
// spending a pkscript with OP_CSV within it *must* be >= 2.
|
// spending a pkscript with OP_CSV within it *must* be >= 2.
|
||||||
@ -829,10 +704,10 @@ func htlcSpendSuccess(signer Signer, signDesc *SignDescriptor,
|
|||||||
return witnessStack, nil
|
return witnessStack, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// htlcSpendRevoke spends a second-level HTLC output. This function is to be
|
// HtlcSpendRevoke spends a second-level HTLC output. This function is to be
|
||||||
// used by the sender or receiver of an HTLC to claim the HTLC after a revoked
|
// used by the sender or receiver of an HTLC to claim the HTLC after a revoked
|
||||||
// commitment transaction was broadcast.
|
// commitment transaction was broadcast.
|
||||||
func htlcSpendRevoke(signer Signer, signDesc *SignDescriptor,
|
func HtlcSpendRevoke(signer Signer, signDesc *SignDescriptor,
|
||||||
revokeTx *wire.MsgTx) (wire.TxWitness, error) {
|
revokeTx *wire.MsgTx) (wire.TxWitness, error) {
|
||||||
|
|
||||||
// We don't need any spacial modifications to the transaction as this
|
// We don't need any spacial modifications to the transaction as this
|
||||||
@ -885,11 +760,11 @@ func HtlcSecondLevelSpend(signer Signer, signDesc *SignDescriptor,
|
|||||||
return witnessStack, nil
|
return witnessStack, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// lockTimeToSequence converts the passed relative locktime to a sequence
|
// LockTimeToSequence converts the passed relative locktime to a sequence
|
||||||
// number in accordance to BIP-68.
|
// number in accordance to BIP-68.
|
||||||
// See: https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki
|
// See: https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki
|
||||||
// * (Compatibility)
|
// * (Compatibility)
|
||||||
func lockTimeToSequence(isSeconds bool, locktime uint32) uint32 {
|
func LockTimeToSequence(isSeconds bool, locktime uint32) uint32 {
|
||||||
if !isSeconds {
|
if !isSeconds {
|
||||||
// The locktime is to be expressed in confirmations.
|
// The locktime is to be expressed in confirmations.
|
||||||
return locktime
|
return locktime
|
||||||
@ -1235,71 +1110,6 @@ func DeriveRevocationPrivKey(revokeBasePriv *btcec.PrivateKey,
|
|||||||
return priv
|
return priv
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetStateNumHint encodes the current state number within the passed
|
|
||||||
// commitment transaction by re-purposing the locktime and sequence fields in
|
|
||||||
// the commitment transaction to encode the obfuscated state number. The state
|
|
||||||
// number is encoded using 48 bits. The lower 24 bits of the lock time are the
|
|
||||||
// lower 24 bits of the obfuscated state number and the lower 24 bits of the
|
|
||||||
// sequence field are the higher 24 bits. Finally before encoding, the
|
|
||||||
// obfuscator is XOR'd against the state number in order to hide the exact
|
|
||||||
// state number from the PoV of outside parties.
|
|
||||||
func SetStateNumHint(commitTx *wire.MsgTx, stateNum uint64,
|
|
||||||
obfuscator [StateHintSize]byte) error {
|
|
||||||
|
|
||||||
// With the current schema we are only able to encode state num
|
|
||||||
// hints up to 2^48. Therefore if the passed height is greater than our
|
|
||||||
// state hint ceiling, then exit early.
|
|
||||||
if stateNum > maxStateHint {
|
|
||||||
return fmt.Errorf("unable to encode state, %v is greater "+
|
|
||||||
"state num that max of %v", stateNum, maxStateHint)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(commitTx.TxIn) != 1 {
|
|
||||||
return fmt.Errorf("commitment tx must have exactly 1 input, "+
|
|
||||||
"instead has %v", len(commitTx.TxIn))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert the obfuscator into a uint64, then XOR that against the
|
|
||||||
// targeted height in order to obfuscate the state number of the
|
|
||||||
// commitment transaction in the case that either commitment
|
|
||||||
// transaction is broadcast directly on chain.
|
|
||||||
var obfs [8]byte
|
|
||||||
copy(obfs[2:], obfuscator[:])
|
|
||||||
xorInt := binary.BigEndian.Uint64(obfs[:])
|
|
||||||
|
|
||||||
stateNum = stateNum ^ xorInt
|
|
||||||
|
|
||||||
// Set the height bit of the sequence number in order to disable any
|
|
||||||
// sequence locks semantics.
|
|
||||||
commitTx.TxIn[0].Sequence = uint32(stateNum>>24) | wire.SequenceLockTimeDisabled
|
|
||||||
commitTx.LockTime = uint32(stateNum&0xFFFFFF) | TimelockShift
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetStateNumHint recovers the current state number given a commitment
|
|
||||||
// transaction which has previously had the state number encoded within it via
|
|
||||||
// setStateNumHint and a shared obfuscator.
|
|
||||||
//
|
|
||||||
// See setStateNumHint for further details w.r.t exactly how the state-hints
|
|
||||||
// are encoded.
|
|
||||||
func GetStateNumHint(commitTx *wire.MsgTx, obfuscator [StateHintSize]byte) uint64 {
|
|
||||||
// Convert the obfuscator into a uint64, this will be used to
|
|
||||||
// de-obfuscate the final recovered state number.
|
|
||||||
var obfs [8]byte
|
|
||||||
copy(obfs[2:], obfuscator[:])
|
|
||||||
xorInt := binary.BigEndian.Uint64(obfs[:])
|
|
||||||
|
|
||||||
// Retrieve the state hint from the sequence number and locktime
|
|
||||||
// of the transaction.
|
|
||||||
stateNumXor := uint64(commitTx.TxIn[0].Sequence&0xFFFFFF) << 24
|
|
||||||
stateNumXor |= uint64(commitTx.LockTime & 0xFFFFFF)
|
|
||||||
|
|
||||||
// Finally, to obtain the final state number, we XOR by the obfuscator
|
|
||||||
// value to de-obfuscate the state number.
|
|
||||||
return stateNumXor ^ xorInt
|
|
||||||
}
|
|
||||||
|
|
||||||
// ComputeCommitmentPoint generates a commitment point given a commitment
|
// ComputeCommitmentPoint generates a commitment point given a commitment
|
||||||
// secret. The commitment point for each state is used to randomize each key in
|
// secret. The commitment point for each state is used to randomize each key in
|
||||||
// the key-ring and also to used as a tweak to derive new public+private keys
|
// the key-ring and also to used as a tweak to derive new public+private keys
|
@ -1,4 +1,4 @@
|
|||||||
package lnwallet
|
package input
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@ -6,7 +6,6 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec"
|
"github.com/btcsuite/btcd/btcec"
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
@ -16,211 +15,6 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestCommitmentSpendValidation test the spendability of both outputs within
|
|
||||||
// the commitment transaction.
|
|
||||||
//
|
|
||||||
// The following spending cases are covered by this test:
|
|
||||||
// * Alice's spend from the delayed output on her commitment transaction.
|
|
||||||
// * Bob's spend from Alice's delayed output when she broadcasts a revoked
|
|
||||||
// commitment transaction.
|
|
||||||
// * Bob's spend from his unencumbered output within Alice's commitment
|
|
||||||
// transaction.
|
|
||||||
func TestCommitmentSpendValidation(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
// We generate a fake output, and the corresponding txin. This output
|
|
||||||
// doesn't need to exist, as we'll only be validating spending from the
|
|
||||||
// transaction that references this.
|
|
||||||
txid, err := chainhash.NewHash(testHdSeed.CloneBytes())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to create txid: %v", err)
|
|
||||||
}
|
|
||||||
fundingOut := &wire.OutPoint{
|
|
||||||
Hash: *txid,
|
|
||||||
Index: 50,
|
|
||||||
}
|
|
||||||
fakeFundingTxIn := wire.NewTxIn(fundingOut, nil, nil)
|
|
||||||
|
|
||||||
const channelBalance = btcutil.Amount(1 * 10e8)
|
|
||||||
const csvTimeout = uint32(5)
|
|
||||||
|
|
||||||
// We also set up set some resources for the commitment transaction.
|
|
||||||
// Each side currently has 1 BTC within the channel, with a total
|
|
||||||
// channel capacity of 2BTC.
|
|
||||||
aliceKeyPriv, aliceKeyPub := btcec.PrivKeyFromBytes(btcec.S256(),
|
|
||||||
testWalletPrivKey)
|
|
||||||
bobKeyPriv, bobKeyPub := btcec.PrivKeyFromBytes(btcec.S256(),
|
|
||||||
bobsPrivKey)
|
|
||||||
|
|
||||||
revocationPreimage := testHdSeed.CloneBytes()
|
|
||||||
commitSecret, commitPoint := btcec.PrivKeyFromBytes(btcec.S256(),
|
|
||||||
revocationPreimage)
|
|
||||||
revokePubKey := DeriveRevocationPubkey(bobKeyPub, commitPoint)
|
|
||||||
|
|
||||||
aliceDelayKey := TweakPubKey(aliceKeyPub, commitPoint)
|
|
||||||
bobPayKey := TweakPubKey(bobKeyPub, commitPoint)
|
|
||||||
|
|
||||||
aliceCommitTweak := SingleTweakBytes(commitPoint, aliceKeyPub)
|
|
||||||
bobCommitTweak := SingleTweakBytes(commitPoint, bobKeyPub)
|
|
||||||
|
|
||||||
aliceSelfOutputSigner := &mockSigner{
|
|
||||||
privkeys: []*btcec.PrivateKey{aliceKeyPriv},
|
|
||||||
}
|
|
||||||
|
|
||||||
// With all the test data set up, we create the commitment transaction.
|
|
||||||
// We only focus on a single party's transactions, as the scripts are
|
|
||||||
// identical with the roles reversed.
|
|
||||||
//
|
|
||||||
// This is Alice's commitment transaction, so she must wait a CSV delay
|
|
||||||
// of 5 blocks before sweeping the output, while bob can spend
|
|
||||||
// immediately with either the revocation key, or his regular key.
|
|
||||||
keyRing := &CommitmentKeyRing{
|
|
||||||
DelayKey: aliceDelayKey,
|
|
||||||
RevocationKey: revokePubKey,
|
|
||||||
NoDelayKey: bobPayKey,
|
|
||||||
}
|
|
||||||
commitmentTx, err := CreateCommitTx(*fakeFundingTxIn, keyRing, csvTimeout,
|
|
||||||
channelBalance, channelBalance, DefaultDustLimit())
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to create commitment transaction: %v", nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
delayOutput := commitmentTx.TxOut[0]
|
|
||||||
regularOutput := commitmentTx.TxOut[1]
|
|
||||||
|
|
||||||
// We're testing an uncooperative close, output sweep, so construct a
|
|
||||||
// transaction which sweeps the funds to a random address.
|
|
||||||
targetOutput, err := CommitScriptUnencumbered(aliceKeyPub)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to create target output: %v", err)
|
|
||||||
}
|
|
||||||
sweepTx := wire.NewMsgTx(2)
|
|
||||||
sweepTx.AddTxIn(wire.NewTxIn(&wire.OutPoint{
|
|
||||||
Hash: commitmentTx.TxHash(),
|
|
||||||
Index: 0,
|
|
||||||
}, nil, nil))
|
|
||||||
sweepTx.AddTxOut(&wire.TxOut{
|
|
||||||
PkScript: targetOutput,
|
|
||||||
Value: 0.5 * 10e8,
|
|
||||||
})
|
|
||||||
|
|
||||||
// First, we'll test spending with Alice's key after the timeout.
|
|
||||||
delayScript, err := CommitScriptToSelf(csvTimeout, aliceDelayKey,
|
|
||||||
revokePubKey)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to generate alice delay script: %v", err)
|
|
||||||
}
|
|
||||||
sweepTx.TxIn[0].Sequence = lockTimeToSequence(false, csvTimeout)
|
|
||||||
signDesc := &SignDescriptor{
|
|
||||||
WitnessScript: delayScript,
|
|
||||||
KeyDesc: keychain.KeyDescriptor{
|
|
||||||
PubKey: aliceKeyPub,
|
|
||||||
},
|
|
||||||
SingleTweak: aliceCommitTweak,
|
|
||||||
SigHashes: txscript.NewTxSigHashes(sweepTx),
|
|
||||||
Output: &wire.TxOut{
|
|
||||||
Value: int64(channelBalance),
|
|
||||||
},
|
|
||||||
HashType: txscript.SigHashAll,
|
|
||||||
InputIndex: 0,
|
|
||||||
}
|
|
||||||
aliceWitnessSpend, err := CommitSpendTimeout(aliceSelfOutputSigner,
|
|
||||||
signDesc, sweepTx)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to generate delay commit spend witness: %v", err)
|
|
||||||
}
|
|
||||||
sweepTx.TxIn[0].Witness = aliceWitnessSpend
|
|
||||||
vm, err := txscript.NewEngine(delayOutput.PkScript,
|
|
||||||
sweepTx, 0, txscript.StandardVerifyFlags, nil,
|
|
||||||
nil, int64(channelBalance))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to create engine: %v", err)
|
|
||||||
}
|
|
||||||
if err := vm.Execute(); err != nil {
|
|
||||||
t.Fatalf("spend from delay output is invalid: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
bobSigner := &mockSigner{privkeys: []*btcec.PrivateKey{bobKeyPriv}}
|
|
||||||
|
|
||||||
// Next, we'll test bob spending with the derived revocation key to
|
|
||||||
// simulate the scenario when Alice broadcasts this commitment
|
|
||||||
// transaction after it's been revoked.
|
|
||||||
signDesc = &SignDescriptor{
|
|
||||||
KeyDesc: keychain.KeyDescriptor{
|
|
||||||
PubKey: bobKeyPub,
|
|
||||||
},
|
|
||||||
DoubleTweak: commitSecret,
|
|
||||||
WitnessScript: delayScript,
|
|
||||||
SigHashes: txscript.NewTxSigHashes(sweepTx),
|
|
||||||
Output: &wire.TxOut{
|
|
||||||
Value: int64(channelBalance),
|
|
||||||
},
|
|
||||||
HashType: txscript.SigHashAll,
|
|
||||||
InputIndex: 0,
|
|
||||||
}
|
|
||||||
bobWitnessSpend, err := CommitSpendRevoke(bobSigner, signDesc,
|
|
||||||
sweepTx)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to generate revocation witness: %v", err)
|
|
||||||
}
|
|
||||||
sweepTx.TxIn[0].Witness = bobWitnessSpend
|
|
||||||
vm, err = txscript.NewEngine(delayOutput.PkScript,
|
|
||||||
sweepTx, 0, txscript.StandardVerifyFlags, nil,
|
|
||||||
nil, int64(channelBalance))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to create engine: %v", err)
|
|
||||||
}
|
|
||||||
if err := vm.Execute(); err != nil {
|
|
||||||
t.Fatalf("revocation spend is invalid: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// In order to test the final scenario, we modify the TxIn of the sweep
|
|
||||||
// transaction to instead point to the regular output (non delay)
|
|
||||||
// within the commitment transaction.
|
|
||||||
sweepTx.TxIn[0] = &wire.TxIn{
|
|
||||||
PreviousOutPoint: wire.OutPoint{
|
|
||||||
Hash: commitmentTx.TxHash(),
|
|
||||||
Index: 1,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, we test bob sweeping his output as normal in the case that
|
|
||||||
// Alice broadcasts this commitment transaction.
|
|
||||||
bobScriptP2WKH, err := CommitScriptUnencumbered(bobPayKey)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to create bob p2wkh script: %v", err)
|
|
||||||
}
|
|
||||||
signDesc = &SignDescriptor{
|
|
||||||
KeyDesc: keychain.KeyDescriptor{
|
|
||||||
PubKey: bobKeyPub,
|
|
||||||
},
|
|
||||||
SingleTweak: bobCommitTweak,
|
|
||||||
WitnessScript: bobScriptP2WKH,
|
|
||||||
SigHashes: txscript.NewTxSigHashes(sweepTx),
|
|
||||||
Output: &wire.TxOut{
|
|
||||||
Value: int64(channelBalance),
|
|
||||||
PkScript: bobScriptP2WKH,
|
|
||||||
},
|
|
||||||
HashType: txscript.SigHashAll,
|
|
||||||
InputIndex: 0,
|
|
||||||
}
|
|
||||||
bobRegularSpend, err := CommitSpendNoDelay(bobSigner, signDesc,
|
|
||||||
sweepTx)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to create bob regular spend: %v", err)
|
|
||||||
}
|
|
||||||
sweepTx.TxIn[0].Witness = bobRegularSpend
|
|
||||||
vm, err = txscript.NewEngine(regularOutput.PkScript,
|
|
||||||
sweepTx, 0, txscript.StandardVerifyFlags, nil,
|
|
||||||
nil, int64(channelBalance))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to create engine: %v", err)
|
|
||||||
}
|
|
||||||
if err := vm.Execute(); err != nil {
|
|
||||||
t.Fatalf("bob p2wkh spend is invalid: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestRevocationKeyDerivation tests that given a public key, and a revocation
|
// TestRevocationKeyDerivation tests that given a public key, and a revocation
|
||||||
// hash, the homomorphic revocation public and private key derivation work
|
// hash, the homomorphic revocation public and private key derivation work
|
||||||
// properly.
|
// properly.
|
||||||
@ -352,7 +146,7 @@ func TestHTLCSenderSpendValidation(t *testing.T) {
|
|||||||
revocationKey := DeriveRevocationPubkey(bobKeyPub, commitPoint)
|
revocationKey := DeriveRevocationPubkey(bobKeyPub, commitPoint)
|
||||||
|
|
||||||
// Generate the raw HTLC redemption scripts, and its p2wsh counterpart.
|
// Generate the raw HTLC redemption scripts, and its p2wsh counterpart.
|
||||||
htlcWitnessScript, err := senderHTLCScript(aliceLocalKey, bobLocalKey,
|
htlcWitnessScript, err := SenderHTLCScript(aliceLocalKey, bobLocalKey,
|
||||||
revocationKey, paymentHash[:])
|
revocationKey, paymentHash[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create htlc sender script: %v", err)
|
t.Fatalf("unable to create htlc sender script: %v", err)
|
||||||
@ -394,8 +188,8 @@ func TestHTLCSenderSpendValidation(t *testing.T) {
|
|||||||
// Finally, we'll create mock signers for both of them based on their
|
// Finally, we'll create mock signers for both of them based on their
|
||||||
// private keys. This test simplifies a bit and uses the same key as
|
// private keys. This test simplifies a bit and uses the same key as
|
||||||
// the base point for all scripts and derivations.
|
// the base point for all scripts and derivations.
|
||||||
bobSigner := &mockSigner{privkeys: []*btcec.PrivateKey{bobKeyPriv}}
|
bobSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{bobKeyPriv}}
|
||||||
aliceSigner := &mockSigner{privkeys: []*btcec.PrivateKey{aliceKeyPriv}}
|
aliceSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{aliceKeyPriv}}
|
||||||
|
|
||||||
// We'll also generate a signature on the sweep transaction above
|
// We'll also generate a signature on the sweep transaction above
|
||||||
// that will act as Bob's signature to Alice for the second level HTLC
|
// that will act as Bob's signature to Alice for the second level HTLC
|
||||||
@ -436,7 +230,7 @@ func TestHTLCSenderSpendValidation(t *testing.T) {
|
|||||||
InputIndex: 0,
|
InputIndex: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
return senderHtlcSpendRevoke(bobSigner, signDesc,
|
return SenderHtlcSpendRevokeWithKey(bobSigner, signDesc,
|
||||||
revocationKey, sweepTx)
|
revocationKey, sweepTx)
|
||||||
}),
|
}),
|
||||||
true,
|
true,
|
||||||
@ -501,7 +295,7 @@ func TestHTLCSenderSpendValidation(t *testing.T) {
|
|||||||
InputIndex: 0,
|
InputIndex: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
return senderHtlcSpendTimeout(bobRecvrSig, aliceSigner,
|
return SenderHtlcSpendTimeout(bobRecvrSig, aliceSigner,
|
||||||
signDesc, sweepTx)
|
signDesc, sweepTx)
|
||||||
}),
|
}),
|
||||||
true,
|
true,
|
||||||
@ -607,7 +401,7 @@ func TestHTLCReceiverSpendValidation(t *testing.T) {
|
|||||||
revocationKey := DeriveRevocationPubkey(aliceKeyPub, commitPoint)
|
revocationKey := DeriveRevocationPubkey(aliceKeyPub, commitPoint)
|
||||||
|
|
||||||
// Generate the raw HTLC redemption scripts, and its p2wsh counterpart.
|
// Generate the raw HTLC redemption scripts, and its p2wsh counterpart.
|
||||||
htlcWitnessScript, err := receiverHTLCScript(cltvTimeout, aliceLocalKey,
|
htlcWitnessScript, err := ReceiverHTLCScript(cltvTimeout, aliceLocalKey,
|
||||||
bobLocalKey, revocationKey, paymentHash[:])
|
bobLocalKey, revocationKey, paymentHash[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create htlc sender script: %v", err)
|
t.Fatalf("unable to create htlc sender script: %v", err)
|
||||||
@ -652,8 +446,8 @@ func TestHTLCReceiverSpendValidation(t *testing.T) {
|
|||||||
// Finally, we'll create mock signers for both of them based on their
|
// Finally, we'll create mock signers for both of them based on their
|
||||||
// private keys. This test simplifies a bit and uses the same key as
|
// private keys. This test simplifies a bit and uses the same key as
|
||||||
// the base point for all scripts and derivations.
|
// the base point for all scripts and derivations.
|
||||||
bobSigner := &mockSigner{privkeys: []*btcec.PrivateKey{bobKeyPriv}}
|
bobSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{bobKeyPriv}}
|
||||||
aliceSigner := &mockSigner{privkeys: []*btcec.PrivateKey{aliceKeyPriv}}
|
aliceSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{aliceKeyPriv}}
|
||||||
|
|
||||||
// We'll also generate a signature on the sweep transaction above
|
// We'll also generate a signature on the sweep transaction above
|
||||||
// that will act as Alice's signature to Bob for the second level HTLC
|
// that will act as Alice's signature to Bob for the second level HTLC
|
||||||
@ -694,7 +488,7 @@ func TestHTLCReceiverSpendValidation(t *testing.T) {
|
|||||||
InputIndex: 0,
|
InputIndex: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
return receiverHtlcSpendRedeem(aliceSenderSig,
|
return ReceiverHtlcSpendRedeem(aliceSenderSig,
|
||||||
bytes.Repeat([]byte{1}, 45), bobSigner,
|
bytes.Repeat([]byte{1}, 45), bobSigner,
|
||||||
signDesc, sweepTx)
|
signDesc, sweepTx)
|
||||||
|
|
||||||
@ -716,7 +510,7 @@ func TestHTLCReceiverSpendValidation(t *testing.T) {
|
|||||||
InputIndex: 0,
|
InputIndex: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
return receiverHtlcSpendRedeem(aliceSenderSig,
|
return ReceiverHtlcSpendRedeem(aliceSenderSig,
|
||||||
paymentPreimage[:], bobSigner,
|
paymentPreimage[:], bobSigner,
|
||||||
signDesc, sweepTx)
|
signDesc, sweepTx)
|
||||||
}),
|
}),
|
||||||
@ -737,7 +531,7 @@ func TestHTLCReceiverSpendValidation(t *testing.T) {
|
|||||||
InputIndex: 0,
|
InputIndex: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
return receiverHtlcSpendRevoke(aliceSigner,
|
return ReceiverHtlcSpendRevokeWithKey(aliceSigner,
|
||||||
signDesc, revocationKey, sweepTx)
|
signDesc, revocationKey, sweepTx)
|
||||||
}),
|
}),
|
||||||
true,
|
true,
|
||||||
@ -757,7 +551,7 @@ func TestHTLCReceiverSpendValidation(t *testing.T) {
|
|||||||
InputIndex: 0,
|
InputIndex: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
return receiverHtlcSpendTimeout(aliceSigner, signDesc,
|
return ReceiverHtlcSpendTimeout(aliceSigner, signDesc,
|
||||||
sweepTx, int32(cltvTimeout-2))
|
sweepTx, int32(cltvTimeout-2))
|
||||||
}),
|
}),
|
||||||
false,
|
false,
|
||||||
@ -777,7 +571,7 @@ func TestHTLCReceiverSpendValidation(t *testing.T) {
|
|||||||
InputIndex: 0,
|
InputIndex: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
return receiverHtlcSpendTimeout(aliceSigner, signDesc,
|
return ReceiverHtlcSpendTimeout(aliceSigner, signDesc,
|
||||||
sweepTx, int32(cltvTimeout))
|
sweepTx, int32(cltvTimeout))
|
||||||
}),
|
}),
|
||||||
true,
|
true,
|
||||||
@ -880,7 +674,7 @@ func TestSecondLevelHtlcSpends(t *testing.T) {
|
|||||||
// Finally we'll generate the HTLC script itself that we'll be spending
|
// Finally we'll generate the HTLC script itself that we'll be spending
|
||||||
// from. The revocation clause can be claimed by Alice, while Bob can
|
// from. The revocation clause can be claimed by Alice, while Bob can
|
||||||
// sweep the output after a particular delay.
|
// sweep the output after a particular delay.
|
||||||
htlcWitnessScript, err := secondLevelHtlcScript(revocationKey,
|
htlcWitnessScript, err := SecondLevelHtlcScript(revocationKey,
|
||||||
delayKey, claimDelay)
|
delayKey, claimDelay)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create htlc script: %v", err)
|
t.Fatalf("unable to create htlc script: %v", err)
|
||||||
@ -900,8 +694,8 @@ func TestSecondLevelHtlcSpends(t *testing.T) {
|
|||||||
// Finally, we'll create mock signers for both of them based on their
|
// Finally, we'll create mock signers for both of them based on their
|
||||||
// private keys. This test simplifies a bit and uses the same key as
|
// private keys. This test simplifies a bit and uses the same key as
|
||||||
// the base point for all scripts and derivations.
|
// the base point for all scripts and derivations.
|
||||||
bobSigner := &mockSigner{privkeys: []*btcec.PrivateKey{bobKeyPriv}}
|
bobSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{bobKeyPriv}}
|
||||||
aliceSigner := &mockSigner{privkeys: []*btcec.PrivateKey{aliceKeyPriv}}
|
aliceSigner := &MockSigner{Privkeys: []*btcec.PrivateKey{aliceKeyPriv}}
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
witness func() wire.TxWitness
|
witness func() wire.TxWitness
|
||||||
@ -923,7 +717,7 @@ func TestSecondLevelHtlcSpends(t *testing.T) {
|
|||||||
InputIndex: 0,
|
InputIndex: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
return htlcSpendRevoke(aliceSigner, signDesc,
|
return HtlcSpendRevoke(aliceSigner, signDesc,
|
||||||
sweepTx)
|
sweepTx)
|
||||||
}),
|
}),
|
||||||
false,
|
false,
|
||||||
@ -943,7 +737,7 @@ func TestSecondLevelHtlcSpends(t *testing.T) {
|
|||||||
InputIndex: 0,
|
InputIndex: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
return htlcSpendRevoke(aliceSigner, signDesc,
|
return HtlcSpendRevoke(aliceSigner, signDesc,
|
||||||
sweepTx)
|
sweepTx)
|
||||||
}),
|
}),
|
||||||
true,
|
true,
|
||||||
@ -965,7 +759,7 @@ func TestSecondLevelHtlcSpends(t *testing.T) {
|
|||||||
InputIndex: 0,
|
InputIndex: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
return htlcSpendSuccess(bobSigner, signDesc,
|
return HtlcSpendSuccess(bobSigner, signDesc,
|
||||||
sweepTx, claimDelay-3)
|
sweepTx, claimDelay-3)
|
||||||
}),
|
}),
|
||||||
false,
|
false,
|
||||||
@ -986,7 +780,7 @@ func TestSecondLevelHtlcSpends(t *testing.T) {
|
|||||||
InputIndex: 0,
|
InputIndex: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
return htlcSpendSuccess(bobSigner, signDesc,
|
return HtlcSpendSuccess(bobSigner, signDesc,
|
||||||
sweepTx, claimDelay)
|
sweepTx, claimDelay)
|
||||||
}),
|
}),
|
||||||
false,
|
false,
|
||||||
@ -1007,7 +801,7 @@ func TestSecondLevelHtlcSpends(t *testing.T) {
|
|||||||
InputIndex: 0,
|
InputIndex: 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
return htlcSpendSuccess(bobSigner, signDesc,
|
return HtlcSpendSuccess(bobSigner, signDesc,
|
||||||
sweepTx, claimDelay)
|
sweepTx, claimDelay)
|
||||||
}),
|
}),
|
||||||
true,
|
true,
|
||||||
@ -1053,97 +847,6 @@ func TestSecondLevelHtlcSpends(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCommitTxStateHint(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
|
|
||||||
stateHintTests := []struct {
|
|
||||||
name string
|
|
||||||
from uint64
|
|
||||||
to uint64
|
|
||||||
inputs int
|
|
||||||
shouldFail bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "states 0 to 1000",
|
|
||||||
from: 0,
|
|
||||||
to: 1000,
|
|
||||||
inputs: 1,
|
|
||||||
shouldFail: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "states 'maxStateHint-1000' to 'maxStateHint'",
|
|
||||||
from: maxStateHint - 1000,
|
|
||||||
to: maxStateHint,
|
|
||||||
inputs: 1,
|
|
||||||
shouldFail: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "state 'maxStateHint+1'",
|
|
||||||
from: maxStateHint + 1,
|
|
||||||
to: maxStateHint + 10,
|
|
||||||
inputs: 1,
|
|
||||||
shouldFail: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "commit transaction with two inputs",
|
|
||||||
inputs: 2,
|
|
||||||
shouldFail: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var obfuscator [StateHintSize]byte
|
|
||||||
copy(obfuscator[:], testHdSeed[:StateHintSize])
|
|
||||||
timeYesterday := uint32(time.Now().Unix() - 24*60*60)
|
|
||||||
|
|
||||||
for _, test := range stateHintTests {
|
|
||||||
commitTx := wire.NewMsgTx(2)
|
|
||||||
|
|
||||||
// Add supplied number of inputs to the commitment transaction.
|
|
||||||
for i := 0; i < test.inputs; i++ {
|
|
||||||
commitTx.AddTxIn(&wire.TxIn{})
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := test.from; i <= test.to; i++ {
|
|
||||||
stateNum := uint64(i)
|
|
||||||
|
|
||||||
err := SetStateNumHint(commitTx, stateNum, obfuscator)
|
|
||||||
if err != nil && !test.shouldFail {
|
|
||||||
t.Fatalf("unable to set state num %v: %v", i, err)
|
|
||||||
} else if err == nil && test.shouldFail {
|
|
||||||
t.Fatalf("Failed(%v): test should fail but did not", test.name)
|
|
||||||
}
|
|
||||||
|
|
||||||
locktime := commitTx.LockTime
|
|
||||||
sequence := commitTx.TxIn[0].Sequence
|
|
||||||
|
|
||||||
// Locktime should not be less than 500,000,000 and not larger
|
|
||||||
// than the time 24 hours ago. One day should provide a good
|
|
||||||
// enough buffer for the tests.
|
|
||||||
if locktime < 5e8 || locktime > timeYesterday {
|
|
||||||
if !test.shouldFail {
|
|
||||||
t.Fatalf("The value of locktime (%v) may cause the commitment "+
|
|
||||||
"transaction to be unspendable", locktime)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if sequence&wire.SequenceLockTimeDisabled == 0 {
|
|
||||||
if !test.shouldFail {
|
|
||||||
t.Fatalf("Sequence locktime is NOT disabled when it should be")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extractedStateNum := GetStateNumHint(commitTx, obfuscator)
|
|
||||||
if extractedStateNum != stateNum && !test.shouldFail {
|
|
||||||
t.Fatalf("state number mismatched, expected %v, got %v",
|
|
||||||
stateNum, extractedStateNum)
|
|
||||||
} else if extractedStateNum == stateNum && test.shouldFail {
|
|
||||||
t.Fatalf("Failed(%v): test should fail but did not", test.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
t.Logf("Passed: %v", test.name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestSpecificationKeyDerivation implements the test vectors provided in
|
// TestSpecificationKeyDerivation implements the test vectors provided in
|
||||||
// BOLT-03, Appendix E.
|
// BOLT-03, Appendix E.
|
||||||
func TestSpecificationKeyDerivation(t *testing.T) {
|
func TestSpecificationKeyDerivation(t *testing.T) {
|
@ -1,4 +1,4 @@
|
|||||||
package lnwallet
|
package input
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
@ -1,4 +1,4 @@
|
|||||||
package lnwallet
|
package input
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
41
input/signer.go
Normal file
41
input/signer.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package input
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/btcsuite/btcd/wire"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Signer represents an abstract object capable of generating raw signatures as
|
||||||
|
// well as full complete input scripts given a valid SignDescriptor and
|
||||||
|
// transaction. This interface fully abstracts away signing paving the way for
|
||||||
|
// Signer implementations such as hardware wallets, hardware tokens, HSM's, or
|
||||||
|
// simply a regular wallet.
|
||||||
|
type Signer interface {
|
||||||
|
// SignOutputRaw generates a signature for the passed transaction
|
||||||
|
// according to the data within the passed SignDescriptor.
|
||||||
|
//
|
||||||
|
// NOTE: The resulting signature should be void of a sighash byte.
|
||||||
|
SignOutputRaw(tx *wire.MsgTx, signDesc *SignDescriptor) ([]byte, error)
|
||||||
|
|
||||||
|
// ComputeInputScript generates a complete InputIndex for the passed
|
||||||
|
// transaction with the signature as defined within the passed
|
||||||
|
// SignDescriptor. This method should be capable of generating the
|
||||||
|
// proper input script for both regular p2wkh output and p2wkh outputs
|
||||||
|
// nested within a regular p2sh output.
|
||||||
|
//
|
||||||
|
// NOTE: This method will ignore any tweak parameters set within the
|
||||||
|
// passed SignDescriptor as it assumes a set of typical script
|
||||||
|
// templates (p2wkh, np2wkh, etc).
|
||||||
|
ComputeInputScript(tx *wire.MsgTx, signDesc *SignDescriptor) (*Script, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Script represents any script inputs required to redeem a previous
|
||||||
|
// output. This struct is used rather than just a witness, or scripSig in order
|
||||||
|
// to accommodate nested p2sh which utilizes both types of input scripts.
|
||||||
|
type Script struct {
|
||||||
|
// Witness is the full witness stack required to unlock this output.
|
||||||
|
Witness wire.TxWitness
|
||||||
|
|
||||||
|
// SigScript will only be populated if this is an input script sweeping
|
||||||
|
// a nested p2sh output.
|
||||||
|
SigScript []byte
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package lnwallet
|
package input
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/btcsuite/btcd/blockchain"
|
"github.com/btcsuite/btcd/blockchain"
|
||||||
@ -359,10 +359,10 @@ const (
|
|||||||
OfferedHtlcPenaltyWitnessSize = 1 + 1 + 73 + 1 + 33 + 1 + OfferedHtlcScriptSize
|
OfferedHtlcPenaltyWitnessSize = 1 + 1 + 73 + 1 + 33 + 1 + OfferedHtlcScriptSize
|
||||||
)
|
)
|
||||||
|
|
||||||
// estimateCommitTxWeight estimate commitment transaction weight depending on
|
// EstimateCommitTxWeight estimate commitment transaction weight depending on
|
||||||
// the precalculated weight of base transaction, witness data, which is needed
|
// the precalculated weight of base transaction, witness data, which is needed
|
||||||
// for paying for funding tx, and htlc weight multiplied by their count.
|
// for paying for funding tx, and htlc weight multiplied by their count.
|
||||||
func estimateCommitTxWeight(count int, prediction bool) int64 {
|
func EstimateCommitTxWeight(count int, prediction bool) int64 {
|
||||||
// Make prediction about the size of commitment transaction with
|
// Make prediction about the size of commitment transaction with
|
||||||
// additional HTLC.
|
// additional HTLC.
|
||||||
if prediction {
|
if prediction {
|
189
input/test_utils.go
Normal file
189
input/test_utils.go
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
package input
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/btcsuite/btcd/btcec"
|
||||||
|
"github.com/btcsuite/btcd/chaincfg"
|
||||||
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
|
"github.com/btcsuite/btcd/txscript"
|
||||||
|
"github.com/btcsuite/btcd/wire"
|
||||||
|
"github.com/btcsuite/btcutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
|
||||||
|
// For simplicity a single priv key controls all of our test outputs.
|
||||||
|
testWalletPrivKey = []byte{
|
||||||
|
0x2b, 0xd8, 0x06, 0xc9, 0x7f, 0x0e, 0x00, 0xaf,
|
||||||
|
0x1a, 0x1f, 0xc3, 0x32, 0x8f, 0xa7, 0x63, 0xa9,
|
||||||
|
0x26, 0x97, 0x23, 0xc8, 0xdb, 0x8f, 0xac, 0x4f,
|
||||||
|
0x93, 0xaf, 0x71, 0xdb, 0x18, 0x6d, 0x6e, 0x90,
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're alice :)
|
||||||
|
bobsPrivKey = []byte{
|
||||||
|
0x81, 0xb6, 0x37, 0xd8, 0xfc, 0xd2, 0xc6, 0xda,
|
||||||
|
0x63, 0x59, 0xe6, 0x96, 0x31, 0x13, 0xa1, 0x17,
|
||||||
|
0xd, 0xe7, 0x95, 0xe4, 0xb7, 0x25, 0xb8, 0x4d,
|
||||||
|
0x1e, 0xb, 0x4c, 0xfd, 0x9e, 0xc5, 0x8c, 0xe9,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use a hard-coded HD seed.
|
||||||
|
testHdSeed = chainhash.Hash{
|
||||||
|
0xb7, 0x94, 0x38, 0x5f, 0x2d, 0x1e, 0xf7, 0xab,
|
||||||
|
0x4d, 0x92, 0x73, 0xd1, 0x90, 0x63, 0x81, 0xb4,
|
||||||
|
0x4f, 0x2f, 0x6f, 0x25, 0x88, 0xa3, 0xef, 0xb9,
|
||||||
|
0x6a, 0x49, 0x18, 0x83, 0x31, 0x98, 0x47, 0x53,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockSigner is a simple implementation of the Signer interface. Each one has
|
||||||
|
// a set of private keys in a slice and can sign messages using the appropriate
|
||||||
|
// one.
|
||||||
|
type MockSigner struct {
|
||||||
|
Privkeys []*btcec.PrivateKey
|
||||||
|
NetParams *chaincfg.Params
|
||||||
|
}
|
||||||
|
|
||||||
|
// SignOutputRaw generates a signature for the passed transaction according to
|
||||||
|
// the data within the passed SignDescriptor.
|
||||||
|
func (m *MockSigner) SignOutputRaw(tx *wire.MsgTx, signDesc *SignDescriptor) ([]byte, error) {
|
||||||
|
pubkey := signDesc.KeyDesc.PubKey
|
||||||
|
switch {
|
||||||
|
case signDesc.SingleTweak != nil:
|
||||||
|
pubkey = TweakPubKeyWithTweak(pubkey, signDesc.SingleTweak)
|
||||||
|
case signDesc.DoubleTweak != nil:
|
||||||
|
pubkey = DeriveRevocationPubkey(pubkey, signDesc.DoubleTweak.PubKey())
|
||||||
|
}
|
||||||
|
|
||||||
|
hash160 := btcutil.Hash160(pubkey.SerializeCompressed())
|
||||||
|
privKey := m.findKey(hash160, signDesc.SingleTweak, signDesc.DoubleTweak)
|
||||||
|
if privKey == nil {
|
||||||
|
return nil, fmt.Errorf("Mock signer does not have key")
|
||||||
|
}
|
||||||
|
|
||||||
|
sig, err := txscript.RawTxInWitnessSignature(tx, signDesc.SigHashes,
|
||||||
|
signDesc.InputIndex, signDesc.Output.Value, signDesc.WitnessScript,
|
||||||
|
txscript.SigHashAll, privKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return sig[:len(sig)-1], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ComputeInputScript generates a complete InputIndex for the passed transaction
|
||||||
|
// with the signature as defined within the passed SignDescriptor. This method
|
||||||
|
// should be capable of generating the proper input script for both regular
|
||||||
|
// p2wkh output and p2wkh outputs nested within a regular p2sh output.
|
||||||
|
func (m *MockSigner) ComputeInputScript(tx *wire.MsgTx, signDesc *SignDescriptor) (*Script, error) {
|
||||||
|
scriptType, addresses, _, err := txscript.ExtractPkScriptAddrs(
|
||||||
|
signDesc.Output.PkScript, m.NetParams)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch scriptType {
|
||||||
|
case txscript.PubKeyHashTy:
|
||||||
|
privKey := m.findKey(addresses[0].ScriptAddress(), signDesc.SingleTweak,
|
||||||
|
signDesc.DoubleTweak)
|
||||||
|
if privKey == nil {
|
||||||
|
return nil, fmt.Errorf("Mock signer does not have key for "+
|
||||||
|
"address %v", addresses[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
sigScript, err := txscript.SignatureScript(
|
||||||
|
tx, signDesc.InputIndex, signDesc.Output.PkScript,
|
||||||
|
txscript.SigHashAll, privKey, true,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Script{SigScript: sigScript}, nil
|
||||||
|
|
||||||
|
case txscript.WitnessV0PubKeyHashTy:
|
||||||
|
privKey := m.findKey(addresses[0].ScriptAddress(), signDesc.SingleTweak,
|
||||||
|
signDesc.DoubleTweak)
|
||||||
|
if privKey == nil {
|
||||||
|
return nil, fmt.Errorf("Mock signer does not have key for "+
|
||||||
|
"address %v", addresses[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
witnessScript, err := txscript.WitnessSignature(tx, signDesc.SigHashes,
|
||||||
|
signDesc.InputIndex, signDesc.Output.Value,
|
||||||
|
signDesc.Output.PkScript, txscript.SigHashAll, privKey, true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Script{Witness: witnessScript}, nil
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("Unexpected script type: %v", scriptType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// findKey searches through all stored private keys and returns one
|
||||||
|
// corresponding to the hashed pubkey if it can be found. The public key may
|
||||||
|
// either correspond directly to the private key or to the private key with a
|
||||||
|
// tweak applied.
|
||||||
|
func (m *MockSigner) findKey(needleHash160 []byte, singleTweak []byte,
|
||||||
|
doubleTweak *btcec.PrivateKey) *btcec.PrivateKey {
|
||||||
|
|
||||||
|
for _, privkey := range m.Privkeys {
|
||||||
|
// First check whether public key is directly derived from private key.
|
||||||
|
hash160 := btcutil.Hash160(privkey.PubKey().SerializeCompressed())
|
||||||
|
if bytes.Equal(hash160, needleHash160) {
|
||||||
|
return privkey
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise check if public key is derived from tweaked private key.
|
||||||
|
switch {
|
||||||
|
case singleTweak != nil:
|
||||||
|
privkey = TweakPrivKey(privkey, singleTweak)
|
||||||
|
case doubleTweak != nil:
|
||||||
|
privkey = DeriveRevocationPrivKey(privkey, doubleTweak)
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
hash160 = btcutil.Hash160(privkey.PubKey().SerializeCompressed())
|
||||||
|
if bytes.Equal(hash160, needleHash160) {
|
||||||
|
return privkey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// pubkeyFromHex parses a Bitcoin public key from a hex encoded string.
|
||||||
|
func pubkeyFromHex(keyHex string) (*btcec.PublicKey, error) {
|
||||||
|
bytes, err := hex.DecodeString(keyHex)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return btcec.ParsePubKey(bytes, btcec.S256())
|
||||||
|
}
|
||||||
|
|
||||||
|
// privkeyFromHex parses a Bitcoin private key from a hex encoded string.
|
||||||
|
func privkeyFromHex(keyHex string) (*btcec.PrivateKey, error) {
|
||||||
|
bytes, err := hex.DecodeString(keyHex)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
key, _ := btcec.PrivKeyFromBytes(btcec.S256(), bytes)
|
||||||
|
return key, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// pubkeyToHex serializes a Bitcoin public key to a hex encoded string.
|
||||||
|
func pubkeyToHex(key *btcec.PublicKey) string {
|
||||||
|
return hex.EncodeToString(key.SerializeCompressed())
|
||||||
|
}
|
||||||
|
|
||||||
|
// privkeyFromHex serializes a Bitcoin private key to a hex encoded string.
|
||||||
|
func privkeyToHex(key *btcec.PrivateKey) string {
|
||||||
|
return hex.EncodeToString(key.Serialize())
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package lnwallet
|
package input
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
@ -1,4 +1,4 @@
|
|||||||
package lnwallet
|
package input
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
@ -1,4 +1,4 @@
|
|||||||
package lnwallet
|
package input
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -125,7 +125,7 @@ func (wt WitnessType) String() string {
|
|||||||
// outputs. This function acts as an abstraction layer, hiding the details of
|
// outputs. This function acts as an abstraction layer, hiding the details of
|
||||||
// the underlying script.
|
// the underlying script.
|
||||||
type WitnessGenerator func(tx *wire.MsgTx, hc *txscript.TxSigHashes,
|
type WitnessGenerator func(tx *wire.MsgTx, hc *txscript.TxSigHashes,
|
||||||
inputIndex int) (*InputScript, error)
|
inputIndex int) (*Script, error)
|
||||||
|
|
||||||
// GenWitnessFunc will return a WitnessGenerator function that an output uses
|
// GenWitnessFunc will return a WitnessGenerator function that an output uses
|
||||||
// to generate the witness and optionally the sigScript for a sweep
|
// to generate the witness and optionally the sigScript for a sweep
|
||||||
@ -135,7 +135,7 @@ func (wt WitnessType) GenWitnessFunc(signer Signer,
|
|||||||
descriptor *SignDescriptor) WitnessGenerator {
|
descriptor *SignDescriptor) WitnessGenerator {
|
||||||
|
|
||||||
return func(tx *wire.MsgTx, hc *txscript.TxSigHashes,
|
return func(tx *wire.MsgTx, hc *txscript.TxSigHashes,
|
||||||
inputIndex int) (*InputScript, error) {
|
inputIndex int) (*Script, error) {
|
||||||
|
|
||||||
desc := descriptor
|
desc := descriptor
|
||||||
desc.SigHashes = hc
|
desc.SigHashes = hc
|
||||||
@ -148,7 +148,7 @@ func (wt WitnessType) GenWitnessFunc(signer Signer,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &InputScript{
|
return &Script{
|
||||||
Witness: witness,
|
Witness: witness,
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
@ -158,7 +158,7 @@ func (wt WitnessType) GenWitnessFunc(signer Signer,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &InputScript{
|
return &Script{
|
||||||
Witness: witness,
|
Witness: witness,
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
@ -168,7 +168,7 @@ func (wt WitnessType) GenWitnessFunc(signer Signer,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &InputScript{
|
return &Script{
|
||||||
Witness: witness,
|
Witness: witness,
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
@ -178,7 +178,7 @@ func (wt WitnessType) GenWitnessFunc(signer Signer,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &InputScript{
|
return &Script{
|
||||||
Witness: witness,
|
Witness: witness,
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
@ -188,7 +188,7 @@ func (wt WitnessType) GenWitnessFunc(signer Signer,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &InputScript{
|
return &Script{
|
||||||
Witness: witness,
|
Witness: witness,
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
@ -198,7 +198,7 @@ func (wt WitnessType) GenWitnessFunc(signer Signer,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &InputScript{
|
return &Script{
|
||||||
Witness: witness,
|
Witness: witness,
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
@ -208,7 +208,7 @@ func (wt WitnessType) GenWitnessFunc(signer Signer,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &InputScript{
|
return &Script{
|
||||||
Witness: witness,
|
Witness: witness,
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
@ -216,22 +216,22 @@ func (wt WitnessType) GenWitnessFunc(signer Signer,
|
|||||||
// We pass in a value of -1 for the timeout, as we
|
// We pass in a value of -1 for the timeout, as we
|
||||||
// expect the caller to have already set the lock time
|
// expect the caller to have already set the lock time
|
||||||
// value.
|
// value.
|
||||||
witness, err := receiverHtlcSpendTimeout(signer, desc, tx, -1)
|
witness, err := ReceiverHtlcSpendTimeout(signer, desc, tx, -1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &InputScript{
|
return &Script{
|
||||||
Witness: witness,
|
Witness: witness,
|
||||||
}, nil
|
}, nil
|
||||||
|
|
||||||
case HtlcSecondLevelRevoke:
|
case HtlcSecondLevelRevoke:
|
||||||
witness, err := htlcSpendRevoke(signer, desc, tx)
|
witness, err := HtlcSpendRevoke(signer, desc, tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &InputScript{
|
return &Script{
|
||||||
Witness: witness,
|
Witness: witness,
|
||||||
}, nil
|
}, nil
|
||||||
|
|
@ -4,11 +4,11 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/btcsuite/btcd/chaincfg"
|
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/btcsuite/btcd/chaincfg"
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
package signrpc
|
package signrpc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/macaroons"
|
"github.com/lightningnetwork/lnd/macaroons"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -29,5 +29,5 @@ type Config struct {
|
|||||||
// Signer is the signer instance that backs the signer RPC server. The
|
// Signer is the signer instance that backs the signer RPC server. The
|
||||||
// job of the signer RPC server is simply to proxy valid requests to
|
// job of the signer RPC server is simply to proxy valid requests to
|
||||||
// the active signer instance.
|
// the active signer instance.
|
||||||
Signer lnwallet.Signer
|
Signer input.Signer
|
||||||
}
|
}
|
||||||
|
@ -13,9 +13,10 @@ import (
|
|||||||
"github.com/btcsuite/btcd/btcec"
|
"github.com/btcsuite/btcd/btcec"
|
||||||
"github.com/btcsuite/btcd/txscript"
|
"github.com/btcsuite/btcd/txscript"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"gopkg.in/macaroon-bakery.v2/bakery"
|
"gopkg.in/macaroon-bakery.v2/bakery"
|
||||||
)
|
)
|
||||||
@ -206,7 +207,7 @@ func (s *Server) SignOutputRaw(ctx context.Context, in *SignReq) (*SignResp, err
|
|||||||
|
|
||||||
// With the transaction deserialized, we'll now convert sign descs so
|
// With the transaction deserialized, we'll now convert sign descs so
|
||||||
// we can feed it into the actual signer.
|
// we can feed it into the actual signer.
|
||||||
signDescs := make([]*lnwallet.SignDescriptor, 0, len(in.SignDescs))
|
signDescs := make([]*input.SignDescriptor, 0, len(in.SignDescs))
|
||||||
for _, signDesc := range in.SignDescs {
|
for _, signDesc := range in.SignDescs {
|
||||||
keyDesc := signDesc.KeyDesc
|
keyDesc := signDesc.KeyDesc
|
||||||
|
|
||||||
@ -278,7 +279,7 @@ func (s *Server) SignOutputRaw(ctx context.Context, in *SignReq) (*SignResp, err
|
|||||||
// Finally, with verification and parsing complete, we can
|
// Finally, with verification and parsing complete, we can
|
||||||
// construct the final sign descriptor to generate the proper
|
// construct the final sign descriptor to generate the proper
|
||||||
// signature for this input.
|
// signature for this input.
|
||||||
signDescs = append(signDescs, &lnwallet.SignDescriptor{
|
signDescs = append(signDescs, &input.SignDescriptor{
|
||||||
KeyDesc: keychain.KeyDescriptor{
|
KeyDesc: keychain.KeyDescriptor{
|
||||||
KeyLocator: keyLoc,
|
KeyLocator: keyLoc,
|
||||||
PubKey: targetPubKey,
|
PubKey: targetPubKey,
|
||||||
@ -353,13 +354,13 @@ func (s *Server) ComputeInputScript(ctx context.Context,
|
|||||||
|
|
||||||
sigHashCache := txscript.NewTxSigHashes(&txToSign)
|
sigHashCache := txscript.NewTxSigHashes(&txToSign)
|
||||||
|
|
||||||
signDescs := make([]*lnwallet.SignDescriptor, 0, len(in.SignDescs))
|
signDescs := make([]*input.SignDescriptor, 0, len(in.SignDescs))
|
||||||
for _, signDesc := range in.SignDescs {
|
for _, signDesc := range in.SignDescs {
|
||||||
// For this method, the only fields that we care about are the
|
// For this method, the only fields that we care about are the
|
||||||
// hash type, and the information concerning the output as we
|
// hash type, and the information concerning the output as we
|
||||||
// only know how to provide full witnesses for outputs that we
|
// only know how to provide full witnesses for outputs that we
|
||||||
// solely control.
|
// solely control.
|
||||||
signDescs = append(signDescs, &lnwallet.SignDescriptor{
|
signDescs = append(signDescs, &input.SignDescriptor{
|
||||||
Output: &wire.TxOut{
|
Output: &wire.TxOut{
|
||||||
Value: signDesc.Output.Value,
|
Value: signDesc.Output.Value,
|
||||||
PkScript: signDesc.Output.PkScript,
|
PkScript: signDesc.Output.PkScript,
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
base "github.com/btcsuite/btcwallet/wallet"
|
base "github.com/btcsuite/btcwallet/wallet"
|
||||||
"github.com/btcsuite/btcwallet/walletdb"
|
"github.com/btcsuite/btcwallet/walletdb"
|
||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
)
|
)
|
||||||
@ -132,18 +133,18 @@ func (b *BtcWallet) fetchPrivKey(keyDesc *keychain.KeyDescriptor) (*btcec.Privat
|
|||||||
// maybeTweakPrivKey examines the single and double tweak parameters on the
|
// maybeTweakPrivKey examines the single and double tweak parameters on the
|
||||||
// passed sign descriptor and may perform a mapping on the passed private key
|
// passed sign descriptor and may perform a mapping on the passed private key
|
||||||
// in order to utilize the tweaks, if populated.
|
// in order to utilize the tweaks, if populated.
|
||||||
func maybeTweakPrivKey(signDesc *lnwallet.SignDescriptor,
|
func maybeTweakPrivKey(signDesc *input.SignDescriptor,
|
||||||
privKey *btcec.PrivateKey) (*btcec.PrivateKey, error) {
|
privKey *btcec.PrivateKey) (*btcec.PrivateKey, error) {
|
||||||
|
|
||||||
var retPriv *btcec.PrivateKey
|
var retPriv *btcec.PrivateKey
|
||||||
switch {
|
switch {
|
||||||
|
|
||||||
case signDesc.SingleTweak != nil:
|
case signDesc.SingleTweak != nil:
|
||||||
retPriv = lnwallet.TweakPrivKey(privKey,
|
retPriv = input.TweakPrivKey(privKey,
|
||||||
signDesc.SingleTweak)
|
signDesc.SingleTweak)
|
||||||
|
|
||||||
case signDesc.DoubleTweak != nil:
|
case signDesc.DoubleTweak != nil:
|
||||||
retPriv = lnwallet.DeriveRevocationPrivKey(privKey,
|
retPriv = input.DeriveRevocationPrivKey(privKey,
|
||||||
signDesc.DoubleTweak)
|
signDesc.DoubleTweak)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -158,7 +159,7 @@ func maybeTweakPrivKey(signDesc *lnwallet.SignDescriptor,
|
|||||||
//
|
//
|
||||||
// This is a part of the WalletController interface.
|
// This is a part of the WalletController interface.
|
||||||
func (b *BtcWallet) SignOutputRaw(tx *wire.MsgTx,
|
func (b *BtcWallet) SignOutputRaw(tx *wire.MsgTx,
|
||||||
signDesc *lnwallet.SignDescriptor) ([]byte, error) {
|
signDesc *input.SignDescriptor) ([]byte, error) {
|
||||||
|
|
||||||
witnessScript := signDesc.WitnessScript
|
witnessScript := signDesc.WitnessScript
|
||||||
|
|
||||||
@ -199,7 +200,7 @@ func (b *BtcWallet) SignOutputRaw(tx *wire.MsgTx,
|
|||||||
//
|
//
|
||||||
// This is a part of the WalletController interface.
|
// This is a part of the WalletController interface.
|
||||||
func (b *BtcWallet) ComputeInputScript(tx *wire.MsgTx,
|
func (b *BtcWallet) ComputeInputScript(tx *wire.MsgTx,
|
||||||
signDesc *lnwallet.SignDescriptor) (*lnwallet.InputScript, error) {
|
signDesc *input.SignDescriptor) (*input.Script, error) {
|
||||||
|
|
||||||
outputScript := signDesc.Output.PkScript
|
outputScript := signDesc.Output.PkScript
|
||||||
walletAddr, err := b.fetchOutputAddr(outputScript)
|
walletAddr, err := b.fetchOutputAddr(outputScript)
|
||||||
@ -214,7 +215,7 @@ func (b *BtcWallet) ComputeInputScript(tx *wire.MsgTx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
var witnessProgram []byte
|
var witnessProgram []byte
|
||||||
inputScript := &lnwallet.InputScript{}
|
inputScript := &input.Script{}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
|
|
||||||
@ -282,7 +283,7 @@ func (b *BtcWallet) ComputeInputScript(tx *wire.MsgTx,
|
|||||||
|
|
||||||
// A compile time check to ensure that BtcWallet implements the Signer
|
// A compile time check to ensure that BtcWallet implements the Signer
|
||||||
// interface.
|
// interface.
|
||||||
var _ lnwallet.Signer = (*BtcWallet)(nil)
|
var _ input.Signer = (*BtcWallet)(nil)
|
||||||
|
|
||||||
// SignMessage attempts to sign a target message with the private key that
|
// SignMessage attempts to sign a target message with the private key that
|
||||||
// corresponds to the passed public key. If the target private key is unable to
|
// corresponds to the passed public key. If the target private key is unable to
|
||||||
|
@ -9,17 +9,18 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/blockchain"
|
"github.com/btcsuite/btcd/blockchain"
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
|
||||||
"github.com/davecgh/go-spew/spew"
|
|
||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec"
|
"github.com/btcsuite/btcd/btcec"
|
||||||
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
"github.com/btcsuite/btcd/txscript"
|
"github.com/btcsuite/btcd/txscript"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/btcsuite/btcutil/txsort"
|
"github.com/btcsuite/btcutil/txsort"
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
)
|
)
|
||||||
|
|
||||||
var zeroHash chainhash.Hash
|
var zeroHash chainhash.Hash
|
||||||
@ -967,16 +968,16 @@ func deriveCommitmentKeys(commitPoint *btcec.PublicKey, isOurCommit bool,
|
|||||||
keyRing := &CommitmentKeyRing{
|
keyRing := &CommitmentKeyRing{
|
||||||
CommitPoint: commitPoint,
|
CommitPoint: commitPoint,
|
||||||
|
|
||||||
LocalCommitKeyTweak: SingleTweakBytes(
|
LocalCommitKeyTweak: input.SingleTweakBytes(
|
||||||
commitPoint, localChanCfg.PaymentBasePoint.PubKey,
|
commitPoint, localChanCfg.PaymentBasePoint.PubKey,
|
||||||
),
|
),
|
||||||
LocalHtlcKeyTweak: SingleTweakBytes(
|
LocalHtlcKeyTweak: input.SingleTweakBytes(
|
||||||
commitPoint, localChanCfg.HtlcBasePoint.PubKey,
|
commitPoint, localChanCfg.HtlcBasePoint.PubKey,
|
||||||
),
|
),
|
||||||
LocalHtlcKey: TweakPubKey(
|
LocalHtlcKey: input.TweakPubKey(
|
||||||
localChanCfg.HtlcBasePoint.PubKey, commitPoint,
|
localChanCfg.HtlcBasePoint.PubKey, commitPoint,
|
||||||
),
|
),
|
||||||
RemoteHtlcKey: TweakPubKey(
|
RemoteHtlcKey: input.TweakPubKey(
|
||||||
remoteChanCfg.HtlcBasePoint.PubKey, commitPoint,
|
remoteChanCfg.HtlcBasePoint.PubKey, commitPoint,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@ -1003,9 +1004,9 @@ func deriveCommitmentKeys(commitPoint *btcec.PublicKey, isOurCommit bool,
|
|||||||
|
|
||||||
// With the base points assigned, we can now derive the actual keys
|
// With the base points assigned, we can now derive the actual keys
|
||||||
// using the base point, and the current commitment tweak.
|
// using the base point, and the current commitment tweak.
|
||||||
keyRing.DelayKey = TweakPubKey(delayBasePoint, commitPoint)
|
keyRing.DelayKey = input.TweakPubKey(delayBasePoint, commitPoint)
|
||||||
keyRing.NoDelayKey = TweakPubKey(noDelayBasePoint, commitPoint)
|
keyRing.NoDelayKey = input.TweakPubKey(noDelayBasePoint, commitPoint)
|
||||||
keyRing.RevocationKey = DeriveRevocationPubkey(
|
keyRing.RevocationKey = input.DeriveRevocationPubkey(
|
||||||
revocationBasePoint, commitPoint,
|
revocationBasePoint, commitPoint,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1285,11 +1286,11 @@ type LightningChannel struct {
|
|||||||
// Signer is the main signer instances that will be responsible for
|
// Signer is the main signer instances that will be responsible for
|
||||||
// signing any HTLC and commitment transaction generated by the state
|
// signing any HTLC and commitment transaction generated by the state
|
||||||
// machine.
|
// machine.
|
||||||
Signer Signer
|
Signer input.Signer
|
||||||
|
|
||||||
// signDesc is the primary sign descriptor that is capable of signing
|
// signDesc is the primary sign descriptor that is capable of signing
|
||||||
// the commitment transaction that spends the multi-sig output.
|
// the commitment transaction that spends the multi-sig output.
|
||||||
signDesc *SignDescriptor
|
signDesc *input.SignDescriptor
|
||||||
|
|
||||||
channelEvents chainntnfs.ChainNotifier
|
channelEvents chainntnfs.ChainNotifier
|
||||||
|
|
||||||
@ -1363,7 +1364,7 @@ type LightningChannel struct {
|
|||||||
// settled channel state. Throughout state transitions, then channel will
|
// settled channel state. Throughout state transitions, then channel will
|
||||||
// automatically persist pertinent state to the database in an efficient
|
// automatically persist pertinent state to the database in an efficient
|
||||||
// manner.
|
// manner.
|
||||||
func NewLightningChannel(signer Signer, pCache PreimageCache,
|
func NewLightningChannel(signer input.Signer, pCache PreimageCache,
|
||||||
state *channeldb.OpenChannel,
|
state *channeldb.OpenChannel,
|
||||||
sigPool *SigPool) (*LightningChannel, error) {
|
sigPool *SigPool) (*LightningChannel, error) {
|
||||||
|
|
||||||
@ -1423,16 +1424,16 @@ func (lc *LightningChannel) createSignDesc() error {
|
|||||||
localKey := lc.localChanCfg.MultiSigKey.PubKey.SerializeCompressed()
|
localKey := lc.localChanCfg.MultiSigKey.PubKey.SerializeCompressed()
|
||||||
remoteKey := lc.remoteChanCfg.MultiSigKey.PubKey.SerializeCompressed()
|
remoteKey := lc.remoteChanCfg.MultiSigKey.PubKey.SerializeCompressed()
|
||||||
|
|
||||||
multiSigScript, err := GenMultiSigScript(localKey, remoteKey)
|
multiSigScript, err := input.GenMultiSigScript(localKey, remoteKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fundingPkScript, err := WitnessScriptHash(multiSigScript)
|
fundingPkScript, err := input.WitnessScriptHash(multiSigScript)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
lc.signDesc = &SignDescriptor{
|
lc.signDesc = &input.SignDescriptor{
|
||||||
KeyDesc: lc.localChanCfg.MultiSigKey,
|
KeyDesc: lc.localChanCfg.MultiSigKey,
|
||||||
WitnessScript: multiSigScript,
|
WitnessScript: multiSigScript,
|
||||||
Output: &wire.TxOut{
|
Output: &wire.TxOut{
|
||||||
@ -1616,7 +1617,7 @@ func (lc *LightningChannel) restoreCommitState(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
localCommitPoint := ComputeCommitmentPoint(ourRevPreImage[:])
|
localCommitPoint := input.ComputeCommitmentPoint(ourRevPreImage[:])
|
||||||
remoteCommitPoint := lc.channelState.RemoteCurrentRevocation
|
remoteCommitPoint := lc.channelState.RemoteCurrentRevocation
|
||||||
|
|
||||||
// With the revocation state reconstructed, we can now convert the disk
|
// With the revocation state reconstructed, we can now convert the disk
|
||||||
@ -1859,7 +1860,7 @@ type HtlcRetribution struct {
|
|||||||
// SignDesc is a design descriptor capable of generating the necessary
|
// SignDesc is a design descriptor capable of generating the necessary
|
||||||
// signatures to satisfy the revocation clause of the HTLC's public key
|
// signatures to satisfy the revocation clause of the HTLC's public key
|
||||||
// script.
|
// script.
|
||||||
SignDesc SignDescriptor
|
SignDesc input.SignDescriptor
|
||||||
|
|
||||||
// OutPoint is the target outpoint of this HTLC pointing to the
|
// OutPoint is the target outpoint of this HTLC pointing to the
|
||||||
// breached commitment transaction.
|
// breached commitment transaction.
|
||||||
@ -1915,7 +1916,7 @@ type BreachRetribution struct {
|
|||||||
//
|
//
|
||||||
// NOTE: A nil value indicates that the local output is considered dust
|
// NOTE: A nil value indicates that the local output is considered dust
|
||||||
// according to the remote party's dust limit.
|
// according to the remote party's dust limit.
|
||||||
LocalOutputSignDesc *SignDescriptor
|
LocalOutputSignDesc *input.SignDescriptor
|
||||||
|
|
||||||
// LocalOutpoint is the outpoint of the output paying to us (the local
|
// LocalOutpoint is the outpoint of the output paying to us (the local
|
||||||
// party) within the breach transaction.
|
// party) within the breach transaction.
|
||||||
@ -1928,7 +1929,7 @@ type BreachRetribution struct {
|
|||||||
//
|
//
|
||||||
// NOTE: A nil value indicates that the local output is considered dust
|
// NOTE: A nil value indicates that the local output is considered dust
|
||||||
// according to the remote party's dust limit.
|
// according to the remote party's dust limit.
|
||||||
RemoteOutputSignDesc *SignDescriptor
|
RemoteOutputSignDesc *input.SignDescriptor
|
||||||
|
|
||||||
// RemoteOutpoint is the outpoint of the output paying to the remote
|
// RemoteOutpoint is the outpoint of the output paying to the remote
|
||||||
// party within the breach transaction.
|
// party within the breach transaction.
|
||||||
@ -1983,17 +1984,17 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
|
|||||||
// number so we can have the proper witness script to sign and include
|
// number so we can have the proper witness script to sign and include
|
||||||
// within the final witness.
|
// within the final witness.
|
||||||
remoteDelay := uint32(chanState.RemoteChanCfg.CsvDelay)
|
remoteDelay := uint32(chanState.RemoteChanCfg.CsvDelay)
|
||||||
remotePkScript, err := CommitScriptToSelf(
|
remotePkScript, err := input.CommitScriptToSelf(
|
||||||
remoteDelay, keyRing.DelayKey, keyRing.RevocationKey,
|
remoteDelay, keyRing.DelayKey, keyRing.RevocationKey,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
remoteWitnessHash, err := WitnessScriptHash(remotePkScript)
|
remoteWitnessHash, err := input.WitnessScriptHash(remotePkScript)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
localPkScript, err := CommitScriptUnencumbered(keyRing.NoDelayKey)
|
localPkScript, err := input.CommitScriptUnencumbered(keyRing.NoDelayKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -2019,8 +2020,8 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
|
|||||||
// commitment outputs. If either is considered dust using the remote
|
// commitment outputs. If either is considered dust using the remote
|
||||||
// party's dust limit, the respective sign descriptor will be nil.
|
// party's dust limit, the respective sign descriptor will be nil.
|
||||||
var (
|
var (
|
||||||
localSignDesc *SignDescriptor
|
localSignDesc *input.SignDescriptor
|
||||||
remoteSignDesc *SignDescriptor
|
remoteSignDesc *input.SignDescriptor
|
||||||
)
|
)
|
||||||
|
|
||||||
// Compute the local and remote balances in satoshis.
|
// Compute the local and remote balances in satoshis.
|
||||||
@ -2030,7 +2031,7 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
|
|||||||
// If the local balance exceeds the remote party's dust limit,
|
// If the local balance exceeds the remote party's dust limit,
|
||||||
// instantiate the local sign descriptor.
|
// instantiate the local sign descriptor.
|
||||||
if localAmt >= chanState.RemoteChanCfg.DustLimit {
|
if localAmt >= chanState.RemoteChanCfg.DustLimit {
|
||||||
localSignDesc = &SignDescriptor{
|
localSignDesc = &input.SignDescriptor{
|
||||||
SingleTweak: keyRing.LocalCommitKeyTweak,
|
SingleTweak: keyRing.LocalCommitKeyTweak,
|
||||||
KeyDesc: chanState.LocalChanCfg.PaymentBasePoint,
|
KeyDesc: chanState.LocalChanCfg.PaymentBasePoint,
|
||||||
WitnessScript: localPkScript,
|
WitnessScript: localPkScript,
|
||||||
@ -2045,7 +2046,7 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
|
|||||||
// Similarly, if the remote balance exceeds the remote party's dust
|
// Similarly, if the remote balance exceeds the remote party's dust
|
||||||
// limit, assemble the remote sign descriptor.
|
// limit, assemble the remote sign descriptor.
|
||||||
if remoteAmt >= chanState.RemoteChanCfg.DustLimit {
|
if remoteAmt >= chanState.RemoteChanCfg.DustLimit {
|
||||||
remoteSignDesc = &SignDescriptor{
|
remoteSignDesc = &input.SignDescriptor{
|
||||||
KeyDesc: chanState.LocalChanCfg.RevocationBasePoint,
|
KeyDesc: chanState.LocalChanCfg.RevocationBasePoint,
|
||||||
DoubleTweak: commitmentSecret,
|
DoubleTweak: commitmentSecret,
|
||||||
WitnessScript: remotePkScript,
|
WitnessScript: remotePkScript,
|
||||||
@ -2081,7 +2082,7 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
|
|||||||
// as we'll need it if we're revoking an HTLC output on the
|
// as we'll need it if we're revoking an HTLC output on the
|
||||||
// remote commitment transaction, and *they* go to the second
|
// remote commitment transaction, and *they* go to the second
|
||||||
// level.
|
// level.
|
||||||
secondLevelWitnessScript, err := secondLevelHtlcScript(
|
secondLevelWitnessScript, err := input.SecondLevelHtlcScript(
|
||||||
keyRing.RevocationKey, keyRing.DelayKey, remoteDelay,
|
keyRing.RevocationKey, keyRing.DelayKey, remoteDelay,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -2092,7 +2093,7 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
|
|||||||
// the sender of the HTLC (relative to us). So we'll
|
// the sender of the HTLC (relative to us). So we'll
|
||||||
// re-generate the sender HTLC script.
|
// re-generate the sender HTLC script.
|
||||||
if htlc.Incoming {
|
if htlc.Incoming {
|
||||||
htlcWitnessScript, err = senderHTLCScript(
|
htlcWitnessScript, err = input.SenderHTLCScript(
|
||||||
keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey,
|
keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey,
|
||||||
keyRing.RevocationKey, htlc.RHash[:],
|
keyRing.RevocationKey, htlc.RHash[:],
|
||||||
)
|
)
|
||||||
@ -2104,7 +2105,7 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
|
|||||||
// Otherwise, is this was an outgoing HTLC that we
|
// Otherwise, is this was an outgoing HTLC that we
|
||||||
// sent, then from the PoV of the remote commitment
|
// sent, then from the PoV of the remote commitment
|
||||||
// state, they're the receiver of this HTLC.
|
// state, they're the receiver of this HTLC.
|
||||||
htlcWitnessScript, err = receiverHTLCScript(
|
htlcWitnessScript, err = input.ReceiverHTLCScript(
|
||||||
htlc.RefundTimeout, keyRing.LocalHtlcKey,
|
htlc.RefundTimeout, keyRing.LocalHtlcKey,
|
||||||
keyRing.RemoteHtlcKey, keyRing.RevocationKey,
|
keyRing.RemoteHtlcKey, keyRing.RevocationKey,
|
||||||
htlc.RHash[:],
|
htlc.RHash[:],
|
||||||
@ -2114,13 +2115,13 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
htlcPkScript, err := WitnessScriptHash(htlcWitnessScript)
|
htlcPkScript, err := input.WitnessScriptHash(htlcWitnessScript)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
htlcRetributions = append(htlcRetributions, HtlcRetribution{
|
htlcRetributions = append(htlcRetributions, HtlcRetribution{
|
||||||
SignDesc: SignDescriptor{
|
SignDesc: input.SignDescriptor{
|
||||||
KeyDesc: chanState.LocalChanCfg.RevocationBasePoint,
|
KeyDesc: chanState.LocalChanCfg.RevocationBasePoint,
|
||||||
DoubleTweak: commitmentSecret,
|
DoubleTweak: commitmentSecret,
|
||||||
WitnessScript: htlcWitnessScript,
|
WitnessScript: htlcWitnessScript,
|
||||||
@ -2161,13 +2162,13 @@ func NewBreachRetribution(chanState *channeldb.OpenChannel, stateNum uint64,
|
|||||||
// htlcTimeoutFee returns the fee in satoshis required for an HTLC timeout
|
// htlcTimeoutFee returns the fee in satoshis required for an HTLC timeout
|
||||||
// transaction based on the current fee rate.
|
// transaction based on the current fee rate.
|
||||||
func htlcTimeoutFee(feePerKw SatPerKWeight) btcutil.Amount {
|
func htlcTimeoutFee(feePerKw SatPerKWeight) btcutil.Amount {
|
||||||
return feePerKw.FeeForWeight(HtlcTimeoutWeight)
|
return feePerKw.FeeForWeight(input.HtlcTimeoutWeight)
|
||||||
}
|
}
|
||||||
|
|
||||||
// htlcSuccessFee returns the fee in satoshis required for an HTLC success
|
// htlcSuccessFee returns the fee in satoshis required for an HTLC success
|
||||||
// transaction based on the current fee rate.
|
// transaction based on the current fee rate.
|
||||||
func htlcSuccessFee(feePerKw SatPerKWeight) btcutil.Amount {
|
func htlcSuccessFee(feePerKw SatPerKWeight) btcutil.Amount {
|
||||||
return feePerKw.FeeForWeight(HtlcSuccessWeight)
|
return feePerKw.FeeForWeight(input.HtlcSuccessWeight)
|
||||||
}
|
}
|
||||||
|
|
||||||
// htlcIsDust determines if an HTLC output is dust or not depending on two
|
// htlcIsDust determines if an HTLC output is dust or not depending on two
|
||||||
@ -2364,7 +2365,7 @@ func (lc *LightningChannel) createCommitmentTx(c *commitment,
|
|||||||
// on its total weight. Once we have the total weight, we'll multiply
|
// on its total weight. Once we have the total weight, we'll multiply
|
||||||
// by the current fee-per-kw, then divide by 1000 to get the proper
|
// by the current fee-per-kw, then divide by 1000 to get the proper
|
||||||
// fee.
|
// fee.
|
||||||
totalCommitWeight := CommitWeight + (HtlcWeight * numHTLCs)
|
totalCommitWeight := input.CommitWeight + (input.HtlcWeight * numHTLCs)
|
||||||
|
|
||||||
// With the weight known, we can now calculate the commitment fee,
|
// With the weight known, we can now calculate the commitment fee,
|
||||||
// ensuring that we account for any dust outputs trimmed above.
|
// ensuring that we account for any dust outputs trimmed above.
|
||||||
@ -2813,7 +2814,7 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing,
|
|||||||
// Finally, we'll generate a sign descriptor to generate a
|
// Finally, we'll generate a sign descriptor to generate a
|
||||||
// signature to give to the remote party for this commitment
|
// signature to give to the remote party for this commitment
|
||||||
// transaction. Note we use the raw HTLC amount.
|
// transaction. Note we use the raw HTLC amount.
|
||||||
sigJob.SignDesc = SignDescriptor{
|
sigJob.SignDesc = input.SignDescriptor{
|
||||||
KeyDesc: localChanCfg.HtlcBasePoint,
|
KeyDesc: localChanCfg.HtlcBasePoint,
|
||||||
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
||||||
WitnessScript: htlc.theirWitnessScript,
|
WitnessScript: htlc.theirWitnessScript,
|
||||||
@ -2864,7 +2865,7 @@ func genRemoteHtlcSigJobs(keyRing *CommitmentKeyRing,
|
|||||||
// Finally, we'll generate a sign descriptor to generate a
|
// Finally, we'll generate a sign descriptor to generate a
|
||||||
// signature to give to the remote party for this commitment
|
// signature to give to the remote party for this commitment
|
||||||
// transaction. Note we use the raw HTLC amount.
|
// transaction. Note we use the raw HTLC amount.
|
||||||
sigJob.SignDesc = SignDescriptor{
|
sigJob.SignDesc = input.SignDescriptor{
|
||||||
KeyDesc: localChanCfg.HtlcBasePoint,
|
KeyDesc: localChanCfg.HtlcBasePoint,
|
||||||
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
||||||
WitnessScript: htlc.theirWitnessScript,
|
WitnessScript: htlc.theirWitnessScript,
|
||||||
@ -3559,7 +3560,7 @@ func ChanSyncMsg(c *channeldb.OpenChannel) (*lnwire.ChannelReestablish, error) {
|
|||||||
NextLocalCommitHeight: nextLocalCommitHeight,
|
NextLocalCommitHeight: nextLocalCommitHeight,
|
||||||
RemoteCommitTailHeight: remoteChainTipHeight,
|
RemoteCommitTailHeight: remoteChainTipHeight,
|
||||||
LastRemoteCommitSecret: lastCommitSecret,
|
LastRemoteCommitSecret: lastCommitSecret,
|
||||||
LocalUnrevokedCommitPoint: ComputeCommitmentPoint(
|
LocalUnrevokedCommitPoint: input.ComputeCommitmentPoint(
|
||||||
currentCommitSecret[:],
|
currentCommitSecret[:],
|
||||||
),
|
),
|
||||||
}, nil
|
}, nil
|
||||||
@ -3627,7 +3628,7 @@ func (lc *LightningChannel) computeView(view *htlcView, remoteChain bool,
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
totalHtlcWeight += HtlcWeight
|
totalHtlcWeight += input.HtlcWeight
|
||||||
}
|
}
|
||||||
for _, htlc := range filteredHTLCView.theirUpdates {
|
for _, htlc := range filteredHTLCView.theirUpdates {
|
||||||
if htlcIsDust(!remoteChain, !remoteChain, feePerKw,
|
if htlcIsDust(!remoteChain, !remoteChain, feePerKw,
|
||||||
@ -3635,10 +3636,10 @@ func (lc *LightningChannel) computeView(view *htlcView, remoteChain bool,
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
totalHtlcWeight += HtlcWeight
|
totalHtlcWeight += input.HtlcWeight
|
||||||
}
|
}
|
||||||
|
|
||||||
totalCommitWeight := CommitWeight + totalHtlcWeight
|
totalCommitWeight := input.CommitWeight + totalHtlcWeight
|
||||||
return ourBalance, theirBalance, totalCommitWeight, filteredHTLCView
|
return ourBalance, theirBalance, totalCommitWeight, filteredHTLCView
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4031,7 +4032,7 @@ func (lc *LightningChannel) ReceiveNewCommitment(commitSig lnwire.Sig,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
commitPoint := ComputeCommitmentPoint(commitSecret[:])
|
commitPoint := input.ComputeCommitmentPoint(commitSecret[:])
|
||||||
keyRing := deriveCommitmentKeys(commitPoint, true, lc.localChanCfg,
|
keyRing := deriveCommitmentKeys(commitPoint, true, lc.localChanCfg,
|
||||||
lc.remoteChanCfg)
|
lc.remoteChanCfg)
|
||||||
|
|
||||||
@ -4258,7 +4259,7 @@ func (lc *LightningChannel) ReceiveRevocation(revMsg *lnwire.RevokeAndAck) (
|
|||||||
// revealed secret to derive a revocation key with our revocation base
|
// revealed secret to derive a revocation key with our revocation base
|
||||||
// point, then it matches the current revocation of the remote party.
|
// point, then it matches the current revocation of the remote party.
|
||||||
currentCommitPoint := lc.channelState.RemoteCurrentRevocation
|
currentCommitPoint := lc.channelState.RemoteCurrentRevocation
|
||||||
derivedCommitPoint := ComputeCommitmentPoint(revMsg.Revocation[:])
|
derivedCommitPoint := input.ComputeCommitmentPoint(revMsg.Revocation[:])
|
||||||
if !derivedCommitPoint.IsEqual(currentCommitPoint) {
|
if !derivedCommitPoint.IsEqual(currentCommitPoint) {
|
||||||
return nil, nil, nil, fmt.Errorf("revocation key mismatch")
|
return nil, nil, nil, fmt.Errorf("revocation key mismatch")
|
||||||
}
|
}
|
||||||
@ -4496,7 +4497,7 @@ func (lc *LightningChannel) NextRevocationKey() (*btcec.PublicKey, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return ComputeCommitmentPoint(revocation[:]), nil
|
return input.ComputeCommitmentPoint(revocation[:]), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitNextRevocation inserts the passed commitment point as the _next_
|
// InitNextRevocation inserts the passed commitment point as the _next_
|
||||||
@ -4872,7 +4873,7 @@ func genHtlcScript(isIncoming, ourCommit bool, timeout uint32, rHash [32]byte,
|
|||||||
// transaction. So we need to use the receiver's version of HTLC the
|
// transaction. So we need to use the receiver's version of HTLC the
|
||||||
// script.
|
// script.
|
||||||
case isIncoming && ourCommit:
|
case isIncoming && ourCommit:
|
||||||
witnessScript, err = receiverHTLCScript(timeout,
|
witnessScript, err = input.ReceiverHTLCScript(timeout,
|
||||||
keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey,
|
keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey,
|
||||||
keyRing.RevocationKey, rHash[:])
|
keyRing.RevocationKey, rHash[:])
|
||||||
|
|
||||||
@ -4880,21 +4881,21 @@ func genHtlcScript(isIncoming, ourCommit bool, timeout uint32, rHash [32]byte,
|
|||||||
// being added to their commitment transaction, so we use the sender's
|
// being added to their commitment transaction, so we use the sender's
|
||||||
// version of the HTLC script.
|
// version of the HTLC script.
|
||||||
case isIncoming && !ourCommit:
|
case isIncoming && !ourCommit:
|
||||||
witnessScript, err = senderHTLCScript(keyRing.RemoteHtlcKey,
|
witnessScript, err = input.SenderHTLCScript(keyRing.RemoteHtlcKey,
|
||||||
keyRing.LocalHtlcKey, keyRing.RevocationKey, rHash[:])
|
keyRing.LocalHtlcKey, keyRing.RevocationKey, rHash[:])
|
||||||
|
|
||||||
// We're sending an HTLC which is being added to our commitment
|
// We're sending an HTLC which is being added to our commitment
|
||||||
// transaction. Therefore, we need to use the sender's version of the
|
// transaction. Therefore, we need to use the sender's version of the
|
||||||
// HTLC script.
|
// HTLC script.
|
||||||
case !isIncoming && ourCommit:
|
case !isIncoming && ourCommit:
|
||||||
witnessScript, err = senderHTLCScript(keyRing.LocalHtlcKey,
|
witnessScript, err = input.SenderHTLCScript(keyRing.LocalHtlcKey,
|
||||||
keyRing.RemoteHtlcKey, keyRing.RevocationKey, rHash[:])
|
keyRing.RemoteHtlcKey, keyRing.RevocationKey, rHash[:])
|
||||||
|
|
||||||
// Finally, we're paying the remote party via an HTLC, which is being
|
// Finally, we're paying the remote party via an HTLC, which is being
|
||||||
// added to their commitment transaction. Therefore, we use the
|
// added to their commitment transaction. Therefore, we use the
|
||||||
// receiver's version of the HTLC script.
|
// receiver's version of the HTLC script.
|
||||||
case !isIncoming && !ourCommit:
|
case !isIncoming && !ourCommit:
|
||||||
witnessScript, err = receiverHTLCScript(timeout, keyRing.LocalHtlcKey,
|
witnessScript, err = input.ReceiverHTLCScript(timeout, keyRing.LocalHtlcKey,
|
||||||
keyRing.RemoteHtlcKey, keyRing.RevocationKey, rHash[:])
|
keyRing.RemoteHtlcKey, keyRing.RevocationKey, rHash[:])
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -4903,7 +4904,7 @@ func genHtlcScript(isIncoming, ourCommit bool, timeout uint32, rHash [32]byte,
|
|||||||
|
|
||||||
// Now that we have the redeem scripts, create the P2WSH public key
|
// Now that we have the redeem scripts, create the P2WSH public key
|
||||||
// script for the output itself.
|
// script for the output itself.
|
||||||
htlcP2WSH, err := WitnessScriptHash(witnessScript)
|
htlcP2WSH, err := input.WitnessScriptHash(witnessScript)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
@ -4972,7 +4973,7 @@ func (lc *LightningChannel) getSignedCommitTx() (*wire.MsgTx, error) {
|
|||||||
ourKey := lc.localChanCfg.MultiSigKey.PubKey.SerializeCompressed()
|
ourKey := lc.localChanCfg.MultiSigKey.PubKey.SerializeCompressed()
|
||||||
theirKey := lc.remoteChanCfg.MultiSigKey.PubKey.SerializeCompressed()
|
theirKey := lc.remoteChanCfg.MultiSigKey.PubKey.SerializeCompressed()
|
||||||
|
|
||||||
commitTx.TxIn[0].Witness = SpendMultiSig(
|
commitTx.TxIn[0].Witness = input.SpendMultiSig(
|
||||||
lc.signDesc.WitnessScript, ourKey,
|
lc.signDesc.WitnessScript, ourKey,
|
||||||
ourSig, theirKey, theirSig,
|
ourSig, theirKey, theirSig,
|
||||||
)
|
)
|
||||||
@ -4990,7 +4991,7 @@ type CommitOutputResolution struct {
|
|||||||
|
|
||||||
// SelfOutputSignDesc is a fully populated sign descriptor capable of
|
// SelfOutputSignDesc is a fully populated sign descriptor capable of
|
||||||
// generating a valid signature to sweep the output paying to us.
|
// generating a valid signature to sweep the output paying to us.
|
||||||
SelfOutputSignDesc SignDescriptor
|
SelfOutputSignDesc input.SignDescriptor
|
||||||
|
|
||||||
// MaturityDelay is the relative time-lock, in blocks for all outputs
|
// MaturityDelay is the relative time-lock, in blocks for all outputs
|
||||||
// that pay to the local party within the broadcast commitment
|
// that pay to the local party within the broadcast commitment
|
||||||
@ -5046,7 +5047,7 @@ type UnilateralCloseSummary struct {
|
|||||||
// happen in case we have lost state) it should be set to an empty struct, in
|
// happen in case we have lost state) it should be set to an empty struct, in
|
||||||
// which case we will attempt to sweep the non-HTLC output using the passed
|
// which case we will attempt to sweep the non-HTLC output using the passed
|
||||||
// commitPoint.
|
// commitPoint.
|
||||||
func NewUnilateralCloseSummary(chanState *channeldb.OpenChannel, signer Signer,
|
func NewUnilateralCloseSummary(chanState *channeldb.OpenChannel, signer input.Signer,
|
||||||
pCache PreimageCache, commitSpend *chainntnfs.SpendDetail,
|
pCache PreimageCache, commitSpend *chainntnfs.SpendDetail,
|
||||||
remoteCommit channeldb.ChannelCommitment,
|
remoteCommit channeldb.ChannelCommitment,
|
||||||
commitPoint *btcec.PublicKey) (*UnilateralCloseSummary, error) {
|
commitPoint *btcec.PublicKey) (*UnilateralCloseSummary, error) {
|
||||||
@ -5074,7 +5075,7 @@ func NewUnilateralCloseSummary(chanState *channeldb.OpenChannel, signer Signer,
|
|||||||
// Before we can generate the proper sign descriptor, we'll need to
|
// Before we can generate the proper sign descriptor, we'll need to
|
||||||
// locate the output index of our non-delayed output on the commitment
|
// locate the output index of our non-delayed output on the commitment
|
||||||
// transaction.
|
// transaction.
|
||||||
selfP2WKH, err := CommitScriptUnencumbered(keyRing.NoDelayKey)
|
selfP2WKH, err := input.CommitScriptUnencumbered(keyRing.NoDelayKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to create self commit script: %v", err)
|
return nil, fmt.Errorf("unable to create self commit script: %v", err)
|
||||||
}
|
}
|
||||||
@ -5103,7 +5104,7 @@ func NewUnilateralCloseSummary(chanState *channeldb.OpenChannel, signer Signer,
|
|||||||
localPayBase := chanState.LocalChanCfg.PaymentBasePoint
|
localPayBase := chanState.LocalChanCfg.PaymentBasePoint
|
||||||
commitResolution = &CommitOutputResolution{
|
commitResolution = &CommitOutputResolution{
|
||||||
SelfOutPoint: *selfPoint,
|
SelfOutPoint: *selfPoint,
|
||||||
SelfOutputSignDesc: SignDescriptor{
|
SelfOutputSignDesc: input.SignDescriptor{
|
||||||
KeyDesc: localPayBase,
|
KeyDesc: localPayBase,
|
||||||
SingleTweak: keyRing.LocalCommitKeyTweak,
|
SingleTweak: keyRing.LocalCommitKeyTweak,
|
||||||
WitnessScript: selfP2WKH,
|
WitnessScript: selfP2WKH,
|
||||||
@ -5190,7 +5191,7 @@ type IncomingHtlcResolution struct {
|
|||||||
// SweepSignDesc is a sign descriptor that has been populated with the
|
// SweepSignDesc is a sign descriptor that has been populated with the
|
||||||
// necessary items required to spend the sole output of the above
|
// necessary items required to spend the sole output of the above
|
||||||
// transaction.
|
// transaction.
|
||||||
SweepSignDesc SignDescriptor
|
SweepSignDesc input.SignDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
// OutgoingHtlcResolution houses the information necessary to sweep any
|
// OutgoingHtlcResolution houses the information necessary to sweep any
|
||||||
@ -5230,7 +5231,7 @@ type OutgoingHtlcResolution struct {
|
|||||||
// SweepSignDesc is a sign descriptor that has been populated with the
|
// SweepSignDesc is a sign descriptor that has been populated with the
|
||||||
// necessary items required to spend the sole output of the above
|
// necessary items required to spend the sole output of the above
|
||||||
// transaction.
|
// transaction.
|
||||||
SweepSignDesc SignDescriptor
|
SweepSignDesc input.SignDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
// HtlcResolutions contains the items necessary to sweep HTLC's on chain
|
// HtlcResolutions contains the items necessary to sweep HTLC's on chain
|
||||||
@ -5250,7 +5251,7 @@ type HtlcResolutions struct {
|
|||||||
// newOutgoingHtlcResolution generates a new HTLC resolution capable of
|
// newOutgoingHtlcResolution generates a new HTLC resolution capable of
|
||||||
// allowing the caller to sweep an outgoing HTLC present on either their, or
|
// allowing the caller to sweep an outgoing HTLC present on either their, or
|
||||||
// the remote party's commitment transaction.
|
// the remote party's commitment transaction.
|
||||||
func newOutgoingHtlcResolution(signer Signer, localChanCfg *channeldb.ChannelConfig,
|
func newOutgoingHtlcResolution(signer input.Signer, localChanCfg *channeldb.ChannelConfig,
|
||||||
commitHash chainhash.Hash, htlc *channeldb.HTLC, keyRing *CommitmentKeyRing,
|
commitHash chainhash.Hash, htlc *channeldb.HTLC, keyRing *CommitmentKeyRing,
|
||||||
feePerKw SatPerKWeight, dustLimit btcutil.Amount, csvDelay uint32, localCommit bool,
|
feePerKw SatPerKWeight, dustLimit btcutil.Amount, csvDelay uint32, localCommit bool,
|
||||||
) (*OutgoingHtlcResolution, error) {
|
) (*OutgoingHtlcResolution, error) {
|
||||||
@ -5266,14 +5267,14 @@ func newOutgoingHtlcResolution(signer Signer, localChanCfg *channeldb.ChannelCon
|
|||||||
if !localCommit {
|
if !localCommit {
|
||||||
// First, we'll re-generate the script used to send the HTLC to
|
// First, we'll re-generate the script used to send the HTLC to
|
||||||
// the remote party within their commitment transaction.
|
// the remote party within their commitment transaction.
|
||||||
htlcReceiverScript, err := receiverHTLCScript(htlc.RefundTimeout,
|
htlcReceiverScript, err := input.ReceiverHTLCScript(htlc.RefundTimeout,
|
||||||
keyRing.LocalHtlcKey, keyRing.RemoteHtlcKey,
|
keyRing.LocalHtlcKey, keyRing.RemoteHtlcKey,
|
||||||
keyRing.RevocationKey, htlc.RHash[:],
|
keyRing.RevocationKey, htlc.RHash[:],
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
htlcScriptHash, err := WitnessScriptHash(htlcReceiverScript)
|
htlcScriptHash, err := input.WitnessScriptHash(htlcReceiverScript)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -5283,7 +5284,7 @@ func newOutgoingHtlcResolution(signer Signer, localChanCfg *channeldb.ChannelCon
|
|||||||
return &OutgoingHtlcResolution{
|
return &OutgoingHtlcResolution{
|
||||||
Expiry: htlc.RefundTimeout,
|
Expiry: htlc.RefundTimeout,
|
||||||
ClaimOutpoint: op,
|
ClaimOutpoint: op,
|
||||||
SweepSignDesc: SignDescriptor{
|
SweepSignDesc: input.SignDescriptor{
|
||||||
KeyDesc: localChanCfg.HtlcBasePoint,
|
KeyDesc: localChanCfg.HtlcBasePoint,
|
||||||
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
||||||
WitnessScript: htlcReceiverScript,
|
WitnessScript: htlcReceiverScript,
|
||||||
@ -5318,12 +5319,12 @@ func newOutgoingHtlcResolution(signer Signer, localChanCfg *channeldb.ChannelCon
|
|||||||
// With the transaction created, we can generate a sign descriptor
|
// With the transaction created, we can generate a sign descriptor
|
||||||
// that's capable of generating the signature required to spend the
|
// that's capable of generating the signature required to spend the
|
||||||
// HTLC output using the timeout transaction.
|
// HTLC output using the timeout transaction.
|
||||||
htlcCreationScript, err := senderHTLCScript(keyRing.LocalHtlcKey,
|
htlcCreationScript, err := input.SenderHTLCScript(keyRing.LocalHtlcKey,
|
||||||
keyRing.RemoteHtlcKey, keyRing.RevocationKey, htlc.RHash[:])
|
keyRing.RemoteHtlcKey, keyRing.RevocationKey, htlc.RHash[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
timeoutSignDesc := SignDescriptor{
|
timeoutSignDesc := input.SignDescriptor{
|
||||||
KeyDesc: localChanCfg.HtlcBasePoint,
|
KeyDesc: localChanCfg.HtlcBasePoint,
|
||||||
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
||||||
WitnessScript: htlcCreationScript,
|
WitnessScript: htlcCreationScript,
|
||||||
@ -5337,7 +5338,7 @@ func newOutgoingHtlcResolution(signer Signer, localChanCfg *channeldb.ChannelCon
|
|||||||
|
|
||||||
// With the sign desc created, we can now construct the full witness
|
// With the sign desc created, we can now construct the full witness
|
||||||
// for the timeout transaction, and populate it as well.
|
// for the timeout transaction, and populate it as well.
|
||||||
timeoutWitness, err := senderHtlcSpendTimeout(
|
timeoutWitness, err := input.SenderHtlcSpendTimeout(
|
||||||
htlc.Signature, signer, &timeoutSignDesc, timeoutTx,
|
htlc.Signature, signer, &timeoutSignDesc, timeoutTx,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -5348,18 +5349,18 @@ func newOutgoingHtlcResolution(signer Signer, localChanCfg *channeldb.ChannelCon
|
|||||||
// Finally, we'll generate the script output that the timeout
|
// Finally, we'll generate the script output that the timeout
|
||||||
// transaction creates so we can generate the signDesc required to
|
// transaction creates so we can generate the signDesc required to
|
||||||
// complete the claim process after a delay period.
|
// complete the claim process after a delay period.
|
||||||
htlcSweepScript, err := secondLevelHtlcScript(
|
htlcSweepScript, err := input.SecondLevelHtlcScript(
|
||||||
keyRing.RevocationKey, keyRing.DelayKey, csvDelay,
|
keyRing.RevocationKey, keyRing.DelayKey, csvDelay,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
htlcScriptHash, err := WitnessScriptHash(htlcSweepScript)
|
htlcScriptHash, err := input.WitnessScriptHash(htlcSweepScript)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
localDelayTweak := SingleTweakBytes(
|
localDelayTweak := input.SingleTweakBytes(
|
||||||
keyRing.CommitPoint, localChanCfg.DelayBasePoint.PubKey,
|
keyRing.CommitPoint, localChanCfg.DelayBasePoint.PubKey,
|
||||||
)
|
)
|
||||||
return &OutgoingHtlcResolution{
|
return &OutgoingHtlcResolution{
|
||||||
@ -5370,7 +5371,7 @@ func newOutgoingHtlcResolution(signer Signer, localChanCfg *channeldb.ChannelCon
|
|||||||
Hash: timeoutTx.TxHash(),
|
Hash: timeoutTx.TxHash(),
|
||||||
Index: 0,
|
Index: 0,
|
||||||
},
|
},
|
||||||
SweepSignDesc: SignDescriptor{
|
SweepSignDesc: input.SignDescriptor{
|
||||||
KeyDesc: localChanCfg.DelayBasePoint,
|
KeyDesc: localChanCfg.DelayBasePoint,
|
||||||
SingleTweak: localDelayTweak,
|
SingleTweak: localDelayTweak,
|
||||||
WitnessScript: htlcSweepScript,
|
WitnessScript: htlcSweepScript,
|
||||||
@ -5390,7 +5391,7 @@ func newOutgoingHtlcResolution(signer Signer, localChanCfg *channeldb.ChannelCon
|
|||||||
// they can just sweep the output immediately with knowledge of the pre-image.
|
// they can just sweep the output immediately with knowledge of the pre-image.
|
||||||
//
|
//
|
||||||
// TODO(roasbeef) consolidate code with above func
|
// TODO(roasbeef) consolidate code with above func
|
||||||
func newIncomingHtlcResolution(signer Signer, localChanCfg *channeldb.ChannelConfig,
|
func newIncomingHtlcResolution(signer input.Signer, localChanCfg *channeldb.ChannelConfig,
|
||||||
commitHash chainhash.Hash, htlc *channeldb.HTLC, keyRing *CommitmentKeyRing,
|
commitHash chainhash.Hash, htlc *channeldb.HTLC, keyRing *CommitmentKeyRing,
|
||||||
feePerKw SatPerKWeight, dustLimit btcutil.Amount, csvDelay uint32,
|
feePerKw SatPerKWeight, dustLimit btcutil.Amount, csvDelay uint32,
|
||||||
localCommit bool, preimage [32]byte) (*IncomingHtlcResolution, error) {
|
localCommit bool, preimage [32]byte) (*IncomingHtlcResolution, error) {
|
||||||
@ -5405,14 +5406,14 @@ func newIncomingHtlcResolution(signer Signer, localChanCfg *channeldb.ChannelCon
|
|||||||
if !localCommit {
|
if !localCommit {
|
||||||
// First, we'll re-generate the script the remote party used to
|
// First, we'll re-generate the script the remote party used to
|
||||||
// send the HTLC to us in their commitment transaction.
|
// send the HTLC to us in their commitment transaction.
|
||||||
htlcSenderScript, err := senderHTLCScript(
|
htlcSenderScript, err := input.SenderHTLCScript(
|
||||||
keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey,
|
keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey,
|
||||||
keyRing.RevocationKey, htlc.RHash[:],
|
keyRing.RevocationKey, htlc.RHash[:],
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
htlcScriptHash, err := WitnessScriptHash(htlcSenderScript)
|
htlcScriptHash, err := input.WitnessScriptHash(htlcSenderScript)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -5423,7 +5424,7 @@ func newIncomingHtlcResolution(signer Signer, localChanCfg *channeldb.ChannelCon
|
|||||||
Preimage: preimage,
|
Preimage: preimage,
|
||||||
ClaimOutpoint: op,
|
ClaimOutpoint: op,
|
||||||
CsvDelay: csvDelay,
|
CsvDelay: csvDelay,
|
||||||
SweepSignDesc: SignDescriptor{
|
SweepSignDesc: input.SignDescriptor{
|
||||||
KeyDesc: localChanCfg.HtlcBasePoint,
|
KeyDesc: localChanCfg.HtlcBasePoint,
|
||||||
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
||||||
WitnessScript: htlcSenderScript,
|
WitnessScript: htlcSenderScript,
|
||||||
@ -5452,14 +5453,14 @@ func newIncomingHtlcResolution(signer Signer, localChanCfg *channeldb.ChannelCon
|
|||||||
|
|
||||||
// Once we've created the second-level transaction, we'll generate the
|
// Once we've created the second-level transaction, we'll generate the
|
||||||
// SignDesc needed spend the HTLC output using the success transaction.
|
// SignDesc needed spend the HTLC output using the success transaction.
|
||||||
htlcCreationScript, err := receiverHTLCScript(htlc.RefundTimeout,
|
htlcCreationScript, err := input.ReceiverHTLCScript(htlc.RefundTimeout,
|
||||||
keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey,
|
keyRing.RemoteHtlcKey, keyRing.LocalHtlcKey,
|
||||||
keyRing.RevocationKey, htlc.RHash[:],
|
keyRing.RevocationKey, htlc.RHash[:],
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
successSignDesc := SignDescriptor{
|
successSignDesc := input.SignDescriptor{
|
||||||
KeyDesc: localChanCfg.HtlcBasePoint,
|
KeyDesc: localChanCfg.HtlcBasePoint,
|
||||||
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
SingleTweak: keyRing.LocalHtlcKeyTweak,
|
||||||
WitnessScript: htlcCreationScript,
|
WitnessScript: htlcCreationScript,
|
||||||
@ -5473,7 +5474,7 @@ func newIncomingHtlcResolution(signer Signer, localChanCfg *channeldb.ChannelCon
|
|||||||
|
|
||||||
// Next, we'll construct the full witness needed to satisfy the input
|
// Next, we'll construct the full witness needed to satisfy the input
|
||||||
// of the success transaction.
|
// of the success transaction.
|
||||||
successWitness, err := receiverHtlcSpendRedeem(
|
successWitness, err := input.ReceiverHtlcSpendRedeem(
|
||||||
htlc.Signature, preimage[:], signer, &successSignDesc, successTx,
|
htlc.Signature, preimage[:], signer, &successSignDesc, successTx,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -5484,18 +5485,18 @@ func newIncomingHtlcResolution(signer Signer, localChanCfg *channeldb.ChannelCon
|
|||||||
// Finally, we'll generate the script that the second-level transaction
|
// Finally, we'll generate the script that the second-level transaction
|
||||||
// creates so we can generate the proper signDesc to sweep it after the
|
// creates so we can generate the proper signDesc to sweep it after the
|
||||||
// CSV delay has passed.
|
// CSV delay has passed.
|
||||||
htlcSweepScript, err := secondLevelHtlcScript(
|
htlcSweepScript, err := input.SecondLevelHtlcScript(
|
||||||
keyRing.RevocationKey, keyRing.DelayKey, csvDelay,
|
keyRing.RevocationKey, keyRing.DelayKey, csvDelay,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
htlcScriptHash, err := WitnessScriptHash(htlcSweepScript)
|
htlcScriptHash, err := input.WitnessScriptHash(htlcSweepScript)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
localDelayTweak := SingleTweakBytes(
|
localDelayTweak := input.SingleTweakBytes(
|
||||||
keyRing.CommitPoint, localChanCfg.DelayBasePoint.PubKey,
|
keyRing.CommitPoint, localChanCfg.DelayBasePoint.PubKey,
|
||||||
)
|
)
|
||||||
return &IncomingHtlcResolution{
|
return &IncomingHtlcResolution{
|
||||||
@ -5506,7 +5507,7 @@ func newIncomingHtlcResolution(signer Signer, localChanCfg *channeldb.ChannelCon
|
|||||||
Hash: successTx.TxHash(),
|
Hash: successTx.TxHash(),
|
||||||
Index: 0,
|
Index: 0,
|
||||||
},
|
},
|
||||||
SweepSignDesc: SignDescriptor{
|
SweepSignDesc: input.SignDescriptor{
|
||||||
KeyDesc: localChanCfg.DelayBasePoint,
|
KeyDesc: localChanCfg.DelayBasePoint,
|
||||||
SingleTweak: localDelayTweak,
|
SingleTweak: localDelayTweak,
|
||||||
WitnessScript: htlcSweepScript,
|
WitnessScript: htlcSweepScript,
|
||||||
@ -5547,7 +5548,7 @@ func (r *OutgoingHtlcResolution) HtlcPoint() wire.OutPoint {
|
|||||||
// the local key used when generating the HTLC scrips. This function is to be
|
// the local key used when generating the HTLC scrips. This function is to be
|
||||||
// used in two cases: force close, or a unilateral close.
|
// used in two cases: force close, or a unilateral close.
|
||||||
func extractHtlcResolutions(feePerKw SatPerKWeight, ourCommit bool,
|
func extractHtlcResolutions(feePerKw SatPerKWeight, ourCommit bool,
|
||||||
signer Signer, htlcs []channeldb.HTLC, keyRing *CommitmentKeyRing,
|
signer input.Signer, htlcs []channeldb.HTLC, keyRing *CommitmentKeyRing,
|
||||||
localChanCfg, remoteChanCfg *channeldb.ChannelConfig,
|
localChanCfg, remoteChanCfg *channeldb.ChannelConfig,
|
||||||
commitHash chainhash.Hash, pCache PreimageCache) (*HtlcResolutions, error) {
|
commitHash chainhash.Hash, pCache PreimageCache) (*HtlcResolutions, error) {
|
||||||
|
|
||||||
@ -5692,7 +5693,7 @@ func (lc *LightningChannel) ForceClose() (*LocalForceCloseSummary, error) {
|
|||||||
// NewLocalForceCloseSummary generates a LocalForceCloseSummary from the given
|
// NewLocalForceCloseSummary generates a LocalForceCloseSummary from the given
|
||||||
// channel state. The passed commitTx must be a fully signed commitment
|
// channel state. The passed commitTx must be a fully signed commitment
|
||||||
// transaction corresponding to localCommit.
|
// transaction corresponding to localCommit.
|
||||||
func NewLocalForceCloseSummary(chanState *channeldb.OpenChannel, signer Signer,
|
func NewLocalForceCloseSummary(chanState *channeldb.OpenChannel, signer input.Signer,
|
||||||
pCache PreimageCache, commitTx *wire.MsgTx,
|
pCache PreimageCache, commitTx *wire.MsgTx,
|
||||||
localCommit channeldb.ChannelCommitment) (*LocalForceCloseSummary, error) {
|
localCommit channeldb.ChannelCommitment) (*LocalForceCloseSummary, error) {
|
||||||
|
|
||||||
@ -5707,15 +5708,15 @@ func NewLocalForceCloseSummary(chanState *channeldb.OpenChannel, signer Signer,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
commitPoint := ComputeCommitmentPoint(revocation[:])
|
commitPoint := input.ComputeCommitmentPoint(revocation[:])
|
||||||
keyRing := deriveCommitmentKeys(commitPoint, true, &chanState.LocalChanCfg,
|
keyRing := deriveCommitmentKeys(commitPoint, true, &chanState.LocalChanCfg,
|
||||||
&chanState.RemoteChanCfg)
|
&chanState.RemoteChanCfg)
|
||||||
selfScript, err := CommitScriptToSelf(csvTimeout, keyRing.DelayKey,
|
selfScript, err := input.CommitScriptToSelf(csvTimeout, keyRing.DelayKey,
|
||||||
keyRing.RevocationKey)
|
keyRing.RevocationKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
payToUsScriptHash, err := WitnessScriptHash(selfScript)
|
payToUsScriptHash, err := input.WitnessScriptHash(selfScript)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -5745,7 +5746,7 @@ func NewLocalForceCloseSummary(chanState *channeldb.OpenChannel, signer Signer,
|
|||||||
// nil.
|
// nil.
|
||||||
var commitResolution *CommitOutputResolution
|
var commitResolution *CommitOutputResolution
|
||||||
if len(delayScript) != 0 {
|
if len(delayScript) != 0 {
|
||||||
singleTweak := SingleTweakBytes(
|
singleTweak := input.SingleTweakBytes(
|
||||||
commitPoint, chanState.LocalChanCfg.DelayBasePoint.PubKey,
|
commitPoint, chanState.LocalChanCfg.DelayBasePoint.PubKey,
|
||||||
)
|
)
|
||||||
localBalance := localCommit.LocalBalance
|
localBalance := localCommit.LocalBalance
|
||||||
@ -5754,7 +5755,7 @@ func NewLocalForceCloseSummary(chanState *channeldb.OpenChannel, signer Signer,
|
|||||||
Hash: commitTx.TxHash(),
|
Hash: commitTx.TxHash(),
|
||||||
Index: delayIndex,
|
Index: delayIndex,
|
||||||
},
|
},
|
||||||
SelfOutputSignDesc: SignDescriptor{
|
SelfOutputSignDesc: input.SignDescriptor{
|
||||||
KeyDesc: chanState.LocalChanCfg.DelayBasePoint,
|
KeyDesc: chanState.LocalChanCfg.DelayBasePoint,
|
||||||
SingleTweak: singleTweak,
|
SingleTweak: singleTweak,
|
||||||
WitnessScript: selfScript,
|
WitnessScript: selfScript,
|
||||||
@ -5916,7 +5917,7 @@ func (lc *LightningChannel) CompleteCooperativeClose(localSig, remoteSig []byte,
|
|||||||
// pubkeys+sigs on the stack.
|
// pubkeys+sigs on the stack.
|
||||||
ourKey := lc.localChanCfg.MultiSigKey.PubKey.SerializeCompressed()
|
ourKey := lc.localChanCfg.MultiSigKey.PubKey.SerializeCompressed()
|
||||||
theirKey := lc.remoteChanCfg.MultiSigKey.PubKey.SerializeCompressed()
|
theirKey := lc.remoteChanCfg.MultiSigKey.PubKey.SerializeCompressed()
|
||||||
witness := SpendMultiSig(lc.signDesc.WitnessScript, ourKey,
|
witness := input.SpendMultiSig(lc.signDesc.WitnessScript, ourKey,
|
||||||
localSig, theirKey, remoteSig)
|
localSig, theirKey, remoteSig)
|
||||||
closeTx.TxIn[0].Witness = witness
|
closeTx.TxIn[0].Witness = witness
|
||||||
|
|
||||||
@ -6121,7 +6122,7 @@ func (lc *LightningChannel) generateRevocation(height uint64) (*lnwire.RevokeAnd
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
revocationMsg.NextRevocationKey = ComputeCommitmentPoint(nextCommitSecret[:])
|
revocationMsg.NextRevocationKey = input.ComputeCommitmentPoint(nextCommitSecret[:])
|
||||||
revocationMsg.ChanID = lnwire.NewChanIDFromOutPoint(
|
revocationMsg.ChanID = lnwire.NewChanIDFromOutPoint(
|
||||||
&lc.channelState.FundingOutpoint)
|
&lc.channelState.FundingOutpoint)
|
||||||
|
|
||||||
@ -6142,19 +6143,19 @@ func CreateCommitTx(fundingOutput wire.TxIn,
|
|||||||
// output after a relative block delay, or the remote node can claim
|
// output after a relative block delay, or the remote node can claim
|
||||||
// the funds with the revocation key if we broadcast a revoked
|
// the funds with the revocation key if we broadcast a revoked
|
||||||
// commitment transaction.
|
// commitment transaction.
|
||||||
ourRedeemScript, err := CommitScriptToSelf(csvTimeout, keyRing.DelayKey,
|
ourRedeemScript, err := input.CommitScriptToSelf(csvTimeout, keyRing.DelayKey,
|
||||||
keyRing.RevocationKey)
|
keyRing.RevocationKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
payToUsScriptHash, err := WitnessScriptHash(ourRedeemScript)
|
payToUsScriptHash, err := input.WitnessScriptHash(ourRedeemScript)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next, we create the script paying to them. This is just a regular
|
// Next, we create the script paying to them. This is just a regular
|
||||||
// P2WPKH output, without any added CSV delay.
|
// P2WPKH output, without any added CSV delay.
|
||||||
theirWitnessKeyHash, err := CommitScriptUnencumbered(keyRing.NoDelayKey)
|
theirWitnessKeyHash, err := input.CommitScriptUnencumbered(keyRing.NoDelayKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -6223,7 +6224,7 @@ func CreateCooperativeCloseTx(fundingTxIn wire.TxIn,
|
|||||||
// CalcFee returns the commitment fee to use for the given
|
// CalcFee returns the commitment fee to use for the given
|
||||||
// fee rate (fee-per-kw).
|
// fee rate (fee-per-kw).
|
||||||
func (lc *LightningChannel) CalcFee(feeRate SatPerKWeight) btcutil.Amount {
|
func (lc *LightningChannel) CalcFee(feeRate SatPerKWeight) btcutil.Amount {
|
||||||
return feeRate.FeeForWeight(CommitWeight)
|
return feeRate.FeeForWeight(input.CommitWeight)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RemoteNextRevocation returns the channelState's RemoteNextRevocation.
|
// RemoteNextRevocation returns the channelState's RemoteNextRevocation.
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -403,7 +404,7 @@ func TestCheckCommitTxSize(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actualCost := blockchain.GetTransactionWeight(btcutil.NewTx(commitTx))
|
actualCost := blockchain.GetTransactionWeight(btcutil.NewTx(commitTx))
|
||||||
estimatedCost := estimateCommitTxWeight(count, false)
|
estimatedCost := input.EstimateCommitTxWeight(count, false)
|
||||||
|
|
||||||
diff := int(estimatedCost - actualCost)
|
diff := int(estimatedCost - actualCost)
|
||||||
if 0 > diff || BaseCommitmentTxSizeEstimationError < diff {
|
if 0 > diff || BaseCommitmentTxSizeEstimationError < diff {
|
||||||
@ -624,7 +625,7 @@ func TestForceClose(t *testing.T) {
|
|||||||
|
|
||||||
// Factoring in the fee rate, Alice's amount should properly reflect
|
// Factoring in the fee rate, Alice's amount should properly reflect
|
||||||
// that we've added two additional HTLC to the commitment transaction.
|
// that we've added two additional HTLC to the commitment transaction.
|
||||||
totalCommitWeight := CommitWeight + (HtlcWeight * 2)
|
totalCommitWeight := input.CommitWeight + (input.HtlcWeight * 2)
|
||||||
feePerKw := SatPerKWeight(aliceChannel.channelState.LocalCommitment.FeePerKw)
|
feePerKw := SatPerKWeight(aliceChannel.channelState.LocalCommitment.FeePerKw)
|
||||||
commitFee := feePerKw.FeeForWeight(totalCommitWeight)
|
commitFee := feePerKw.FeeForWeight(totalCommitWeight)
|
||||||
expectedAmount := (aliceChannel.Capacity / 2) - htlcAmount.ToSatoshis() - commitFee
|
expectedAmount := (aliceChannel.Capacity / 2) - htlcAmount.ToSatoshis() - commitFee
|
||||||
@ -680,7 +681,7 @@ func TestForceClose(t *testing.T) {
|
|||||||
Value: htlcResolution.SweepSignDesc.Output.Value,
|
Value: htlcResolution.SweepSignDesc.Output.Value,
|
||||||
})
|
})
|
||||||
htlcResolution.SweepSignDesc.InputIndex = 0
|
htlcResolution.SweepSignDesc.InputIndex = 0
|
||||||
sweepTx.TxIn[0].Witness, err = htlcSpendSuccess(aliceChannel.Signer,
|
sweepTx.TxIn[0].Witness, err = input.HtlcSpendSuccess(aliceChannel.Signer,
|
||||||
&htlcResolution.SweepSignDesc, sweepTx,
|
&htlcResolution.SweepSignDesc, sweepTx,
|
||||||
uint32(aliceChannel.channelState.LocalChanCfg.CsvDelay))
|
uint32(aliceChannel.channelState.LocalChanCfg.CsvDelay))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -741,7 +742,7 @@ func TestForceClose(t *testing.T) {
|
|||||||
Value: inHtlcResolution.SweepSignDesc.Output.Value,
|
Value: inHtlcResolution.SweepSignDesc.Output.Value,
|
||||||
})
|
})
|
||||||
inHtlcResolution.SweepSignDesc.InputIndex = 0
|
inHtlcResolution.SweepSignDesc.InputIndex = 0
|
||||||
sweepTx.TxIn[0].Witness, err = htlcSpendSuccess(aliceChannel.Signer,
|
sweepTx.TxIn[0].Witness, err = input.HtlcSpendSuccess(aliceChannel.Signer,
|
||||||
&inHtlcResolution.SweepSignDesc, sweepTx,
|
&inHtlcResolution.SweepSignDesc, sweepTx,
|
||||||
uint32(aliceChannel.channelState.LocalChanCfg.CsvDelay))
|
uint32(aliceChannel.channelState.LocalChanCfg.CsvDelay))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -5007,7 +5008,7 @@ func TestChannelUnilateralCloseHtlcResolution(t *testing.T) {
|
|||||||
|
|
||||||
// With the transaction constructed, we'll generate a witness that
|
// With the transaction constructed, we'll generate a witness that
|
||||||
// should be valid for it, and verify using an instance of Script.
|
// should be valid for it, and verify using an instance of Script.
|
||||||
sweepTx.TxIn[0].Witness, err = receiverHtlcSpendTimeout(
|
sweepTx.TxIn[0].Witness, err = input.ReceiverHtlcSpendTimeout(
|
||||||
aliceChannel.Signer, &outHtlcResolution.SweepSignDesc,
|
aliceChannel.Signer, &outHtlcResolution.SweepSignDesc,
|
||||||
sweepTx, int32(outHtlcResolution.Expiry),
|
sweepTx, int32(outHtlcResolution.Expiry),
|
||||||
)
|
)
|
||||||
@ -5041,7 +5042,7 @@ func TestChannelUnilateralCloseHtlcResolution(t *testing.T) {
|
|||||||
inHtlcResolution.SweepSignDesc.SigHashes = txscript.NewTxSigHashes(
|
inHtlcResolution.SweepSignDesc.SigHashes = txscript.NewTxSigHashes(
|
||||||
sweepTx,
|
sweepTx,
|
||||||
)
|
)
|
||||||
sweepTx.TxIn[0].Witness, err = SenderHtlcSpendRedeem(
|
sweepTx.TxIn[0].Witness, err = input.SenderHtlcSpendRedeem(
|
||||||
aliceChannel.Signer, &inHtlcResolution.SweepSignDesc,
|
aliceChannel.Signer, &inHtlcResolution.SweepSignDesc,
|
||||||
sweepTx, preimageBob[:],
|
sweepTx, preimageBob[:],
|
||||||
)
|
)
|
||||||
@ -5172,7 +5173,7 @@ func TestChannelUnilateralClosePendingCommit(t *testing.T) {
|
|||||||
Value: aliceSignDesc.Output.Value,
|
Value: aliceSignDesc.Output.Value,
|
||||||
})
|
})
|
||||||
aliceSignDesc.SigHashes = txscript.NewTxSigHashes(sweepTx)
|
aliceSignDesc.SigHashes = txscript.NewTxSigHashes(sweepTx)
|
||||||
sweepTx.TxIn[0].Witness, err = CommitSpendNoDelay(
|
sweepTx.TxIn[0].Witness, err = input.CommitSpendNoDelay(
|
||||||
aliceChannel.Signer, &aliceSignDesc, sweepTx,
|
aliceChannel.Signer, &aliceSignDesc, sweepTx,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"github.com/btcsuite/btcd/chaincfg"
|
"github.com/btcsuite/btcd/chaincfg"
|
||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -37,7 +38,7 @@ type Config struct {
|
|||||||
// used to generate signature for all inputs to potential funding
|
// used to generate signature for all inputs to potential funding
|
||||||
// transactions, as well as for spends from the funding transaction to
|
// transactions, as well as for spends from the funding transaction to
|
||||||
// update the commitment state.
|
// update the commitment state.
|
||||||
Signer Signer
|
Signer input.Signer
|
||||||
|
|
||||||
// FeeEstimator is the implementation that the wallet will use for the
|
// FeeEstimator is the implementation that the wallet will use for the
|
||||||
// calculation of on-chain transaction fees.
|
// calculation of on-chain transaction fees.
|
||||||
|
@ -253,30 +253,6 @@ type BlockChainIO interface {
|
|||||||
GetBlock(blockHash *chainhash.Hash) (*wire.MsgBlock, error)
|
GetBlock(blockHash *chainhash.Hash) (*wire.MsgBlock, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Signer represents an abstract object capable of generating raw signatures as
|
|
||||||
// well as full complete input scripts given a valid SignDescriptor and
|
|
||||||
// transaction. This interface fully abstracts away signing paving the way for
|
|
||||||
// Signer implementations such as hardware wallets, hardware tokens, HSM's, or
|
|
||||||
// simply a regular wallet.
|
|
||||||
type Signer interface {
|
|
||||||
// SignOutputRaw generates a signature for the passed transaction
|
|
||||||
// according to the data within the passed SignDescriptor.
|
|
||||||
//
|
|
||||||
// NOTE: The resulting signature should be void of a sighash byte.
|
|
||||||
SignOutputRaw(tx *wire.MsgTx, signDesc *SignDescriptor) ([]byte, error)
|
|
||||||
|
|
||||||
// ComputeInputScript generates a complete InputIndex for the passed
|
|
||||||
// transaction with the signature as defined within the passed
|
|
||||||
// SignDescriptor. This method should be capable of generating the
|
|
||||||
// proper input script for both regular p2wkh output and p2wkh outputs
|
|
||||||
// nested within a regular p2sh output.
|
|
||||||
//
|
|
||||||
// NOTE: This method will ignore any tweak parameters set within the
|
|
||||||
// passed SignDescriptor as it assumes a set of typical script
|
|
||||||
// templates (p2wkh, np2wkh, etc).
|
|
||||||
ComputeInputScript(tx *wire.MsgTx, signDesc *SignDescriptor) (*InputScript, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MessageSigner represents an abstract object capable of signing arbitrary
|
// MessageSigner represents an abstract object capable of signing arbitrary
|
||||||
// messages. The capabilities of this interface are used to sign announcements
|
// messages. The capabilities of this interface are used to sign announcements
|
||||||
// to the network, or just arbitrary messages that leverage the wallet's keys
|
// to the network, or just arbitrary messages that leverage the wallet's keys
|
||||||
|
@ -35,6 +35,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
"github.com/lightningnetwork/lnd/chainntnfs/btcdnotify"
|
"github.com/lightningnetwork/lnd/chainntnfs/btcdnotify"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet/btcwallet"
|
"github.com/lightningnetwork/lnd/lnwallet/btcwallet"
|
||||||
@ -353,7 +354,7 @@ func loadTestCredits(miner *rpctest.Harness, w *lnwallet.LightningWallet,
|
|||||||
func createTestWallet(tempTestDir string, miningNode *rpctest.Harness,
|
func createTestWallet(tempTestDir string, miningNode *rpctest.Harness,
|
||||||
netParams *chaincfg.Params, notifier chainntnfs.ChainNotifier,
|
netParams *chaincfg.Params, notifier chainntnfs.ChainNotifier,
|
||||||
wc lnwallet.WalletController, keyRing keychain.SecretKeyRing,
|
wc lnwallet.WalletController, keyRing keychain.SecretKeyRing,
|
||||||
signer lnwallet.Signer, bio lnwallet.BlockChainIO) (*lnwallet.LightningWallet, error) {
|
signer input.Signer, bio lnwallet.BlockChainIO) (*lnwallet.LightningWallet, error) {
|
||||||
|
|
||||||
dbDir := filepath.Join(tempTestDir, "cdb")
|
dbDir := filepath.Join(tempTestDir, "cdb")
|
||||||
cdb, err := channeldb.Open(dbDir)
|
cdb, err := channeldb.Open(dbDir)
|
||||||
@ -434,7 +435,7 @@ func testDualFundingReservationWorkflow(miner *rpctest.Harness,
|
|||||||
ChanReserve: fundingAmount / 100,
|
ChanReserve: fundingAmount / 100,
|
||||||
MaxPendingAmount: lnwire.NewMSatFromSatoshis(fundingAmount),
|
MaxPendingAmount: lnwire.NewMSatFromSatoshis(fundingAmount),
|
||||||
MinHTLC: 1,
|
MinHTLC: 1,
|
||||||
MaxAcceptedHtlcs: lnwallet.MaxHTLCNumber / 2,
|
MaxAcceptedHtlcs: input.MaxHTLCNumber / 2,
|
||||||
CsvDelay: csvDelay,
|
CsvDelay: csvDelay,
|
||||||
}
|
}
|
||||||
err = aliceChanReservation.CommitConstraints(channelConstraints)
|
err = aliceChanReservation.CommitConstraints(channelConstraints)
|
||||||
@ -866,7 +867,7 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness,
|
|||||||
ChanReserve: fundingAmt / 100,
|
ChanReserve: fundingAmt / 100,
|
||||||
MaxPendingAmount: lnwire.NewMSatFromSatoshis(fundingAmt),
|
MaxPendingAmount: lnwire.NewMSatFromSatoshis(fundingAmt),
|
||||||
MinHTLC: 1,
|
MinHTLC: 1,
|
||||||
MaxAcceptedHtlcs: lnwallet.MaxHTLCNumber / 2,
|
MaxAcceptedHtlcs: input.MaxHTLCNumber / 2,
|
||||||
CsvDelay: csvDelay,
|
CsvDelay: csvDelay,
|
||||||
}
|
}
|
||||||
err = aliceChanReservation.CommitConstraints(channelConstraints)
|
err = aliceChanReservation.CommitConstraints(channelConstraints)
|
||||||
@ -1528,7 +1529,7 @@ func testPublishTransaction(r *rpctest.Harness,
|
|||||||
|
|
||||||
// Now we can populate the sign descriptor which we'll use to
|
// Now we can populate the sign descriptor which we'll use to
|
||||||
// generate the signature.
|
// generate the signature.
|
||||||
signDesc := &lnwallet.SignDescriptor{
|
signDesc := &input.SignDescriptor{
|
||||||
KeyDesc: keychain.KeyDescriptor{
|
KeyDesc: keychain.KeyDescriptor{
|
||||||
PubKey: pubKey.PubKey,
|
PubKey: pubKey.PubKey,
|
||||||
},
|
},
|
||||||
@ -1783,10 +1784,10 @@ func testSignOutputUsingTweaks(r *rpctest.Harness,
|
|||||||
commitSecret, commitPoint := btcec.PrivKeyFromBytes(btcec.S256(),
|
commitSecret, commitPoint := btcec.PrivKeyFromBytes(btcec.S256(),
|
||||||
commitPreimage)
|
commitPreimage)
|
||||||
|
|
||||||
revocationKey := lnwallet.DeriveRevocationPubkey(pubKey.PubKey, commitPoint)
|
revocationKey := input.DeriveRevocationPubkey(pubKey.PubKey, commitPoint)
|
||||||
commitTweak := lnwallet.SingleTweakBytes(commitPoint, pubKey.PubKey)
|
commitTweak := input.SingleTweakBytes(commitPoint, pubKey.PubKey)
|
||||||
|
|
||||||
tweakedPub := lnwallet.TweakPubKey(pubKey.PubKey, commitPoint)
|
tweakedPub := input.TweakPubKey(pubKey.PubKey, commitPoint)
|
||||||
|
|
||||||
// As we'd like to test both single and double tweaks, we'll repeat
|
// As we'd like to test both single and double tweaks, we'll repeat
|
||||||
// the same set up twice. The first will use a regular single tweak,
|
// the same set up twice. The first will use a regular single tweak,
|
||||||
@ -1856,7 +1857,7 @@ func testSignOutputUsingTweaks(r *rpctest.Harness,
|
|||||||
// private tweak value as the key in the script is derived
|
// private tweak value as the key in the script is derived
|
||||||
// based on this tweak value and the key we originally
|
// based on this tweak value and the key we originally
|
||||||
// generated above.
|
// generated above.
|
||||||
signDesc := &lnwallet.SignDescriptor{
|
signDesc := &input.SignDescriptor{
|
||||||
KeyDesc: keychain.KeyDescriptor{
|
KeyDesc: keychain.KeyDescriptor{
|
||||||
PubKey: baseKey.PubKey,
|
PubKey: baseKey.PubKey,
|
||||||
},
|
},
|
||||||
@ -2392,8 +2393,8 @@ func runTests(t *testing.T, walletDriver *lnwallet.WalletDriver,
|
|||||||
var (
|
var (
|
||||||
bio lnwallet.BlockChainIO
|
bio lnwallet.BlockChainIO
|
||||||
|
|
||||||
aliceSigner lnwallet.Signer
|
aliceSigner input.Signer
|
||||||
bobSigner lnwallet.Signer
|
bobSigner input.Signer
|
||||||
|
|
||||||
aliceKeyRing keychain.SecretKeyRing
|
aliceKeyRing keychain.SecretKeyRing
|
||||||
bobKeyRing keychain.SecretKeyRing
|
bobKeyRing keychain.SecretKeyRing
|
||||||
|
@ -3,10 +3,11 @@ package lnwallet
|
|||||||
import (
|
import (
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/btcsuite/btcwallet/wallet/txrules"
|
"github.com/btcsuite/btcwallet/wallet/txrules"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DefaultDustLimit is used to calculate the dust HTLC amount which will be
|
// DefaultDustLimit is used to calculate the dust HTLC amount which will be
|
||||||
// send to other node during funding process.
|
// send to other node during funding process.
|
||||||
func DefaultDustLimit() btcutil.Amount {
|
func DefaultDustLimit() btcutil.Amount {
|
||||||
return txrules.GetDustThreshold(P2WSHSize, txrules.DefaultRelayFeePerKb)
|
return txrules.GetDustThreshold(input.P2WSHSize, txrules.DefaultRelayFeePerKb)
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -49,18 +50,6 @@ func (c *ChannelContribution) toChanConfig() channeldb.ChannelConfig {
|
|||||||
return *c.ChannelConfig
|
return *c.ChannelConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// InputScript represents any script inputs required to redeem a previous
|
|
||||||
// output. This struct is used rather than just a witness, or scripSig in order
|
|
||||||
// to accommodate nested p2sh which utilizes both types of input scripts.
|
|
||||||
type InputScript struct {
|
|
||||||
// Witness is the full witness stack required to unlock this output.
|
|
||||||
Witness wire.TxWitness
|
|
||||||
|
|
||||||
// SigScript will only be populated if this is an input script sweeping
|
|
||||||
// a nested p2sh output.
|
|
||||||
SigScript []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChannelReservation represents an intent to open a lightning payment channel
|
// ChannelReservation represents an intent to open a lightning payment channel
|
||||||
// with a counterparty. The funding processes from reservation to channel opening
|
// with a counterparty. The funding processes from reservation to channel opening
|
||||||
// is a 3-step process. In order to allow for full concurrency during the
|
// is a 3-step process. In order to allow for full concurrency during the
|
||||||
@ -102,8 +91,8 @@ type ChannelReservation struct {
|
|||||||
|
|
||||||
// In order of sorted inputs. Sorting is done in accordance
|
// In order of sorted inputs. Sorting is done in accordance
|
||||||
// to BIP-69: https://github.com/bitcoin/bips/blob/master/bip-0069.mediawiki.
|
// to BIP-69: https://github.com/bitcoin/bips/blob/master/bip-0069.mediawiki.
|
||||||
ourFundingInputScripts []*InputScript
|
ourFundingInputScripts []*input.Script
|
||||||
theirFundingInputScripts []*InputScript
|
theirFundingInputScripts []*input.Script
|
||||||
|
|
||||||
// Our signature for their version of the commitment transaction.
|
// Our signature for their version of the commitment transaction.
|
||||||
ourCommitmentSig []byte
|
ourCommitmentSig []byte
|
||||||
@ -149,7 +138,7 @@ func NewChannelReservation(capacity, fundingAmt btcutil.Amount,
|
|||||||
initiator bool
|
initiator bool
|
||||||
)
|
)
|
||||||
|
|
||||||
commitFee := commitFeePerKw.FeeForWeight(CommitWeight)
|
commitFee := commitFeePerKw.FeeForWeight(input.CommitWeight)
|
||||||
fundingMSat := lnwire.NewMSatFromSatoshis(fundingAmt)
|
fundingMSat := lnwire.NewMSatFromSatoshis(fundingAmt)
|
||||||
capacityMSat := lnwire.NewMSatFromSatoshis(capacity)
|
capacityMSat := lnwire.NewMSatFromSatoshis(capacity)
|
||||||
feeMSat := lnwire.NewMSatFromSatoshis(commitFee)
|
feeMSat := lnwire.NewMSatFromSatoshis(commitFee)
|
||||||
@ -320,9 +309,9 @@ func (r *ChannelReservation) CommitConstraints(c *channeldb.ChannelConstraints)
|
|||||||
|
|
||||||
// Fail if maxHtlcs is above the maximum allowed number of 483. This
|
// Fail if maxHtlcs is above the maximum allowed number of 483. This
|
||||||
// number is specified in BOLT-02.
|
// number is specified in BOLT-02.
|
||||||
if c.MaxAcceptedHtlcs > uint16(MaxHTLCNumber/2) {
|
if c.MaxAcceptedHtlcs > uint16(input.MaxHTLCNumber/2) {
|
||||||
return ErrMaxHtlcNumTooLarge(
|
return ErrMaxHtlcNumTooLarge(
|
||||||
c.MaxAcceptedHtlcs, uint16(MaxHTLCNumber/2),
|
c.MaxAcceptedHtlcs, uint16(input.MaxHTLCNumber/2),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,7 +413,7 @@ func (r *ChannelReservation) TheirContribution() *ChannelContribution {
|
|||||||
//
|
//
|
||||||
// NOTE: These signatures will only be populated after a call to
|
// NOTE: These signatures will only be populated after a call to
|
||||||
// .ProcessContribution()
|
// .ProcessContribution()
|
||||||
func (r *ChannelReservation) OurSignatures() ([]*InputScript, []byte) {
|
func (r *ChannelReservation) OurSignatures() ([]*input.Script, []byte) {
|
||||||
r.RLock()
|
r.RLock()
|
||||||
defer r.RUnlock()
|
defer r.RUnlock()
|
||||||
return r.ourFundingInputScripts, r.ourCommitmentSig
|
return r.ourFundingInputScripts, r.ourCommitmentSig
|
||||||
@ -443,7 +432,7 @@ func (r *ChannelReservation) OurSignatures() ([]*InputScript, []byte) {
|
|||||||
// block until the funding transaction obtains the configured number of
|
// block until the funding transaction obtains the configured number of
|
||||||
// confirmations. Once the method unblocks, a LightningChannel instance is
|
// confirmations. Once the method unblocks, a LightningChannel instance is
|
||||||
// returned, marking the channel available for updates.
|
// returned, marking the channel available for updates.
|
||||||
func (r *ChannelReservation) CompleteReservation(fundingInputScripts []*InputScript,
|
func (r *ChannelReservation) CompleteReservation(fundingInputScripts []*input.Script,
|
||||||
commitmentSig []byte) (*channeldb.OpenChannel, error) {
|
commitmentSig []byte) (*channeldb.OpenChannel, error) {
|
||||||
|
|
||||||
// TODO(roasbeef): add flag for watch or not?
|
// TODO(roasbeef): add flag for watch or not?
|
||||||
@ -494,7 +483,7 @@ func (r *ChannelReservation) CompleteReservationSingle(fundingPoint *wire.OutPoi
|
|||||||
//
|
//
|
||||||
// NOTE: These attributes will be unpopulated before a call to
|
// NOTE: These attributes will be unpopulated before a call to
|
||||||
// .CompleteReservation().
|
// .CompleteReservation().
|
||||||
func (r *ChannelReservation) TheirSignatures() ([]*InputScript, []byte) {
|
func (r *ChannelReservation) TheirSignatures() ([]*input.Script, []byte) {
|
||||||
r.RLock()
|
r.RLock()
|
||||||
defer r.RUnlock()
|
defer r.RUnlock()
|
||||||
return r.theirFundingInputScripts, r.theirCommitmentSig
|
return r.theirFundingInputScripts, r.theirCommitmentSig
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec"
|
"github.com/btcsuite/btcd/btcec"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -76,7 +77,7 @@ type SignJob struct {
|
|||||||
// SignDesc is intended to be a full populated SignDescriptor which
|
// SignDesc is intended to be a full populated SignDescriptor which
|
||||||
// encodes the necessary material (keys, witness script, etc) required
|
// encodes the necessary material (keys, witness script, etc) required
|
||||||
// to generate a valid signature for the specified input.
|
// to generate a valid signature for the specified input.
|
||||||
SignDesc SignDescriptor
|
SignDesc input.SignDescriptor
|
||||||
|
|
||||||
// Tx is the transaction to be signed. This is required to generate the
|
// Tx is the transaction to be signed. This is required to generate the
|
||||||
// proper sighash for the input to be signed.
|
// proper sighash for the input to be signed.
|
||||||
@ -127,7 +128,7 @@ type SigPool struct {
|
|||||||
started uint32 // To be used atomically.
|
started uint32 // To be used atomically.
|
||||||
stopped uint32 // To be used atomically.
|
stopped uint32 // To be used atomically.
|
||||||
|
|
||||||
signer Signer
|
signer input.Signer
|
||||||
|
|
||||||
verifyJobs chan VerifyJob
|
verifyJobs chan VerifyJob
|
||||||
signJobs chan SignJob
|
signJobs chan SignJob
|
||||||
@ -141,7 +142,7 @@ type SigPool struct {
|
|||||||
// NewSigPool creates a new signature pool with the specified number of
|
// NewSigPool creates a new signature pool with the specified number of
|
||||||
// workers. The recommended parameter for the number of works is the number of
|
// workers. The recommended parameter for the number of works is the number of
|
||||||
// physical CPU cores available on the target machine.
|
// physical CPU cores available on the target machine.
|
||||||
func NewSigPool(numWorkers int, signer Signer) *SigPool {
|
func NewSigPool(numWorkers int, signer input.Signer) *SigPool {
|
||||||
return &SigPool{
|
return &SigPool{
|
||||||
signer: signer,
|
signer: signer,
|
||||||
numWorkers: numWorkers,
|
numWorkers: numWorkers,
|
||||||
|
@ -8,7 +8,8 @@ import (
|
|||||||
"github.com/btcsuite/btcd/txscript"
|
"github.com/btcsuite/btcd/txscript"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestTxWeightEstimator tests that transaction weight estimates are calculated
|
// TestTxWeightEstimator tests that transaction weight estimates are calculated
|
||||||
@ -106,7 +107,7 @@ func TestTxWeightEstimator(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i, test := range testCases {
|
for i, test := range testCases {
|
||||||
var weightEstimate lnwallet.TxWeightEstimator
|
var weightEstimate input.TxWeightEstimator
|
||||||
tx := wire.NewMsgTx(1)
|
tx := wire.NewMsgTx(1)
|
||||||
|
|
||||||
for j := 0; j < test.numP2PKHInputs; j++ {
|
for j := 0; j < test.numP2PKHInputs; j++ {
|
||||||
|
@ -6,19 +6,17 @@ import (
|
|||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec"
|
"github.com/btcsuite/btcd/btcec"
|
||||||
"github.com/btcsuite/btcd/chaincfg"
|
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
"github.com/btcsuite/btcd/txscript"
|
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/lightningnetwork/lnd/shachain"
|
"github.com/lightningnetwork/lnd/shachain"
|
||||||
@ -143,7 +141,7 @@ func CreateTestChannels() (*LightningChannel, *LightningChannel, func(), error)
|
|||||||
MaxPendingAmount: lnwire.NewMSatFromSatoshis(channelCapacity),
|
MaxPendingAmount: lnwire.NewMSatFromSatoshis(channelCapacity),
|
||||||
ChanReserve: channelCapacity / 100,
|
ChanReserve: channelCapacity / 100,
|
||||||
MinHTLC: 0,
|
MinHTLC: 0,
|
||||||
MaxAcceptedHtlcs: MaxHTLCNumber / 2,
|
MaxAcceptedHtlcs: input.MaxHTLCNumber / 2,
|
||||||
CsvDelay: uint16(csvTimeoutAlice),
|
CsvDelay: uint16(csvTimeoutAlice),
|
||||||
},
|
},
|
||||||
MultiSigKey: keychain.KeyDescriptor{
|
MultiSigKey: keychain.KeyDescriptor{
|
||||||
@ -168,7 +166,7 @@ func CreateTestChannels() (*LightningChannel, *LightningChannel, func(), error)
|
|||||||
MaxPendingAmount: lnwire.NewMSatFromSatoshis(channelCapacity),
|
MaxPendingAmount: lnwire.NewMSatFromSatoshis(channelCapacity),
|
||||||
ChanReserve: channelCapacity / 100,
|
ChanReserve: channelCapacity / 100,
|
||||||
MinHTLC: 0,
|
MinHTLC: 0,
|
||||||
MaxAcceptedHtlcs: MaxHTLCNumber / 2,
|
MaxAcceptedHtlcs: input.MaxHTLCNumber / 2,
|
||||||
CsvDelay: uint16(csvTimeoutBob),
|
CsvDelay: uint16(csvTimeoutBob),
|
||||||
},
|
},
|
||||||
MultiSigKey: keychain.KeyDescriptor{
|
MultiSigKey: keychain.KeyDescriptor{
|
||||||
@ -197,7 +195,7 @@ func CreateTestChannels() (*LightningChannel, *LightningChannel, func(), error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
bobCommitPoint := ComputeCommitmentPoint(bobFirstRevoke[:])
|
bobCommitPoint := input.ComputeCommitmentPoint(bobFirstRevoke[:])
|
||||||
|
|
||||||
aliceRoot, err := chainhash.NewHash(aliceKeys[0].Serialize())
|
aliceRoot, err := chainhash.NewHash(aliceKeys[0].Serialize())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -208,7 +206,7 @@ func CreateTestChannels() (*LightningChannel, *LightningChannel, func(), error)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
aliceCommitPoint := ComputeCommitmentPoint(aliceFirstRevoke[:])
|
aliceCommitPoint := input.ComputeCommitmentPoint(aliceFirstRevoke[:])
|
||||||
|
|
||||||
aliceCommitTx, bobCommitTx, err := CreateCommitmentTxns(channelBal,
|
aliceCommitTx, bobCommitTx, err := CreateCommitmentTxns(channelBal,
|
||||||
channelBal, &aliceCfg, &bobCfg, aliceCommitPoint, bobCommitPoint,
|
channelBal, &aliceCfg, &bobCfg, aliceCommitPoint, bobCommitPoint,
|
||||||
@ -300,8 +298,8 @@ func CreateTestChannels() (*LightningChannel, *LightningChannel, func(), error)
|
|||||||
Packager: channeldb.NewChannelPackager(shortChanID),
|
Packager: channeldb.NewChannelPackager(shortChanID),
|
||||||
}
|
}
|
||||||
|
|
||||||
aliceSigner := &mockSigner{privkeys: aliceKeys}
|
aliceSigner := &input.MockSigner{Privkeys: aliceKeys}
|
||||||
bobSigner := &mockSigner{privkeys: bobKeys}
|
bobSigner := &input.MockSigner{Privkeys: bobKeys}
|
||||||
|
|
||||||
pCache := &mockPreimageCache{
|
pCache := &mockPreimageCache{
|
||||||
// hash -> preimage
|
// hash -> preimage
|
||||||
@ -389,118 +387,6 @@ func initRevocationWindows(chanA, chanB *LightningChannel) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// mockSigner is a simple implementation of the Signer interface. Each one has
|
|
||||||
// a set of private keys in a slice and can sign messages using the appropriate
|
|
||||||
// one.
|
|
||||||
type mockSigner struct {
|
|
||||||
privkeys []*btcec.PrivateKey
|
|
||||||
netParams *chaincfg.Params
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx, signDesc *SignDescriptor) ([]byte, error) {
|
|
||||||
pubkey := signDesc.KeyDesc.PubKey
|
|
||||||
switch {
|
|
||||||
case signDesc.SingleTweak != nil:
|
|
||||||
pubkey = TweakPubKeyWithTweak(pubkey, signDesc.SingleTweak)
|
|
||||||
case signDesc.DoubleTweak != nil:
|
|
||||||
pubkey = DeriveRevocationPubkey(pubkey, signDesc.DoubleTweak.PubKey())
|
|
||||||
}
|
|
||||||
|
|
||||||
hash160 := btcutil.Hash160(pubkey.SerializeCompressed())
|
|
||||||
privKey := m.findKey(hash160, signDesc.SingleTweak, signDesc.DoubleTweak)
|
|
||||||
if privKey == nil {
|
|
||||||
return nil, fmt.Errorf("Mock signer does not have key")
|
|
||||||
}
|
|
||||||
|
|
||||||
sig, err := txscript.RawTxInWitnessSignature(tx, signDesc.SigHashes,
|
|
||||||
signDesc.InputIndex, signDesc.Output.Value, signDesc.WitnessScript,
|
|
||||||
txscript.SigHashAll, privKey)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return sig[:len(sig)-1], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *mockSigner) ComputeInputScript(tx *wire.MsgTx, signDesc *SignDescriptor) (*InputScript, error) {
|
|
||||||
scriptType, addresses, _, err := txscript.ExtractPkScriptAddrs(
|
|
||||||
signDesc.Output.PkScript, m.netParams)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch scriptType {
|
|
||||||
case txscript.PubKeyHashTy:
|
|
||||||
privKey := m.findKey(addresses[0].ScriptAddress(), signDesc.SingleTweak,
|
|
||||||
signDesc.DoubleTweak)
|
|
||||||
if privKey == nil {
|
|
||||||
return nil, fmt.Errorf("Mock signer does not have key for "+
|
|
||||||
"address %v", addresses[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
sigScript, err := txscript.SignatureScript(
|
|
||||||
tx, signDesc.InputIndex, signDesc.Output.PkScript,
|
|
||||||
txscript.SigHashAll, privKey, true,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &InputScript{SigScript: sigScript}, nil
|
|
||||||
|
|
||||||
case txscript.WitnessV0PubKeyHashTy:
|
|
||||||
privKey := m.findKey(addresses[0].ScriptAddress(), signDesc.SingleTweak,
|
|
||||||
signDesc.DoubleTweak)
|
|
||||||
if privKey == nil {
|
|
||||||
return nil, fmt.Errorf("Mock signer does not have key for "+
|
|
||||||
"address %v", addresses[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
witnessScript, err := txscript.WitnessSignature(tx, signDesc.SigHashes,
|
|
||||||
signDesc.InputIndex, signDesc.Output.Value,
|
|
||||||
signDesc.Output.PkScript, txscript.SigHashAll, privKey, true)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &InputScript{Witness: witnessScript}, nil
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("Unexpected script type: %v", scriptType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// findKey searches through all stored private keys and returns one
|
|
||||||
// corresponding to the hashed pubkey if it can be found. The public key may
|
|
||||||
// either correspond directly to the private key or to the private key with a
|
|
||||||
// tweak applied.
|
|
||||||
func (m *mockSigner) findKey(needleHash160 []byte, singleTweak []byte,
|
|
||||||
doubleTweak *btcec.PrivateKey) *btcec.PrivateKey {
|
|
||||||
|
|
||||||
for _, privkey := range m.privkeys {
|
|
||||||
// First check whether public key is directly derived from private key.
|
|
||||||
hash160 := btcutil.Hash160(privkey.PubKey().SerializeCompressed())
|
|
||||||
if bytes.Equal(hash160, needleHash160) {
|
|
||||||
return privkey
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise check if public key is derived from tweaked private key.
|
|
||||||
switch {
|
|
||||||
case singleTweak != nil:
|
|
||||||
privkey = TweakPrivKey(privkey, singleTweak)
|
|
||||||
case doubleTweak != nil:
|
|
||||||
privkey = DeriveRevocationPrivKey(privkey, doubleTweak)
|
|
||||||
default:
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
hash160 = btcutil.Hash160(privkey.PubKey().SerializeCompressed())
|
|
||||||
if bytes.Equal(hash160, needleHash160) {
|
|
||||||
return privkey
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type mockPreimageCache struct {
|
type mockPreimageCache struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
preimageMap map[[32]byte][]byte
|
preimageMap map[[32]byte][]byte
|
||||||
|
202
lnwallet/transactions.go
Normal file
202
lnwallet/transactions.go
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
package lnwallet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/btcsuite/btcd/btcec"
|
||||||
|
"github.com/btcsuite/btcd/wire"
|
||||||
|
"github.com/btcsuite/btcutil"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// StateHintSize is the total number of bytes used between the sequence
|
||||||
|
// number and locktime of the commitment transaction use to encode a hint
|
||||||
|
// to the state number of a particular commitment transaction.
|
||||||
|
StateHintSize = 6
|
||||||
|
|
||||||
|
// MaxStateHint is the maximum state number we're able to encode using
|
||||||
|
// StateHintSize bytes amongst the sequence number and locktime fields
|
||||||
|
// of the commitment transaction.
|
||||||
|
maxStateHint uint64 = (1 << 48) - 1
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// TimelockShift is used to make sure the commitment transaction is
|
||||||
|
// spendable by setting the locktime with it so that it is larger than
|
||||||
|
// 500,000,000, thus interpreting it as Unix epoch timestamp and not
|
||||||
|
// a block height. It is also smaller than the current timestamp which
|
||||||
|
// has bit (1 << 30) set, so there is no risk of having the commitment
|
||||||
|
// transaction be rejected. This way we can safely use the lower 24 bits
|
||||||
|
// of the locktime field for part of the obscured commitment transaction
|
||||||
|
// number.
|
||||||
|
TimelockShift = uint32(1 << 29)
|
||||||
|
)
|
||||||
|
|
||||||
|
// createHtlcSuccessTx creates a transaction that spends the output on the
|
||||||
|
// commitment transaction of the peer that receives an HTLC. This transaction
|
||||||
|
// essentially acts as an off-chain covenant as it's only permitted to spend
|
||||||
|
// the designated HTLC output, and also that spend can _only_ be used as a
|
||||||
|
// state transition to create another output which actually allows redemption
|
||||||
|
// or revocation of an HTLC.
|
||||||
|
//
|
||||||
|
// In order to spend the HTLC output, the witness for the passed transaction
|
||||||
|
// should be:
|
||||||
|
// * <0> <sender sig> <recvr sig> <preimage>
|
||||||
|
func createHtlcSuccessTx(htlcOutput wire.OutPoint, htlcAmt btcutil.Amount,
|
||||||
|
csvDelay uint32,
|
||||||
|
revocationKey, delayKey *btcec.PublicKey) (*wire.MsgTx, error) {
|
||||||
|
|
||||||
|
// Create a version two transaction (as the success version of this
|
||||||
|
// spends an output with a CSV timeout).
|
||||||
|
successTx := wire.NewMsgTx(2)
|
||||||
|
|
||||||
|
// The input to the transaction is the outpoint that creates the
|
||||||
|
// original HTLC on the sender's commitment transaction.
|
||||||
|
successTx.AddTxIn(&wire.TxIn{
|
||||||
|
PreviousOutPoint: htlcOutput,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Next, we'll generate the script used as the output for all second
|
||||||
|
// level HTLC which forces a covenant w.r.t what can be done with all
|
||||||
|
// HTLC outputs.
|
||||||
|
witnessScript, err := input.SecondLevelHtlcScript(revocationKey, delayKey,
|
||||||
|
csvDelay)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pkScript, err := input.WitnessScriptHash(witnessScript)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, the output is simply the amount of the HTLC (minus the
|
||||||
|
// required fees), paying to the timeout script.
|
||||||
|
successTx.AddTxOut(&wire.TxOut{
|
||||||
|
Value: int64(htlcAmt),
|
||||||
|
PkScript: pkScript,
|
||||||
|
})
|
||||||
|
|
||||||
|
return successTx, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// createHtlcTimeoutTx creates a transaction that spends the HTLC output on the
|
||||||
|
// commitment transaction of the peer that created an HTLC (the sender). This
|
||||||
|
// transaction essentially acts as an off-chain covenant as it spends a 2-of-2
|
||||||
|
// multi-sig output. This output requires a signature from both the sender and
|
||||||
|
// receiver of the HTLC. By using a distinct transaction, we're able to
|
||||||
|
// uncouple the timeout and delay clauses of the HTLC contract. This
|
||||||
|
// transaction is locked with an absolute lock-time so the sender can only
|
||||||
|
// attempt to claim the output using it after the lock time has passed.
|
||||||
|
//
|
||||||
|
// In order to spend the HTLC output, the witness for the passed transaction
|
||||||
|
// should be:
|
||||||
|
// * <0> <sender sig> <receiver sig> <0>
|
||||||
|
//
|
||||||
|
// NOTE: The passed amount for the HTLC should take into account the required
|
||||||
|
// fee rate at the time the HTLC was created. The fee should be able to
|
||||||
|
// entirely pay for this (tiny: 1-in 1-out) transaction.
|
||||||
|
func createHtlcTimeoutTx(htlcOutput wire.OutPoint, htlcAmt btcutil.Amount,
|
||||||
|
cltvExpiry, csvDelay uint32,
|
||||||
|
revocationKey, delayKey *btcec.PublicKey) (*wire.MsgTx, error) {
|
||||||
|
|
||||||
|
// Create a version two transaction (as the success version of this
|
||||||
|
// spends an output with a CSV timeout), and set the lock-time to the
|
||||||
|
// specified absolute lock-time in blocks.
|
||||||
|
timeoutTx := wire.NewMsgTx(2)
|
||||||
|
timeoutTx.LockTime = cltvExpiry
|
||||||
|
|
||||||
|
// The input to the transaction is the outpoint that creates the
|
||||||
|
// original HTLC on the sender's commitment transaction.
|
||||||
|
timeoutTx.AddTxIn(&wire.TxIn{
|
||||||
|
PreviousOutPoint: htlcOutput,
|
||||||
|
})
|
||||||
|
|
||||||
|
// Next, we'll generate the script used as the output for all second
|
||||||
|
// level HTLC which forces a covenant w.r.t what can be done with all
|
||||||
|
// HTLC outputs.
|
||||||
|
witnessScript, err := input.SecondLevelHtlcScript(revocationKey, delayKey,
|
||||||
|
csvDelay)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pkScript, err := input.WitnessScriptHash(witnessScript)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, the output is simply the amount of the HTLC (minus the
|
||||||
|
// required fees), paying to the regular second level HTLC script.
|
||||||
|
timeoutTx.AddTxOut(&wire.TxOut{
|
||||||
|
Value: int64(htlcAmt),
|
||||||
|
PkScript: pkScript,
|
||||||
|
})
|
||||||
|
|
||||||
|
return timeoutTx, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetStateNumHint encodes the current state number within the passed
|
||||||
|
// commitment transaction by re-purposing the locktime and sequence fields in
|
||||||
|
// the commitment transaction to encode the obfuscated state number. The state
|
||||||
|
// number is encoded using 48 bits. The lower 24 bits of the lock time are the
|
||||||
|
// lower 24 bits of the obfuscated state number and the lower 24 bits of the
|
||||||
|
// sequence field are the higher 24 bits. Finally before encoding, the
|
||||||
|
// obfuscator is XOR'd against the state number in order to hide the exact
|
||||||
|
// state number from the PoV of outside parties.
|
||||||
|
func SetStateNumHint(commitTx *wire.MsgTx, stateNum uint64,
|
||||||
|
obfuscator [StateHintSize]byte) error {
|
||||||
|
|
||||||
|
// With the current schema we are only able to encode state num
|
||||||
|
// hints up to 2^48. Therefore if the passed height is greater than our
|
||||||
|
// state hint ceiling, then exit early.
|
||||||
|
if stateNum > maxStateHint {
|
||||||
|
return fmt.Errorf("unable to encode state, %v is greater "+
|
||||||
|
"state num that max of %v", stateNum, maxStateHint)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(commitTx.TxIn) != 1 {
|
||||||
|
return fmt.Errorf("commitment tx must have exactly 1 input, "+
|
||||||
|
"instead has %v", len(commitTx.TxIn))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the obfuscator into a uint64, then XOR that against the
|
||||||
|
// targeted height in order to obfuscate the state number of the
|
||||||
|
// commitment transaction in the case that either commitment
|
||||||
|
// transaction is broadcast directly on chain.
|
||||||
|
var obfs [8]byte
|
||||||
|
copy(obfs[2:], obfuscator[:])
|
||||||
|
xorInt := binary.BigEndian.Uint64(obfs[:])
|
||||||
|
|
||||||
|
stateNum = stateNum ^ xorInt
|
||||||
|
|
||||||
|
// Set the height bit of the sequence number in order to disable any
|
||||||
|
// sequence locks semantics.
|
||||||
|
commitTx.TxIn[0].Sequence = uint32(stateNum>>24) | wire.SequenceLockTimeDisabled
|
||||||
|
commitTx.LockTime = uint32(stateNum&0xFFFFFF) | TimelockShift
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetStateNumHint recovers the current state number given a commitment
|
||||||
|
// transaction which has previously had the state number encoded within it via
|
||||||
|
// setStateNumHint and a shared obfuscator.
|
||||||
|
//
|
||||||
|
// See setStateNumHint for further details w.r.t exactly how the state-hints
|
||||||
|
// are encoded.
|
||||||
|
func GetStateNumHint(commitTx *wire.MsgTx, obfuscator [StateHintSize]byte) uint64 {
|
||||||
|
// Convert the obfuscator into a uint64, this will be used to
|
||||||
|
// de-obfuscate the final recovered state number.
|
||||||
|
var obfs [8]byte
|
||||||
|
copy(obfs[2:], obfuscator[:])
|
||||||
|
xorInt := binary.BigEndian.Uint64(obfs[:])
|
||||||
|
|
||||||
|
// Retrieve the state hint from the sequence number and locktime
|
||||||
|
// of the transaction.
|
||||||
|
stateNumXor := uint64(commitTx.TxIn[0].Sequence&0xFFFFFF) << 24
|
||||||
|
stateNumXor |= uint64(commitTx.LockTime & 0xFFFFFF)
|
||||||
|
|
||||||
|
// Finally, to obtain the final state number, we XOR by the obfuscator
|
||||||
|
// value to de-obfuscate the state number.
|
||||||
|
return stateNumXor ^ xorInt
|
||||||
|
}
|
@ -5,14 +5,17 @@ import (
|
|||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec"
|
"github.com/btcsuite/btcd/btcec"
|
||||||
"github.com/btcsuite/btcd/chaincfg"
|
"github.com/btcsuite/btcd/chaincfg"
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
|
"github.com/btcsuite/btcd/txscript"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/lightningnetwork/lnd/shachain"
|
"github.com/lightningnetwork/lnd/shachain"
|
||||||
@ -378,7 +381,7 @@ func TestCommitmentAndHTLCTransactions(t *testing.T) {
|
|||||||
ChannelConstraints: channeldb.ChannelConstraints{
|
ChannelConstraints: channeldb.ChannelConstraints{
|
||||||
DustLimit: tc.dustLimit,
|
DustLimit: tc.dustLimit,
|
||||||
MaxPendingAmount: lnwire.NewMSatFromSatoshis(tc.fundingAmount),
|
MaxPendingAmount: lnwire.NewMSatFromSatoshis(tc.fundingAmount),
|
||||||
MaxAcceptedHtlcs: MaxHTLCNumber,
|
MaxAcceptedHtlcs: input.MaxHTLCNumber,
|
||||||
CsvDelay: tc.localCsvDelay,
|
CsvDelay: tc.localCsvDelay,
|
||||||
},
|
},
|
||||||
MultiSigKey: keychain.KeyDescriptor{
|
MultiSigKey: keychain.KeyDescriptor{
|
||||||
@ -408,11 +411,11 @@ func TestCommitmentAndHTLCTransactions(t *testing.T) {
|
|||||||
Capacity: tc.fundingAmount,
|
Capacity: tc.fundingAmount,
|
||||||
RevocationProducer: shachain.NewRevocationProducer(zeroHash),
|
RevocationProducer: shachain.NewRevocationProducer(zeroHash),
|
||||||
}
|
}
|
||||||
signer := &mockSigner{
|
signer := &input.MockSigner{
|
||||||
privkeys: []*btcec.PrivateKey{
|
Privkeys: []*btcec.PrivateKey{
|
||||||
tc.localFundingPrivKey, tc.localPaymentPrivKey,
|
tc.localFundingPrivKey, tc.localPaymentPrivKey,
|
||||||
},
|
},
|
||||||
netParams: tc.netParams,
|
NetParams: tc.netParams,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct a LightningChannel manually because we don't have nor need all
|
// Construct a LightningChannel manually because we don't have nor need all
|
||||||
@ -431,7 +434,7 @@ func TestCommitmentAndHTLCTransactions(t *testing.T) {
|
|||||||
|
|
||||||
// The commitmentPoint is technically hidden in the spec, but we need it to
|
// The commitmentPoint is technically hidden in the spec, but we need it to
|
||||||
// generate the correct tweak.
|
// generate the correct tweak.
|
||||||
tweak := SingleTweakBytes(tc.commitmentPoint, tc.localPaymentBasePoint)
|
tweak := input.SingleTweakBytes(tc.commitmentPoint, tc.localPaymentBasePoint)
|
||||||
keys := &CommitmentKeyRing{
|
keys := &CommitmentKeyRing{
|
||||||
CommitPoint: tc.commitmentPoint,
|
CommitPoint: tc.commitmentPoint,
|
||||||
LocalCommitKeyTweak: tweak,
|
LocalCommitKeyTweak: tweak,
|
||||||
@ -910,3 +913,299 @@ func htlcViewFromHTLCs(htlcs []channeldb.HTLC) *htlcView {
|
|||||||
}
|
}
|
||||||
return &theHTLCView
|
return &theHTLCView
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCommitTxStateHint(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
stateHintTests := []struct {
|
||||||
|
name string
|
||||||
|
from uint64
|
||||||
|
to uint64
|
||||||
|
inputs int
|
||||||
|
shouldFail bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "states 0 to 1000",
|
||||||
|
from: 0,
|
||||||
|
to: 1000,
|
||||||
|
inputs: 1,
|
||||||
|
shouldFail: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "states 'maxStateHint-1000' to 'maxStateHint'",
|
||||||
|
from: maxStateHint - 1000,
|
||||||
|
to: maxStateHint,
|
||||||
|
inputs: 1,
|
||||||
|
shouldFail: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "state 'maxStateHint+1'",
|
||||||
|
from: maxStateHint + 1,
|
||||||
|
to: maxStateHint + 10,
|
||||||
|
inputs: 1,
|
||||||
|
shouldFail: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "commit transaction with two inputs",
|
||||||
|
inputs: 2,
|
||||||
|
shouldFail: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var obfuscator [StateHintSize]byte
|
||||||
|
copy(obfuscator[:], testHdSeed[:StateHintSize])
|
||||||
|
timeYesterday := uint32(time.Now().Unix() - 24*60*60)
|
||||||
|
|
||||||
|
for _, test := range stateHintTests {
|
||||||
|
commitTx := wire.NewMsgTx(2)
|
||||||
|
|
||||||
|
// Add supplied number of inputs to the commitment transaction.
|
||||||
|
for i := 0; i < test.inputs; i++ {
|
||||||
|
commitTx.AddTxIn(&wire.TxIn{})
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := test.from; i <= test.to; i++ {
|
||||||
|
stateNum := uint64(i)
|
||||||
|
|
||||||
|
err := SetStateNumHint(commitTx, stateNum, obfuscator)
|
||||||
|
if err != nil && !test.shouldFail {
|
||||||
|
t.Fatalf("unable to set state num %v: %v", i, err)
|
||||||
|
} else if err == nil && test.shouldFail {
|
||||||
|
t.Fatalf("Failed(%v): test should fail but did not", test.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
locktime := commitTx.LockTime
|
||||||
|
sequence := commitTx.TxIn[0].Sequence
|
||||||
|
|
||||||
|
// Locktime should not be less than 500,000,000 and not larger
|
||||||
|
// than the time 24 hours ago. One day should provide a good
|
||||||
|
// enough buffer for the tests.
|
||||||
|
if locktime < 5e8 || locktime > timeYesterday {
|
||||||
|
if !test.shouldFail {
|
||||||
|
t.Fatalf("The value of locktime (%v) may cause the commitment "+
|
||||||
|
"transaction to be unspendable", locktime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if sequence&wire.SequenceLockTimeDisabled == 0 {
|
||||||
|
if !test.shouldFail {
|
||||||
|
t.Fatalf("Sequence locktime is NOT disabled when it should be")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extractedStateNum := GetStateNumHint(commitTx, obfuscator)
|
||||||
|
if extractedStateNum != stateNum && !test.shouldFail {
|
||||||
|
t.Fatalf("state number mismatched, expected %v, got %v",
|
||||||
|
stateNum, extractedStateNum)
|
||||||
|
} else if extractedStateNum == stateNum && test.shouldFail {
|
||||||
|
t.Fatalf("Failed(%v): test should fail but did not", test.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.Logf("Passed: %v", test.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestCommitmentSpendValidation test the spendability of both outputs within
|
||||||
|
// the commitment transaction.
|
||||||
|
//
|
||||||
|
// The following spending cases are covered by this test:
|
||||||
|
// * Alice's spend from the delayed output on her commitment transaction.
|
||||||
|
// * Bob's spend from Alice's delayed output when she broadcasts a revoked
|
||||||
|
// commitment transaction.
|
||||||
|
// * Bob's spend from his unencumbered output within Alice's commitment
|
||||||
|
// transaction.
|
||||||
|
func TestCommitmentSpendValidation(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// We generate a fake output, and the corresponding txin. This output
|
||||||
|
// doesn't need to exist, as we'll only be validating spending from the
|
||||||
|
// transaction that references this.
|
||||||
|
txid, err := chainhash.NewHash(testHdSeed.CloneBytes())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to create txid: %v", err)
|
||||||
|
}
|
||||||
|
fundingOut := &wire.OutPoint{
|
||||||
|
Hash: *txid,
|
||||||
|
Index: 50,
|
||||||
|
}
|
||||||
|
fakeFundingTxIn := wire.NewTxIn(fundingOut, nil, nil)
|
||||||
|
|
||||||
|
const channelBalance = btcutil.Amount(1 * 10e8)
|
||||||
|
const csvTimeout = uint32(5)
|
||||||
|
|
||||||
|
// We also set up set some resources for the commitment transaction.
|
||||||
|
// Each side currently has 1 BTC within the channel, with a total
|
||||||
|
// channel capacity of 2BTC.
|
||||||
|
aliceKeyPriv, aliceKeyPub := btcec.PrivKeyFromBytes(btcec.S256(),
|
||||||
|
testWalletPrivKey)
|
||||||
|
bobKeyPriv, bobKeyPub := btcec.PrivKeyFromBytes(btcec.S256(),
|
||||||
|
bobsPrivKey)
|
||||||
|
|
||||||
|
revocationPreimage := testHdSeed.CloneBytes()
|
||||||
|
commitSecret, commitPoint := btcec.PrivKeyFromBytes(btcec.S256(),
|
||||||
|
revocationPreimage)
|
||||||
|
revokePubKey := input.DeriveRevocationPubkey(bobKeyPub, commitPoint)
|
||||||
|
|
||||||
|
aliceDelayKey := input.TweakPubKey(aliceKeyPub, commitPoint)
|
||||||
|
bobPayKey := input.TweakPubKey(bobKeyPub, commitPoint)
|
||||||
|
|
||||||
|
aliceCommitTweak := input.SingleTweakBytes(commitPoint, aliceKeyPub)
|
||||||
|
bobCommitTweak := input.SingleTweakBytes(commitPoint, bobKeyPub)
|
||||||
|
|
||||||
|
aliceSelfOutputSigner := &input.MockSigner{
|
||||||
|
Privkeys: []*btcec.PrivateKey{aliceKeyPriv},
|
||||||
|
}
|
||||||
|
|
||||||
|
// With all the test data set up, we create the commitment transaction.
|
||||||
|
// We only focus on a single party's transactions, as the scripts are
|
||||||
|
// identical with the roles reversed.
|
||||||
|
//
|
||||||
|
// This is Alice's commitment transaction, so she must wait a CSV delay
|
||||||
|
// of 5 blocks before sweeping the output, while bob can spend
|
||||||
|
// immediately with either the revocation key, or his regular key.
|
||||||
|
keyRing := &CommitmentKeyRing{
|
||||||
|
DelayKey: aliceDelayKey,
|
||||||
|
RevocationKey: revokePubKey,
|
||||||
|
NoDelayKey: bobPayKey,
|
||||||
|
}
|
||||||
|
commitmentTx, err := CreateCommitTx(*fakeFundingTxIn, keyRing, csvTimeout,
|
||||||
|
channelBalance, channelBalance, DefaultDustLimit())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to create commitment transaction: %v", nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
delayOutput := commitmentTx.TxOut[0]
|
||||||
|
regularOutput := commitmentTx.TxOut[1]
|
||||||
|
|
||||||
|
// We're testing an uncooperative close, output sweep, so construct a
|
||||||
|
// transaction which sweeps the funds to a random address.
|
||||||
|
targetOutput, err := input.CommitScriptUnencumbered(aliceKeyPub)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to create target output: %v", err)
|
||||||
|
}
|
||||||
|
sweepTx := wire.NewMsgTx(2)
|
||||||
|
sweepTx.AddTxIn(wire.NewTxIn(&wire.OutPoint{
|
||||||
|
Hash: commitmentTx.TxHash(),
|
||||||
|
Index: 0,
|
||||||
|
}, nil, nil))
|
||||||
|
sweepTx.AddTxOut(&wire.TxOut{
|
||||||
|
PkScript: targetOutput,
|
||||||
|
Value: 0.5 * 10e8,
|
||||||
|
})
|
||||||
|
|
||||||
|
// First, we'll test spending with Alice's key after the timeout.
|
||||||
|
delayScript, err := input.CommitScriptToSelf(csvTimeout, aliceDelayKey,
|
||||||
|
revokePubKey)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate alice delay script: %v", err)
|
||||||
|
}
|
||||||
|
sweepTx.TxIn[0].Sequence = input.LockTimeToSequence(false, csvTimeout)
|
||||||
|
signDesc := &input.SignDescriptor{
|
||||||
|
WitnessScript: delayScript,
|
||||||
|
KeyDesc: keychain.KeyDescriptor{
|
||||||
|
PubKey: aliceKeyPub,
|
||||||
|
},
|
||||||
|
SingleTweak: aliceCommitTweak,
|
||||||
|
SigHashes: txscript.NewTxSigHashes(sweepTx),
|
||||||
|
Output: &wire.TxOut{
|
||||||
|
Value: int64(channelBalance),
|
||||||
|
},
|
||||||
|
HashType: txscript.SigHashAll,
|
||||||
|
InputIndex: 0,
|
||||||
|
}
|
||||||
|
aliceWitnessSpend, err := input.CommitSpendTimeout(aliceSelfOutputSigner,
|
||||||
|
signDesc, sweepTx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate delay commit spend witness: %v", err)
|
||||||
|
}
|
||||||
|
sweepTx.TxIn[0].Witness = aliceWitnessSpend
|
||||||
|
vm, err := txscript.NewEngine(delayOutput.PkScript,
|
||||||
|
sweepTx, 0, txscript.StandardVerifyFlags, nil,
|
||||||
|
nil, int64(channelBalance))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to create engine: %v", err)
|
||||||
|
}
|
||||||
|
if err := vm.Execute(); err != nil {
|
||||||
|
t.Fatalf("spend from delay output is invalid: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
bobSigner := &input.MockSigner{Privkeys: []*btcec.PrivateKey{bobKeyPriv}}
|
||||||
|
|
||||||
|
// Next, we'll test bob spending with the derived revocation key to
|
||||||
|
// simulate the scenario when Alice broadcasts this commitment
|
||||||
|
// transaction after it's been revoked.
|
||||||
|
signDesc = &input.SignDescriptor{
|
||||||
|
KeyDesc: keychain.KeyDescriptor{
|
||||||
|
PubKey: bobKeyPub,
|
||||||
|
},
|
||||||
|
DoubleTweak: commitSecret,
|
||||||
|
WitnessScript: delayScript,
|
||||||
|
SigHashes: txscript.NewTxSigHashes(sweepTx),
|
||||||
|
Output: &wire.TxOut{
|
||||||
|
Value: int64(channelBalance),
|
||||||
|
},
|
||||||
|
HashType: txscript.SigHashAll,
|
||||||
|
InputIndex: 0,
|
||||||
|
}
|
||||||
|
bobWitnessSpend, err := input.CommitSpendRevoke(bobSigner, signDesc,
|
||||||
|
sweepTx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate revocation witness: %v", err)
|
||||||
|
}
|
||||||
|
sweepTx.TxIn[0].Witness = bobWitnessSpend
|
||||||
|
vm, err = txscript.NewEngine(delayOutput.PkScript,
|
||||||
|
sweepTx, 0, txscript.StandardVerifyFlags, nil,
|
||||||
|
nil, int64(channelBalance))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to create engine: %v", err)
|
||||||
|
}
|
||||||
|
if err := vm.Execute(); err != nil {
|
||||||
|
t.Fatalf("revocation spend is invalid: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// In order to test the final scenario, we modify the TxIn of the sweep
|
||||||
|
// transaction to instead point to the regular output (non delay)
|
||||||
|
// within the commitment transaction.
|
||||||
|
sweepTx.TxIn[0] = &wire.TxIn{
|
||||||
|
PreviousOutPoint: wire.OutPoint{
|
||||||
|
Hash: commitmentTx.TxHash(),
|
||||||
|
Index: 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, we test bob sweeping his output as normal in the case that
|
||||||
|
// Alice broadcasts this commitment transaction.
|
||||||
|
bobScriptP2WKH, err := input.CommitScriptUnencumbered(bobPayKey)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to create bob p2wkh script: %v", err)
|
||||||
|
}
|
||||||
|
signDesc = &input.SignDescriptor{
|
||||||
|
KeyDesc: keychain.KeyDescriptor{
|
||||||
|
PubKey: bobKeyPub,
|
||||||
|
},
|
||||||
|
SingleTweak: bobCommitTweak,
|
||||||
|
WitnessScript: bobScriptP2WKH,
|
||||||
|
SigHashes: txscript.NewTxSigHashes(sweepTx),
|
||||||
|
Output: &wire.TxOut{
|
||||||
|
Value: int64(channelBalance),
|
||||||
|
PkScript: bobScriptP2WKH,
|
||||||
|
},
|
||||||
|
HashType: txscript.SigHashAll,
|
||||||
|
InputIndex: 0,
|
||||||
|
}
|
||||||
|
bobRegularSpend, err := input.CommitSpendNoDelay(bobSigner, signDesc,
|
||||||
|
sweepTx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to create bob regular spend: %v", err)
|
||||||
|
}
|
||||||
|
sweepTx.TxIn[0].Witness = bobRegularSpend
|
||||||
|
vm, err = txscript.NewEngine(regularOutput.PkScript,
|
||||||
|
sweepTx, 0, txscript.StandardVerifyFlags, nil,
|
||||||
|
nil, int64(channelBalance))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to create engine: %v", err)
|
||||||
|
}
|
||||||
|
if err := vm.Execute(); err != nil {
|
||||||
|
t.Fatalf("bob p2wkh spend is invalid: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -19,6 +19,7 @@ import (
|
|||||||
"github.com/btcsuite/btcutil/txsort"
|
"github.com/btcsuite/btcutil/txsort"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/lightningnetwork/lnd/shachain"
|
"github.com/lightningnetwork/lnd/shachain"
|
||||||
@ -167,7 +168,7 @@ type addCounterPartySigsMsg struct {
|
|||||||
// Should be order of sorted inputs that are theirs. Sorting is done
|
// Should be order of sorted inputs that are theirs. Sorting is done
|
||||||
// in accordance to BIP-69:
|
// in accordance to BIP-69:
|
||||||
// https://github.com/bitcoin/bips/blob/master/bip-0069.mediawiki.
|
// https://github.com/bitcoin/bips/blob/master/bip-0069.mediawiki.
|
||||||
theirFundingInputScripts []*InputScript
|
theirFundingInputScripts []*input.Script
|
||||||
|
|
||||||
// This should be 1/2 of the signatures needed to successfully spend our
|
// This should be 1/2 of the signatures needed to successfully spend our
|
||||||
// version of the commitment transaction.
|
// version of the commitment transaction.
|
||||||
@ -562,7 +563,7 @@ func (l *LightningWallet) handleFundingReserveRequest(req *InitFundingReserveMsg
|
|||||||
req.resp <- nil
|
req.resp <- nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
reservation.ourContribution.FirstCommitmentPoint = ComputeCommitmentPoint(
|
reservation.ourContribution.FirstCommitmentPoint = input.ComputeCommitmentPoint(
|
||||||
firstPreimage[:],
|
firstPreimage[:],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -712,7 +713,7 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) {
|
|||||||
// Finally, add the 2-of-2 multi-sig output which will set up the lightning
|
// Finally, add the 2-of-2 multi-sig output which will set up the lightning
|
||||||
// channel.
|
// channel.
|
||||||
channelCapacity := int64(pendingReservation.partialState.Capacity)
|
channelCapacity := int64(pendingReservation.partialState.Capacity)
|
||||||
witnessScript, multiSigOut, err := GenFundingPkScript(
|
witnessScript, multiSigOut, err := input.GenFundingPkScript(
|
||||||
ourKey.PubKey.SerializeCompressed(),
|
ourKey.PubKey.SerializeCompressed(),
|
||||||
theirKey.PubKey.SerializeCompressed(), channelCapacity,
|
theirKey.PubKey.SerializeCompressed(), channelCapacity,
|
||||||
)
|
)
|
||||||
@ -729,9 +730,9 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) {
|
|||||||
|
|
||||||
// Next, sign all inputs that are ours, collecting the signatures in
|
// Next, sign all inputs that are ours, collecting the signatures in
|
||||||
// order of the inputs.
|
// order of the inputs.
|
||||||
pendingReservation.ourFundingInputScripts = make([]*InputScript, 0,
|
pendingReservation.ourFundingInputScripts = make([]*input.Script, 0,
|
||||||
len(ourContribution.Inputs))
|
len(ourContribution.Inputs))
|
||||||
signDesc := SignDescriptor{
|
signDesc := input.SignDescriptor{
|
||||||
HashType: txscript.SigHashAll,
|
HashType: txscript.SigHashAll,
|
||||||
SigHashes: txscript.NewTxSigHashes(fundingTx),
|
SigHashes: txscript.NewTxSigHashes(fundingTx),
|
||||||
}
|
}
|
||||||
@ -767,7 +768,7 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) {
|
|||||||
// since the outputs are canonically sorted. If this is a single funder
|
// since the outputs are canonically sorted. If this is a single funder
|
||||||
// workflow, then we'll also need to send this to the remote node.
|
// workflow, then we'll also need to send this to the remote node.
|
||||||
fundingTxID := fundingTx.TxHash()
|
fundingTxID := fundingTx.TxHash()
|
||||||
_, multiSigIndex := FindScriptOutputIndex(fundingTx, multiSigOut.PkScript)
|
_, multiSigIndex := input.FindScriptOutputIndex(fundingTx, multiSigOut.PkScript)
|
||||||
fundingOutpoint := wire.NewOutPoint(&fundingTxID, multiSigIndex)
|
fundingOutpoint := wire.NewOutPoint(&fundingTxID, multiSigIndex)
|
||||||
pendingReservation.partialState.FundingOutpoint = *fundingOutpoint
|
pendingReservation.partialState.FundingOutpoint = *fundingOutpoint
|
||||||
|
|
||||||
@ -858,7 +859,7 @@ func (l *LightningWallet) handleContributionMsg(req *addContributionMsg) {
|
|||||||
|
|
||||||
// Generate a signature for their version of the initial commitment
|
// Generate a signature for their version of the initial commitment
|
||||||
// transaction.
|
// transaction.
|
||||||
signDesc = SignDescriptor{
|
signDesc = input.SignDescriptor{
|
||||||
WitnessScript: witnessScript,
|
WitnessScript: witnessScript,
|
||||||
KeyDesc: ourKey,
|
KeyDesc: ourKey,
|
||||||
Output: multiSigOut,
|
Output: multiSigOut,
|
||||||
@ -966,7 +967,7 @@ func (l *LightningWallet) handleFundingCounterPartySigs(msg *addCounterPartySigs
|
|||||||
//
|
//
|
||||||
// TODO(roasbeef): when dual funder pass actual
|
// TODO(roasbeef): when dual funder pass actual
|
||||||
// height-hint
|
// height-hint
|
||||||
pkScript, err := WitnessScriptHash(
|
pkScript, err := input.WitnessScriptHash(
|
||||||
txin.Witness[len(txin.Witness)-1],
|
txin.Witness[len(txin.Witness)-1],
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1013,7 +1014,7 @@ func (l *LightningWallet) handleFundingCounterPartySigs(msg *addCounterPartySigs
|
|||||||
// Re-generate both the witnessScript and p2sh output. We sign the
|
// Re-generate both the witnessScript and p2sh output. We sign the
|
||||||
// witnessScript script, but include the p2sh output as the subscript
|
// witnessScript script, but include the p2sh output as the subscript
|
||||||
// for verification.
|
// for verification.
|
||||||
witnessScript, _, err := GenFundingPkScript(
|
witnessScript, _, err := input.GenFundingPkScript(
|
||||||
ourKey.PubKey.SerializeCompressed(),
|
ourKey.PubKey.SerializeCompressed(),
|
||||||
theirKey.PubKey.SerializeCompressed(),
|
theirKey.PubKey.SerializeCompressed(),
|
||||||
int64(res.partialState.Capacity),
|
int64(res.partialState.Capacity),
|
||||||
@ -1165,7 +1166,7 @@ func (l *LightningWallet) handleSingleFunderSigs(req *addSingleFunderSigsMsg) {
|
|||||||
hashCache := txscript.NewTxSigHashes(ourCommitTx)
|
hashCache := txscript.NewTxSigHashes(ourCommitTx)
|
||||||
theirKey := pendingReservation.theirContribution.MultiSigKey
|
theirKey := pendingReservation.theirContribution.MultiSigKey
|
||||||
ourKey := pendingReservation.ourContribution.MultiSigKey
|
ourKey := pendingReservation.ourContribution.MultiSigKey
|
||||||
witnessScript, _, err := GenFundingPkScript(
|
witnessScript, _, err := input.GenFundingPkScript(
|
||||||
ourKey.PubKey.SerializeCompressed(),
|
ourKey.PubKey.SerializeCompressed(),
|
||||||
theirKey.PubKey.SerializeCompressed(), channelValue,
|
theirKey.PubKey.SerializeCompressed(), channelValue,
|
||||||
)
|
)
|
||||||
@ -1201,13 +1202,13 @@ func (l *LightningWallet) handleSingleFunderSigs(req *addSingleFunderSigsMsg) {
|
|||||||
// With their signature for our version of the commitment transactions
|
// With their signature for our version of the commitment transactions
|
||||||
// verified, we can now generate a signature for their version,
|
// verified, we can now generate a signature for their version,
|
||||||
// allowing the funding transaction to be safely broadcast.
|
// allowing the funding transaction to be safely broadcast.
|
||||||
p2wsh, err := WitnessScriptHash(witnessScript)
|
p2wsh, err := input.WitnessScriptHash(witnessScript)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
req.err <- err
|
req.err <- err
|
||||||
req.completeChan <- nil
|
req.completeChan <- nil
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
signDesc := SignDescriptor{
|
signDesc := input.SignDescriptor{
|
||||||
WitnessScript: witnessScript,
|
WitnessScript: witnessScript,
|
||||||
KeyDesc: ourKey,
|
KeyDesc: ourKey,
|
||||||
Output: &wire.TxOut{
|
Output: &wire.TxOut{
|
||||||
@ -1401,7 +1402,7 @@ func coinSelect(feeRate SatPerKWeight, amt btcutil.Amount,
|
|||||||
return nil, 0, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var weightEstimate TxWeightEstimator
|
var weightEstimate input.TxWeightEstimator
|
||||||
|
|
||||||
for _, utxo := range selectedUtxos {
|
for _, utxo := range selectedUtxos {
|
||||||
switch utxo.AddressType {
|
switch utxo.AddressType {
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
package macaroons_test
|
package macaroons_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/lightningnetwork/lnd/macaroons"
|
|
||||||
"gopkg.in/macaroon.v2"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/macaroons"
|
||||||
|
macaroon "gopkg.in/macaroon.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
16
mock.go
16
mock.go
@ -12,7 +12,9 @@ import (
|
|||||||
"github.com/btcsuite/btcd/txscript"
|
"github.com/btcsuite/btcd/txscript"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
|
|
||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
)
|
)
|
||||||
@ -25,7 +27,7 @@ type mockSigner struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx,
|
func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx,
|
||||||
signDesc *lnwallet.SignDescriptor) ([]byte, error) {
|
signDesc *input.SignDescriptor) ([]byte, error) {
|
||||||
amt := signDesc.Output.Value
|
amt := signDesc.Output.Value
|
||||||
witnessScript := signDesc.WitnessScript
|
witnessScript := signDesc.WitnessScript
|
||||||
privKey := m.key
|
privKey := m.key
|
||||||
@ -36,10 +38,10 @@ func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx,
|
|||||||
|
|
||||||
switch {
|
switch {
|
||||||
case signDesc.SingleTweak != nil:
|
case signDesc.SingleTweak != nil:
|
||||||
privKey = lnwallet.TweakPrivKey(privKey,
|
privKey = input.TweakPrivKey(privKey,
|
||||||
signDesc.SingleTweak)
|
signDesc.SingleTweak)
|
||||||
case signDesc.DoubleTweak != nil:
|
case signDesc.DoubleTweak != nil:
|
||||||
privKey = lnwallet.DeriveRevocationPrivKey(privKey,
|
privKey = input.DeriveRevocationPrivKey(privKey,
|
||||||
signDesc.DoubleTweak)
|
signDesc.DoubleTweak)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,7 +56,7 @@ func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockSigner) ComputeInputScript(tx *wire.MsgTx,
|
func (m *mockSigner) ComputeInputScript(tx *wire.MsgTx,
|
||||||
signDesc *lnwallet.SignDescriptor) (*lnwallet.InputScript, error) {
|
signDesc *input.SignDescriptor) (*input.Script, error) {
|
||||||
|
|
||||||
// TODO(roasbeef): expose tweaked signer from lnwallet so don't need to
|
// TODO(roasbeef): expose tweaked signer from lnwallet so don't need to
|
||||||
// duplicate this code?
|
// duplicate this code?
|
||||||
@ -63,10 +65,10 @@ func (m *mockSigner) ComputeInputScript(tx *wire.MsgTx,
|
|||||||
|
|
||||||
switch {
|
switch {
|
||||||
case signDesc.SingleTweak != nil:
|
case signDesc.SingleTweak != nil:
|
||||||
privKey = lnwallet.TweakPrivKey(privKey,
|
privKey = input.TweakPrivKey(privKey,
|
||||||
signDesc.SingleTweak)
|
signDesc.SingleTweak)
|
||||||
case signDesc.DoubleTweak != nil:
|
case signDesc.DoubleTweak != nil:
|
||||||
privKey = lnwallet.DeriveRevocationPrivKey(privKey,
|
privKey = input.DeriveRevocationPrivKey(privKey,
|
||||||
signDesc.DoubleTweak)
|
signDesc.DoubleTweak)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +79,7 @@ func (m *mockSigner) ComputeInputScript(tx *wire.MsgTx,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return &lnwallet.InputScript{
|
return &input.Script{
|
||||||
Witness: witnessScript,
|
Witness: witnessScript,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ import (
|
|||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/lightningnetwork/lnd/routing/chainview"
|
"github.com/lightningnetwork/lnd/routing/chainview"
|
||||||
@ -87,7 +88,7 @@ func createChannelEdge(ctx *testCtx, bitcoinKey1, bitcoinKey2 []byte,
|
|||||||
*lnwire.ShortChannelID, error) {
|
*lnwire.ShortChannelID, error) {
|
||||||
|
|
||||||
fundingTx := wire.NewMsgTx(2)
|
fundingTx := wire.NewMsgTx(2)
|
||||||
_, tx, err := lnwallet.GenFundingPkScript(
|
_, tx, err := input.GenFundingPkScript(
|
||||||
bitcoinKey1,
|
bitcoinKey1,
|
||||||
bitcoinKey2,
|
bitcoinKey2,
|
||||||
int64(chanValue),
|
int64(chanValue),
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec"
|
"github.com/btcsuite/btcd/btcec"
|
||||||
"github.com/coreos/bbolt"
|
"github.com/coreos/bbolt"
|
||||||
|
|
||||||
"github.com/lightningnetwork/lightning-onion"
|
"github.com/lightningnetwork/lightning-onion"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
@ -16,9 +16,11 @@ import (
|
|||||||
"github.com/coreos/bbolt"
|
"github.com/coreos/bbolt"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
|
|
||||||
"github.com/lightningnetwork/lightning-onion"
|
"github.com/lightningnetwork/lightning-onion"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/lightningnetwork/lnd/multimutex"
|
"github.com/lightningnetwork/lnd/multimutex"
|
||||||
@ -1034,13 +1036,13 @@ func (r *ChannelRouter) processUpdate(msg interface{}) error {
|
|||||||
// Recreate witness output to be sure that declared in channel
|
// Recreate witness output to be sure that declared in channel
|
||||||
// edge bitcoin keys and channel value corresponds to the
|
// edge bitcoin keys and channel value corresponds to the
|
||||||
// reality.
|
// reality.
|
||||||
witnessScript, err := lnwallet.GenMultiSigScript(
|
witnessScript, err := input.GenMultiSigScript(
|
||||||
msg.BitcoinKey1Bytes[:], msg.BitcoinKey2Bytes[:],
|
msg.BitcoinKey1Bytes[:], msg.BitcoinKey2Bytes[:],
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fundingPkScript, err := lnwallet.WitnessScriptHash(witnessScript)
|
fundingPkScript, err := input.WitnessScriptHash(witnessScript)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -9,14 +9,14 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/wire"
|
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
|
||||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec"
|
"github.com/btcsuite/btcd/btcec"
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
|
||||||
"github.com/lightningnetwork/lightning-onion"
|
"github.com/lightningnetwork/lightning-onion"
|
||||||
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
|
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -31,6 +31,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/build"
|
"github.com/lightningnetwork/lnd/build"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/invoices"
|
"github.com/lightningnetwork/lnd/invoices"
|
||||||
"github.com/lightningnetwork/lnd/lncfg"
|
"github.com/lightningnetwork/lnd/lncfg"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
@ -1991,7 +1992,7 @@ func (r *rpcServer) PendingChannels(ctx context.Context,
|
|||||||
localCommitment := pendingChan.LocalCommitment
|
localCommitment := pendingChan.LocalCommitment
|
||||||
utx := btcutil.NewTx(localCommitment.CommitTx)
|
utx := btcutil.NewTx(localCommitment.CommitTx)
|
||||||
commitBaseWeight := blockchain.GetTransactionWeight(utx)
|
commitBaseWeight := blockchain.GetTransactionWeight(utx)
|
||||||
commitWeight := commitBaseWeight + lnwallet.WitnessCommitmentTxWeight
|
commitWeight := commitBaseWeight + input.WitnessCommitmentTxWeight
|
||||||
|
|
||||||
resp.PendingOpenChannels[i] = &lnrpc.PendingChannelsResponse_PendingOpenChannel{
|
resp.PendingOpenChannels[i] = &lnrpc.PendingChannelsResponse_PendingOpenChannel{
|
||||||
Channel: &lnrpc.PendingChannelsResponse_PendingChannel{
|
Channel: &lnrpc.PendingChannelsResponse_PendingChannel{
|
||||||
@ -2320,7 +2321,7 @@ func (r *rpcServer) ListChannels(ctx context.Context,
|
|||||||
localCommit := dbChannel.LocalCommitment
|
localCommit := dbChannel.LocalCommitment
|
||||||
utx := btcutil.NewTx(localCommit.CommitTx)
|
utx := btcutil.NewTx(localCommit.CommitTx)
|
||||||
commitBaseWeight := blockchain.GetTransactionWeight(utx)
|
commitBaseWeight := blockchain.GetTransactionWeight(utx)
|
||||||
commitWeight := commitBaseWeight + lnwallet.WitnessCommitmentTxWeight
|
commitWeight := commitBaseWeight + input.WitnessCommitmentTxWeight
|
||||||
|
|
||||||
localBalance := localCommit.LocalBalance
|
localBalance := localCommit.LocalBalance
|
||||||
remoteBalance := localCommit.RemoteBalance
|
remoteBalance := localCommit.RemoteBalance
|
||||||
|
@ -24,13 +24,14 @@ import (
|
|||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/coreos/bbolt"
|
"github.com/coreos/bbolt"
|
||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
"github.com/lightningnetwork/lightning-onion"
|
sphinx "github.com/lightningnetwork/lightning-onion"
|
||||||
"github.com/lightningnetwork/lnd/autopilot"
|
"github.com/lightningnetwork/lnd/autopilot"
|
||||||
"github.com/lightningnetwork/lnd/brontide"
|
"github.com/lightningnetwork/lnd/brontide"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/contractcourt"
|
"github.com/lightningnetwork/lnd/contractcourt"
|
||||||
"github.com/lightningnetwork/lnd/discovery"
|
"github.com/lightningnetwork/lnd/discovery"
|
||||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/invoices"
|
"github.com/lightningnetwork/lnd/invoices"
|
||||||
"github.com/lightningnetwork/lnd/lncfg"
|
"github.com/lightningnetwork/lnd/lncfg"
|
||||||
"github.com/lightningnetwork/lnd/lnpeer"
|
"github.com/lightningnetwork/lnd/lnpeer"
|
||||||
@ -913,7 +914,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, cc *chainControl,
|
|||||||
RequiredRemoteMaxHTLCs: func(chanAmt btcutil.Amount) uint16 {
|
RequiredRemoteMaxHTLCs: func(chanAmt btcutil.Amount) uint16 {
|
||||||
// By default, we'll permit them to utilize the full
|
// By default, we'll permit them to utilize the full
|
||||||
// channel bandwidth.
|
// channel bandwidth.
|
||||||
return uint16(lnwallet.MaxHTLCNumber / 2)
|
return uint16(input.MaxHTLCNumber / 2)
|
||||||
},
|
},
|
||||||
ZombieSweeperInterval: 1 * time.Minute,
|
ZombieSweeperInterval: 1 * time.Minute,
|
||||||
ReservationTimeout: 10 * time.Minute,
|
ReservationTimeout: 10 * time.Minute,
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ type pendingInput struct {
|
|||||||
|
|
||||||
// input is the original struct that contains the input and sign
|
// input is the original struct that contains the input and sign
|
||||||
// descriptor.
|
// descriptor.
|
||||||
input Input
|
input input.Input
|
||||||
|
|
||||||
// ntfnRegCancel is populated with a function that cancels the chain
|
// ntfnRegCancel is populated with a function that cancels the chain
|
||||||
// notifier spend registration.
|
// notifier spend registration.
|
||||||
@ -111,7 +112,7 @@ type UtxoSweeperConfig struct {
|
|||||||
|
|
||||||
// Signer is used by the sweeper to generate valid witnesses at the
|
// Signer is used by the sweeper to generate valid witnesses at the
|
||||||
// time the incubated outputs need to be spent.
|
// time the incubated outputs need to be spent.
|
||||||
Signer lnwallet.Signer
|
Signer input.Signer
|
||||||
|
|
||||||
// SweepTxConfTarget assigns a confirmation target for sweep txes on
|
// SweepTxConfTarget assigns a confirmation target for sweep txes on
|
||||||
// which the fee calculation will be based.
|
// which the fee calculation will be based.
|
||||||
@ -148,7 +149,7 @@ type Result struct {
|
|||||||
// sweepInputMessage structs are used in the internal channel between the
|
// sweepInputMessage structs are used in the internal channel between the
|
||||||
// SweepInput call and the sweeper main loop.
|
// SweepInput call and the sweeper main loop.
|
||||||
type sweepInputMessage struct {
|
type sweepInputMessage struct {
|
||||||
input Input
|
input input.Input
|
||||||
resultChan chan Result
|
resultChan chan Result
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -256,7 +257,7 @@ func (s *UtxoSweeper) Stop() error {
|
|||||||
// NOTE: Extreme care needs to be taken that input isn't changed externally.
|
// NOTE: Extreme care needs to be taken that input isn't changed externally.
|
||||||
// Because it is an interface and we don't know what is exactly behind it, we
|
// Because it is an interface and we don't know what is exactly behind it, we
|
||||||
// cannot make a local copy in sweeper.
|
// cannot make a local copy in sweeper.
|
||||||
func (s *UtxoSweeper) SweepInput(input Input) (chan Result, error) {
|
func (s *UtxoSweeper) SweepInput(input input.Input) (chan Result, error) {
|
||||||
if input == nil || input.OutPoint() == nil || input.SignDesc() == nil {
|
if input == nil || input.OutPoint() == nil || input.SignDesc() == nil {
|
||||||
return nil, errors.New("nil input received")
|
return nil, errors.New("nil input received")
|
||||||
}
|
}
|
||||||
@ -550,7 +551,7 @@ func (s *UtxoSweeper) getInputLists(currentHeight int32,
|
|||||||
// contain inputs that failed before. Therefore we also add sets
|
// contain inputs that failed before. Therefore we also add sets
|
||||||
// consisting of only new inputs to the list, to make sure that new
|
// consisting of only new inputs to the list, to make sure that new
|
||||||
// inputs are given a good, isolated chance of being published.
|
// inputs are given a good, isolated chance of being published.
|
||||||
var newInputs, retryInputs []Input
|
var newInputs, retryInputs []input.Input
|
||||||
for _, input := range s.pendingInputs {
|
for _, input := range s.pendingInputs {
|
||||||
// Skip inputs that have a minimum publish height that is not
|
// Skip inputs that have a minimum publish height that is not
|
||||||
// yet reached.
|
// yet reached.
|
||||||
@ -750,7 +751,7 @@ func (s *UtxoSweeper) waitForSpend(outpoint wire.OutPoint,
|
|||||||
// - Make handling re-orgs easier.
|
// - Make handling re-orgs easier.
|
||||||
// - Thwart future possible fee sniping attempts.
|
// - Thwart future possible fee sniping attempts.
|
||||||
// - Make us blend in with the bitcoind wallet.
|
// - Make us blend in with the bitcoind wallet.
|
||||||
func (s *UtxoSweeper) CreateSweepTx(inputs []Input, feePref FeePreference,
|
func (s *UtxoSweeper) CreateSweepTx(inputs []input.Input, feePref FeePreference,
|
||||||
currentBlockHeight uint32) (*wire.MsgTx, error) {
|
currentBlockHeight uint32) (*wire.MsgTx, error) {
|
||||||
|
|
||||||
feePerKw, err := DetermineFeePerKw(s.cfg.FeeEstimator, feePref)
|
feePerKw, err := DetermineFeePerKw(s.cfg.FeeEstimator, feePref)
|
||||||
|
@ -12,8 +12,8 @@ import (
|
|||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/lightningnetwork/lnd/build"
|
"github.com/lightningnetwork/lnd/build"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -38,7 +38,7 @@ type sweeperTestContext struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
spendableInputs []*BaseInput
|
spendableInputs []*input.BaseInput
|
||||||
testInputCount int
|
testInputCount int
|
||||||
|
|
||||||
testPubKey, _ = btcec.ParsePubKey([]byte{
|
testPubKey, _ = btcec.ParsePubKey([]byte{
|
||||||
@ -53,17 +53,17 @@ var (
|
|||||||
}, btcec.S256())
|
}, btcec.S256())
|
||||||
)
|
)
|
||||||
|
|
||||||
func createTestInput(value int64, witnessType lnwallet.WitnessType) BaseInput {
|
func createTestInput(value int64, witnessType input.WitnessType) input.BaseInput {
|
||||||
hash := chainhash.Hash{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
hash := chainhash.Hash{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
byte(testInputCount)}
|
byte(testInputCount)}
|
||||||
|
|
||||||
input := MakeBaseInput(
|
input := input.MakeBaseInput(
|
||||||
&wire.OutPoint{
|
&wire.OutPoint{
|
||||||
Hash: hash,
|
Hash: hash,
|
||||||
},
|
},
|
||||||
witnessType,
|
witnessType,
|
||||||
&lnwallet.SignDescriptor{
|
&input.SignDescriptor{
|
||||||
Output: &wire.TxOut{
|
Output: &wire.TxOut{
|
||||||
Value: value,
|
Value: value,
|
||||||
},
|
},
|
||||||
@ -83,7 +83,7 @@ func init() {
|
|||||||
// Create a set of test spendable inputs.
|
// Create a set of test spendable inputs.
|
||||||
for i := 0; i < 5; i++ {
|
for i := 0; i < 5; i++ {
|
||||||
input := createTestInput(int64(10000+i*500),
|
input := createTestInput(int64(10000+i*500),
|
||||||
lnwallet.CommitmentTimeLock)
|
input.CommitmentTimeLock)
|
||||||
|
|
||||||
spendableInputs = append(spendableInputs, &input)
|
spendableInputs = append(spendableInputs, &input)
|
||||||
}
|
}
|
||||||
@ -303,7 +303,7 @@ func TestDust(t *testing.T) {
|
|||||||
// Create an input so that the output after paying fees is still
|
// Create an input so that the output after paying fees is still
|
||||||
// positive (400 sat), but less than the dust limit (537 sat) for the
|
// positive (400 sat), but less than the dust limit (537 sat) for the
|
||||||
// sweep tx output script (P2WPKH).
|
// sweep tx output script (P2WPKH).
|
||||||
dustInput := createTestInput(5260, lnwallet.CommitmentTimeLock)
|
dustInput := createTestInput(5260, input.CommitmentTimeLock)
|
||||||
|
|
||||||
_, err := ctx.sweeper.SweepInput(&dustInput)
|
_, err := ctx.sweeper.SweepInput(&dustInput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -314,7 +314,7 @@ func TestDust(t *testing.T) {
|
|||||||
// that the sweep output will not be relayed and not generate the tx.
|
// that the sweep output will not be relayed and not generate the tx.
|
||||||
|
|
||||||
// Sweep another input that brings the tx output above the dust limit.
|
// Sweep another input that brings the tx output above the dust limit.
|
||||||
largeInput := createTestInput(100000, lnwallet.CommitmentTimeLock)
|
largeInput := createTestInput(100000, input.CommitmentTimeLock)
|
||||||
|
|
||||||
_, err = ctx.sweeper.SweepInput(&largeInput)
|
_, err = ctx.sweeper.SweepInput(&largeInput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -344,7 +344,7 @@ func TestNegativeInput(t *testing.T) {
|
|||||||
|
|
||||||
// Sweep an input large enough to cover fees, so in any case the tx
|
// Sweep an input large enough to cover fees, so in any case the tx
|
||||||
// output will be above the dust limit.
|
// output will be above the dust limit.
|
||||||
largeInput := createTestInput(100000, lnwallet.CommitmentNoDelay)
|
largeInput := createTestInput(100000, input.CommitmentNoDelay)
|
||||||
largeInputResult, err := ctx.sweeper.SweepInput(&largeInput)
|
largeInputResult, err := ctx.sweeper.SweepInput(&largeInput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -353,7 +353,7 @@ func TestNegativeInput(t *testing.T) {
|
|||||||
// Sweep an additional input with a negative net yield. The weight of
|
// Sweep an additional input with a negative net yield. The weight of
|
||||||
// the HtlcAcceptedRemoteSuccess input type adds more in fees than its
|
// the HtlcAcceptedRemoteSuccess input type adds more in fees than its
|
||||||
// value at the current fee level.
|
// value at the current fee level.
|
||||||
negInput := createTestInput(2900, lnwallet.HtlcOfferedRemoteTimeout)
|
negInput := createTestInput(2900, input.HtlcOfferedRemoteTimeout)
|
||||||
negInputResult, err := ctx.sweeper.SweepInput(&negInput)
|
negInputResult, err := ctx.sweeper.SweepInput(&negInput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -361,7 +361,7 @@ func TestNegativeInput(t *testing.T) {
|
|||||||
|
|
||||||
// Sweep a third input that has a smaller output than the previous one,
|
// Sweep a third input that has a smaller output than the previous one,
|
||||||
// but yields positively because of its lower weight.
|
// but yields positively because of its lower weight.
|
||||||
positiveInput := createTestInput(2800, lnwallet.CommitmentNoDelay)
|
positiveInput := createTestInput(2800, input.CommitmentNoDelay)
|
||||||
positiveInputResult, err := ctx.sweeper.SweepInput(&positiveInput)
|
positiveInputResult, err := ctx.sweeper.SweepInput(&positiveInput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
@ -390,7 +390,7 @@ func TestNegativeInput(t *testing.T) {
|
|||||||
ctx.estimator.updateFees(1000, 1000)
|
ctx.estimator.updateFees(1000, 1000)
|
||||||
|
|
||||||
// Create another large input
|
// Create another large input
|
||||||
secondLargeInput := createTestInput(100000, lnwallet.CommitmentNoDelay)
|
secondLargeInput := createTestInput(100000, input.CommitmentNoDelay)
|
||||||
secondLargeInputResult, err := ctx.sweeper.SweepInput(&secondLargeInput)
|
secondLargeInputResult, err := ctx.sweeper.SweepInput(&secondLargeInput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -21,15 +21,15 @@ type mockSigner struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx,
|
func (m *mockSigner) SignOutputRaw(tx *wire.MsgTx,
|
||||||
signDesc *lnwallet.SignDescriptor) ([]byte, error) {
|
signDesc *input.SignDescriptor) ([]byte, error) {
|
||||||
|
|
||||||
return []byte{}, nil
|
return []byte{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockSigner) ComputeInputScript(tx *wire.MsgTx,
|
func (m *mockSigner) ComputeInputScript(tx *wire.MsgTx,
|
||||||
signDesc *lnwallet.SignDescriptor) (*lnwallet.InputScript, error) {
|
signDesc *input.SignDescriptor) (*input.Script, error) {
|
||||||
|
|
||||||
return &lnwallet.InputScript{}, nil
|
return &input.Script{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MockNotifier simulates the chain notifier for test purposes. This type is
|
// MockNotifier simulates the chain notifier for test purposes. This type is
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/btcsuite/btcwallet/wallet/txrules"
|
"github.com/btcsuite/btcwallet/wallet/txrules"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -21,21 +22,21 @@ var (
|
|||||||
|
|
||||||
// inputSet is a set of inputs that can be used as the basis to generate a tx
|
// inputSet is a set of inputs that can be used as the basis to generate a tx
|
||||||
// on.
|
// on.
|
||||||
type inputSet []Input
|
type inputSet []input.Input
|
||||||
|
|
||||||
// generateInputPartitionings goes through all given inputs and constructs sets
|
// generateInputPartitionings goes through all given inputs and constructs sets
|
||||||
// of inputs that can be used to generate a sensible transaction. Each set
|
// of inputs that can be used to generate a sensible transaction. Each set
|
||||||
// contains up to the configured maximum number of inputs. Negative yield
|
// contains up to the configured maximum number of inputs. Negative yield
|
||||||
// inputs are skipped. No input sets with a total value after fees below the
|
// inputs are skipped. No input sets with a total value after fees below the
|
||||||
// dust limit are returned.
|
// dust limit are returned.
|
||||||
func generateInputPartitionings(sweepableInputs []Input,
|
func generateInputPartitionings(sweepableInputs []input.Input,
|
||||||
relayFeePerKW, feePerKW lnwallet.SatPerKWeight,
|
relayFeePerKW, feePerKW lnwallet.SatPerKWeight,
|
||||||
maxInputsPerTx int) ([]inputSet, error) {
|
maxInputsPerTx int) ([]inputSet, error) {
|
||||||
|
|
||||||
// Calculate dust limit based on the P2WPKH output script of the sweep
|
// Calculate dust limit based on the P2WPKH output script of the sweep
|
||||||
// txes.
|
// txes.
|
||||||
dustLimit := txrules.GetDustThreshold(
|
dustLimit := txrules.GetDustThreshold(
|
||||||
lnwallet.P2WPKHSize,
|
input.P2WPKHSize,
|
||||||
btcutil.Amount(relayFeePerKW.FeePerKVByte()),
|
btcutil.Amount(relayFeePerKW.FeePerKVByte()),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -113,10 +114,10 @@ func generateInputPartitionings(sweepableInputs []Input,
|
|||||||
// up the utxo set even if it costs us some fees up front. In the spirit of
|
// up the utxo set even if it costs us some fees up front. In the spirit of
|
||||||
// minimizing any negative externalities we cause for the Bitcoin system as a
|
// minimizing any negative externalities we cause for the Bitcoin system as a
|
||||||
// whole.
|
// whole.
|
||||||
func getPositiveYieldInputs(sweepableInputs []Input, maxInputs int,
|
func getPositiveYieldInputs(sweepableInputs []input.Input, maxInputs int,
|
||||||
feePerKW lnwallet.SatPerKWeight) (int, btcutil.Amount) {
|
feePerKW lnwallet.SatPerKWeight) (int, btcutil.Amount) {
|
||||||
|
|
||||||
var weightEstimate lnwallet.TxWeightEstimator
|
var weightEstimate input.TxWeightEstimator
|
||||||
|
|
||||||
// Add the sweep tx output to the weight estimate.
|
// Add the sweep tx output to the weight estimate.
|
||||||
weightEstimate.AddP2WKHOutput()
|
weightEstimate.AddP2WKHOutput()
|
||||||
@ -166,9 +167,9 @@ func getPositiveYieldInputs(sweepableInputs []Input, maxInputs int,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// createSweepTx builds a signed tx spending the inputs to a the output script.
|
// createSweepTx builds a signed tx spending the inputs to a the output script.
|
||||||
func createSweepTx(inputs []Input, outputPkScript []byte,
|
func createSweepTx(inputs []input.Input, outputPkScript []byte,
|
||||||
currentBlockHeight uint32, feePerKw lnwallet.SatPerKWeight,
|
currentBlockHeight uint32, feePerKw lnwallet.SatPerKWeight,
|
||||||
signer lnwallet.Signer) (*wire.MsgTx, error) {
|
signer input.Signer) (*wire.MsgTx, error) {
|
||||||
|
|
||||||
inputs, txWeight, csvCount, cltvCount := getWeightEstimate(inputs)
|
inputs, txWeight, csvCount, cltvCount := getWeightEstimate(inputs)
|
||||||
|
|
||||||
@ -222,7 +223,7 @@ func createSweepTx(inputs []Input, outputPkScript []byte,
|
|||||||
|
|
||||||
// With all the inputs in place, use each output's unique input script
|
// With all the inputs in place, use each output's unique input script
|
||||||
// function to generate the final witness required for spending.
|
// function to generate the final witness required for spending.
|
||||||
addInputScript := func(idx int, tso Input) error {
|
addInputScript := func(idx int, tso input.Input) error {
|
||||||
inputScript, err := tso.CraftInputScript(
|
inputScript, err := tso.CraftInputScript(
|
||||||
signer, sweepTx, hashCache, idx,
|
signer, sweepTx, hashCache, idx,
|
||||||
)
|
)
|
||||||
@ -254,62 +255,62 @@ func createSweepTx(inputs []Input, outputPkScript []byte,
|
|||||||
// the given input if it would be included in a tx. We also return if the
|
// the given input if it would be included in a tx. We also return if the
|
||||||
// output itself is a nested p2sh output, if so then we need to take into
|
// output itself is a nested p2sh output, if so then we need to take into
|
||||||
// account the extra sigScript data size.
|
// account the extra sigScript data size.
|
||||||
func getInputWitnessSizeUpperBound(input Input) (int, bool, error) {
|
func getInputWitnessSizeUpperBound(inp input.Input) (int, bool, error) {
|
||||||
switch input.WitnessType() {
|
switch inp.WitnessType() {
|
||||||
|
|
||||||
// Outputs on a remote commitment transaction that pay directly to us.
|
// Outputs on a remote commitment transaction that pay directly to us.
|
||||||
case lnwallet.WitnessKeyHash:
|
case input.WitnessKeyHash:
|
||||||
fallthrough
|
fallthrough
|
||||||
case lnwallet.CommitmentNoDelay:
|
case input.CommitmentNoDelay:
|
||||||
return lnwallet.P2WKHWitnessSize, false, nil
|
return input.P2WKHWitnessSize, false, nil
|
||||||
|
|
||||||
// Outputs on a past commitment transaction that pay directly
|
// Outputs on a past commitment transaction that pay directly
|
||||||
// to us.
|
// to us.
|
||||||
case lnwallet.CommitmentTimeLock:
|
case input.CommitmentTimeLock:
|
||||||
return lnwallet.ToLocalTimeoutWitnessSize, false, nil
|
return input.ToLocalTimeoutWitnessSize, false, nil
|
||||||
|
|
||||||
// Outgoing second layer HTLC's that have confirmed within the
|
// Outgoing second layer HTLC's that have confirmed within the
|
||||||
// chain, and the output they produced is now mature enough to
|
// chain, and the output they produced is now mature enough to
|
||||||
// sweep.
|
// sweep.
|
||||||
case lnwallet.HtlcOfferedTimeoutSecondLevel:
|
case input.HtlcOfferedTimeoutSecondLevel:
|
||||||
return lnwallet.ToLocalTimeoutWitnessSize, false, nil
|
return input.ToLocalTimeoutWitnessSize, false, nil
|
||||||
|
|
||||||
// Incoming second layer HTLC's that have confirmed within the
|
// Incoming second layer HTLC's that have confirmed within the
|
||||||
// chain, and the output they produced is now mature enough to
|
// chain, and the output they produced is now mature enough to
|
||||||
// sweep.
|
// sweep.
|
||||||
case lnwallet.HtlcAcceptedSuccessSecondLevel:
|
case input.HtlcAcceptedSuccessSecondLevel:
|
||||||
return lnwallet.ToLocalTimeoutWitnessSize, false, nil
|
return input.ToLocalTimeoutWitnessSize, false, nil
|
||||||
|
|
||||||
// An HTLC on the commitment transaction of the remote party,
|
// An HTLC on the commitment transaction of the remote party,
|
||||||
// that has had its absolute timelock expire.
|
// that has had its absolute timelock expire.
|
||||||
case lnwallet.HtlcOfferedRemoteTimeout:
|
case input.HtlcOfferedRemoteTimeout:
|
||||||
return lnwallet.AcceptedHtlcTimeoutWitnessSize, false, nil
|
return input.AcceptedHtlcTimeoutWitnessSize, false, nil
|
||||||
|
|
||||||
// An HTLC on the commitment transaction of the remote party,
|
// An HTLC on the commitment transaction of the remote party,
|
||||||
// that can be swept with the preimage.
|
// that can be swept with the preimage.
|
||||||
case lnwallet.HtlcAcceptedRemoteSuccess:
|
case input.HtlcAcceptedRemoteSuccess:
|
||||||
return lnwallet.OfferedHtlcSuccessWitnessSize, false, nil
|
return input.OfferedHtlcSuccessWitnessSize, false, nil
|
||||||
|
|
||||||
// A nested P2SH input that has a p2wkh witness script. We'll mark this
|
// A nested P2SH input that has a p2wkh witness script. We'll mark this
|
||||||
// as nested P2SH so the caller can estimate the weight properly
|
// as nested P2SH so the caller can estimate the weight properly
|
||||||
// including the sigScript.
|
// including the sigScript.
|
||||||
case lnwallet.NestedWitnessKeyHash:
|
case input.NestedWitnessKeyHash:
|
||||||
return lnwallet.P2WKHWitnessSize, true, nil
|
return input.P2WKHWitnessSize, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0, false, fmt.Errorf("unexpected witness type: %v",
|
return 0, false, fmt.Errorf("unexpected witness type: %v",
|
||||||
input.WitnessType())
|
inp.WitnessType())
|
||||||
}
|
}
|
||||||
|
|
||||||
// getWeightEstimate returns a weight estimate for the given inputs.
|
// getWeightEstimate returns a weight estimate for the given inputs.
|
||||||
// Additionally, it returns counts for the number of csv and cltv inputs.
|
// Additionally, it returns counts for the number of csv and cltv inputs.
|
||||||
func getWeightEstimate(inputs []Input) ([]Input, int64, int, int) {
|
func getWeightEstimate(inputs []input.Input) ([]input.Input, int64, int, int) {
|
||||||
// We initialize a weight estimator so we can accurately asses the
|
// We initialize a weight estimator so we can accurately asses the
|
||||||
// amount of fees we need to pay for this sweep transaction.
|
// amount of fees we need to pay for this sweep transaction.
|
||||||
//
|
//
|
||||||
// TODO(roasbeef): can be more intelligent about buffering outputs to
|
// TODO(roasbeef): can be more intelligent about buffering outputs to
|
||||||
// be more efficient on-chain.
|
// be more efficient on-chain.
|
||||||
var weightEstimate lnwallet.TxWeightEstimator
|
var weightEstimate input.TxWeightEstimator
|
||||||
|
|
||||||
// Our sweep transaction will pay to a single segwit p2wkh address,
|
// Our sweep transaction will pay to a single segwit p2wkh address,
|
||||||
// ensure it contributes to our weight estimate.
|
// ensure it contributes to our weight estimate.
|
||||||
@ -319,16 +320,16 @@ func getWeightEstimate(inputs []Input) ([]Input, int64, int, int) {
|
|||||||
// weight of its witness, and add it to the proper set of spendable
|
// weight of its witness, and add it to the proper set of spendable
|
||||||
// outputs.
|
// outputs.
|
||||||
var (
|
var (
|
||||||
sweepInputs []Input
|
sweepInputs []input.Input
|
||||||
csvCount, cltvCount int
|
csvCount, cltvCount int
|
||||||
)
|
)
|
||||||
for i := range inputs {
|
for i := range inputs {
|
||||||
input := inputs[i]
|
inp := inputs[i]
|
||||||
|
|
||||||
// For fee estimation purposes, we'll now attempt to obtain an
|
// For fee estimation purposes, we'll now attempt to obtain an
|
||||||
// upper bound on the weight this input will add when fully
|
// upper bound on the weight this input will add when fully
|
||||||
// populated.
|
// populated.
|
||||||
size, isNestedP2SH, err := getInputWitnessSizeUpperBound(input)
|
size, isNestedP2SH, err := getInputWitnessSizeUpperBound(inp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warn(err)
|
log.Warn(err)
|
||||||
|
|
||||||
@ -345,15 +346,15 @@ func getWeightEstimate(inputs []Input) ([]Input, int64, int, int) {
|
|||||||
weightEstimate.AddWitnessInput(size)
|
weightEstimate.AddWitnessInput(size)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch input.WitnessType() {
|
switch inp.WitnessType() {
|
||||||
case lnwallet.CommitmentTimeLock,
|
case input.CommitmentTimeLock,
|
||||||
lnwallet.HtlcOfferedTimeoutSecondLevel,
|
input.HtlcOfferedTimeoutSecondLevel,
|
||||||
lnwallet.HtlcAcceptedSuccessSecondLevel:
|
input.HtlcAcceptedSuccessSecondLevel:
|
||||||
csvCount++
|
csvCount++
|
||||||
case lnwallet.HtlcOfferedRemoteTimeout:
|
case input.HtlcOfferedRemoteTimeout:
|
||||||
cltvCount++
|
cltvCount++
|
||||||
}
|
}
|
||||||
sweepInputs = append(sweepInputs, input)
|
sweepInputs = append(sweepInputs, inp)
|
||||||
}
|
}
|
||||||
|
|
||||||
txWeight := int64(weightEstimate.Weight())
|
txWeight := int64(weightEstimate.Weight())
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/btcsuite/btcd/txscript"
|
"github.com/btcsuite/btcd/txscript"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -152,7 +153,7 @@ func CraftSweepAllTx(feeRate lnwallet.SatPerKWeight, blockHeight uint32,
|
|||||||
deliveryAddr btcutil.Address, coinSelectLocker CoinSelectionLocker,
|
deliveryAddr btcutil.Address, coinSelectLocker CoinSelectionLocker,
|
||||||
utxoSource UtxoSource, outpointLocker OutpointLocker,
|
utxoSource UtxoSource, outpointLocker OutpointLocker,
|
||||||
feeEstimator lnwallet.FeeEstimator,
|
feeEstimator lnwallet.FeeEstimator,
|
||||||
signer lnwallet.Signer) (*WalletSweepPackage, error) {
|
signer input.Signer) (*WalletSweepPackage, error) {
|
||||||
|
|
||||||
// TODO(roasbeef): turn off ATPL as well when available?
|
// TODO(roasbeef): turn off ATPL as well when available?
|
||||||
|
|
||||||
@ -206,7 +207,7 @@ func CraftSweepAllTx(feeRate lnwallet.SatPerKWeight, blockHeight uint32,
|
|||||||
// Now that we've locked all the potential outputs to sweep, we'll
|
// Now that we've locked all the potential outputs to sweep, we'll
|
||||||
// assemble an input for each of them, so we can hand it off to the
|
// assemble an input for each of them, so we can hand it off to the
|
||||||
// sweeper to generate and sign a transaction for us.
|
// sweeper to generate and sign a transaction for us.
|
||||||
var inputsToSweep []Input
|
var inputsToSweep []input.Input
|
||||||
for _, output := range allOutputs {
|
for _, output := range allOutputs {
|
||||||
// We'll consult the utxoSource for information concerning this
|
// We'll consult the utxoSource for information concerning this
|
||||||
// outpoint, we'll need to properly populate a signDescriptor
|
// outpoint, we'll need to properly populate a signDescriptor
|
||||||
@ -222,7 +223,7 @@ func CraftSweepAllTx(feeRate lnwallet.SatPerKWeight, blockHeight uint32,
|
|||||||
// we only need to populate the output value and output script.
|
// we only need to populate the output value and output script.
|
||||||
// The rest of the items will be populated internally within
|
// The rest of the items will be populated internally within
|
||||||
// the sweeper via the witness generation function.
|
// the sweeper via the witness generation function.
|
||||||
signDesc := &lnwallet.SignDescriptor{
|
signDesc := &input.SignDescriptor{
|
||||||
Output: outputInfo,
|
Output: outputInfo,
|
||||||
HashType: txscript.SigHashAll,
|
HashType: txscript.SigHashAll,
|
||||||
}
|
}
|
||||||
@ -232,18 +233,18 @@ func CraftSweepAllTx(feeRate lnwallet.SatPerKWeight, blockHeight uint32,
|
|||||||
// Based on the output type, we'll map it to the proper witness
|
// Based on the output type, we'll map it to the proper witness
|
||||||
// type so we can generate the set of input scripts needed to
|
// type so we can generate the set of input scripts needed to
|
||||||
// sweep the output.
|
// sweep the output.
|
||||||
var witnessType lnwallet.WitnessType
|
var witnessType input.WitnessType
|
||||||
switch {
|
switch {
|
||||||
|
|
||||||
// If this is a p2wkh output, then we'll assume it's a witness
|
// If this is a p2wkh output, then we'll assume it's a witness
|
||||||
// key hash witness type.
|
// key hash witness type.
|
||||||
case txscript.IsPayToWitnessPubKeyHash(pkScript):
|
case txscript.IsPayToWitnessPubKeyHash(pkScript):
|
||||||
witnessType = lnwallet.WitnessKeyHash
|
witnessType = input.WitnessKeyHash
|
||||||
|
|
||||||
// If this is a p2sh output, then as since it's under control
|
// If this is a p2sh output, then as since it's under control
|
||||||
// of the wallet, we'll assume it's a nested p2sh output.
|
// of the wallet, we'll assume it's a nested p2sh output.
|
||||||
case txscript.IsPayToScriptHash(pkScript):
|
case txscript.IsPayToScriptHash(pkScript):
|
||||||
witnessType = lnwallet.NestedWitnessKeyHash
|
witnessType = input.NestedWitnessKeyHash
|
||||||
|
|
||||||
// All other output types we count as unknown and will fail to
|
// All other output types we count as unknown and will fail to
|
||||||
// sweep.
|
// sweep.
|
||||||
@ -257,7 +258,7 @@ func CraftSweepAllTx(feeRate lnwallet.SatPerKWeight, blockHeight uint32,
|
|||||||
// Now that we've constructed the items required, we'll make an
|
// Now that we've constructed the items required, we'll make an
|
||||||
// input which can be passed to the sweeper for ultimate
|
// input which can be passed to the sweeper for ultimate
|
||||||
// sweeping.
|
// sweeping.
|
||||||
input := MakeBaseInput(&output.OutPoint, witnessType, signDesc, 0)
|
input := input.MakeBaseInput(&output.OutPoint, witnessType, signDesc, 0)
|
||||||
inputsToSweep = append(inputsToSweep, &input)
|
inputsToSweep = append(inputsToSweep, &input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/contractcourt"
|
"github.com/lightningnetwork/lnd/contractcourt"
|
||||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
@ -170,7 +171,7 @@ func createTestPeer(notifier chainntnfs.ChainNotifier,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, err
|
return nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
bobCommitPoint := lnwallet.ComputeCommitmentPoint(bobFirstRevoke[:])
|
bobCommitPoint := input.ComputeCommitmentPoint(bobFirstRevoke[:])
|
||||||
|
|
||||||
aliceRoot, err := chainhash.NewHash(aliceKeyPriv.Serialize())
|
aliceRoot, err := chainhash.NewHash(aliceKeyPriv.Serialize())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -181,7 +182,7 @@ func createTestPeer(notifier chainntnfs.ChainNotifier,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, nil, err
|
return nil, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
aliceCommitPoint := lnwallet.ComputeCommitmentPoint(aliceFirstRevoke[:])
|
aliceCommitPoint := input.ComputeCommitmentPoint(aliceFirstRevoke[:])
|
||||||
|
|
||||||
aliceCommitTx, bobCommitTx, err := lnwallet.CreateCommitmentTxns(channelBal,
|
aliceCommitTx, bobCommitTx, err := lnwallet.CreateCommitmentTxns(channelBal,
|
||||||
channelBal, &aliceCfg, &bobCfg, aliceCommitPoint, bobCommitPoint,
|
channelBal, &aliceCfg, &bobCfg, aliceCommitPoint, bobCommitPoint,
|
||||||
@ -214,7 +215,7 @@ func createTestPeer(notifier chainntnfs.ChainNotifier,
|
|||||||
LocalBalance: lnwire.NewMSatFromSatoshis(channelBal),
|
LocalBalance: lnwire.NewMSatFromSatoshis(channelBal),
|
||||||
RemoteBalance: lnwire.NewMSatFromSatoshis(channelBal),
|
RemoteBalance: lnwire.NewMSatFromSatoshis(channelBal),
|
||||||
FeePerKw: btcutil.Amount(feePerKw),
|
FeePerKw: btcutil.Amount(feePerKw),
|
||||||
CommitFee: feePerKw.FeeForWeight(lnwallet.CommitWeight),
|
CommitFee: feePerKw.FeeForWeight(input.CommitWeight),
|
||||||
CommitTx: aliceCommitTx,
|
CommitTx: aliceCommitTx,
|
||||||
CommitSig: bytes.Repeat([]byte{1}, 71),
|
CommitSig: bytes.Repeat([]byte{1}, 71),
|
||||||
}
|
}
|
||||||
@ -223,7 +224,7 @@ func createTestPeer(notifier chainntnfs.ChainNotifier,
|
|||||||
LocalBalance: lnwire.NewMSatFromSatoshis(channelBal),
|
LocalBalance: lnwire.NewMSatFromSatoshis(channelBal),
|
||||||
RemoteBalance: lnwire.NewMSatFromSatoshis(channelBal),
|
RemoteBalance: lnwire.NewMSatFromSatoshis(channelBal),
|
||||||
FeePerKw: btcutil.Amount(feePerKw),
|
FeePerKw: btcutil.Amount(feePerKw),
|
||||||
CommitFee: feePerKw.FeeForWeight(lnwallet.CommitWeight),
|
CommitFee: feePerKw.FeeForWeight(input.CommitWeight),
|
||||||
CommitTx: bobCommitTx,
|
CommitTx: bobCommitTx,
|
||||||
CommitSig: bytes.Repeat([]byte{1}, 71),
|
CommitSig: bytes.Repeat([]byte{1}, 71),
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/lightningnetwork/lnd/sweep"
|
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/txscript"
|
"github.com/btcsuite/btcd/txscript"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
@ -17,7 +15,9 @@ import (
|
|||||||
|
|
||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
|
"github.com/lightningnetwork/lnd/sweep"
|
||||||
)
|
)
|
||||||
|
|
||||||
// SUMMARY OF OUTPUT STATES
|
// SUMMARY OF OUTPUT STATES
|
||||||
@ -196,7 +196,7 @@ type NurseryConfig struct {
|
|||||||
Store NurseryStore
|
Store NurseryStore
|
||||||
|
|
||||||
// Sweep sweeps an input back to the wallet.
|
// Sweep sweeps an input back to the wallet.
|
||||||
SweepInput func(input sweep.Input) (chan sweep.Result, error)
|
SweepInput func(input input.Input) (chan sweep.Result, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// utxoNursery is a system dedicated to incubating time-locked outputs created
|
// utxoNursery is a system dedicated to incubating time-locked outputs created
|
||||||
@ -368,7 +368,7 @@ func (u *utxoNursery) IncubateOutputs(chanPoint wire.OutPoint,
|
|||||||
&commitResolution.SelfOutPoint,
|
&commitResolution.SelfOutPoint,
|
||||||
&chanPoint,
|
&chanPoint,
|
||||||
commitResolution.MaturityDelay,
|
commitResolution.MaturityDelay,
|
||||||
lnwallet.CommitmentTimeLock,
|
input.CommitmentTimeLock,
|
||||||
&commitResolution.SelfOutputSignDesc,
|
&commitResolution.SelfOutputSignDesc,
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
@ -389,7 +389,7 @@ func (u *utxoNursery) IncubateOutputs(chanPoint wire.OutPoint,
|
|||||||
for _, htlcRes := range incomingHtlcs {
|
for _, htlcRes := range incomingHtlcs {
|
||||||
htlcOutput := makeKidOutput(
|
htlcOutput := makeKidOutput(
|
||||||
&htlcRes.ClaimOutpoint, &chanPoint, htlcRes.CsvDelay,
|
&htlcRes.ClaimOutpoint, &chanPoint, htlcRes.CsvDelay,
|
||||||
lnwallet.HtlcAcceptedSuccessSecondLevel,
|
input.HtlcAcceptedSuccessSecondLevel,
|
||||||
&htlcRes.SweepSignDesc, 0,
|
&htlcRes.SweepSignDesc, 0,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -421,7 +421,7 @@ func (u *utxoNursery) IncubateOutputs(chanPoint wire.OutPoint,
|
|||||||
// indicate this is actually a CLTV output.
|
// indicate this is actually a CLTV output.
|
||||||
htlcOutput := makeKidOutput(
|
htlcOutput := makeKidOutput(
|
||||||
&htlcRes.ClaimOutpoint, &chanPoint, 0,
|
&htlcRes.ClaimOutpoint, &chanPoint, 0,
|
||||||
lnwallet.HtlcOfferedRemoteTimeout,
|
input.HtlcOfferedRemoteTimeout,
|
||||||
&htlcRes.SweepSignDesc, htlcRes.Expiry,
|
&htlcRes.SweepSignDesc, htlcRes.Expiry,
|
||||||
)
|
)
|
||||||
kidOutputs = append(kidOutputs, htlcOutput)
|
kidOutputs = append(kidOutputs, htlcOutput)
|
||||||
@ -533,13 +533,13 @@ func (u *utxoNursery) NurseryReport(
|
|||||||
// Preschool outputs are awaiting the
|
// Preschool outputs are awaiting the
|
||||||
// confirmation of the commitment transaction.
|
// confirmation of the commitment transaction.
|
||||||
switch kid.WitnessType() {
|
switch kid.WitnessType() {
|
||||||
case lnwallet.CommitmentTimeLock:
|
case input.CommitmentTimeLock:
|
||||||
report.AddLimboCommitment(&kid)
|
report.AddLimboCommitment(&kid)
|
||||||
|
|
||||||
// An HTLC output on our commitment transaction
|
// An HTLC output on our commitment transaction
|
||||||
// where the second-layer transaction hasn't
|
// where the second-layer transaction hasn't
|
||||||
// yet confirmed.
|
// yet confirmed.
|
||||||
case lnwallet.HtlcAcceptedSuccessSecondLevel:
|
case input.HtlcAcceptedSuccessSecondLevel:
|
||||||
report.AddLimboStage1SuccessHtlc(&kid)
|
report.AddLimboStage1SuccessHtlc(&kid)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -549,13 +549,13 @@ func (u *utxoNursery) NurseryReport(
|
|||||||
// We can distinguish them via their witness
|
// We can distinguish them via their witness
|
||||||
// types.
|
// types.
|
||||||
switch kid.WitnessType() {
|
switch kid.WitnessType() {
|
||||||
case lnwallet.CommitmentTimeLock:
|
case input.CommitmentTimeLock:
|
||||||
// The commitment transaction has been
|
// The commitment transaction has been
|
||||||
// confirmed, and we are waiting the CSV
|
// confirmed, and we are waiting the CSV
|
||||||
// delay to expire.
|
// delay to expire.
|
||||||
report.AddLimboCommitment(&kid)
|
report.AddLimboCommitment(&kid)
|
||||||
|
|
||||||
case lnwallet.HtlcOfferedRemoteTimeout:
|
case input.HtlcOfferedRemoteTimeout:
|
||||||
// This is an HTLC output on the
|
// This is an HTLC output on the
|
||||||
// commitment transaction of the remote
|
// commitment transaction of the remote
|
||||||
// party. The CLTV timelock has
|
// party. The CLTV timelock has
|
||||||
@ -563,9 +563,9 @@ func (u *utxoNursery) NurseryReport(
|
|||||||
// it.
|
// it.
|
||||||
report.AddLimboDirectHtlc(&kid)
|
report.AddLimboDirectHtlc(&kid)
|
||||||
|
|
||||||
case lnwallet.HtlcAcceptedSuccessSecondLevel:
|
case input.HtlcAcceptedSuccessSecondLevel:
|
||||||
fallthrough
|
fallthrough
|
||||||
case lnwallet.HtlcOfferedTimeoutSecondLevel:
|
case input.HtlcOfferedTimeoutSecondLevel:
|
||||||
// The htlc timeout or success
|
// The htlc timeout or success
|
||||||
// transaction has confirmed, and the
|
// transaction has confirmed, and the
|
||||||
// CSV delay has begun ticking.
|
// CSV delay has begun ticking.
|
||||||
@ -578,17 +578,17 @@ func (u *utxoNursery) NurseryReport(
|
|||||||
// will contribute towards the recovered
|
// will contribute towards the recovered
|
||||||
// balance.
|
// balance.
|
||||||
switch kid.WitnessType() {
|
switch kid.WitnessType() {
|
||||||
case lnwallet.CommitmentTimeLock:
|
case input.CommitmentTimeLock:
|
||||||
// The commitment output was
|
// The commitment output was
|
||||||
// successfully swept back into a
|
// successfully swept back into a
|
||||||
// regular p2wkh output.
|
// regular p2wkh output.
|
||||||
report.AddRecoveredCommitment(&kid)
|
report.AddRecoveredCommitment(&kid)
|
||||||
|
|
||||||
case lnwallet.HtlcAcceptedSuccessSecondLevel:
|
case input.HtlcAcceptedSuccessSecondLevel:
|
||||||
fallthrough
|
fallthrough
|
||||||
case lnwallet.HtlcOfferedTimeoutSecondLevel:
|
case input.HtlcOfferedTimeoutSecondLevel:
|
||||||
fallthrough
|
fallthrough
|
||||||
case lnwallet.HtlcOfferedRemoteTimeout:
|
case input.HtlcOfferedRemoteTimeout:
|
||||||
// This htlc output successfully
|
// This htlc output successfully
|
||||||
// resides in a p2wkh output belonging
|
// resides in a p2wkh output belonging
|
||||||
// to the user.
|
// to the user.
|
||||||
@ -1301,7 +1301,7 @@ func makeBabyOutput(chanPoint *wire.OutPoint,
|
|||||||
|
|
||||||
htlcOutpoint := htlcResolution.ClaimOutpoint
|
htlcOutpoint := htlcResolution.ClaimOutpoint
|
||||||
blocksToMaturity := htlcResolution.CsvDelay
|
blocksToMaturity := htlcResolution.CsvDelay
|
||||||
witnessType := lnwallet.HtlcOfferedTimeoutSecondLevel
|
witnessType := input.HtlcOfferedTimeoutSecondLevel
|
||||||
|
|
||||||
kid := makeKidOutput(
|
kid := makeKidOutput(
|
||||||
&htlcOutpoint, chanPoint, blocksToMaturity, witnessType,
|
&htlcOutpoint, chanPoint, blocksToMaturity, witnessType,
|
||||||
@ -1380,15 +1380,15 @@ type kidOutput struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func makeKidOutput(outpoint, originChanPoint *wire.OutPoint,
|
func makeKidOutput(outpoint, originChanPoint *wire.OutPoint,
|
||||||
blocksToMaturity uint32, witnessType lnwallet.WitnessType,
|
blocksToMaturity uint32, witnessType input.WitnessType,
|
||||||
signDescriptor *lnwallet.SignDescriptor,
|
signDescriptor *input.SignDescriptor,
|
||||||
absoluteMaturity uint32) kidOutput {
|
absoluteMaturity uint32) kidOutput {
|
||||||
|
|
||||||
// This is an HTLC either if it's an incoming HTLC on our commitment
|
// This is an HTLC either if it's an incoming HTLC on our commitment
|
||||||
// transaction, or is an outgoing HTLC on the commitment transaction of
|
// transaction, or is an outgoing HTLC on the commitment transaction of
|
||||||
// the remote peer.
|
// the remote peer.
|
||||||
isHtlc := (witnessType == lnwallet.HtlcAcceptedSuccessSecondLevel ||
|
isHtlc := (witnessType == input.HtlcAcceptedSuccessSecondLevel ||
|
||||||
witnessType == lnwallet.HtlcOfferedRemoteTimeout)
|
witnessType == input.HtlcOfferedRemoteTimeout)
|
||||||
|
|
||||||
// heightHint can be safely set to zero here, because after this
|
// heightHint can be safely set to zero here, because after this
|
||||||
// function returns, nursery will set a proper confirmation height in
|
// function returns, nursery will set a proper confirmation height in
|
||||||
@ -1464,7 +1464,7 @@ func (k *kidOutput) Encode(w io.Writer) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return lnwallet.WriteSignDescriptor(w, k.SignDesc())
|
return input.WriteSignDescriptor(w, k.SignDesc())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode takes a byte array representation of a kidOutput and converts it to an
|
// Decode takes a byte array representation of a kidOutput and converts it to an
|
||||||
@ -1509,9 +1509,9 @@ func (k *kidOutput) Decode(r io.Reader) error {
|
|||||||
if _, err := r.Read(scratch[:2]); err != nil {
|
if _, err := r.Read(scratch[:2]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
k.witnessType = lnwallet.WitnessType(byteOrder.Uint16(scratch[:2]))
|
k.witnessType = input.WitnessType(byteOrder.Uint16(scratch[:2]))
|
||||||
|
|
||||||
return lnwallet.ReadSignDescriptor(r, &k.signDesc)
|
return input.ReadSignDescriptor(r, &k.signDesc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(bvu): copied from channeldb, remove repetition
|
// TODO(bvu): copied from channeldb, remove repetition
|
||||||
@ -1551,4 +1551,4 @@ func readOutpoint(r io.Reader, o *wire.OutPoint) error {
|
|||||||
// Compile-time constraint to ensure kidOutput implements the
|
// Compile-time constraint to ensure kidOutput implements the
|
||||||
// Input interface.
|
// Input interface.
|
||||||
|
|
||||||
var _ sweep.Input = (*kidOutput)(nil)
|
var _ input.Input = (*kidOutput)(nil)
|
||||||
|
@ -5,8 +5,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
|
||||||
"github.com/lightningnetwork/lnd/sweep"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"math"
|
"math"
|
||||||
"os"
|
"os"
|
||||||
@ -21,7 +19,10 @@ import (
|
|||||||
"github.com/btcsuite/btcd/txscript"
|
"github.com/btcsuite/btcd/txscript"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
|
"github.com/lightningnetwork/lnd/sweep"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -108,7 +109,7 @@ var (
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
signDescriptors = []lnwallet.SignDescriptor{
|
signDescriptors = []input.SignDescriptor{
|
||||||
{
|
{
|
||||||
SingleTweak: []byte{
|
SingleTweak: []byte{
|
||||||
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||||
@ -206,7 +207,7 @@ var (
|
|||||||
breachedOutput: breachedOutput{
|
breachedOutput: breachedOutput{
|
||||||
amt: btcutil.Amount(13e7),
|
amt: btcutil.Amount(13e7),
|
||||||
outpoint: outPoints[1],
|
outpoint: outPoints[1],
|
||||||
witnessType: lnwallet.CommitmentTimeLock,
|
witnessType: input.CommitmentTimeLock,
|
||||||
confHeight: uint32(1000),
|
confHeight: uint32(1000),
|
||||||
},
|
},
|
||||||
originChanPoint: outPoints[0],
|
originChanPoint: outPoints[0],
|
||||||
@ -217,7 +218,7 @@ var (
|
|||||||
breachedOutput: breachedOutput{
|
breachedOutput: breachedOutput{
|
||||||
amt: btcutil.Amount(24e7),
|
amt: btcutil.Amount(24e7),
|
||||||
outpoint: outPoints[2],
|
outpoint: outPoints[2],
|
||||||
witnessType: lnwallet.CommitmentTimeLock,
|
witnessType: input.CommitmentTimeLock,
|
||||||
confHeight: uint32(1000),
|
confHeight: uint32(1000),
|
||||||
},
|
},
|
||||||
originChanPoint: outPoints[0],
|
originChanPoint: outPoints[0],
|
||||||
@ -228,7 +229,7 @@ var (
|
|||||||
breachedOutput: breachedOutput{
|
breachedOutput: breachedOutput{
|
||||||
amt: btcutil.Amount(2e5),
|
amt: btcutil.Amount(2e5),
|
||||||
outpoint: outPoints[3],
|
outpoint: outPoints[3],
|
||||||
witnessType: lnwallet.CommitmentTimeLock,
|
witnessType: input.CommitmentTimeLock,
|
||||||
confHeight: uint32(500),
|
confHeight: uint32(500),
|
||||||
},
|
},
|
||||||
originChanPoint: outPoints[0],
|
originChanPoint: outPoints[0],
|
||||||
@ -239,7 +240,7 @@ var (
|
|||||||
breachedOutput: breachedOutput{
|
breachedOutput: breachedOutput{
|
||||||
amt: btcutil.Amount(10e6),
|
amt: btcutil.Amount(10e6),
|
||||||
outpoint: outPoints[4],
|
outpoint: outPoints[4],
|
||||||
witnessType: lnwallet.CommitmentTimeLock,
|
witnessType: input.CommitmentTimeLock,
|
||||||
confHeight: uint32(500),
|
confHeight: uint32(500),
|
||||||
},
|
},
|
||||||
originChanPoint: outPoints[0],
|
originChanPoint: outPoints[0],
|
||||||
@ -597,7 +598,7 @@ func createOutgoingRes(onLocalCommitment bool) *lnwallet.OutgoingHtlcResolution
|
|||||||
|
|
||||||
outgoingRes := lnwallet.OutgoingHtlcResolution{
|
outgoingRes := lnwallet.OutgoingHtlcResolution{
|
||||||
Expiry: 125,
|
Expiry: 125,
|
||||||
SweepSignDesc: lnwallet.SignDescriptor{
|
SweepSignDesc: input.SignDescriptor{
|
||||||
Output: &wire.TxOut{
|
Output: &wire.TxOut{
|
||||||
Value: 10000,
|
Value: 10000,
|
||||||
},
|
},
|
||||||
@ -630,7 +631,7 @@ func createCommitmentRes() *lnwallet.CommitOutputResolution {
|
|||||||
// Set up a commitment output resolution to hand off to nursery.
|
// Set up a commitment output resolution to hand off to nursery.
|
||||||
commitRes := lnwallet.CommitOutputResolution{
|
commitRes := lnwallet.CommitOutputResolution{
|
||||||
SelfOutPoint: wire.OutPoint{},
|
SelfOutPoint: wire.OutPoint{},
|
||||||
SelfOutputSignDesc: lnwallet.SignDescriptor{
|
SelfOutputSignDesc: input.SignDescriptor{
|
||||||
Output: &wire.TxOut{
|
Output: &wire.TxOut{
|
||||||
Value: 10000,
|
Value: 10000,
|
||||||
},
|
},
|
||||||
@ -1027,15 +1028,15 @@ type nurseryMockSigner struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *nurseryMockSigner) SignOutputRaw(tx *wire.MsgTx,
|
func (m *nurseryMockSigner) SignOutputRaw(tx *wire.MsgTx,
|
||||||
signDesc *lnwallet.SignDescriptor) ([]byte, error) {
|
signDesc *input.SignDescriptor) ([]byte, error) {
|
||||||
|
|
||||||
return []byte{}, nil
|
return []byte{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *nurseryMockSigner) ComputeInputScript(tx *wire.MsgTx,
|
func (m *nurseryMockSigner) ComputeInputScript(tx *wire.MsgTx,
|
||||||
signDesc *lnwallet.SignDescriptor) (*lnwallet.InputScript, error) {
|
signDesc *input.SignDescriptor) (*input.Script, error) {
|
||||||
|
|
||||||
return &lnwallet.InputScript{}, nil
|
return &input.Script{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type mockSweeper struct {
|
type mockSweeper struct {
|
||||||
@ -1044,18 +1045,18 @@ type mockSweeper struct {
|
|||||||
resultChans map[wire.OutPoint]chan sweep.Result
|
resultChans map[wire.OutPoint]chan sweep.Result
|
||||||
t *testing.T
|
t *testing.T
|
||||||
|
|
||||||
sweepChan chan sweep.Input
|
sweepChan chan input.Input
|
||||||
}
|
}
|
||||||
|
|
||||||
func newMockSweeper(t *testing.T) *mockSweeper {
|
func newMockSweeper(t *testing.T) *mockSweeper {
|
||||||
return &mockSweeper{
|
return &mockSweeper{
|
||||||
resultChans: make(map[wire.OutPoint]chan sweep.Result),
|
resultChans: make(map[wire.OutPoint]chan sweep.Result),
|
||||||
sweepChan: make(chan sweep.Input, 1),
|
sweepChan: make(chan input.Input, 1),
|
||||||
t: t,
|
t: t,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *mockSweeper) sweepInput(input sweep.Input) (chan sweep.Result, error) {
|
func (s *mockSweeper) sweepInput(input input.Input) (chan sweep.Result, error) {
|
||||||
utxnLog.Debugf("mockSweeper sweepInput called for %v", *input.OutPoint())
|
utxnLog.Debugf("mockSweeper sweepInput called for %v", *input.OutPoint())
|
||||||
|
|
||||||
select {
|
select {
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec"
|
"github.com/btcsuite/btcd/btcec"
|
||||||
"github.com/btcsuite/btcd/txscript"
|
"github.com/btcsuite/btcd/txscript"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -163,7 +163,7 @@ func (b *JusticeKit) CommitToLocalWitnessScript() ([]byte, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return lnwallet.CommitScriptToSelf(
|
return input.CommitScriptToSelf(
|
||||||
b.CSVDelay, localDelayedPubKey, revocationPubKey,
|
b.CSVDelay, localDelayedPubKey, revocationPubKey,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec"
|
"github.com/btcsuite/btcd/btcec"
|
||||||
"github.com/btcsuite/btcd/txscript"
|
"github.com/btcsuite/btcd/txscript"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/lightningnetwork/lnd/watchtower/blob"
|
"github.com/lightningnetwork/lnd/watchtower/blob"
|
||||||
)
|
)
|
||||||
@ -356,7 +356,7 @@ func TestJusticeKitToLocalWitnessConstruction(t *testing.T) {
|
|||||||
|
|
||||||
// Compute the expected to-local script, which is a function of the CSV
|
// Compute the expected to-local script, which is a function of the CSV
|
||||||
// delay, revocation pubkey and delay pubkey.
|
// delay, revocation pubkey and delay pubkey.
|
||||||
expToLocalScript, err := lnwallet.CommitScriptToSelf(
|
expToLocalScript, err := input.CommitScriptToSelf(
|
||||||
csvDelay, delayPrivKey.PubKey(), revPrivKey.PubKey(),
|
csvDelay, delayPrivKey.PubKey(), revPrivKey.PubKey(),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
"github.com/btcsuite/btcd/txscript"
|
"github.com/btcsuite/btcd/txscript"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/watchtower/blob"
|
"github.com/lightningnetwork/lnd/watchtower/blob"
|
||||||
"github.com/lightningnetwork/lnd/watchtower/wtdb"
|
"github.com/lightningnetwork/lnd/watchtower/wtdb"
|
||||||
)
|
)
|
||||||
@ -60,7 +60,7 @@ func (p *JusticeDescriptor) commitToLocalInput() (*breachedInput, error) {
|
|||||||
|
|
||||||
// Compute the witness script hash, which will be used to locate the
|
// Compute the witness script hash, which will be used to locate the
|
||||||
// input on the breaching commitment transaction.
|
// input on the breaching commitment transaction.
|
||||||
toLocalWitnessHash, err := lnwallet.WitnessScriptHash(toLocalScript)
|
toLocalWitnessHash, err := input.WitnessScriptHash(toLocalScript)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -112,7 +112,7 @@ func (p *JusticeDescriptor) commitToRemoteInput() (*breachedInput, error) {
|
|||||||
|
|
||||||
// Compute the witness script hash from the to-remote pubkey, which will
|
// Compute the witness script hash from the to-remote pubkey, which will
|
||||||
// be used to locate the input on the breach commitment transaction.
|
// be used to locate the input on the breach commitment transaction.
|
||||||
toRemoteScriptHash, err := lnwallet.CommitScriptUnencumbered(
|
toRemoteScriptHash, err := input.CommitScriptUnencumbered(
|
||||||
toRemotePubKey,
|
toRemotePubKey,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -226,7 +226,7 @@ func (p *JusticeDescriptor) assembleJusticeTxn(txWeight int64,
|
|||||||
func (p *JusticeDescriptor) CreateJusticeTxn() (*wire.MsgTx, error) {
|
func (p *JusticeDescriptor) CreateJusticeTxn() (*wire.MsgTx, error) {
|
||||||
var (
|
var (
|
||||||
sweepInputs = make([]*breachedInput, 0, 2)
|
sweepInputs = make([]*breachedInput, 0, 2)
|
||||||
weightEstimate lnwallet.TxWeightEstimator
|
weightEstimate input.TxWeightEstimator
|
||||||
)
|
)
|
||||||
|
|
||||||
// Add our reward address to the weight estimate.
|
// Add our reward address to the weight estimate.
|
||||||
@ -235,10 +235,10 @@ func (p *JusticeDescriptor) CreateJusticeTxn() (*wire.MsgTx, error) {
|
|||||||
// Add the sweep address's contribution, depending on whether it is a
|
// Add the sweep address's contribution, depending on whether it is a
|
||||||
// p2wkh or p2wsh output.
|
// p2wkh or p2wsh output.
|
||||||
switch len(p.JusticeKit.SweepAddress) {
|
switch len(p.JusticeKit.SweepAddress) {
|
||||||
case lnwallet.P2WPKHSize:
|
case input.P2WPKHSize:
|
||||||
weightEstimate.AddP2WKHOutput()
|
weightEstimate.AddP2WKHOutput()
|
||||||
|
|
||||||
case lnwallet.P2WSHSize:
|
case input.P2WSHSize:
|
||||||
weightEstimate.AddP2WSHOutput()
|
weightEstimate.AddP2WSHOutput()
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -251,7 +251,7 @@ func (p *JusticeDescriptor) CreateJusticeTxn() (*wire.MsgTx, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
weightEstimate.AddWitnessInput(lnwallet.ToLocalPenaltyWitnessSize)
|
weightEstimate.AddWitnessInput(input.ToLocalPenaltyWitnessSize)
|
||||||
sweepInputs = append(sweepInputs, toLocalInput)
|
sweepInputs = append(sweepInputs, toLocalInput)
|
||||||
|
|
||||||
// If the justice kit specifies that we have to sweep the to-remote
|
// If the justice kit specifies that we have to sweep the to-remote
|
||||||
@ -262,7 +262,7 @@ func (p *JusticeDescriptor) CreateJusticeTxn() (*wire.MsgTx, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
weightEstimate.AddWitnessInput(lnwallet.P2WKHWitnessSize)
|
weightEstimate.AddWitnessInput(input.P2WKHWitnessSize)
|
||||||
sweepInputs = append(sweepInputs, toRemoteInput)
|
sweepInputs = append(sweepInputs, toRemoteInput)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,7 +281,7 @@ func (p *JusticeDescriptor) CreateJusticeTxn() (*wire.MsgTx, error) {
|
|||||||
func findTxOutByPkScript(txn *wire.MsgTx,
|
func findTxOutByPkScript(txn *wire.MsgTx,
|
||||||
pkScript []byte) (uint32, *wire.TxOut, error) {
|
pkScript []byte) (uint32, *wire.TxOut, error) {
|
||||||
|
|
||||||
found, index := lnwallet.FindScriptOutputIndex(txn, pkScript)
|
found, index := input.FindScriptOutputIndex(txn, pkScript)
|
||||||
if !found {
|
if !found {
|
||||||
return 0, nil, ErrOutputNotFound
|
return 0, nil, ErrOutputNotFound
|
||||||
}
|
}
|
||||||
|
@ -13,8 +13,8 @@ import (
|
|||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/lightningnetwork/lnd/watchtower/blob"
|
"github.com/lightningnetwork/lnd/watchtower/blob"
|
||||||
"github.com/lightningnetwork/lnd/watchtower/lookout"
|
"github.com/lightningnetwork/lnd/watchtower/lookout"
|
||||||
@ -59,7 +59,7 @@ func newMockSigner() *mockSigner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *mockSigner) SignOutputRaw(tx *wire.MsgTx,
|
func (s *mockSigner) SignOutputRaw(tx *wire.MsgTx,
|
||||||
signDesc *lnwallet.SignDescriptor) ([]byte, error) {
|
signDesc *input.SignDescriptor) ([]byte, error) {
|
||||||
|
|
||||||
witnessScript := signDesc.WitnessScript
|
witnessScript := signDesc.WitnessScript
|
||||||
amt := signDesc.Output.Value
|
amt := signDesc.Output.Value
|
||||||
@ -81,7 +81,7 @@ func (s *mockSigner) SignOutputRaw(tx *wire.MsgTx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *mockSigner) ComputeInputScript(tx *wire.MsgTx,
|
func (s *mockSigner) ComputeInputScript(tx *wire.MsgTx,
|
||||||
signDesc *lnwallet.SignDescriptor) (*lnwallet.InputScript, error) {
|
signDesc *input.SignDescriptor) (*input.Script, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ func TestJusticeDescriptor(t *testing.T) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Construct the to-local witness script.
|
// Construct the to-local witness script.
|
||||||
toLocalScript, err := lnwallet.CommitScriptToSelf(
|
toLocalScript, err := input.CommitScriptToSelf(
|
||||||
csvDelay, toLocalPK, revPK,
|
csvDelay, toLocalPK, revPK,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -130,13 +130,13 @@ func TestJusticeDescriptor(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compute the to-local witness script hash.
|
// Compute the to-local witness script hash.
|
||||||
toLocalScriptHash, err := lnwallet.WitnessScriptHash(toLocalScript)
|
toLocalScriptHash, err := input.WitnessScriptHash(toLocalScript)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create to-local witness script hash: %v", err)
|
t.Fatalf("unable to create to-local witness script hash: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the to-remote witness script hash.
|
// Compute the to-remote witness script hash.
|
||||||
toRemoteScriptHash, err := lnwallet.CommitScriptUnencumbered(toRemotePK)
|
toRemoteScriptHash, err := input.CommitScriptUnencumbered(toRemotePK)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create to-remote script: %v", err)
|
t.Fatalf("unable to create to-remote script: %v", err)
|
||||||
}
|
}
|
||||||
@ -160,11 +160,11 @@ func TestJusticeDescriptor(t *testing.T) {
|
|||||||
breachTxID := breachTxn.TxHash()
|
breachTxID := breachTxn.TxHash()
|
||||||
|
|
||||||
// Compute the weight estimate for our justice transaction.
|
// Compute the weight estimate for our justice transaction.
|
||||||
var weightEstimate lnwallet.TxWeightEstimator
|
var weightEstimate input.TxWeightEstimator
|
||||||
weightEstimate.AddP2WKHOutput()
|
weightEstimate.AddP2WKHOutput()
|
||||||
weightEstimate.AddP2WKHOutput()
|
weightEstimate.AddP2WKHOutput()
|
||||||
weightEstimate.AddWitnessInput(lnwallet.ToLocalPenaltyWitnessSize)
|
weightEstimate.AddWitnessInput(input.ToLocalPenaltyWitnessSize)
|
||||||
weightEstimate.AddWitnessInput(lnwallet.P2WKHWitnessSize)
|
weightEstimate.AddWitnessInput(input.P2WKHWitnessSize)
|
||||||
txWeight := weightEstimate.Weight()
|
txWeight := weightEstimate.Weight()
|
||||||
|
|
||||||
// Create a session info so that simulate agreement of the sweep
|
// Create a session info so that simulate agreement of the sweep
|
||||||
@ -235,7 +235,7 @@ func TestJusticeDescriptor(t *testing.T) {
|
|||||||
hashCache := txscript.NewTxSigHashes(justiceTxn)
|
hashCache := txscript.NewTxSigHashes(justiceTxn)
|
||||||
|
|
||||||
// Create the sign descriptor used to sign for the to-local input.
|
// Create the sign descriptor used to sign for the to-local input.
|
||||||
toLocalSignDesc := &lnwallet.SignDescriptor{
|
toLocalSignDesc := &input.SignDescriptor{
|
||||||
KeyDesc: keychain.KeyDescriptor{
|
KeyDesc: keychain.KeyDescriptor{
|
||||||
KeyLocator: revKeyLoc,
|
KeyLocator: revKeyLoc,
|
||||||
},
|
},
|
||||||
@ -247,7 +247,7 @@ func TestJusticeDescriptor(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the sign descriptor used to sign for the to-remote input.
|
// Create the sign descriptor used to sign for the to-remote input.
|
||||||
toRemoteSignDesc := &lnwallet.SignDescriptor{
|
toRemoteSignDesc := &input.SignDescriptor{
|
||||||
KeyDesc: keychain.KeyDescriptor{
|
KeyDesc: keychain.KeyDescriptor{
|
||||||
KeyLocator: toRemoteKeyLoc,
|
KeyLocator: toRemoteKeyLoc,
|
||||||
PubKey: toRemotePK,
|
PubKey: toRemotePK,
|
||||||
@ -274,7 +274,7 @@ func TestJusticeDescriptor(t *testing.T) {
|
|||||||
// Compute the witness for the to-remote input. The first element is a
|
// Compute the witness for the to-remote input. The first element is a
|
||||||
// DER-encoded signature under the to-remote pubkey. The sighash flag is
|
// DER-encoded signature under the to-remote pubkey. The sighash flag is
|
||||||
// also present, so we trim it.
|
// also present, so we trim it.
|
||||||
toRemoteWitness, err := lnwallet.CommitSpendNoDelay(
|
toRemoteWitness, err := input.CommitSpendNoDelay(
|
||||||
signer, toRemoteSignDesc, justiceTxn,
|
signer, toRemoteSignDesc, justiceTxn,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user