Skip to content

Commit

Permalink
Merge pull request #1048 from lightninglabs/tap-channel-rpcs
Browse files Browse the repository at this point in the history
[custom channels]: add new RPC methods for asset channel specific calls
  • Loading branch information
Roasbeef authored Aug 9, 2024
2 parents 1b5a4ef + 23c09ff commit a8d8b5a
Show file tree
Hide file tree
Showing 18 changed files with 2,767 additions and 96 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ require (
github.com/lib/pq v1.10.9
github.com/lightninglabs/aperture v0.1.21-beta.0.20230705004936-87bb996a4030
github.com/lightninglabs/lightning-node-connect/hashmailrpc v1.0.2
github.com/lightninglabs/lndclient v1.0.1-0.20240723001046-925d3c8297bf
github.com/lightninglabs/lndclient v1.0.1-0.20240725080034-64a756aa4c36
github.com/lightninglabs/neutrino/cache v1.1.2
github.com/lightningnetwork/lnd v0.18.0-beta.rc4.0.20240723043204-f09d4042aee4
github.com/lightningnetwork/lnd/cert v1.2.2
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -480,8 +480,8 @@ github.com/lightninglabs/lightning-node-connect v0.2.5-alpha h1:ZRVChwczFXK0CEbx
github.com/lightninglabs/lightning-node-connect v0.2.5-alpha/go.mod h1:A9Pof9fETkH+F67BnOmrBDThPKstqp73wlImWOZvTXQ=
github.com/lightninglabs/lightning-node-connect/hashmailrpc v1.0.2 h1:Er1miPZD2XZwcfE4xoS5AILqP1mj7kqnhbBSxW9BDxY=
github.com/lightninglabs/lightning-node-connect/hashmailrpc v1.0.2/go.mod h1:antQGRDRJiuyQF6l+k6NECCSImgCpwaZapATth2Chv4=
github.com/lightninglabs/lndclient v1.0.1-0.20240723001046-925d3c8297bf h1:VcTK/juPtAqwEBckCcSHCsVRSbHGbWtDZgnXL5JOLkg=
github.com/lightninglabs/lndclient v1.0.1-0.20240723001046-925d3c8297bf/go.mod h1:bxd2a15cIaW8KKcmOf9nNDI/GTxxj0upEYs1EIkttqw=
github.com/lightninglabs/lndclient v1.0.1-0.20240725080034-64a756aa4c36 h1:gfJ3TOuqSnuXEo1Boj1H9P6tpxPSH9cvi+rB10L0svI=
github.com/lightninglabs/lndclient v1.0.1-0.20240725080034-64a756aa4c36/go.mod h1:bxd2a15cIaW8KKcmOf9nNDI/GTxxj0upEYs1EIkttqw=
github.com/lightninglabs/neutrino v0.16.1-0.20240425105051-602843d34ffd h1:D8aRocHpoCv43hL8egXEMYyPmyOiefFHZ66338KQB2s=
github.com/lightninglabs/neutrino v0.16.1-0.20240425105051-602843d34ffd/go.mod h1:x3OmY2wsA18+Kc3TSV2QpSUewOCiscw2mKpXgZv2kZk=
github.com/lightninglabs/neutrino/cache v1.1.2 h1:C9DY/DAPaPxbFC+xNNEI/z1SJY9GS3shmlu5hIQ798g=
Expand Down
92 changes: 92 additions & 0 deletions itest/channels_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package itest

import (
"context"

"github.com/lightninglabs/taproot-assets/rfqmsg"
tchrpc "github.com/lightninglabs/taproot-assets/taprpc/tapchannelrpc"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/record"
"github.com/stretchr/testify/require"
)

var (
dummyByteArr = [32]byte{0x01, 0x02, 0x03, 0x04}
)

// testChannelRPCs tests that we can call all Taproot Asset Channel related
// RPCs and get the correct error message back (as we can't really test the
// actual functionality without running within litd). This at least makes sure
// we've set up everything correctly in terms of macaroons and permissions.
func testChannelRPCs(t *harnessTest) {
ctx := context.Background()

// The EncodeCustomRecords RPC is available, as it only does static
// encoding.
encodeReq := &tchrpc.EncodeCustomRecordsRequest_RouterSendPayment{
RouterSendPayment: &tchrpc.RouterSendPaymentData{
RfqId: dummyByteArr[:],
},
}
encodeResp, err := t.tapd.EncodeCustomRecords(
ctx, &tchrpc.EncodeCustomRecordsRequest{
Input: encodeReq,
},
)
require.NoError(t.t, err)
require.Len(t.t, encodeResp.CustomRecords, 2)

var rfqIdType rfqmsg.HtlcRfqIDType
rfqIdTlvTypeNumber := uint64(rfqIdType.TypeVal())
require.Len(t.t, encodeResp.CustomRecords[rfqIdTlvTypeNumber], 32)

// All the following calls can't go fully through, and we'll encounter
// an error at some point.
_, err = t.tapd.FundChannel(ctx, &tchrpc.FundChannelRequest{})
require.ErrorContains(t.t, err, "only available when running inside")

// Try the keysend path first, which should go all the way through to
// lnd, where it should fail because we didn't set a timeout.
stream, err := t.tapd.SendPayment(ctx, &tchrpc.SendPaymentRequest{
AssetAmount: 123,
AssetId: dummyByteArr[:],
PaymentRequest: &routerrpc.SendPaymentRequest{
DestCustomRecords: map[uint64][]byte{
record.KeySendType: dummyByteArr[:],
},
},
})
require.NoError(t.t, err)

_, err = stream.Recv()
require.ErrorContains(t.t, err, "timeout_seconds")

// Now let's also try the invoice path, which should fail because we
// don't have any asset channels with peers that we could ask for a
// quote.
invoiceResp := t.lndHarness.Alice.RPC.AddInvoice(&lnrpc.Invoice{
AmtPaidSat: 1234,
})
stream, err = t.tapd.SendPayment(ctx, &tchrpc.SendPaymentRequest{
AssetId: dummyByteArr[:],
PaymentRequest: &routerrpc.SendPaymentRequest{
PaymentRequest: invoiceResp.PaymentRequest,
},
})
require.NoError(t.t, err)

_, err = stream.Recv()
require.ErrorContains(t.t, err, "no asset channel balance found")

// We can't add an invoice either, because we have no peers to do RFQ
// negotiation with.
_, err = t.tapd.AddInvoice(ctx, &tchrpc.AddInvoiceRequest{
AssetAmount: 123,
AssetId: dummyByteArr[:],
InvoiceRequest: &lnrpc.Invoice{
Private: false,
},
})
require.ErrorContains(t.t, err, "no asset channel balance found")
}
5 changes: 5 additions & 0 deletions itest/tapd_harness.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/lightninglabs/taproot-assets/taprpc/assetwalletrpc"
"github.com/lightninglabs/taproot-assets/taprpc/mintrpc"
"github.com/lightninglabs/taproot-assets/taprpc/rfqrpc"
tchrpc "github.com/lightninglabs/taproot-assets/taprpc/tapchannelrpc"
"github.com/lightninglabs/taproot-assets/taprpc/tapdevrpc"
"github.com/lightninglabs/taproot-assets/taprpc/universerpc"
"github.com/lightningnetwork/lnd/lnrpc"
Expand Down Expand Up @@ -96,6 +97,7 @@ type tapdHarness struct {
assetwalletrpc.AssetWalletClient
mintrpc.MintClient
rfqrpc.RfqClient
tchrpc.TaprootAssetChannelsClient
universerpc.UniverseClient
tapdevrpc.TapDevClient
}
Expand Down Expand Up @@ -348,6 +350,9 @@ func (hs *tapdHarness) start(expectErrExit bool) error {
hs.AssetWalletClient = assetwalletrpc.NewAssetWalletClient(rpcConn)
hs.MintClient = mintrpc.NewMintClient(rpcConn)
hs.RfqClient = rfqrpc.NewRfqClient(rpcConn)
hs.TaprootAssetChannelsClient = tchrpc.NewTaprootAssetChannelsClient(
rpcConn,
)
hs.UniverseClient = universerpc.NewUniverseClient(rpcConn)
hs.TapDevClient = tapdevrpc.NewTapDevClient(rpcConn)

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 @@ -304,6 +304,10 @@ var testCases = []*testCase{
name: "anchor multiple virtual transactions",
test: testAnchorMultipleVirtualTransactions,
},
{
name: "channel RPCs",
test: testChannelRPCs,
},
}

var optionalTestCases = []*testCase{
Expand Down
8 changes: 8 additions & 0 deletions perms/perms.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,14 @@ var (
Entity: "channels",
Action: "write",
}},
"/tapchannelrpc.TaprootAssetChannels/SendPayment": {{
Entity: "channels",
Action: "write",
}},
"/tapchannelrpc.TaprootAssetChannels/AddInvoice": {{
Entity: "channels",
Action: "write",
}},
"/tapchannelrpc.TaprootAssetChannels/EncodeCustomRecords": {
// This RPC is completely stateless and doesn't require
// any permissions to use.
Expand Down
4 changes: 4 additions & 0 deletions rfq/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ const (
// DefaultTimeout is the default timeout used for context operations.
DefaultTimeout = 30 * time.Second

// DefaultInvoiceExpiry is the default expiry time for asset invoices.
// The current value corresponds to 5 minutes.
DefaultInvoiceExpiry = time.Second * 300

// CacheCleanupInterval is the interval at which local runtime caches
// are cleaned up.
CacheCleanupInterval = 30 * time.Second
Expand Down
Loading

0 comments on commit a8d8b5a

Please sign in to comment.