Skip to content

Commit

Permalink
WIP: itest
Browse files Browse the repository at this point in the history
  • Loading branch information
ffranr committed Mar 18, 2024
1 parent 7439c7a commit 08b298f
Show file tree
Hide file tree
Showing 2 changed files with 175 additions and 0 deletions.
171 changes: 171 additions & 0 deletions itest/rfq_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,177 @@ func testRfqAssetBuyHtlcIntercept(t *harnessTest) {
require.NoError(t.t, err)
}

// testRfqAssetSellHtlcIntercept tests RFQ negotiation, HTLC interception, and
// validation between three peers. The RFQ negotiation is initiated by an asset
// sell request.
func testRfqAssetSellHtlcIntercept(t *harnessTest) {
// Initialize a new test scenario.
ts := newRfqTestScenario(t)

// Mint an asset with Alice's tapd node.
rpcAssets := MintAssetsConfirmBatch(
t.t, t.lndHarness.Miner.Client, ts.AliceTapd,
[]*mintrpc.MintAssetRequest{issuableAssets[0]},
)
mintedAssetId := rpcAssets[0].AssetGenesis.AssetId

ctxb := context.Background()
ctxt, cancel := context.WithTimeout(ctxb, defaultWaitTimeout)
defer cancel()

// TODO(ffranr): Add an asset buy offer to Bob's tapd node. This will
// allow Alice to sell the newly minted asset to Bob.

// Subscribe to Alice's RFQ events stream.
aliceEventNtfns, err := ts.AliceTapd.SubscribeRfqEventNtfns(
ctxb, &rfqrpc.SubscribeRfqEventNtfnsRequest{},
)
require.NoError(t.t, err)

// Alice sends a sell order to Bob for some amount of the newly minted
// asset.
purchaseAssetAmt := uint64(200)
askAmt := uint64(42000)
sellOrderExpiry := uint64(time.Now().Add(24 * time.Hour).Unix())

_, err = ts.AliceTapd.AddAssetSellOrder(
ctxt, &rfqrpc.AddAssetSellOrderRequest{
AssetSpecifier: &rfqrpc.AssetSpecifier{
Id: &rfqrpc.AssetSpecifier_AssetId{
AssetId: mintedAssetId,
},
},
MaxAssetAmount: purchaseAssetAmt,
MinAsk: askAmt,
Expiry: sellOrderExpiry,

// Here we explicitly specify Bob as the destination
// peer for the sell order. This will prompt Alice's
// tapd node to send a request for quote message to
// Bob's node.
PeerPubKey: ts.BobLnd.PubKey[:],
},
)
require.NoError(t.t, err, "unable to upsert asset sell order")

// Wait until Alice receives an incoming sell quote accept message (sent
// from Bob) RFQ event notification.
waitErr := wait.NoError(func() error {
event, err := aliceEventNtfns.Recv()
require.NoError(t.t, err)

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

return nil
}, defaultWaitTimeout)
require.NoError(t.t, waitErr)

// Alice should have received an accepted quote from Bob. This accepted
// quote can be used by Alice to make a payment to Bob.
acceptedQuotes, err := ts.AliceTapd.QueryRfqPeerAcceptedQuotes(
ctxt, &rfqrpc.QueryRfqPeerAcceptedQuotesRequest{},
)
require.NoError(t.t, err, "unable to query accepted quotes")
require.Len(t.t, acceptedQuotes.SellQuotes, 1)

/////////////////////////////////////////
//// Carol will now use the accepted quote (received from Bob) to create
//// a lightning invoice which will be given to and settled by Alice.
////
//// The payment will be routed through Bob (who will handle the
//// BTC->asset conversion as a last step before reaching Carol). Recall
//// that the payment path is: Alice -> Bob -> Carol. And the Bob -> Carol
//// last hop will constitute the tap asset transfer.
////
//// First, we need to get the short channel ID (scid) for the Alice->Bob
//// channel which Carol will include in her invoice. Then, when Alice
//// pays the invoice, the payment will arrive to Bob's node with the
//// expected scid. Bob will then use the scid to identify the HTLC as
//// relating to the accepted quote.
//acceptedQuote := acceptedQuotes.BuyQuotes[0]
//t.Logf("Accepted quote scid: %d", acceptedQuote.Scid)
//scid := lnwire.NewShortChanIDFromInt(acceptedQuote.Scid)
//
//// Use the agreed upon scid found in the accepted quote to construct a
//// route hop hint for the Alice->Bob step of the payment. The route hop
//// hint will be included in the invoice that Carol hands to Alice.
//aliceBobHopHint := &lnrpc.HopHint{
// NodeId: ts.BobLnd.PubKeyStr,
// ChanId: scid.ToUint64(),
// FeeBaseMsat: uint32(
// chainreg.DefaultBitcoinBaseFeeMSat,
// ),
// FeeProportionalMillionths: uint32(
// chainreg.DefaultBitcoinFeeRate,
// ),
// CltvExpiryDelta: chainreg.DefaultBitcoinTimeLockDelta,
//}
//routeHints := []*lnrpc.RouteHint{
// {
// HopHints: []*lnrpc.HopHint{
// aliceBobHopHint,
// },
// },
//}
//
//// Carol can now finalise the invoice and hand it over to Alice for
//// settlement.
//addInvoiceResp := ts.CarolLnd.RPC.AddInvoice(&lnrpc.Invoice{
// ValueMsat: int64(askAmt),
// RouteHints: routeHints,
//})
//invoice := ts.CarolLnd.RPC.LookupInvoice(addInvoiceResp.RHash)
//
//// Register to receive RFQ events from Bob's tapd node. We'll use this
//// to wait for Bob to receive the HTLC with the asset transfer specific
//// scid.
//bobEventNtfns, err := ts.BobTapd.SubscribeRfqEventNtfns(
// ctxb, &rfqrpc.SubscribeRfqEventNtfnsRequest{},
//)
//require.NoError(t.t, err)
//
//// Alice pays the invoice.
//t.Log("Alice paying invoice")
//req := &routerrpc.SendPaymentRequest{
// PaymentRequest: invoice.PaymentRequest,
// TimeoutSeconds: int32(wait.PaymentTimeout.Seconds()),
// FeeLimitMsat: math.MaxInt64,
//}
//ts.AliceLnd.RPC.SendPayment(req)
//t.Log("Alice payment sent")
//
//// 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
//// then validate it against the accepted quote.
//waitErr = wait.NoError(func() error {
// t.Log("Waiting for Bob to receive HTLC")
//
// event, err := bobEventNtfns.Recv()
// require.NoError(t.t, err)
//
// acceptHtlc, ok := event.Event.(*rfqrpc.RfqEvent_AcceptHtlc)
// if ok {
// require.Equal(
// t.t, acceptedQuote.Scid,
// acceptHtlc.AcceptHtlc.Scid,
// )
// t.Log("Bob has accepted the HTLC")
// return nil
// }
//
// return fmt.Errorf("unexpected event: %v", event)
//}, defaultWaitTimeout)
//require.NoError(t.t, waitErr)
//
//// Close event streams.
//err = carolEventNtfns.CloseSend()
//require.NoError(t.t, err)
//
//err = bobEventNtfns.CloseSend()
//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,
Expand Down
4 changes: 4 additions & 0 deletions itest/test_list_on_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,10 @@ var testCases = []*testCase{
name: "rfq asset buy htlc intercept",
test: testRfqAssetBuyHtlcIntercept,
},
{
name: "rfq asset sell htlc intercept",
test: testRfqAssetSellHtlcIntercept,
},
}

var optionalTestCases = []*testCase{
Expand Down

0 comments on commit 08b298f

Please sign in to comment.