23cc8389f2
In this commit, we update the `HopIterator` to gain awareness of the new TLV hop payload. The default `HopIterator` will now hide the details of the TLV from the caller, and return the same `ForwardingInfo` struct in a uniform manner. We also add a new method: `ExtraOnionBlob` to allow the caller to obtain the raw EOB (the serialized TLV stream) to pass around. Within the link, we'll now pass the EOB information into the invoice registry. This allows the registry to parse out any additional information from the EOB that it needs to settle the payment, such as a preimage shard in the AMP case.
110 lines
3.1 KiB
Go
110 lines
3.1 KiB
Go
package htlcswitch
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"testing"
|
|
|
|
"github.com/davecgh/go-spew/spew"
|
|
sphinx "github.com/lightningnetwork/lightning-onion"
|
|
"github.com/lightningnetwork/lnd/lnwire"
|
|
"github.com/lightningnetwork/lnd/tlv"
|
|
)
|
|
|
|
// TestSphinxHopIteratorForwardingInstructions tests that we're able to
|
|
// properly decode an onion payload, no matter the payload type, into the
|
|
// original set of forwarding instructions.
|
|
func TestSphinxHopIteratorForwardingInstructions(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
// First, we'll make the hop data that the sender would create to send
|
|
// an HTLC through our imaginary route.
|
|
hopData := sphinx.HopData{
|
|
ForwardAmount: 100000,
|
|
OutgoingCltv: 4343,
|
|
}
|
|
copy(hopData.NextAddress[:], bytes.Repeat([]byte("a"), 8))
|
|
|
|
// Next, we'll make the hop forwarding information that we should
|
|
// extract each type, no matter the payload type.
|
|
nextAddrInt := binary.BigEndian.Uint64(hopData.NextAddress[:])
|
|
expectedFwdInfo := ForwardingInfo{
|
|
NextHop: lnwire.NewShortChanIDFromInt(nextAddrInt),
|
|
AmountToForward: lnwire.MilliSatoshi(hopData.ForwardAmount),
|
|
OutgoingCTLV: hopData.OutgoingCltv,
|
|
}
|
|
|
|
// For our TLV payload, we'll serialize the hop into into a TLV stream
|
|
// as we would normally in the routing network.
|
|
var b bytes.Buffer
|
|
tlvRecords := []tlv.Record{
|
|
tlv.MakeDynamicRecord(
|
|
tlv.AmtOnionType, &hopData.ForwardAmount, func() uint64 {
|
|
return tlv.SizeTUint64(hopData.ForwardAmount)
|
|
},
|
|
tlv.ETUint64, tlv.DTUint64,
|
|
),
|
|
tlv.MakeDynamicRecord(
|
|
tlv.LockTimeOnionType, &hopData.OutgoingCltv, func() uint64 {
|
|
return tlv.SizeTUint32(hopData.OutgoingCltv)
|
|
},
|
|
tlv.ETUint32, tlv.DTUint32,
|
|
),
|
|
tlv.MakePrimitiveRecord(tlv.NextHopOnionType, &nextAddrInt),
|
|
}
|
|
tlvStream, err := tlv.NewStream(tlvRecords...)
|
|
if err != nil {
|
|
t.Fatalf("unable to create stream: %v", err)
|
|
}
|
|
if err := tlvStream.Encode(&b); err != nil {
|
|
t.Fatalf("unable to encode stream: %v", err)
|
|
}
|
|
|
|
var testCases = []struct {
|
|
sphinxPacket *sphinx.ProcessedPacket
|
|
expectedFwdInfo ForwardingInfo
|
|
}{
|
|
// A regular legacy payload that signals more hops.
|
|
{
|
|
sphinxPacket: &sphinx.ProcessedPacket{
|
|
Payload: sphinx.HopPayload{
|
|
Type: sphinx.PayloadLegacy,
|
|
},
|
|
Action: sphinx.MoreHops,
|
|
ForwardingInstructions: &hopData,
|
|
},
|
|
expectedFwdInfo: expectedFwdInfo,
|
|
},
|
|
// A TLV payload, we can leave off the action as we'll always
|
|
// read the cid encoded.
|
|
{
|
|
sphinxPacket: &sphinx.ProcessedPacket{
|
|
Payload: sphinx.HopPayload{
|
|
Type: sphinx.PayloadTLV,
|
|
Payload: b.Bytes(),
|
|
},
|
|
},
|
|
expectedFwdInfo: expectedFwdInfo,
|
|
},
|
|
}
|
|
|
|
// Finally, we'll test that we get the same set of
|
|
// ForwardingInstructions for each payload type.
|
|
iterator := sphinxHopIterator{}
|
|
for i, testCase := range testCases {
|
|
iterator.processedPacket = testCase.sphinxPacket
|
|
|
|
fwdInfo, err := iterator.ForwardingInstructions()
|
|
if err != nil {
|
|
t.Fatalf("#%v: unable to extract forwarding "+
|
|
"instructions: %v", i, err)
|
|
}
|
|
|
|
if fwdInfo != testCase.expectedFwdInfo {
|
|
t.Fatalf("#%v: wrong fwding info: expected %v, got %v",
|
|
i, spew.Sdump(testCase.expectedFwdInfo),
|
|
spew.Sdump(fwdInfo))
|
|
}
|
|
}
|
|
}
|