Skip to content

Commit

Permalink
itest+rfq: re-enable and fix RFQ itests
Browse files Browse the repository at this point in the history
  • Loading branch information
guggero committed Oct 22, 2024
1 parent 930a3c2 commit 1bbe907
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 98 deletions.
12 changes: 6 additions & 6 deletions itest/assets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,7 @@ func testMintAssetNameCollisionError(t *harnessTest) {
require.Equal(t.t, a.GroupKey, b.GroupKey)
require.Equal(t.t, a.GroupAnchor, b.GroupAnchor)
}

// If we attempt to add both assets to the same batch, the second mint
// call should fail.
collideResp, err := t.tapd.MintAsset(ctxt, &assetCollide)
Expand Down Expand Up @@ -376,12 +377,11 @@ func testMintAssetNameCollisionError(t *harnessTest) {

// The only change in the returned batch after cancellation should be
// the batch state.
cancelBatch, err := t.tapd.ListBatches(
ctxt, &mintrpc.ListBatchRequest{
Filter: &mintrpc.ListBatchRequest_BatchKey{
BatchKey: collideResp.PendingBatch.BatchKey,
},
})
cancelBatch, err := t.tapd.ListBatches(ctxt, &mintrpc.ListBatchRequest{
Filter: &mintrpc.ListBatchRequest_BatchKey{
BatchKey: collideResp.PendingBatch.BatchKey,
},
})
require.NoError(t.t, err)

require.Len(t.t, cancelBatch.Batches, 1)
Expand Down
119 changes: 42 additions & 77 deletions itest/rfq_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"time"

"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/wire"
"github.com/lightninglabs/taproot-assets/rfqmsg"
"github.com/lightninglabs/taproot-assets/taprpc/mintrpc"
"github.com/lightninglabs/taproot-assets/taprpc/rfqrpc"
Expand All @@ -23,6 +22,11 @@ import (
"github.com/stretchr/testify/require"
)

var (
// rfqTimeout is the timeout used for RFQ related operations.
rfqTimeout = 5 * time.Second
)

// testRfqAssetBuyHtlcIntercept tests RFQ negotiation, HTLC interception, and
// validation between three peers. The RFQ negotiation is initiated by an asset
// buy request.
Expand Down Expand Up @@ -97,7 +101,7 @@ func testRfqAssetBuyHtlcIntercept(t *harnessTest) {
// node.
PeerPubKey: ts.BobLnd.PubKey[:],

TimeoutSeconds: 5,
TimeoutSeconds: uint32(rfqTimeout.Seconds()),
},
)
require.NoError(t.t, err, "unable to upsert asset buy order")
Expand All @@ -110,7 +114,7 @@ func testRfqAssetBuyHtlcIntercept(t *harnessTest) {

_, ok := event.Event.(*rfqrpc.RfqEvent_PeerAcceptedBuyQuote)
require.True(t.t, ok, "unexpected event: %v", event)
}, defaultWaitTimeout)
}, rfqTimeout)

// Carol should have received an accepted quote from Bob. This accepted
// quote can be used by Carol to make a payment to Bob.
Expand Down Expand Up @@ -203,7 +207,7 @@ func testRfqAssetBuyHtlcIntercept(t *harnessTest) {
t.t, acceptedQuote.Scid, acceptHtlc.AcceptHtlc.Scid,
)
t.Log("Bob has accepted the HTLC")
}, defaultWaitTimeout)
}, rfqTimeout)

// Close event streams.
err = carolEventNtfns.CloseSend()
Expand Down Expand Up @@ -273,6 +277,8 @@ func testRfqAssetSellHtlcIntercept(t *harnessTest) {
// tapd node to send a request for quote message to
// Bob's node.
PeerPubKey: ts.BobLnd.PubKey[:],

TimeoutSeconds: uint32(rfqTimeout.Seconds()),
},
)
require.NoError(t.t, err, "unable to upsert asset sell order")
Expand All @@ -285,7 +291,7 @@ func testRfqAssetSellHtlcIntercept(t *harnessTest) {

_, ok := event.Event.(*rfqrpc.RfqEvent_PeerAcceptedSellQuote)
require.True(t.t, ok, "unexpected event: %v", event)
}, defaultWaitTimeout)
}, rfqTimeout)

// Alice should have received an accepted quote from Bob. This accepted
// quote can be used by Alice to make a payment to Bob.
Expand Down Expand Up @@ -329,28 +335,21 @@ func testRfqAssetSellHtlcIntercept(t *harnessTest) {
}
routeBuildResp := ts.AliceLnd.RPC.BuildRoute(&routeBuildRequest)

// Add the accepted quote ID as a record to the custom records field of
// the route's first hop.
aliceBobHop := routeBuildResp.Route.Hops[0]
if aliceBobHop.CustomRecords == nil {
aliceBobHop.CustomRecords = make(map[uint64][]byte)
}

var htlcRfqIDTlvType rfqmsg.HtlcRfqIDType
aliceBobHop.CustomRecords[uint64(htlcRfqIDTlvType.TypeVal())] =
acceptedQuote.Id[:]

// Update the route with the modified first hop.
routeBuildResp.Route.Hops[0] = aliceBobHop

// Send the payment to the route.
t.Log("Alice paying invoice")
var htlcRfqIDTlvType rfqmsg.HtlcRfqIDType
routeReq := routerrpc.SendToRouteRequest{
PaymentHash: invoice.RHash,
Route: routeBuildResp.Route,
FirstHopCustomRecords: map[uint64][]byte{
uint64(htlcRfqIDTlvType.TypeVal()): acceptedQuote.Id[:],
},
}
sendAttempt := ts.AliceLnd.RPC.SendToRouteV2(&routeReq)
require.Equal(t.t, lnrpc.HTLCAttempt_SUCCEEDED, sendAttempt.Status)

// The payment will fail since it doesn't transport the correct amount
// of the asset.
require.Equal(t.t, lnrpc.HTLCAttempt_FAILED, sendAttempt.Status)

// At this point Bob should have received a HTLC with the asset transfer
// specific scid. We'll wait for Bob to publish an accept HTLC event and
Expand All @@ -362,11 +361,11 @@ func testRfqAssetSellHtlcIntercept(t *harnessTest) {

_, ok := event.Event.(*rfqrpc.RfqEvent_AcceptHtlc)
require.True(t.t, ok, "unexpected event: %v", event)
}, defaultWaitTimeout)
}, rfqTimeout)

// Confirm that Carol receives the lightning payment from Alice via Bob.
invoice = ts.CarolLnd.RPC.LookupInvoice(addInvoiceResp.RHash)
require.Equal(t.t, invoice.State, lnrpc.Invoice_SETTLED)
require.Equal(t.t, invoice.State, lnrpc.Invoice_OPEN)

// Close event notification streams.
err = aliceEventNtfns.CloseSend()
Expand All @@ -376,44 +375,6 @@ func testRfqAssetSellHtlcIntercept(t *harnessTest) {
require.NoError(t.t, err)
}

// newLndNode creates a new lnd node with the given name and funds its wallet
// with the specified outputs.
func newLndNode(name string, outputFunds []btcutil.Amount,
ht *lntest.HarnessTest) *node.HarnessNode {

newNode := ht.NewNode(name, nil)

// Fund node wallet with specified outputs.
totalTxes := len(outputFunds)
const (
numBlocksSendOutput = 2
minerFeeRate = btcutil.Amount(7500)
)

for i := range outputFunds {
amt := outputFunds[i]

resp := newNode.RPC.NewAddress(&lnrpc.NewAddressRequest{
Type: lnrpc.AddressType_WITNESS_PUBKEY_HASH},
)
addr := ht.DecodeAddress(resp.Address)
addrScript := ht.PayToAddrScript(addr)

output := &wire.TxOut{
PkScript: addrScript,
Value: int64(amt),
}
ht.Miner().SendOutput(output, minerFeeRate)
}

// Mine any funding transactions.
if totalTxes > 0 {
ht.MineBlocksAndAssertNumTxes(numBlocksSendOutput, totalTxes)
}

return newNode
}

// rfqTestScenario is a struct which holds test scenario helper infra.
type rfqTestScenario struct {
testHarness *harnessTest
Expand All @@ -438,42 +399,43 @@ type rfqTestScenario struct {
// It also creates new tapd nodes for each of the LND nodes.
func newRfqTestScenario(t *harnessTest) *rfqTestScenario {
// Specify wallet outputs to fund the wallets of the new nodes.
const (
fundAmount = 1 * btcutil.SatoshiPerBitcoin
numOutputs = 100
totalAmount = fundAmount * numOutputs
)

var outputFunds [numOutputs]btcutil.Amount
for i := range outputFunds {
outputFunds[i] = fundAmount
}
const fundAmount = 1 * btcutil.SatoshiPerBitcoin

// Generate a unique name for each new node.
aliceName := genRandomNodeName("AliceLnd")
bobName := genRandomNodeName("BobLnd")
carolName := genRandomNodeName("CarolLnd")

scidAliasArgs := []string{
"--protocol.option-scid-alias",
"--protocol.anchors",
}

// Create three new nodes.
aliceLnd := newLndNode(aliceName, outputFunds[:], t.lndHarness)
bobLnd := newLndNode(bobName, outputFunds[:], t.lndHarness)
carolLnd := newLndNode(carolName, outputFunds[:], t.lndHarness)
aliceLnd := t.lndHarness.NewNode(aliceName, scidAliasArgs)
t.lndHarness.FundCoins(fundAmount, aliceLnd)

bobLnd := t.lndHarness.NewNode(bobName, scidAliasArgs)
t.lndHarness.FundCoins(fundAmount, bobLnd)

carolLnd := t.lndHarness.NewNode(carolName, scidAliasArgs)
t.lndHarness.FundCoins(fundAmount, carolLnd)

// Now we want to wait for the nodes to catch up.
t.lndHarness.WaitForBlockchainSync(aliceLnd)
t.lndHarness.WaitForBlockchainSync(bobLnd)
t.lndHarness.WaitForBlockchainSync(carolLnd)

// Now block until both wallets have fully synced up.
t.lndHarness.WaitForBalanceConfirmed(aliceLnd, totalAmount)
t.lndHarness.WaitForBalanceConfirmed(bobLnd, totalAmount)
t.lndHarness.WaitForBalanceConfirmed(carolLnd, totalAmount)
t.lndHarness.WaitForBalanceConfirmed(aliceLnd, fundAmount)
t.lndHarness.WaitForBalanceConfirmed(bobLnd, fundAmount)
t.lndHarness.WaitForBalanceConfirmed(carolLnd, fundAmount)

// Connect the nodes.
t.lndHarness.EnsureConnected(aliceLnd, bobLnd)
t.lndHarness.EnsureConnected(bobLnd, carolLnd)

// Open channels between the nodes: Alice -> Bob -> Carol
// Open channels between the nodes: Alice -> Bob -> Carol.
const chanAmt = btcutil.Amount(300000)
p := lntest.OpenChannelParams{Amt: chanAmt}
reqs := []*lntest.OpenChannelRequest{
Expand All @@ -486,6 +448,9 @@ func newRfqTestScenario(t *harnessTest) *rfqTestScenario {
// Make sure Alice is aware of channel Bob -> Carol.
t.lndHarness.AssertTopologyChannelOpen(aliceLnd, bobCarolChannel)

// Make sure Carol is aware of channel Alice -> Bob.
t.lndHarness.AssertTopologyChannelOpen(carolLnd, aliceBobChannel)

// Create tapd nodes.
aliceTapd := setupTapdHarness(t.t, t, aliceLnd, t.universeServer)
bobTapd := setupTapdHarness(t.t, t, bobLnd, t.universeServer)
Expand Down
12 changes: 4 additions & 8 deletions itest/test_list_on_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,14 +299,10 @@ var testCases = []*testCase{
name: "rfq asset buy htlc intercept",
test: testRfqAssetBuyHtlcIntercept,
},

// TODO(ffranr): Re-enable this test once we have a way to set the
// `WireCustomRecords` field in the first hop `UpdateAddHtlc` p2p
// message
//{
// name: "rfq asset sell htlc intercept",
// test: testRfqAssetSellHtlcIntercept,
//},
{
name: "rfq asset sell htlc intercept",
test: testRfqAssetSellHtlcIntercept,
},

{
name: "multi signature on all levels",
Expand Down
15 changes: 8 additions & 7 deletions rfq/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/lightninglabs/taproot-assets/asset"
"github.com/lightninglabs/taproot-assets/fn"
"github.com/lightninglabs/taproot-assets/rfqmsg"
lfn "github.com/lightningnetwork/lnd/fn"
"github.com/lightningnetwork/lnd/lnutils"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/route"
Expand Down Expand Up @@ -521,21 +522,21 @@ func (m *Manager) addScidAlias(scidAlias uint64, assetID asset.ID,
}

// Filter for channels with the given peer.
peerChannels := make([]lndclient.ChannelInfo, 0)
for _, localChan := range localChans {
if localChan.PubKeyBytes == peer {
peerChannels = append(peerChannels, localChan)
}
}
peerChannels := lfn.Filter(func(c lndclient.ChannelInfo) bool {
return c.PubKeyBytes == peer
}, localChans)

// Identify the correct channel to use as the base SCID for the alias
// by inspecting the asset data in the custom channel data.
var (
assetIDStr = assetID.String()
baseSCID uint64
)

for _, localChan := range peerChannels {
if len(localChan.CustomChannelData) == 0 {
continue
}

var assetData rfqmsg.JsonAssetChannel
err = json.Unmarshal(localChan.CustomChannelData, &assetData)
if err != nil {
Expand Down

0 comments on commit 1bbe907

Please sign in to comment.