Merge pull request #6810 from Roasbeef/taproot-errwhere

multi: use taproot errwhere applicable for change/delivery/tower addresses
This commit is contained in:
Olaoluwa Osuntokun authored and GitHub committed 2022-08-12 14:18:35 -07:00
commit d0996a9df8
18 files changed
+136 -66

No files matched your search

+2 -2
View File
@@ -1347,9 +1347,9 @@ func (b *BreachArbiter) createSweepTx(inputs []input.Input) (*wire.MsgTx,
spendableOutputs = make([]input.Input, 0, len(inputs)) spendableOutputs = make([]input.Input, 0, len(inputs))
// 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 p2tr output. Components such as the version,
// nLockTime, and output are already included in the TxWeightEstimator. // nLockTime, and output are already included in the TxWeightEstimator.
weightEstimate.AddP2WKHOutput() weightEstimate.AddP2TROutput()
// Next, we iterate over the breached outputs contained in the // Next, we iterate over the breached outputs contained in the
// retribution info. For each, we switch over the witness type such // retribution info. For each, we switch over the witness type such
+4 -1
View File
@@ -21,12 +21,15 @@
## Taproot ## Taproot
[`lnd` will now refuse to start if it detects the full node backned does not [`lnd` will now refuse to start if it detects the full node backend does not
support Tapoot](https://github.com/lightningnetwork/lnd/pull/6798). support Tapoot](https://github.com/lightningnetwork/lnd/pull/6798).
[`lnd` will now use taproot addresses for co-op closes if the remote peer [`lnd` will now use taproot addresses for co-op closes if the remote peer
supports the feature.](https://github.com/lightningnetwork/lnd/pull/6633) supports the feature.](https://github.com/lightningnetwork/lnd/pull/6633)
The [wallet also creates P2TR change addresses by
default](https://github.com/lightningnetwork/lnd/pull/6810) in most cases.
## `lncli` ## `lncli`
* [Add `payment_addr` flag to * [Add `payment_addr` flag to
+1 -1
View File
@@ -458,7 +458,7 @@ func Main(cfg *Config, lisCfg ListenerCfg, implCfg *ImplementationCfg,
Net: cfg.net, Net: cfg.net,
NewAddress: func() (btcutil.Address, error) { NewAddress: func() (btcutil.Address, error) {
return activeChainControl.Wallet.NewAddress( return activeChainControl.Wallet.NewAddress(
lnwallet.WitnessPubKey, false, lnwallet.TaprootPubkey, false,
lnwallet.DefaultAccountName, lnwallet.DefaultAccountName,
) )
}, },
+4 -3
View File
@@ -98,8 +98,8 @@ func calculateFees(utxos []Coin, feeRate chainfee.SatPerKWeight) (btcutil.Amount
requiredFeeNoChange := feeRate.FeeForWeight(totalWeight) requiredFeeNoChange := feeRate.FeeForWeight(totalWeight)
// Estimate the fee required for a transaction with a change output. // Estimate the fee required for a transaction with a change output.
// Assume that change output is a P2WKH output. // Assume that change output is a P2TR output.
weightEstimate.AddP2WKHOutput() weightEstimate.AddP2TROutput()
// Now that we have added the change output, redo the fee // Now that we have added the change output, redo the fee
// estimate. // estimate.
@@ -209,7 +209,8 @@ func CoinSelectSubtractFees(feeRate chainfee.SatPerKWeight, amt,
// Obtain fee estimates both with and without using a change // Obtain fee estimates both with and without using a change
// output. // output.
requiredFeeNoChange, requiredFeeWithChange, err := calculateFees( requiredFeeNoChange, requiredFeeWithChange, err := calculateFees(
selectedUtxos, feeRate) selectedUtxos, feeRate,
)
if err != nil { if err != nil {
return nil, 0, 0, err return nil, 0, 0, err
} }
+3 -3
View File
@@ -44,7 +44,7 @@ func fundingFee(feeRate chainfee.SatPerKWeight, numInput int, // nolint:unparam
// Optionally count a change output. // Optionally count a change output.
if change { if change {
weightEstimate.AddP2WKHOutput() weightEstimate.AddP2TROutput()
} }
totalWeight := int64(weightEstimate.Weight()) totalWeight := int64(weightEstimate.Weight())
@@ -81,7 +81,7 @@ func TestCalculateFees(t *testing.T) {
}, },
expectedFeeNoChange: 487, expectedFeeNoChange: 487,
expectedFeeWithChange: 611, expectedFeeWithChange: 659,
expectedErr: nil, expectedErr: nil,
}, },
@@ -97,7 +97,7 @@ func TestCalculateFees(t *testing.T) {
}, },
expectedFeeNoChange: 579, expectedFeeNoChange: 579,
expectedFeeWithChange: 703, expectedFeeWithChange: 751,
expectedErr: nil, expectedErr: nil,
}, },
+1 -1
View File
@@ -21,7 +21,7 @@ import (
// //
// Steps to final channel provisioning: // Steps to final channel provisioning:
// 1. Call BindKeys to notify the intent which keys to use when constructing // 1. Call BindKeys to notify the intent which keys to use when constructing
// the multi-sig output. // the multi-sig output.
// 2. Call CompileFundingTx afterwards to obtain the funding transaction. // 2. Call CompileFundingTx afterwards to obtain the funding transaction.
// //
// If either of these steps fail, then the Cancel method MUST be called. // If either of these steps fail, then the Cancel method MUST be called.
+8 -4
View File
@@ -2708,6 +2708,14 @@ var walletTests = []walletTestCase{
name: "change output spend confirmation", name: "change output spend confirmation",
test: testChangeOutputSpendConfirmation, test: testChangeOutputSpendConfirmation,
}, },
{
// TODO(guggero): this test should remain second until dual
// funding can properly exchange full UTXO information and we
// can use P2TR change outputs as the funding inputs for a dual
// funded channel.
name: "dual funder workflow",
test: testDualFundingReservationWorkflow,
},
{ {
name: "spend unconfirmed outputs", name: "spend unconfirmed outputs",
test: testSpendUnconfirmed, test: testSpendUnconfirmed,
@@ -2744,10 +2752,6 @@ var walletTests = []walletTestCase{
name: "single funding workflow external funding tx", name: "single funding workflow external funding tx",
test: testSingleFunderExternalFundingTx, test: testSingleFunderExternalFundingTx,
}, },
{
name: "dual funder workflow",
test: testDualFundingReservationWorkflow,
},
{ {
name: "output locking", name: "output locking",
test: testFundingTransactionLockedOutputs, test: testFundingTransactionLockedOutputs,
+1 -1
View File
@@ -775,7 +775,7 @@ func (l *LightningWallet) handleFundingReserveRequest(req *InitFundingReserveMsg
FeeRate: req.FundingFeePerKw, FeeRate: req.FundingFeePerKw,
ChangeAddr: func() (btcutil.Address, error) { ChangeAddr: func() (btcutil.Address, error) {
return l.NewAddress( return l.NewAddress(
WitnessPubKey, true, DefaultAccountName, TaprootPubkey, true, DefaultAccountName,
) )
}, },
} }
+1 -1
View File
@@ -1330,7 +1330,7 @@ func (r *rpcServer) SendCoins(ctx context.Context,
// ensures this is an address the wallet knows about, // ensures this is an address the wallet knows about,
// allowing us to pass the reserved value check. // allowing us to pass the reserved value check.
changeAddr, err := r.server.cc.Wallet.NewAddress( changeAddr, err := r.server.cc.Wallet.NewAddress(
lnwallet.WitnessPubKey, true, lnwallet.TaprootPubkey, true,
lnwallet.DefaultAccountName, lnwallet.DefaultAccountName,
) )
if err != nil { if err != nil {
+2 -1
View File
@@ -4534,7 +4534,8 @@ func newSweepPkScriptGen(
return func() ([]byte, error) { return func() ([]byte, error) {
sweepAddr, err := wallet.NewAddress( sweepAddr, err := wallet.NewAddress(
lnwallet.WitnessPubKey, false, lnwallet.DefaultAccountName, lnwallet.TaprootPubkey, false,
lnwallet.DefaultAccountName,
) )
if err != nil { if err != nil {
return nil, err return nil, err
+1 -1
View File
@@ -139,7 +139,7 @@ func newTxInputSet(wallet Wallet, feePerKW chainfee.SatPerKWeight,
func (t *txInputSet) enoughInput() bool { func (t *txInputSet) enoughInput() bool {
// If we have a change output above dust, then we certainly have enough // If we have a change output above dust, then we certainly have enough
// inputs to the transaction. // inputs to the transaction.
if t.changeOutput >= lnwallet.DustLimitForSize(input.P2WPKHSize) { if t.changeOutput >= lnwallet.DustLimitForSize(input.P2TRSize) {
return true return true
} }
+2 -2
View File
@@ -111,8 +111,8 @@ func generateInputPartitionings(sweepableInputs []txInput,
// continuing with the remaining inputs will only lead to sets // continuing with the remaining inputs will only lead to sets
// with an even lower output value. // with an even lower output value.
if !txInputs.enoughInput() { if !txInputs.enoughInput() {
// The change output is always a p2wpkh here. // The change output is always a p2tr here.
dl := lnwallet.DustLimitForSize(input.P2WPKHSize) dl := lnwallet.DustLimitForSize(input.P2TRSize)
log.Debugf("Set value %v (r=%v, c=%v) below dust "+ log.Debugf("Set value %v (r=%v, c=%v) below dust "+
"limit of %v", txInputs.totalOutput(), "limit of %v", txInputs.totalOutput(),
txInputs.requiredOutput, txInputs.changeOutput, txInputs.requiredOutput, txInputs.changeOutput,
+12 -3
View File
@@ -10,6 +10,7 @@ import (
"github.com/btcsuite/btcd/btcutil/txsort" "github.com/btcsuite/btcd/btcutil/txsort"
"github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/input" "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"
@@ -228,8 +229,8 @@ func (p *JusticeDescriptor) assembleJusticeTxn(txWeight int64,
i := inputIndex[inp.outPoint] i := inputIndex[inp.outPoint]
justiceTxn.TxIn[i].Witness = inp.witness justiceTxn.TxIn[i].Witness = inp.witness
// Validate the reconstructed witnesses to ensure they are valid // Validate the reconstructed witnesses to ensure they are
// for the breached inputs. // valid for the breached inputs.
vm, err := txscript.NewEngine( vm, err := txscript.NewEngine(
inp.txOut.PkScript, justiceTxn, i, inp.txOut.PkScript, justiceTxn, i,
txscript.StandardVerifyFlags, txscript.StandardVerifyFlags,
@@ -239,7 +240,9 @@ func (p *JusticeDescriptor) assembleJusticeTxn(txWeight int64,
return nil, err return nil, err
} }
if err := vm.Execute(); err != nil { if err := vm.Execute(); err != nil {
return nil, err log.Debugf("Failed to validate justice transaction: %s",
spew.Sdump(justiceTxn))
return nil, fmt.Errorf("error validating TX: %v", err)
} }
} }
@@ -300,6 +303,9 @@ func (p *JusticeDescriptor) CreateJusticeTxn() (*wire.MsgTx, error) {
sweepInputs = append(sweepInputs, toLocalInput) sweepInputs = append(sweepInputs, toLocalInput)
log.Debugf("Found to local witness output=%#v, stack=%v",
toLocalInput.txOut, toLocalInput.witness)
// 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
// output, we'll also try to assemble the output and add it to weight // output, we'll also try to assemble the output and add it to weight
// estimate if successful. // estimate if successful.
@@ -310,6 +316,9 @@ func (p *JusticeDescriptor) CreateJusticeTxn() (*wire.MsgTx, error) {
} }
sweepInputs = append(sweepInputs, toRemoteInput) sweepInputs = append(sweepInputs, toRemoteInput)
log.Debugf("Found to remote witness output=%#v, stack=%v",
toRemoteInput.txOut, toRemoteInput.witness)
if p.JusticeKit.BlobType.IsAnchorChannel() { if p.JusticeKit.BlobType.IsAnchorChannel() {
weightEstimate.AddWitnessInput(input.ToRemoteConfirmedWitnessSize) weightEstimate.AddWitnessInput(input.ToRemoteConfirmedWitnessSize)
} else { } else {
+46 -3
View File
@@ -7,6 +7,7 @@ import (
"github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/btcutil/txsort" "github.com/btcsuite/btcd/btcutil/txsort"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb"
@@ -151,6 +152,42 @@ func (t *backupTask) inputs() map[wire.OutPoint]input.Input {
return inputs return inputs
} }
// addrType returns the type of an address after parsing it and matching it to
// the set of known script templates.
func addrType(pkScript []byte) txscript.ScriptClass {
// We pass in a set of dummy chain params here as they're only needed
// to make the address struct, which we're ignoring anyway (scripts are
// always the same, it's addresses that change across chains).
scriptClass, _, _, _ := txscript.ExtractPkScriptAddrs(
pkScript, &chaincfg.MainNetParams,
)
return scriptClass
}
// addScriptWeight parses the passed pkScript and adds the computed weight cost
// were the script to be added to the justice transaction.
func addScriptWeight(weightEstimate *input.TxWeightEstimator,
pkScript []byte) error {
switch addrType(pkScript) { //nolint: whitespace
case txscript.WitnessV0PubKeyHashTy:
weightEstimate.AddP2WKHOutput()
case txscript.WitnessV0ScriptHashTy:
weightEstimate.AddP2WSHOutput()
case txscript.WitnessV1TaprootTy:
weightEstimate.AddP2TROutput()
default:
return fmt.Errorf("invalid addr type: %v", addrType(pkScript))
}
return nil
}
// bindSession determines if the backupTask is compatible with the passed // bindSession determines if the backupTask is compatible with the passed
// SessionInfo's policy. If no error is returned, the task has been bound to the // SessionInfo's policy. If no error is returned, the task has been bound to the
// session and can be queued to upload to the tower. Otherwise, the bind failed // session and can be queued to upload to the tower. Otherwise, the bind failed
@@ -192,13 +229,19 @@ func (t *backupTask) bindSession(session *wtdb.ClientSessionBody) error {
} }
} }
// All justice transactions have a p2wkh output paying to the victim. // All justice transactions will either use segwit v0 (p2wkh + p2wsh)
weightEstimate.AddP2WKHOutput() // or segwit v1 (p2tr).
if err := addScriptWeight(&weightEstimate, t.sweepPkScript); err != nil {
return err
}
// If the justice transaction has a reward output, add the output's // If the justice transaction has a reward output, add the output's
// contribution to the weight estimate. // contribution to the weight estimate.
if session.Policy.BlobType.Has(blob.FlagReward) { if session.Policy.BlobType.Has(blob.FlagReward) {
weightEstimate.AddP2WKHOutput() err := addScriptWeight(&weightEstimate, session.RewardPkScript)
if err != nil {
return err
}
} }
if t.chanType.HasAnchors() != session.Policy.IsAnchorChannel() { if t.chanType.HasAnchors() != session.Policy.IsAnchorChannel() {
@@ -247,7 +247,7 @@ func genTaskTest(
RewardPkScript: rewardScript, RewardPkScript: rewardScript,
}, },
bindErr: bindErr, bindErr: bindErr,
expSweepScript: makeAddrSlice(22), expSweepScript: sweepAddr,
signer: signer, signer: signer,
chanType: chanType, chanType: chanType,
} }
@@ -259,10 +259,18 @@ var (
blobTypeCommitReward = (blob.FlagCommitOutputs | blob.FlagReward).Type() blobTypeCommitReward = (blob.FlagCommitOutputs | blob.FlagReward).Type()
addr, _ = btcutil.DecodeAddress( addr, _ = btcutil.DecodeAddress(
"mrX9vMRYLfVy1BnZbc5gZjuyaqH3ZW2ZHz", &chaincfg.TestNet3Params, "tb1pw8gzj8clt3v5lxykpgacpju5n8xteskt7gxhmudu6pa70nwfhe6s3unsyk",
&chaincfg.TestNet3Params,
) )
addrScript, _ = txscript.PayToAddrScript(addr) addrScript, _ = txscript.PayToAddrScript(addr)
sweepAddrScript, _ = btcutil.DecodeAddress(
"tb1qs3jyc9sf5kak3x0w99cav9u605aeu3t600xxx0",
&chaincfg.TestNet3Params,
)
sweepAddr, _ = txscript.PayToAddrScript(sweepAddrScript)
) )
// TestBackupTaskBind tests the initialization and binding of a backupTask to a // TestBackupTaskBind tests the initialization and binding of a backupTask to a
@@ -297,9 +305,9 @@ func TestBackupTask(t *testing.T) {
expSweepCommitNoRewardBoth int64 = 299241 expSweepCommitNoRewardBoth int64 = 299241
expSweepCommitNoRewardLocal int64 = 199514 expSweepCommitNoRewardLocal int64 = 199514
expSweepCommitNoRewardRemote int64 = 99561 expSweepCommitNoRewardRemote int64 = 99561
expSweepCommitRewardBoth int64 = 296117 expSweepCommitRewardBoth int64 = 296069
expSweepCommitRewardLocal int64 = 197390 expSweepCommitRewardLocal int64 = 197342
expSweepCommitRewardRemote int64 = 98437 expSweepCommitRewardRemote int64 = 98389
sweepFeeRateNoRewardRemoteDust chainfee.SatPerKWeight = 227500 sweepFeeRateNoRewardRemoteDust chainfee.SatPerKWeight = 227500
sweepFeeRateRewardRemoteDust chainfee.SatPerKWeight = 175350 sweepFeeRateRewardRemoteDust chainfee.SatPerKWeight = 175350
) )
@@ -307,9 +315,9 @@ func TestBackupTask(t *testing.T) {
expSweepCommitNoRewardBoth = 299236 expSweepCommitNoRewardBoth = 299236
expSweepCommitNoRewardLocal = 199513 expSweepCommitNoRewardLocal = 199513
expSweepCommitNoRewardRemote = 99557 expSweepCommitNoRewardRemote = 99557
expSweepCommitRewardBoth = 296112 expSweepCommitRewardBoth = 296064
expSweepCommitRewardLocal = 197389 expSweepCommitRewardLocal = 197341
expSweepCommitRewardRemote = 98433 expSweepCommitRewardRemote = 98385
sweepFeeRateNoRewardRemoteDust = 225400 sweepFeeRateNoRewardRemoteDust = 225400
sweepFeeRateRewardRemoteDust = 174100 sweepFeeRateRewardRemoteDust = 174100
} }
@@ -436,7 +444,7 @@ func TestBackupTask(t *testing.T) {
"commit reward, to-remote output only, creates dust", "commit reward, to-remote output only, creates dust",
1, // stateNum 1, // stateNum
0, // toLocalAmt 0, // toLocalAmt
100000, // toRemoteAmt 108221, // toRemoteAmt
blobTypeCommitReward, // blobType blobTypeCommitReward, // blobType
sweepFeeRateRewardRemoteDust, // sweepFeeRate sweepFeeRateRewardRemoteDust, // sweepFeeRate
addrScript, // rewardScript addrScript, // rewardScript
+2 -1
View File
@@ -58,7 +58,8 @@ var (
// addr is the server's reward address given to watchtower clients. // addr is the server's reward address given to watchtower clients.
addr, _ = btcutil.DecodeAddress( addr, _ = btcutil.DecodeAddress(
"mrX9vMRYLfVy1BnZbc5gZjuyaqH3ZW2ZHz", &chaincfg.TestNet3Params, "tb1pw8gzj8clt3v5lxykpgacpju5n8xteskt7gxhmudu6pa70nwfhe6s3unsyk",
&chaincfg.TestNet3Params,
) )
addrScript, _ = txscript.PayToAddrScript(addr) addrScript, _ = txscript.PayToAddrScript(addr)
+27 -28
View File
@@ -6,7 +6,6 @@ import (
"github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwallet/chainfee"
"github.com/lightningnetwork/lnd/watchtower/blob" "github.com/lightningnetwork/lnd/watchtower/blob"
@@ -156,7 +155,7 @@ func (p Policy) Validate() error {
// of the justice transaction and subtracting an amount that satisfies the // of the justice transaction and subtracting an amount that satisfies the
// policy's fee rate. // policy's fee rate.
func (p *Policy) ComputeAltruistOutput(totalAmt btcutil.Amount, func (p *Policy) ComputeAltruistOutput(totalAmt btcutil.Amount,
txWeight int64) (btcutil.Amount, error) { txWeight int64, sweepScript []byte) (btcutil.Amount, error) {
txFee := p.SweepFeeRate.FeeForWeight(txWeight) txFee := p.SweepFeeRate.FeeForWeight(txWeight)
if txFee > totalAmt { if txFee > totalAmt {
@@ -165,10 +164,9 @@ func (p *Policy) ComputeAltruistOutput(totalAmt btcutil.Amount,
sweepAmt := totalAmt - txFee sweepAmt := totalAmt - txFee
// TODO(conner): replace w/ configurable dust limit // Check that the created outputs won't be dusty. We'll base the dust
// Check that the created outputs won't be dusty. The sweep pkscript is // computation on the type of the script itself.
// currently a p2wpkh, so we'll use that script's dust limit. if sweepAmt < lnwallet.DustLimitForSize(len(sweepScript)) {
if sweepAmt < lnwallet.DustLimitForSize(input.P2WPKHSize) {
return 0, ErrCreatesDust return 0, ErrCreatesDust
} }
@@ -180,7 +178,8 @@ func (p *Policy) ComputeAltruistOutput(totalAmt btcutil.Amount,
// and reward rate. The reward to he tower is subtracted first, before // and reward rate. The reward to he tower is subtracted first, before
// splitting the remaining balance amongst the victim and fees. // splitting the remaining balance amongst the victim and fees.
func (p *Policy) ComputeRewardOutputs(totalAmt btcutil.Amount, func (p *Policy) ComputeRewardOutputs(totalAmt btcutil.Amount,
txWeight int64) (btcutil.Amount, btcutil.Amount, error) { txWeight int64,
rewardScript []byte) (btcutil.Amount, btcutil.Amount, error) {
txFee := p.SweepFeeRate.FeeForWeight(txWeight) txFee := p.SweepFeeRate.FeeForWeight(txWeight)
if txFee > totalAmt { if txFee > totalAmt {
@@ -198,10 +197,9 @@ func (p *Policy) ComputeRewardOutputs(totalAmt btcutil.Amount,
// input value. // input value.
sweepAmt := totalAmt - rewardAmt - txFee sweepAmt := totalAmt - rewardAmt - txFee
// TODO(conner): replace w/ configurable dust limit // Check that the created outputs won't be dusty. We'll base the dust
// Check that the created outputs won't be dusty. The sweep pkscript is // computation on the type of the script itself.
// currently a p2wpkh, so we'll use that script's dust limit. if sweepAmt < lnwallet.DustLimitForSize(len(rewardScript)) {
if sweepAmt < lnwallet.DustLimitForSize(input.P2WPKHSize) {
return 0, 0, ErrCreatesDust return 0, 0, ErrCreatesDust
} }
@@ -231,15 +229,16 @@ func ComputeRewardAmount(total btcutil.Amount, base, rate uint32) btcutil.Amount
return rewardBase + proportional return rewardBase + proportional
} }
// ComputeJusticeTxOuts constructs the justice transaction outputs for the given // ComputeJusticeTxOuts constructs the justice transaction outputs for the
// policy. If the policy specifies a reward for the tower, there will be two // given policy. If the policy specifies a reward for the tower, there will be
// outputs paying to the victim and the tower. Otherwise there will be a single // two outputs paying to the victim and the tower. Otherwise there will be a
// output sweeping funds back to the victim. The totalAmt should be the sum of // single output sweeping funds back to the victim. The totalAmt should be the
// any inputs used in the transaction. The passed txWeight should include the // sum of any inputs used in the transaction. The passed txWeight should
// weight of the outputs for the justice transaction, which is dependent on // include the weight of the outputs for the justice transaction, which is
// whether the justice transaction has a reward. The sweepPkScript should be the // dependent on whether the justice transaction has a reward. The sweepPkScript
// pkScript of the victim to which funds will be recovered. The rewardPkScript // should be the pkScript of the victim to which funds will be recovered. The
// is the pkScript of the tower where its reward will be deposited, and will be // rewardPkScript is the pkScript of the tower where its reward will be
// deposited, and will be
// ignored if the blob type does not specify a reward. // ignored if the blob type does not specify a reward.
func (p *Policy) ComputeJusticeTxOuts(totalAmt btcutil.Amount, txWeight int64, func (p *Policy) ComputeJusticeTxOuts(totalAmt btcutil.Amount, txWeight int64,
sweepPkScript, rewardPkScript []byte) ([]*wire.TxOut, error) { sweepPkScript, rewardPkScript []byte) ([]*wire.TxOut, error) {
@@ -247,19 +246,19 @@ func (p *Policy) ComputeJusticeTxOuts(totalAmt btcutil.Amount, txWeight int64,
var outputs []*wire.TxOut var outputs []*wire.TxOut
// If the policy specifies a reward for the tower, compute a split of // If the policy specifies a reward for the tower, compute a split of
// the funds based on the policy's parameters. Otherwise, we will use an // the funds based on the policy's parameters. Otherwise, we will use
// the altruist output computation and sweep as much of the funds back // the altruist output computation and sweep as much of the funds
// to the victim as possible. // back to the victim as possible.
if p.BlobType.Has(blob.FlagReward) { if p.BlobType.Has(blob.FlagReward) {
// Using the total input amount and the transaction's weight, // Using the total input amount and the transaction's weight,
// compute the sweep and reward amounts. This corresponds to the // compute the sweep and reward amounts. This corresponds to
// amount returned to the victim and the amount paid to the // the amount returned to the victim and the amount paid to the
// tower, respectively. To do so, the required transaction fee // tower, respectively. To do so, the required transaction fee
// is subtracted from the total, and the remaining amount is // is subtracted from the total, and the remaining amount is
// divided according to the prenegotiated reward rate from the // divided according to the pre negotiated reward rate from the
// client's session info. // client's session info.
sweepAmt, rewardAmt, err := p.ComputeRewardOutputs( sweepAmt, rewardAmt, err := p.ComputeRewardOutputs(
totalAmt, txWeight, totalAmt, txWeight, rewardPkScript,
) )
if err != nil { if err != nil {
return nil, err return nil, err
@@ -280,7 +279,7 @@ func (p *Policy) ComputeJusticeTxOuts(totalAmt btcutil.Amount, txWeight int64,
// returned to the victim. To do so, the required transaction // returned to the victim. To do so, the required transaction
// fee is subtracted from the total input amount. // fee is subtracted from the total input amount.
sweepAmt, err := p.ComputeAltruistOutput( sweepAmt, err := p.ComputeAltruistOutput(
totalAmt, txWeight, totalAmt, txWeight, sweepPkScript,
) )
if err != nil { if err != nil {
return nil, err return nil, err
+2 -1
View File
@@ -22,7 +22,8 @@ import (
var ( var (
// addr is the server's reward address given to watchtower clients. // addr is the server's reward address given to watchtower clients.
addr, _ = btcutil.DecodeAddress( addr, _ = btcutil.DecodeAddress(
"mrX9vMRYLfVy1BnZbc5gZjuyaqH3ZW2ZHz", &chaincfg.TestNet3Params, "tb1pw8gzj8clt3v5lxykpgacpju5n8xteskt7gxhmudu6pa70nwfhe6s3unsyk",
&chaincfg.TestNet3Params,
) )
addrScript, _ = txscript.PayToAddrScript(addr) addrScript, _ = txscript.PayToAddrScript(addr)