2017-05-01 19:58:08 +03:00
|
|
|
package htlcswitch
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"crypto/sha256"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/btcsuite/fastsha256"
|
|
|
|
"github.com/go-errors/errors"
|
|
|
|
"github.com/lightningnetwork/lnd/lnwire"
|
|
|
|
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
|
|
|
"github.com/roasbeef/btcd/wire"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
hash1, _ = chainhash.NewHash(bytes.Repeat([]byte("a"), 32))
|
|
|
|
hash2, _ = chainhash.NewHash(bytes.Repeat([]byte("b"), 32))
|
|
|
|
|
|
|
|
chanPoint1 = wire.NewOutPoint(hash1, 0)
|
|
|
|
chanPoint2 = wire.NewOutPoint(hash2, 0)
|
|
|
|
|
|
|
|
chanID1 = lnwire.NewChanIDFromOutPoint(chanPoint1)
|
|
|
|
chanID2 = lnwire.NewChanIDFromOutPoint(chanPoint2)
|
2017-06-17 01:03:30 +03:00
|
|
|
|
|
|
|
aliceChanID = lnwire.NewShortChanIDFromInt(1)
|
|
|
|
bobChanID = lnwire.NewShortChanIDFromInt(2)
|
2017-05-01 19:58:08 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
// TestSwitchForward checks the ability of htlc switch to forward add/settle
|
|
|
|
// requests.
|
|
|
|
func TestSwitchForward(t *testing.T) {
|
|
|
|
var packet *htlcPacket
|
|
|
|
|
|
|
|
alicePeer := newMockServer(t, "alice")
|
|
|
|
bobPeer := newMockServer(t, "bob")
|
|
|
|
|
2017-06-17 01:03:30 +03:00
|
|
|
aliceChannelLink := newMockChannelLink(chanID1, aliceChanID, alicePeer)
|
|
|
|
bobChannelLink := newMockChannelLink(chanID2, bobChanID, bobPeer)
|
2017-05-01 19:58:08 +03:00
|
|
|
|
|
|
|
s := New(Config{})
|
|
|
|
s.Start()
|
|
|
|
if err := s.AddLink(aliceChannelLink); err != nil {
|
|
|
|
t.Fatalf("unable to add alice link: %v", err)
|
|
|
|
}
|
|
|
|
if err := s.AddLink(bobChannelLink); err != nil {
|
|
|
|
t.Fatalf("unable to add bob link: %v", err)
|
|
|
|
}
|
|
|
|
|
2017-06-17 01:03:30 +03:00
|
|
|
// Create request which should be forwarded from Alice channel link to
|
|
|
|
// bob channel link.
|
2017-05-01 19:58:08 +03:00
|
|
|
preimage := [sha256.Size]byte{1}
|
|
|
|
rhash := fastsha256.Sum256(preimage[:])
|
|
|
|
packet = newAddPacket(
|
2017-06-17 01:03:30 +03:00
|
|
|
aliceChannelLink.ShortChanID(),
|
|
|
|
bobChannelLink.ShortChanID(),
|
2017-05-01 19:58:08 +03:00
|
|
|
&lnwire.UpdateAddHTLC{
|
|
|
|
PaymentHash: rhash,
|
|
|
|
Amount: 1,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
// Handle the request and checks that bob channel link received it.
|
|
|
|
if err := s.forward(packet); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-bobChannelLink.packets:
|
|
|
|
break
|
|
|
|
case <-time.After(time.Second):
|
|
|
|
t.Fatal("request was not propogated to destination")
|
|
|
|
}
|
|
|
|
|
|
|
|
if s.circuits.pending() != 1 {
|
|
|
|
t.Fatal("wrong amount of circuits")
|
|
|
|
}
|
|
|
|
|
2017-06-17 01:03:30 +03:00
|
|
|
// Create settle request pretending that bob link handled the add htlc
|
|
|
|
// request and sent the htlc settle request back. This request should
|
|
|
|
// be forwarder back to Alice link.
|
2017-05-01 19:58:08 +03:00
|
|
|
packet = newSettlePacket(
|
2017-06-17 01:03:30 +03:00
|
|
|
bobChannelLink.ShortChanID(),
|
2017-05-01 19:58:08 +03:00
|
|
|
&lnwire.UpdateFufillHTLC{
|
|
|
|
PaymentPreimage: preimage,
|
|
|
|
},
|
|
|
|
rhash, 1)
|
|
|
|
|
|
|
|
// Handle the request and checks that payment circuit works properly.
|
|
|
|
if err := s.forward(packet); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-aliceChannelLink.packets:
|
|
|
|
break
|
|
|
|
case <-time.After(time.Second):
|
2017-06-17 01:03:30 +03:00
|
|
|
t.Fatal("request was not propagated to channelPoint")
|
2017-05-01 19:58:08 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if s.circuits.pending() != 0 {
|
|
|
|
t.Fatal("wrong amount of circuits")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestSwitchCancel checks that if htlc was rejected we remove unused
|
|
|
|
// circuits.
|
|
|
|
func TestSwitchCancel(t *testing.T) {
|
|
|
|
var request *htlcPacket
|
|
|
|
|
|
|
|
alicePeer := newMockServer(t, "alice")
|
|
|
|
bobPeer := newMockServer(t, "bob")
|
|
|
|
|
2017-06-17 01:03:30 +03:00
|
|
|
aliceChannelLink := newMockChannelLink(chanID1, aliceChanID, alicePeer)
|
|
|
|
bobChannelLink := newMockChannelLink(chanID2, bobChanID, bobPeer)
|
2017-05-01 19:58:08 +03:00
|
|
|
|
|
|
|
s := New(Config{})
|
|
|
|
s.Start()
|
|
|
|
if err := s.AddLink(aliceChannelLink); err != nil {
|
|
|
|
t.Fatalf("unable to add alice link: %v", err)
|
|
|
|
}
|
|
|
|
if err := s.AddLink(bobChannelLink); err != nil {
|
|
|
|
t.Fatalf("unable to add bob link: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create request which should be forwarder from alice channel link
|
|
|
|
// to bob channel link.
|
|
|
|
preimage := [sha256.Size]byte{1}
|
|
|
|
rhash := fastsha256.Sum256(preimage[:])
|
|
|
|
request = newAddPacket(
|
2017-06-17 01:03:30 +03:00
|
|
|
aliceChannelLink.ShortChanID(),
|
|
|
|
bobChannelLink.ShortChanID(),
|
2017-05-01 19:58:08 +03:00
|
|
|
&lnwire.UpdateAddHTLC{
|
|
|
|
PaymentHash: rhash,
|
|
|
|
Amount: 1,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
// Handle the request and checks that bob channel link received it.
|
|
|
|
if err := s.forward(request); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-bobChannelLink.packets:
|
|
|
|
break
|
|
|
|
case <-time.After(time.Second):
|
|
|
|
t.Fatal("request was not propogated to destination")
|
|
|
|
}
|
|
|
|
|
|
|
|
if s.circuits.pending() != 1 {
|
|
|
|
t.Fatal("wrong amount of circuits")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create settle request pretending that bob channel link handled
|
|
|
|
// the add htlc request and sent the htlc settle request back. This
|
|
|
|
// request should be forwarder back to alice channel link.
|
|
|
|
request = newFailPacket(
|
2017-06-17 01:03:30 +03:00
|
|
|
bobChannelLink.ShortChanID(),
|
2017-05-01 19:58:08 +03:00
|
|
|
&lnwire.UpdateFailHTLC{},
|
|
|
|
rhash, 1)
|
|
|
|
|
|
|
|
// Handle the request and checks that payment circuit works properly.
|
|
|
|
if err := s.forward(request); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-aliceChannelLink.packets:
|
|
|
|
break
|
|
|
|
case <-time.After(time.Second):
|
|
|
|
t.Fatal("request was not propogated to channelPoint")
|
|
|
|
}
|
|
|
|
|
|
|
|
if s.circuits.pending() != 0 {
|
|
|
|
t.Fatal("wrong amount of circuits")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestSwitchAddSamePayment tests that we send the payment with the same
|
|
|
|
// payment hash.
|
|
|
|
func TestSwitchAddSamePayment(t *testing.T) {
|
|
|
|
var request *htlcPacket
|
|
|
|
|
|
|
|
alicePeer := newMockServer(t, "alice")
|
|
|
|
bobPeer := newMockServer(t, "bob")
|
|
|
|
|
2017-06-17 01:03:30 +03:00
|
|
|
aliceChannelLink := newMockChannelLink(chanID1, aliceChanID, alicePeer)
|
|
|
|
bobChannelLink := newMockChannelLink(chanID2, bobChanID, bobPeer)
|
2017-05-01 19:58:08 +03:00
|
|
|
|
|
|
|
s := New(Config{})
|
|
|
|
s.Start()
|
|
|
|
if err := s.AddLink(aliceChannelLink); err != nil {
|
|
|
|
t.Fatalf("unable to add alice link: %v", err)
|
|
|
|
}
|
|
|
|
if err := s.AddLink(bobChannelLink); err != nil {
|
|
|
|
t.Fatalf("unable to add bob link: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create request which should be forwarder from alice channel link
|
|
|
|
// to bob channel link.
|
|
|
|
preimage := [sha256.Size]byte{1}
|
|
|
|
rhash := fastsha256.Sum256(preimage[:])
|
|
|
|
request = newAddPacket(
|
2017-06-17 01:03:30 +03:00
|
|
|
aliceChannelLink.ShortChanID(),
|
|
|
|
bobChannelLink.ShortChanID(),
|
2017-05-01 19:58:08 +03:00
|
|
|
&lnwire.UpdateAddHTLC{
|
|
|
|
PaymentHash: rhash,
|
|
|
|
Amount: 1,
|
|
|
|
},
|
|
|
|
)
|
|
|
|
|
|
|
|
// Handle the request and checks that bob channel link received it.
|
|
|
|
if err := s.forward(request); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-bobChannelLink.packets:
|
|
|
|
break
|
|
|
|
case <-time.After(time.Second):
|
|
|
|
t.Fatal("request was not propogated to destination")
|
|
|
|
}
|
|
|
|
|
|
|
|
if s.circuits.pending() != 1 {
|
|
|
|
t.Fatal("wrong amount of circuits")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle the request and checks that bob channel link received it.
|
|
|
|
if err := s.forward(request); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if s.circuits.pending() != 2 {
|
|
|
|
t.Fatal("wrong amount of circuits")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create settle request pretending that bob channel link handled
|
|
|
|
// the add htlc request and sent the htlc settle request back. This
|
|
|
|
// request should be forwarder back to alice channel link.
|
|
|
|
request = newFailPacket(
|
2017-06-17 01:03:30 +03:00
|
|
|
bobChannelLink.ShortChanID(),
|
2017-05-01 19:58:08 +03:00
|
|
|
&lnwire.UpdateFailHTLC{},
|
|
|
|
rhash, 1)
|
|
|
|
|
|
|
|
// Handle the request and checks that payment circuit works properly.
|
|
|
|
if err := s.forward(request); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-aliceChannelLink.packets:
|
|
|
|
break
|
|
|
|
case <-time.After(time.Second):
|
|
|
|
t.Fatal("request was not propogated to channelPoint")
|
|
|
|
}
|
|
|
|
|
|
|
|
if s.circuits.pending() != 1 {
|
|
|
|
t.Fatal("wrong amount of circuits")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle the request and checks that payment circuit works properly.
|
|
|
|
if err := s.forward(request); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-aliceChannelLink.packets:
|
|
|
|
break
|
|
|
|
case <-time.After(time.Second):
|
|
|
|
t.Fatal("request was not propogated to channelPoint")
|
|
|
|
}
|
|
|
|
|
|
|
|
if s.circuits.pending() != 0 {
|
|
|
|
t.Fatal("wrong amount of circuits")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// TestSwitchSendPayment tests ability of htlc switch to respond to the
|
|
|
|
// users when response is came back from channel link.
|
|
|
|
func TestSwitchSendPayment(t *testing.T) {
|
|
|
|
alicePeer := newMockServer(t, "alice")
|
2017-06-17 01:03:30 +03:00
|
|
|
aliceChannelLink := newMockChannelLink(chanID1, aliceChanID, alicePeer)
|
2017-05-01 19:58:08 +03:00
|
|
|
|
|
|
|
s := New(Config{})
|
|
|
|
s.Start()
|
|
|
|
if err := s.AddLink(aliceChannelLink); err != nil {
|
|
|
|
t.Fatalf("unable to add link: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create request which should be forwarder from alice channel link
|
|
|
|
// to bob channel link.
|
|
|
|
preimage := [sha256.Size]byte{1}
|
|
|
|
rhash := fastsha256.Sum256(preimage[:])
|
|
|
|
update := &lnwire.UpdateAddHTLC{
|
|
|
|
PaymentHash: rhash,
|
|
|
|
Amount: 1,
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle the request and checks that bob channel link received it.
|
|
|
|
errChan := make(chan error)
|
|
|
|
go func() {
|
|
|
|
_, err := s.SendHTLC(aliceChannelLink.Peer().PubKey(), update)
|
|
|
|
errChan <- err
|
|
|
|
}()
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
// Send the payment with the same payment hash and same
|
|
|
|
// amount and check that it will be propagated successfully
|
|
|
|
_, err := s.SendHTLC(aliceChannelLink.Peer().PubKey(), update)
|
|
|
|
errChan <- err
|
|
|
|
}()
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-aliceChannelLink.packets:
|
|
|
|
break
|
|
|
|
case err := <-errChan:
|
|
|
|
t.Fatalf("unable to send payment: %v", err)
|
|
|
|
case <-time.After(time.Second):
|
|
|
|
t.Fatal("request was not propogated to destination")
|
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
|
|
|
case <-aliceChannelLink.packets:
|
|
|
|
break
|
|
|
|
case err := <-errChan:
|
|
|
|
t.Fatalf("unable to send payment: %v", err)
|
|
|
|
case <-time.After(time.Second):
|
|
|
|
t.Fatal("request was not propogated to destination")
|
|
|
|
}
|
|
|
|
|
|
|
|
if s.numPendingPayments() != 2 {
|
|
|
|
t.Fatal("wrong amount of pending payments")
|
|
|
|
}
|
|
|
|
|
|
|
|
if s.circuits.pending() != 0 {
|
|
|
|
t.Fatal("wrong amount of circuits")
|
|
|
|
}
|
|
|
|
|
2017-06-17 01:03:30 +03:00
|
|
|
// Create fail request pretending that bob channel link handled the add
|
|
|
|
// htlc request with error and sent the htlc fail request back. This
|
|
|
|
// request should be forwarder back to alice channel link.
|
|
|
|
packet := newFailPacket(
|
|
|
|
aliceChannelLink.ShortChanID(),
|
2017-05-01 19:58:08 +03:00
|
|
|
&lnwire.UpdateFailHTLC{
|
|
|
|
Reason: []byte{byte(lnwire.IncorrectValue)},
|
|
|
|
ID: 1,
|
|
|
|
},
|
2017-06-17 01:03:30 +03:00
|
|
|
rhash,
|
|
|
|
1,
|
|
|
|
)
|
2017-05-01 19:58:08 +03:00
|
|
|
|
|
|
|
if err := s.forward(packet); err != nil {
|
|
|
|
t.Fatalf("can't forward htlc packet: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
|
|
|
case err := <-errChan:
|
|
|
|
if err.Error() != errors.New(lnwire.IncorrectValue).Error() {
|
|
|
|
t.Fatal("err wasn't received")
|
|
|
|
}
|
|
|
|
case <-time.After(time.Second):
|
|
|
|
t.Fatal("err wasn't received")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send second failure response and check that user were able to
|
|
|
|
// receive the error.
|
|
|
|
if err := s.forward(packet); err != nil {
|
|
|
|
t.Fatalf("can't forward htlc packet: %v", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
select {
|
|
|
|
case err := <-errChan:
|
|
|
|
if err.Error() != errors.New(lnwire.IncorrectValue).Error() {
|
|
|
|
t.Fatal("err wasn't received")
|
|
|
|
}
|
|
|
|
case <-time.After(time.Second):
|
|
|
|
t.Fatal("err wasn't received")
|
|
|
|
}
|
|
|
|
|
|
|
|
if s.numPendingPayments() != 0 {
|
|
|
|
t.Fatal("wrong amount of pending payments")
|
|
|
|
}
|
|
|
|
}
|