watchtower/wtpolicy: add basic validity constraints
This commit is contained in:
parent
37052f1561
commit
a543c781fe
@ -1069,6 +1069,10 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB,
|
||||
policy.SweepFeeRate = sweepRateSatPerByte.FeePerKWeight()
|
||||
}
|
||||
|
||||
if err := policy.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
s.towerClient, err = wtclient.New(&wtclient.Config{
|
||||
Signer: cc.wallet.Cfg.Signer,
|
||||
NewAddress: newSweepPkScriptGen(cc.wallet),
|
||||
|
@ -27,7 +27,11 @@ const (
|
||||
|
||||
// DefaultSweepFeeRate specifies the fee rate used to construct justice
|
||||
// transactions. The value is expressed in satoshis per kilo-weight.
|
||||
DefaultSweepFeeRate = 3000
|
||||
DefaultSweepFeeRate = lnwallet.SatPerKWeight(12000)
|
||||
|
||||
// MinSweepFeeRate is the minimum sweep fee rate a client may use in its
|
||||
// policy, the current value is 4 sat/kw.
|
||||
MinSweepFeeRate = lnwallet.SatPerKWeight(4000)
|
||||
)
|
||||
|
||||
var (
|
||||
@ -43,6 +47,17 @@ var (
|
||||
// ErrCreatesDust signals that the session's policy would create a dust
|
||||
// output for the victim.
|
||||
ErrCreatesDust = errors.New("justice transaction creates dust at fee rate")
|
||||
|
||||
// ErrAltruistReward signals that the policy is invalid because it
|
||||
// contains a non-zero RewardBase or RewardRate on an altruist policy.
|
||||
ErrAltruistReward = errors.New("altruist policy has reward params")
|
||||
|
||||
// ErrNoMaxUpdates signals that the policy specified zero MaxUpdates.
|
||||
ErrNoMaxUpdates = errors.New("max updates must be positive")
|
||||
|
||||
// ErrSweepFeeRateTooLow signals that the policy's fee rate is too low
|
||||
// to get into the mempool during low congestion.
|
||||
ErrSweepFeeRateTooLow = errors.New("sweep fee rate too low")
|
||||
)
|
||||
|
||||
// DefaultPolicy returns a Policy containing the default parameters that can be
|
||||
@ -50,11 +65,8 @@ var (
|
||||
func DefaultPolicy() Policy {
|
||||
return Policy{
|
||||
TxPolicy: TxPolicy{
|
||||
BlobType: blob.TypeAltruistCommit,
|
||||
RewardRate: DefaultRewardRate,
|
||||
SweepFeeRate: lnwallet.SatPerKWeight(
|
||||
DefaultSweepFeeRate,
|
||||
),
|
||||
BlobType: blob.TypeAltruistCommit,
|
||||
SweepFeeRate: DefaultSweepFeeRate,
|
||||
},
|
||||
MaxUpdates: DefaultMaxUpdates,
|
||||
}
|
||||
@ -107,6 +119,31 @@ func (p Policy) String() string {
|
||||
p.SweepFeeRate)
|
||||
}
|
||||
|
||||
// Validate ensures that the policy satisfies some minimal correctness
|
||||
// constraints.
|
||||
func (p Policy) Validate() error {
|
||||
// RewardBase and RewardRate should not be set if the policy doesn't
|
||||
// have a reward.
|
||||
if !p.BlobType.Has(blob.FlagReward) &&
|
||||
(p.RewardBase != 0 || p.RewardRate != 0) {
|
||||
|
||||
return ErrAltruistReward
|
||||
}
|
||||
|
||||
// MaxUpdates must be positive.
|
||||
if p.MaxUpdates == 0 {
|
||||
return ErrNoMaxUpdates
|
||||
}
|
||||
|
||||
// SweepFeeRate must be sane enough to get in the mempool during low
|
||||
// congestion.
|
||||
if p.SweepFeeRate < MinSweepFeeRate {
|
||||
return ErrSweepFeeRateTooLow
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ComputeAltruistOutput computes the lone output value of a justice transaction
|
||||
// that pays no reward to the tower. The value is computed using the weight of
|
||||
// of the justice transaction and subtracting an amount that satisfies the
|
||||
|
93
watchtower/wtpolicy/policy_test.go
Normal file
93
watchtower/wtpolicy/policy_test.go
Normal file
@ -0,0 +1,93 @@
|
||||
package wtpolicy_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/lightningnetwork/lnd/watchtower/blob"
|
||||
"github.com/lightningnetwork/lnd/watchtower/wtpolicy"
|
||||
)
|
||||
|
||||
var validationTests = []struct {
|
||||
name string
|
||||
policy wtpolicy.Policy
|
||||
expErr error
|
||||
}{
|
||||
{
|
||||
name: "fail no maxupdates",
|
||||
policy: wtpolicy.Policy{
|
||||
TxPolicy: wtpolicy.TxPolicy{
|
||||
BlobType: blob.TypeAltruistCommit,
|
||||
},
|
||||
},
|
||||
expErr: wtpolicy.ErrNoMaxUpdates,
|
||||
},
|
||||
{
|
||||
name: "fail altruist with reward base",
|
||||
policy: wtpolicy.Policy{
|
||||
TxPolicy: wtpolicy.TxPolicy{
|
||||
BlobType: blob.TypeAltruistCommit,
|
||||
RewardBase: 1,
|
||||
},
|
||||
},
|
||||
expErr: wtpolicy.ErrAltruistReward,
|
||||
},
|
||||
{
|
||||
name: "fail altruist with reward rate",
|
||||
policy: wtpolicy.Policy{
|
||||
TxPolicy: wtpolicy.TxPolicy{
|
||||
BlobType: blob.TypeAltruistCommit,
|
||||
RewardRate: 1,
|
||||
},
|
||||
},
|
||||
expErr: wtpolicy.ErrAltruistReward,
|
||||
},
|
||||
{
|
||||
name: "fail sweep fee rate too low",
|
||||
policy: wtpolicy.Policy{
|
||||
TxPolicy: wtpolicy.TxPolicy{
|
||||
BlobType: blob.TypeAltruistCommit,
|
||||
},
|
||||
MaxUpdates: 1,
|
||||
},
|
||||
expErr: wtpolicy.ErrSweepFeeRateTooLow,
|
||||
},
|
||||
{
|
||||
name: "minimal valid altruist policy",
|
||||
policy: wtpolicy.Policy{
|
||||
TxPolicy: wtpolicy.TxPolicy{
|
||||
BlobType: blob.TypeAltruistCommit,
|
||||
SweepFeeRate: wtpolicy.MinSweepFeeRate,
|
||||
},
|
||||
MaxUpdates: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid altruist policy with default sweep rate",
|
||||
policy: wtpolicy.Policy{
|
||||
TxPolicy: wtpolicy.TxPolicy{
|
||||
BlobType: blob.TypeAltruistCommit,
|
||||
SweepFeeRate: wtpolicy.DefaultSweepFeeRate,
|
||||
},
|
||||
MaxUpdates: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid default policy",
|
||||
policy: wtpolicy.DefaultPolicy(),
|
||||
},
|
||||
}
|
||||
|
||||
// TestPolicyValidate asserts that the sanity checks for policies behave as
|
||||
// expected.
|
||||
func TestPolicyValidate(t *testing.T) {
|
||||
for i := range validationTests {
|
||||
test := validationTests[i]
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
err := test.policy.Validate()
|
||||
if err != test.expErr {
|
||||
t.Fatalf("validation error mismatch, "+
|
||||
"want: %v, got: %v", test.expErr, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user