routing: add time lock asserts to NewRoute test

This comment extends the unit tests for NewRoute with checks
on the total time lock for a route as well as the expected time
lock values for every hop along the route.
This commit is contained in:
Joost Jager 2018-06-27 11:01:18 +02:00
parent d4471878df
commit 416f368979

@ -630,36 +630,72 @@ func TestNewRoute(t *testing.T) {
createHop := func(baseFee lnwire.MilliSatoshi, createHop := func(baseFee lnwire.MilliSatoshi,
feeRate lnwire.MilliSatoshi, feeRate lnwire.MilliSatoshi,
capacity btcutil.Amount) (*ChannelHop) { capacity btcutil.Amount,
timeLockDelta uint16) (*ChannelHop) {
return &ChannelHop { return &ChannelHop {
ChannelEdgePolicy: &channeldb.ChannelEdgePolicy { ChannelEdgePolicy: &channeldb.ChannelEdgePolicy {
Node: &channeldb.LightningNode{}, Node: &channeldb.LightningNode{},
FeeProportionalMillionths: feeRate, FeeProportionalMillionths: feeRate,
FeeBaseMSat: baseFee, FeeBaseMSat: baseFee,
TimeLockDelta: timeLockDelta,
}, },
Capacity: capacity, Capacity: capacity,
} }
} }
testCases := []struct { testCases := []struct {
name string // name identifies the test case in the test output.
hops []*ChannelHop name string
paymentAmount lnwire.MilliSatoshi
expectedFees []lnwire.MilliSatoshi // hops is the list of hops (the route) that gets passed into
expectedTotalAmount lnwire.MilliSatoshi // the call to newRoute.
expectError bool hops []*ChannelHop
expectedErrorCode errorCode
// paymentAmount is the amount that is send into the route
// indicated by hops.
paymentAmount lnwire.MilliSatoshi
// expectedFees is a list of fees that every hop is expected
// to charge for forwarding.
expectedFees []lnwire.MilliSatoshi
// expectedTimeLocks is a list of time lock values that every
// hop is expected to specify in its outgoing HTLC. The time
// lock values in this list are relative to the current block
// height.
expectedTimeLocks []uint32
// expectedTotalAmount is the total amount that is expected to
// be returned from newRoute. This amount should include all
// the fees to be paid to intermediate hops.
expectedTotalAmount lnwire.MilliSatoshi
// expectedTotalTimeLock is the time lock that is expected to
// be returned from newRoute. This is the time lock that should
// be specified in the HTLC that is sent by the source node.
// expectedTotalTimeLock is relative to the current block height.
expectedTotalTimeLock uint32
// expectError indicates whether the newRoute call is expected
// to fail or succeed.
expectError bool
// expectedErrorCode indicates the expected error code when
// expectError is true.
expectedErrorCode errorCode
} { } {
{ {
// For a single hop payment, no fees are expected to be paid. // For a single hop payment, no fees are expected to be paid.
name: "single hop", name: "single hop",
paymentAmount: 100000, paymentAmount: 100000,
hops: []*ChannelHop { hops: []*ChannelHop {
createHop(100, 1000, 1000), createHop(100, 1000, 1000, 10),
}, },
expectedFees: []lnwire.MilliSatoshi {0}, expectedFees: []lnwire.MilliSatoshi {0},
expectedTimeLocks: []uint32 {1},
expectedTotalAmount: 100000, expectedTotalAmount: 100000,
expectedTotalTimeLock: 1,
}, { }, {
// For a two hop payment, only the fee for the first hop // For a two hop payment, only the fee for the first hop
// needs to be paid. The destination hop does not require // needs to be paid. The destination hop does not require
@ -667,18 +703,20 @@ func TestNewRoute(t *testing.T) {
name: "two hop", name: "two hop",
paymentAmount: 100000, paymentAmount: 100000,
hops: []*ChannelHop { hops: []*ChannelHop {
createHop(0, 1000, 1000), createHop(0, 1000, 1000, 10),
createHop(30, 1000, 1000), createHop(30, 1000, 1000, 5),
}, },
expectedFees: []lnwire.MilliSatoshi {130, 0}, expectedFees: []lnwire.MilliSatoshi {130, 0},
expectedTimeLocks: []uint32 {1, 1},
expectedTotalAmount: 100130, expectedTotalAmount: 100130,
expectedTotalTimeLock: 6,
}, { }, {
// Insufficient capacity in first channel when fees are added. // Insufficient capacity in first channel when fees are added.
name: "two hop insufficient", name: "two hop insufficient",
paymentAmount: 100000, paymentAmount: 100000,
hops: []*ChannelHop { hops: []*ChannelHop {
createHop(0, 1000, 100), createHop(0, 1000, 100, 10),
createHop(0, 1000, 1000), createHop(0, 1000, 1000, 5),
}, },
expectError: true, expectError: true,
expectedErrorCode: ErrInsufficientCapacity, expectedErrorCode: ErrInsufficientCapacity,
@ -691,12 +729,14 @@ func TestNewRoute(t *testing.T) {
name: "three hop", name: "three hop",
paymentAmount: 100000, paymentAmount: 100000,
hops: []*ChannelHop { hops: []*ChannelHop {
createHop(0, 10, 1000), createHop(0, 10, 1000, 10),
createHop(0, 10, 1000), createHop(0, 10, 1000, 5),
createHop(0, 10, 1000), createHop(0, 10, 1000, 3),
}, },
expectedFees: []lnwire.MilliSatoshi {1, 1, 0}, expectedFees: []lnwire.MilliSatoshi {1, 1, 0},
expectedTotalAmount: 100002, expectedTotalAmount: 100002,
expectedTimeLocks: []uint32 {4, 1, 1},
expectedTotalTimeLock: 9,
}, { }, {
// A three hop payment where the fee of the first hop // A three hop payment where the fee of the first hop
// is slightly higher (11) than the fee at the second hop, // is slightly higher (11) than the fee at the second hop,
@ -704,12 +744,14 @@ func TestNewRoute(t *testing.T) {
name: "three hop with fee carry over", name: "three hop with fee carry over",
paymentAmount: 100000, paymentAmount: 100000,
hops: []*ChannelHop { hops: []*ChannelHop {
createHop(0, 10000, 1000), createHop(0, 10000, 1000, 10),
createHop(0, 10000, 1000), createHop(0, 10000, 1000, 5),
createHop(0, 10000, 1000), createHop(0, 10000, 1000, 3),
}, },
expectedFees: []lnwire.MilliSatoshi {1010, 1000, 0}, expectedFees: []lnwire.MilliSatoshi {1010, 1000, 0},
expectedTotalAmount: 102010, expectedTotalAmount: 102010,
expectedTimeLocks: []uint32 {4, 1, 1},
expectedTotalTimeLock: 9,
}, { }, {
// A three hop payment where the fee policies of the first and // A three hop payment where the fee policies of the first and
// second hop are just high enough to show the fee carry over // second hop are just high enough to show the fee carry over
@ -717,18 +759,20 @@ func TestNewRoute(t *testing.T) {
name: "three hop with minimal fees for carry over", name: "three hop with minimal fees for carry over",
paymentAmount: 100000, paymentAmount: 100000,
hops: []*ChannelHop { hops: []*ChannelHop {
createHop(0, 10000, 1000), createHop(0, 10000, 1000, 10),
// First hop charges 0.1% so the second hop fee // First hop charges 0.1% so the second hop fee
// should show up in the first hop fee as 1 msat // should show up in the first hop fee as 1 msat
// extra. // extra.
createHop(0, 1000, 1000), createHop(0, 1000, 1000, 5),
// Second hop charges a fixed 1000 msat. // Second hop charges a fixed 1000 msat.
createHop(1000, 0, 1000), createHop(1000, 0, 1000, 3),
}, },
expectedFees: []lnwire.MilliSatoshi {101, 1000, 0}, expectedFees: []lnwire.MilliSatoshi {101, 1000, 0},
expectedTotalAmount: 101101, expectedTotalAmount: 101101,
expectedTimeLocks: []uint32 {4, 1, 1},
expectedTotalTimeLock: 9,
} } } }
for _, testCase := range testCases { for _, testCase := range testCases {
@ -739,7 +783,7 @@ func TestNewRoute(t *testing.T) {
testCase.expectedTotalAmount, testCase.expectedTotalAmount,
route.TotalAmount) route.TotalAmount)
} }
for i := 0; i < len(testCase.expectedFees); i++ { for i := 0; i < len(testCase.expectedFees); i++ {
if testCase.expectedFees[i] != if testCase.expectedFees[i] !=
route.Hops[i].Fee { route.Hops[i].Fee {
@ -750,6 +794,31 @@ func TestNewRoute(t *testing.T) {
route.Hops[i].Fee) route.Hops[i].Fee)
} }
} }
expectedTimeLockHeight := startingHeight +
testCase.expectedTotalTimeLock
if route.TotalTimeLock != expectedTimeLockHeight {
t.Errorf("Expected total time lock to be %v" +
", but got %v instead",
expectedTimeLockHeight,
route.TotalTimeLock)
}
for i := 0; i < len(testCase.expectedTimeLocks); i++ {
expectedTimeLockHeight := startingHeight +
testCase.expectedTimeLocks[i]
if expectedTimeLockHeight !=
route.Hops[i].OutgoingTimeLock {
t.Errorf("Expected time lock for hop " +
"%v to be %v, but got %v instead",
i, expectedTimeLockHeight,
route.Hops[i].OutgoingTimeLock)
}
}
} }
t.Run(testCase.name, func(t *testing.T) { t.Run(testCase.name, func(t *testing.T) {