htlcswitch: update test utilities to latest switch/link changes

This commit is contained in:
Olaoluwa Osuntokun 2017-06-17 00:03:30 +02:00
parent 399d193e2c
commit e477241de1
No known key found for this signature in database
GPG Key ID: 9CC5B105D03521A2
3 changed files with 179 additions and 100 deletions

View File

@ -105,6 +105,7 @@ func (m *circuitMap) remove(key circuitKey) (*paymentCircuit, error) {
if circuit.RefCount--; circuit.RefCount == 0 { if circuit.RefCount--; circuit.RefCount == 0 {
delete(m.circuits, key) delete(m.circuits, key)
} }
return circuit, nil return circuit, nil
} }

View File

@ -22,6 +22,9 @@ var (
chanID1 = lnwire.NewChanIDFromOutPoint(chanPoint1) chanID1 = lnwire.NewChanIDFromOutPoint(chanPoint1)
chanID2 = lnwire.NewChanIDFromOutPoint(chanPoint2) chanID2 = lnwire.NewChanIDFromOutPoint(chanPoint2)
aliceChanID = lnwire.NewShortChanIDFromInt(1)
bobChanID = lnwire.NewShortChanIDFromInt(2)
) )
// TestSwitchForward checks the ability of htlc switch to forward add/settle // TestSwitchForward checks the ability of htlc switch to forward add/settle
@ -32,8 +35,8 @@ func TestSwitchForward(t *testing.T) {
alicePeer := newMockServer(t, "alice") alicePeer := newMockServer(t, "alice")
bobPeer := newMockServer(t, "bob") bobPeer := newMockServer(t, "bob")
aliceChannelLink := newMockChannelLink(chanID1, alicePeer) aliceChannelLink := newMockChannelLink(chanID1, aliceChanID, alicePeer)
bobChannelLink := newMockChannelLink(chanID2, bobPeer) bobChannelLink := newMockChannelLink(chanID2, bobChanID, bobPeer)
s := New(Config{}) s := New(Config{})
s.Start() s.Start()
@ -44,13 +47,13 @@ func TestSwitchForward(t *testing.T) {
t.Fatalf("unable to add bob link: %v", err) t.Fatalf("unable to add bob link: %v", err)
} }
// Create request which should be forwarder from alice channel // Create request which should be forwarded from Alice channel link to
// link to bob channel link. // bob channel link.
preimage := [sha256.Size]byte{1} preimage := [sha256.Size]byte{1}
rhash := fastsha256.Sum256(preimage[:]) rhash := fastsha256.Sum256(preimage[:])
packet = newAddPacket( packet = newAddPacket(
aliceChannelLink.ChanID(), aliceChannelLink.ShortChanID(),
NewHopID(bobChannelLink.Peer().PubKey()), bobChannelLink.ShortChanID(),
&lnwire.UpdateAddHTLC{ &lnwire.UpdateAddHTLC{
PaymentHash: rhash, PaymentHash: rhash,
Amount: 1, Amount: 1,
@ -73,11 +76,11 @@ func TestSwitchForward(t *testing.T) {
t.Fatal("wrong amount of circuits") t.Fatal("wrong amount of circuits")
} }
// Create settle request pretending that bob link handled // Create settle request pretending that bob link handled the add htlc
// the add htlc request and sent the htlc settle request back. This // request and sent the htlc settle request back. This request should
// request should be forwarder back to alice link. // be forwarder back to Alice link.
packet = newSettlePacket( packet = newSettlePacket(
bobChannelLink.ChanID(), bobChannelLink.ShortChanID(),
&lnwire.UpdateFufillHTLC{ &lnwire.UpdateFufillHTLC{
PaymentPreimage: preimage, PaymentPreimage: preimage,
}, },
@ -92,7 +95,7 @@ func TestSwitchForward(t *testing.T) {
case <-aliceChannelLink.packets: case <-aliceChannelLink.packets:
break break
case <-time.After(time.Second): case <-time.After(time.Second):
t.Fatal("request was not propogated to channelPoint") t.Fatal("request was not propagated to channelPoint")
} }
if s.circuits.pending() != 0 { if s.circuits.pending() != 0 {
@ -108,8 +111,8 @@ func TestSwitchCancel(t *testing.T) {
alicePeer := newMockServer(t, "alice") alicePeer := newMockServer(t, "alice")
bobPeer := newMockServer(t, "bob") bobPeer := newMockServer(t, "bob")
aliceChannelLink := newMockChannelLink(chanID1, alicePeer) aliceChannelLink := newMockChannelLink(chanID1, aliceChanID, alicePeer)
bobChannelLink := newMockChannelLink(chanID2, bobPeer) bobChannelLink := newMockChannelLink(chanID2, bobChanID, bobPeer)
s := New(Config{}) s := New(Config{})
s.Start() s.Start()
@ -125,8 +128,8 @@ func TestSwitchCancel(t *testing.T) {
preimage := [sha256.Size]byte{1} preimage := [sha256.Size]byte{1}
rhash := fastsha256.Sum256(preimage[:]) rhash := fastsha256.Sum256(preimage[:])
request = newAddPacket( request = newAddPacket(
aliceChannelLink.ChanID(), aliceChannelLink.ShortChanID(),
NewHopID(bobChannelLink.Peer().PubKey()), bobChannelLink.ShortChanID(),
&lnwire.UpdateAddHTLC{ &lnwire.UpdateAddHTLC{
PaymentHash: rhash, PaymentHash: rhash,
Amount: 1, Amount: 1,
@ -153,7 +156,7 @@ func TestSwitchCancel(t *testing.T) {
// the add htlc request and sent the htlc settle request back. This // the add htlc request and sent the htlc settle request back. This
// request should be forwarder back to alice channel link. // request should be forwarder back to alice channel link.
request = newFailPacket( request = newFailPacket(
bobChannelLink.ChanID(), bobChannelLink.ShortChanID(),
&lnwire.UpdateFailHTLC{}, &lnwire.UpdateFailHTLC{},
rhash, 1) rhash, 1)
@ -182,8 +185,8 @@ func TestSwitchAddSamePayment(t *testing.T) {
alicePeer := newMockServer(t, "alice") alicePeer := newMockServer(t, "alice")
bobPeer := newMockServer(t, "bob") bobPeer := newMockServer(t, "bob")
aliceChannelLink := newMockChannelLink(chanID1, alicePeer) aliceChannelLink := newMockChannelLink(chanID1, aliceChanID, alicePeer)
bobChannelLink := newMockChannelLink(chanID2, bobPeer) bobChannelLink := newMockChannelLink(chanID2, bobChanID, bobPeer)
s := New(Config{}) s := New(Config{})
s.Start() s.Start()
@ -199,8 +202,8 @@ func TestSwitchAddSamePayment(t *testing.T) {
preimage := [sha256.Size]byte{1} preimage := [sha256.Size]byte{1}
rhash := fastsha256.Sum256(preimage[:]) rhash := fastsha256.Sum256(preimage[:])
request = newAddPacket( request = newAddPacket(
aliceChannelLink.ChanID(), aliceChannelLink.ShortChanID(),
NewHopID(bobChannelLink.Peer().PubKey()), bobChannelLink.ShortChanID(),
&lnwire.UpdateAddHTLC{ &lnwire.UpdateAddHTLC{
PaymentHash: rhash, PaymentHash: rhash,
Amount: 1, Amount: 1,
@ -236,7 +239,7 @@ func TestSwitchAddSamePayment(t *testing.T) {
// the add htlc request and sent the htlc settle request back. This // the add htlc request and sent the htlc settle request back. This
// request should be forwarder back to alice channel link. // request should be forwarder back to alice channel link.
request = newFailPacket( request = newFailPacket(
bobChannelLink.ChanID(), bobChannelLink.ShortChanID(),
&lnwire.UpdateFailHTLC{}, &lnwire.UpdateFailHTLC{},
rhash, 1) rhash, 1)
@ -277,7 +280,7 @@ func TestSwitchAddSamePayment(t *testing.T) {
// users when response is came back from channel link. // users when response is came back from channel link.
func TestSwitchSendPayment(t *testing.T) { func TestSwitchSendPayment(t *testing.T) {
alicePeer := newMockServer(t, "alice") alicePeer := newMockServer(t, "alice")
aliceChannelLink := newMockChannelLink(chanID1, alicePeer) aliceChannelLink := newMockChannelLink(chanID1, aliceChanID, alicePeer)
s := New(Config{}) s := New(Config{})
s.Start() s.Start()
@ -334,15 +337,18 @@ func TestSwitchSendPayment(t *testing.T) {
t.Fatal("wrong amount of circuits") t.Fatal("wrong amount of circuits")
} }
// Create fail request pretending that bob channel link handled // Create fail request pretending that bob channel link handled the add
// the add htlc request with error and sent the htlc fail request // htlc request with error and sent the htlc fail request back. This
// back. This request should be forwarder back to alice channel link. // request should be forwarder back to alice channel link.
packet := newFailPacket(aliceChannelLink.ChanID(), packet := newFailPacket(
aliceChannelLink.ShortChanID(),
&lnwire.UpdateFailHTLC{ &lnwire.UpdateFailHTLC{
Reason: []byte{byte(lnwire.IncorrectValue)}, Reason: []byte{byte(lnwire.IncorrectValue)},
ID: 1, ID: 1,
}, },
rhash, 1) rhash,
1,
)
if err := s.forward(packet); err != nil { if err := s.forward(packet); err != nil {
t.Fatalf("can't forward htlc packet: %v", err) t.Fatalf("can't forward htlc packet: %v", err)

View File

@ -47,7 +47,7 @@ func generateRandomBytes(n int) ([]byte, error) {
// createTestChannel creates the channel and returns our and remote channels // createTestChannel creates the channel and returns our and remote channels
// representations. // representations.
func createTestChannel(alicePrivKey, bobPrivKey []byte, func createTestChannel(alicePrivKey, bobPrivKey []byte,
aliceAmount, bobAmount btcutil.Amount) ( aliceAmount, bobAmount btcutil.Amount, chanID lnwire.ShortChannelID) (
*lnwallet.LightningChannel, *lnwallet.LightningChannel, func(), error) { *lnwallet.LightningChannel, *lnwallet.LightningChannel, func(), error) {
aliceKeyPriv, aliceKeyPub := btcec.PrivKeyFromBytes(btcec.S256(), alicePrivKey) aliceKeyPriv, aliceKeyPub := btcec.PrivKeyFromBytes(btcec.S256(), alicePrivKey)
@ -167,6 +167,7 @@ func createTestChannel(alicePrivKey, bobPrivKey []byte,
RevocationStore: shachain.NewRevocationStore(), RevocationStore: shachain.NewRevocationStore(),
TheirDustLimit: bobDustLimit, TheirDustLimit: bobDustLimit,
OurDustLimit: aliceDustLimit, OurDustLimit: aliceDustLimit,
ShortChanID: chanID,
Db: dbAlice, Db: dbAlice,
} }
bobChannelState := &channeldb.OpenChannel{ bobChannelState := &channeldb.OpenChannel{
@ -193,6 +194,7 @@ func createTestChannel(alicePrivKey, bobPrivKey []byte,
RevocationStore: shachain.NewRevocationStore(), RevocationStore: shachain.NewRevocationStore(),
TheirDustLimit: aliceDustLimit, TheirDustLimit: aliceDustLimit,
OurDustLimit: bobDustLimit, OurDustLimit: bobDustLimit,
ShortChanID: chanID,
Db: dbBob, Db: dbBob,
} }
@ -243,8 +245,8 @@ func getChanID(msg lnwire.Message) lnwire.ChannelID {
// generatePayment generates the htlc add request by given path blob and // generatePayment generates the htlc add request by given path blob and
// invoice which should be added by destination peer. // invoice which should be added by destination peer.
func generatePayment(amount btcutil.Amount, blob [lnwire.OnionPacketSize]byte) ( func generatePayment(invoiceAmt, htlcAmt btcutil.Amount, timelock uint32,
*channeldb.Invoice, *lnwire.UpdateAddHTLC, error) { blob [lnwire.OnionPacketSize]byte) (*channeldb.Invoice, *lnwire.UpdateAddHTLC, error) {
// Initialize random seed with unix time in order to generate random // Initialize random seed with unix time in order to generate random
// preimage every time. // preimage every time.
@ -256,46 +258,42 @@ func generatePayment(amount btcutil.Amount, blob [lnwire.OnionPacketSize]byte) (
return nil, nil, err return nil, nil, err
} }
copy(preimage[:], r) copy(preimage[:], r)
rhash := fastsha256.Sum256(preimage[:]) rhash := fastsha256.Sum256(preimage[:])
// Generate and add the invoice in carol invoice registry as far as invoice := &channeldb.Invoice{
// htlc request should go to the
return &channeldb.Invoice{
CreationDate: time.Now(), CreationDate: time.Now(),
Terms: channeldb.ContractTerm{ Terms: channeldb.ContractTerm{
Value: amount, Value: invoiceAmt,
PaymentPreimage: preimage, PaymentPreimage: preimage,
}, },
}, }
&lnwire.UpdateAddHTLC{
htlc := &lnwire.UpdateAddHTLC{
PaymentHash: rhash, PaymentHash: rhash,
Amount: amount, Amount: htlcAmt,
Expiry: timelock,
OnionBlob: blob, OnionBlob: blob,
}, nil }
return invoice, htlc, nil
} }
// generateRoute generates the path blob by given array of peers. // generateRoute generates the path blob by given array of peers.
func generateRoute(peers []Peer) ([]byte, [lnwire.OnionPacketSize]byte, error) { func generateRoute(hops ...ForwardingInfo) ([lnwire.OnionPacketSize]byte, error) {
var blob [lnwire.OnionPacketSize]byte var blob [lnwire.OnionPacketSize]byte
if len(peers) == 0 { if len(hops) == 0 {
return nil, blob, errors.New("empty path") return blob, errors.New("empty path")
} }
// Create array of hops in order to create onion blob.
hops := make([]HopID, len(peers)-1)
for i, peer := range peers[1:] {
hops[i] = NewHopID(peer.PubKey())
}
// Initialize iterator and encode it.
var b bytes.Buffer
iterator := newMockHopIterator(hops...) iterator := newMockHopIterator(hops...)
if err := iterator.Encode(&b); err != nil {
return nil, blob, err
}
copy(blob[:], b.Bytes())
return peers[0].PubKey(), blob, nil w := bytes.NewBuffer(blob[0:0])
if err := iterator.EncodeNextHop(w); err != nil {
return blob, err
}
return blob, nil
} }
@ -313,6 +311,60 @@ type threeHopNetwork struct {
firstChannelCleanup func() firstChannelCleanup func()
secondChannelCleanup func() secondChannelCleanup func()
globalPolicy ForwardingPolicy
}
// generateHops...
func generateHops(payAmt btcutil.Amount,
path ...*channelLink) (btcutil.Amount, uint32, []ForwardingInfo) {
lastHop := path[len(path)-1]
var (
runningAmt btcutil.Amount = payAmt
totalTimelock uint32
)
hops := make([]ForwardingInfo, len(path))
for i := len(path) - 1; i >= 0; i-- {
nextHop := exitHop
if i != len(path)-1 {
nextHop = path[i+1].channel.ShortChanID()
}
timeLock := lastHop.cfg.FwrdingPolicy.TimeLockDelta
totalTimelock += timeLock
if i != len(path)-1 {
delta := path[i].cfg.FwrdingPolicy.TimeLockDelta
timeLock = totalTimelock - delta
}
amount := payAmt
if i != len(path)-1 {
prevHop := hops[i+1]
prevAmount := prevHop.AmountToForward
fee := ExpectedFee(path[i].cfg.FwrdingPolicy, prevAmount)
runningAmt += fee
if i == 0 {
amount = prevAmount
} else {
amount = prevAmount + fee
}
}
hops[i] = ForwardingInfo{
Network: BitcoinHop,
NextHop: nextHop,
AmountToForward: amount,
OutgoingCTLV: timeLock,
}
}
return runningAmt, totalTimelock, hops
} }
// makePayment takes the destination node and amount as input, sends the // makePayment takes the destination node and amount as input, sends the
@ -323,36 +375,37 @@ type threeHopNetwork struct {
// * from Alice to Bob // * from Alice to Bob
// * from Alice to Carol through the Bob // * from Alice to Carol through the Bob
// * from Alice to some another peer through the Bob // * from Alice to some another peer through the Bob
func (n *threeHopNetwork) makePayment(peers []Peer, func (n *threeHopNetwork) makePayment(sendingPeer, receivingPeer Peer,
amount btcutil.Amount) (*channeldb.Invoice, error) { firstHopPub [33]byte, hops []ForwardingInfo,
invoiceAmt, htlcAmt btcutil.Amount,
timelock uint32) (*channeldb.Invoice, error) {
// Extract sender peer. sender := sendingPeer.(*mockServer)
senderPeer := peers[0].(*mockServer) receiver := receivingPeer.(*mockServer)
peers = peers[1:]
// Generate route convert it to blob, and return next destination for // Generate route convert it to blob, and return next destination for
// htlc add request. // htlc add request.
firstNode, blob, err := generateRoute(peers) blob, err := generateRoute(hops...)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Generate payment: invoice and htlc. // Generate payment: invoice and htlc.
invoice, htlc, err := generatePayment(amount, blob) invoice, htlc, err := generatePayment(invoiceAmt, htlcAmt, timelock,
blob)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Check who is last in the route and add invoice to server registry. // Check who is last in the route and add invoice to server registry.
receiverPeer := peers[len(peers)-1].(*mockServer) if err := receiver.registry.AddInvoice(invoice); err != nil {
if err := receiverPeer.registry.AddInvoice(invoice); err != nil {
return nil, err return nil, err
} }
// Send payment and expose err channel. // Send payment and expose err channel.
errChan := make(chan error) errChan := make(chan error)
go func() { go func() {
_, err := senderPeer.htlcSwitch.SendHTLC(firstNode, htlc) _, err := sender.htlcSwitch.SendHTLC(firstHopPub, htlc)
errChan <- err errChan <- err
}() }()
@ -360,7 +413,7 @@ func (n *threeHopNetwork) makePayment(peers []Peer,
case err := <-errChan: case err := <-errChan:
return invoice, err return invoice, err
case <-time.After(12 * time.Second): case <-time.After(12 * time.Second):
return invoice, errors.New("htlc was no settled in time") return invoice, errors.New("htlc was not settled in time")
} }
} }
@ -431,63 +484,80 @@ func newThreeHopNetwork(t *testing.T, aliceToBob,
// route which htlc should follow. // route which htlc should follow.
decoder := &mockIteratorDecoder{} decoder := &mockIteratorDecoder{}
firstChanID := lnwire.NewShortChanIDFromInt(4)
secondChanID := lnwire.NewShortChanIDFromInt(5)
// Create lightning channels between Alice<->Bob and Bob<->Carol // Create lightning channels between Alice<->Bob and Bob<->Carol
aliceChannel, firstBobChannel, fCleanUp, err := createTestChannel( aliceChannel, firstBobChannel, fCleanUp, err := createTestChannel(
alicePrivKey, bobPrivKey, aliceToBob, aliceToBob) alicePrivKey, bobPrivKey, aliceToBob, aliceToBob, firstChanID)
if err != nil { if err != nil {
t.Fatalf("unable to create alice<->bob channel: %v", err) t.Fatalf("unable to create alice<->bob channel: %v", err)
} }
secondBobChannel, carolChannel, sCleanUp, err := createTestChannel( secondBobChannel, carolChannel, sCleanUp, err := createTestChannel(
bobPrivKey, carolPrivKey, bobToCarol, bobToCarol) bobPrivKey, carolPrivKey, bobToCarol, bobToCarol, secondChanID)
if err != nil { if err != nil {
t.Fatalf("unable to create bob<->carol channel: %v", err) t.Fatalf("unable to create bob<->carol channel: %v", err)
} }
globalPolicy := ForwardingPolicy{
MinHTLC: 5,
BaseFee: btcutil.Amount(1),
TimeLockDelta: 1,
}
aliceChannelLink := NewChannelLink( aliceChannelLink := NewChannelLink(
&ChannelLinkConfig{ ChannelLinkConfig{
// htlc responses will be sent to this node FwrdingPolicy: globalPolicy,
Peer: bobServer, Peer: bobServer,
// htlc will be propagated to this switch
Switch: aliceServer.htlcSwitch, Switch: aliceServer.htlcSwitch,
// route will be generated by this decoder
DecodeOnion: decoder.Decode, DecodeOnion: decoder.Decode,
Registry: aliceServer.registry, Registry: aliceServer.registry,
}, aliceChannel) },
aliceChannel,
)
if err := aliceServer.htlcSwitch.addLink(aliceChannelLink); err != nil { if err := aliceServer.htlcSwitch.addLink(aliceChannelLink); err != nil {
t.Fatalf("unable to add alice channel link: %v", err) t.Fatalf("unable to add alice channel link: %v", err)
} }
firstBobChannelLink := NewChannelLink( firstBobChannelLink := NewChannelLink(
&ChannelLinkConfig{ ChannelLinkConfig{
FwrdingPolicy: globalPolicy,
Peer: aliceServer, Peer: aliceServer,
Switch: bobServer.htlcSwitch, Switch: bobServer.htlcSwitch,
DecodeOnion: decoder.Decode, DecodeOnion: decoder.Decode,
Registry: bobServer.registry, Registry: bobServer.registry,
}, firstBobChannel) },
firstBobChannel,
)
if err := bobServer.htlcSwitch.addLink(firstBobChannelLink); err != nil { if err := bobServer.htlcSwitch.addLink(firstBobChannelLink); err != nil {
t.Fatalf("unable to add first bob channel link: %v", err) t.Fatalf("unable to add first bob channel link: %v", err)
} }
secondBobChannelLink := NewChannelLink( secondBobChannelLink := NewChannelLink(
&ChannelLinkConfig{ ChannelLinkConfig{
FwrdingPolicy: globalPolicy,
Peer: carolServer, Peer: carolServer,
Switch: bobServer.htlcSwitch, Switch: bobServer.htlcSwitch,
DecodeOnion: decoder.Decode, DecodeOnion: decoder.Decode,
Registry: bobServer.registry, Registry: bobServer.registry,
}, secondBobChannel) },
secondBobChannel,
)
if err := bobServer.htlcSwitch.addLink(secondBobChannelLink); err != nil { if err := bobServer.htlcSwitch.addLink(secondBobChannelLink); err != nil {
t.Fatalf("unable to add second bob channel link: %v", err) t.Fatalf("unable to add second bob channel link: %v", err)
} }
carolChannelLink := NewChannelLink( carolChannelLink := NewChannelLink(
&ChannelLinkConfig{ ChannelLinkConfig{
FwrdingPolicy: globalPolicy,
Peer: bobServer, Peer: bobServer,
Switch: carolServer.htlcSwitch, Switch: carolServer.htlcSwitch,
DecodeOnion: decoder.Decode, DecodeOnion: decoder.Decode,
Registry: carolServer.registry, Registry: carolServer.registry,
}, carolChannel) },
carolChannel,
)
if err := carolServer.htlcSwitch.addLink(carolChannelLink); err != nil { if err := carolServer.htlcSwitch.addLink(carolChannelLink); err != nil {
t.Fatalf("unable to add carol channel link: %v", err) t.Fatalf("unable to add carol channel link: %v", err)
} }
@ -503,5 +573,7 @@ func newThreeHopNetwork(t *testing.T, aliceToBob,
firstChannelCleanup: fCleanUp, firstChannelCleanup: fCleanUp,
secondChannelCleanup: sCleanUp, secondChannelCleanup: sCleanUp,
globalPolicy: globalPolicy,
} }
} }