Skip to content

Commit

Permalink
Merge pull request #906 from GeorgeTsagk/rfq-track-htlc-itests
Browse files Browse the repository at this point in the history
itest: Extend custom channel liquidity itest for RFQ HTLC tracking
  • Loading branch information
GeorgeTsagk authored Dec 6, 2024
2 parents 868e57c + 73bbd6a commit 82c8511
Show file tree
Hide file tree
Showing 5 changed files with 260 additions and 73 deletions.
12 changes: 6 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ require (
github.com/lightninglabs/pool v0.6.5-beta.0.20241015105339-044cb451b5df
github.com/lightninglabs/pool/auctioneerrpc v1.1.2
github.com/lightninglabs/pool/poolrpc v1.0.0
github.com/lightninglabs/taproot-assets v0.5.0-rc1
github.com/lightninglabs/taproot-assets v0.5.0-rc1.0.20241206085244-8113fa8bb314
github.com/lightningnetwork/lnd v0.18.4-beta.rc1
github.com/lightningnetwork/lnd/cert v1.2.2
github.com/lightningnetwork/lnd/fn v1.2.3
Expand All @@ -46,7 +46,7 @@ require (
)

require (
dario.cat/mergo v1.0.0 // indirect
dario.cat/mergo v1.0.1 // indirect
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/NebulousLabs/fastrand v0.0.0-20181203155948-6fb6489aac4e // indirect
Expand Down Expand Up @@ -89,7 +89,7 @@ require (
github.com/fortytw2/leaktest v1.3.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-viper/mapstructure/v2 v2.0.0 // indirect
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.1 // indirect
github.com/golang-migrate/migrate/v4 v4.17.0 // indirect
Expand Down Expand Up @@ -191,12 +191,12 @@ require (
go.etcd.io/etcd/raft/v3 v3.5.12 // indirect
go.etcd.io/etcd/server/v3 v3.5.12 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 // indirect
go.opentelemetry.io/otel v1.28.0 // indirect
go.opentelemetry.io/otel v1.32.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0 // indirect
go.opentelemetry.io/otel/metric v1.28.0 // indirect
go.opentelemetry.io/otel/metric v1.32.0 // indirect
go.opentelemetry.io/otel/sdk v1.21.0 // indirect
go.opentelemetry.io/otel/trace v1.28.0 // indirect
go.opentelemetry.io/otel/trace v1.32.0 // indirect
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/mock v0.4.0 // indirect
Expand Down
28 changes: 14 additions & 14 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -596,8 +596,8 @@ cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoIS
cloud.google.com/go/workflows v1.8.0/go.mod h1:ysGhmEajwZxGn1OhGOGKsTXc5PyxOc0vfKf5Af+to4M=
cloud.google.com/go/workflows v1.9.0/go.mod h1:ZGkj1aFIOd9c8Gerkjjq7OW7I5+l6cSvT3ujaO/WwSA=
cloud.google.com/go/workflows v1.10.0/go.mod h1:fZ8LmRmZQWacon9UCX1r/g/DfAXx5VcPALq2CxzdePw=
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
gioui.org v0.0.0-20210308172011-57750fc8a0a6/go.mod h1:RSH6KIUZ0p2xy5zHDxgAM4zumjgTw83q2ge/PI+yyw8=
git.sr.ht/~sbinet/gg v0.3.1/go.mod h1:KGYtlADtqsqANL9ueOFkWymvzUvLMQllU5Ixo+8v3pc=
Expand Down Expand Up @@ -855,8 +855,8 @@ github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GO
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-viper/mapstructure/v2 v2.0.0 h1:dhn8MZ1gZ0mzeodTG3jt5Vj/o87xZKuNAprG2mQfMfc=
github.com/go-viper/mapstructure/v2 v2.0.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
Expand Down Expand Up @@ -1177,8 +1177,8 @@ github.com/lightninglabs/pool/poolrpc v1.0.0 h1:vvosrgNx9WXF4mcHGqLjZOW8wNM0q+BL
github.com/lightninglabs/pool/poolrpc v1.0.0/go.mod h1:ZqpEpBFRMMBAerMmilEjh27tqauSXDwLaLR0O3jvmMA=
github.com/lightninglabs/protobuf-go-hex-display v1.34.2-hex-display h1:w7FM5LH9Z6CpKxl13mS48idsu6F+cEZf0lkyiV+Dq9g=
github.com/lightninglabs/protobuf-go-hex-display v1.34.2-hex-display/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
github.com/lightninglabs/taproot-assets v0.5.0-rc1 h1:UuDuvOJErqvapdF5gA8gfTy7X8Dfi96fCoNhrRuB9ZA=
github.com/lightninglabs/taproot-assets v0.5.0-rc1/go.mod h1:3MxoqsBdZGju3ExSIA9kFle5nqjWeb4alK4aVlfT0tA=
github.com/lightninglabs/taproot-assets v0.5.0-rc1.0.20241206085244-8113fa8bb314 h1:ykWP63wGxW0OKW4lITz8/lWv6CLMswRRX4DCr37wAkU=
github.com/lightninglabs/taproot-assets v0.5.0-rc1.0.20241206085244-8113fa8bb314/go.mod h1:d9GdY5DVoSh6+dEQRS4UUcjpVvZlAHgP8U2DAp4YedA=
github.com/lightningnetwork/lightning-onion v1.2.1-0.20240712235311-98bd56499dfb h1:yfM05S8DXKhuCBp5qSMZdtSwvJ+GFzl94KbXMNB1JDY=
github.com/lightningnetwork/lightning-onion v1.2.1-0.20240712235311-98bd56499dfb/go.mod h1:c0kvRShutpj3l6B9WtTsNTBUtjSmjZXbJd9ZBRQOSKI=
github.com/lightningnetwork/lnd v0.18.4-beta.rc1 h1:z6hFKvtbfo8udPrIb81GbSoKlUWd06d4LRxTkD19IMQ=
Expand Down Expand Up @@ -1438,20 +1438,20 @@ go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg=
go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo=
go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.57.0 h1:DheMAlT6POBP+gh8RUH19EOTnQIor5QE0uSRPtzCpSw=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.57.0/go.mod h1:wZcGmeVO9nzP67aYSLDqXNWK87EZWhi7JWj1v7ZXf94=
go.opentelemetry.io/otel v1.32.0 h1:WnBN+Xjcteh0zdk01SVqV55d/m62NJLJdIyb4y/WO5U=
go.opentelemetry.io/otel v1.32.0/go.mod h1:00DCVSB0RQcnzlwyTfqtxSm+DRr9hpYrHjNGiBHVQIg=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0 h1:DeFD0VgTZ+Cj6hxravYYZE2W4GlneVH81iAOPjZkzk8=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0/go.mod h1:GijYcYmNpX1KazD5JmWGsi4P7dDTTTnfv1UbGn84MnU=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0 h1:gvmNvqrPYovvyRmCSygkUDyL8lC5Tl845MLEwqpxhEU=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0/go.mod h1:vNUq47TGFioo+ffTSnKNdob241vePmtNZnAODKapKd0=
go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q=
go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s=
go.opentelemetry.io/otel/metric v1.32.0 h1:xV2umtmNcThh2/a/aCP+h64Xx5wsj8qqnkYZktzNa0M=
go.opentelemetry.io/otel/metric v1.32.0/go.mod h1:jH7CIbbK6SH2V2wE16W05BHCtIDzauciCRLoc/SyMv8=
go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8=
go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E=
go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g=
go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
go.opentelemetry.io/otel/trace v1.32.0 h1:WIC9mYrXf8TmY/EXuULKc8hR17vE+Hjv2cssQDe03fM=
go.opentelemetry.io/otel/trace v1.32.0/go.mod h1:+i4rkvCraA+tG6AzwloGaCtkx53Fa+L+V8e9a7YvhT8=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
Expand Down
86 changes: 59 additions & 27 deletions itest/assets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ const (
DefaultPushSat int64 = 1062
)

var (
NoRfqIDOpt = fn.None[rfqmsg.ID]()
)

// createTestAssetNetwork sends asset funds from Charlie to Dave and Erin, so
// they can fund asset channels with Yara and Fabia, respectively. So the asset
// channels created are Charlie->Dave, Dave->Yara, Erin->Fabia. The channels
Expand Down Expand Up @@ -714,6 +718,9 @@ func sendAssetKeySendPayment(t *testing.T, src, dst *HarnessNode, amt uint64,

result, err := getAssetPaymentResult(stream, false)
require.NoError(t, err)
if result.Status == lnrpc.Payment_FAILED {
t.Logf("Failure reason: %v", result.FailureReason)
}
require.Equal(t, expectedStatus, result.Status)

expectedReason := failReason.UnwrapOr(
Expand Down Expand Up @@ -772,7 +779,9 @@ func createAndPayNormalInvoiceWithBtc(t *testing.T, src, dst *HarnessNode,
})
require.NoError(t, err)

payInvoiceWithSatoshi(t, src, invoiceResp, lnrpc.Payment_SUCCEEDED)
payInvoiceWithSatoshi(
t, src, invoiceResp, lnrpc.Payment_SUCCEEDED, false,
)
}

func createAndPayNormalInvoice(t *testing.T, src, rfqPeer, dst *HarnessNode,
Expand All @@ -792,15 +801,15 @@ func createAndPayNormalInvoice(t *testing.T, src, rfqPeer, dst *HarnessNode,

numUnits, _ := payInvoiceWithAssets(
t, src, rfqPeer, invoiceResp.PaymentRequest, assetID, smallShards,
fn.None[lnrpc.Payment_PaymentStatus](),
fn.None[lnrpc.Payment_PaymentStatus](), NoRfqIDOpt,
)

return numUnits
}

func payInvoiceWithSatoshi(t *testing.T, payer *HarnessNode,
invoice *lnrpc.AddInvoiceResponse,
expectedStatus lnrpc.Payment_PaymentStatus) {
expectedStatus lnrpc.Payment_PaymentStatus, expectTimeout bool) {

ctxb := context.Background()
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
Expand All @@ -816,8 +825,12 @@ func payInvoiceWithSatoshi(t *testing.T, payer *HarnessNode,
require.NoError(t, err)

result, err := getPaymentResult(stream)
require.NoError(t, err)
require.Equal(t, expectedStatus, result.Status)
if expectTimeout {
require.ErrorContains(t, err, "context deadline exceeded")
} else {
require.NoError(t, err)
require.Equal(t, expectedStatus, result.Status)
}
}

func payInvoiceWithSatoshiLastHop(t *testing.T, payer *HarnessNode,
Expand Down Expand Up @@ -858,7 +871,8 @@ func payInvoiceWithSatoshiLastHop(t *testing.T, payer *HarnessNode,

func payInvoiceWithAssets(t *testing.T, payer, rfqPeer *HarnessNode,
payReq string, assetID []byte, smallShards bool,
expectedPayStatus fn.Option[lnrpc.Payment_PaymentStatus]) (uint64,
expectedPayStatus fn.Option[lnrpc.Payment_PaymentStatus],
manualRfq fn.Option[rfqmsg.ID]) (uint64,
rfqmath.BigIntFixedPoint) {

ctxb := context.Background()
Expand All @@ -882,44 +896,62 @@ func payInvoiceWithAssets(t *testing.T, payer, rfqPeer *HarnessNode,
sendReq.MaxShardSizeMsat = 80_000_000
}

var rfqBytes []byte
manualRfq.WhenSome(func(i rfqmsg.ID) {
rfqBytes = make([]byte, len(i[:]))
copy(rfqBytes, i[:])
})

stream, err := payerTapd.SendPayment(ctxt, &tchrpc.SendPaymentRequest{
AssetId: assetID,
PeerPubkey: rfqPeer.PubKey[:],
PaymentRequest: sendReq,
RfqId: rfqBytes,
})
require.NoError(t, err)

// We want to receive the accepted quote message first, so we know how
// many assets we're going to pay.
quoteMsg, err := stream.Recv()
require.NoError(t, err)
acceptedQuote := quoteMsg.GetAcceptedSellOrder()
require.NotNil(t, acceptedQuote)
var (
numUnits uint64
rateVal rfqmath.FixedPoint[rfqmath.BigInt]
)

peerPubKey := acceptedQuote.Peer
require.Equal(t, peerPubKey, rfqPeer.PubKeyStr)
if manualRfq.IsNone() {
// We want to receive the accepted quote message first, so we know how
// many assets we're going to pay.
quoteMsg, err := stream.Recv()
require.NoError(t, err)
acceptedQuote := quoteMsg.GetAcceptedSellOrder()
require.NotNil(t, acceptedQuote)

rpcRate := acceptedQuote.BidAssetRate
rate, err := rfqrpc.UnmarshalFixedPoint(rpcRate)
require.NoError(t, err)
peerPubKey := acceptedQuote.Peer
require.Equal(t, peerPubKey, rfqPeer.PubKeyStr)

t.Logf("Got quote for %v asset units per BTC", rate)
rpcRate := acceptedQuote.BidAssetRate
rate, err := rfqrpc.UnmarshalFixedPoint(rpcRate)
require.NoError(t, err)

rateVal = *rate

amountMsat := lnwire.MilliSatoshi(decodedInvoice.NumMsat)
milliSatsFP := rfqmath.MilliSatoshiToUnits(amountMsat, *rate)
numUnits := milliSatsFP.ScaleTo(0).ToUint64()
msatPerUnit := float64(decodedInvoice.NumMsat) / float64(numUnits)
t.Logf("Got quote for %v asset units at %3f msat/unit from peer %s "+
"with SCID %d", numUnits, msatPerUnit, peerPubKey,
acceptedQuote.Scid)
t.Logf("Got quote for %v asset units per BTC", rate)

amountMsat := lnwire.MilliSatoshi(decodedInvoice.NumMsat)
milliSatsFP := rfqmath.MilliSatoshiToUnits(amountMsat, *rate)
numUnits = milliSatsFP.ScaleTo(0).ToUint64()
msatPerUnit := float64(decodedInvoice.NumMsat) / float64(numUnits)
t.Logf("Got quote for %v asset units at %3f msat/unit from peer %s "+
"with SCID %d", numUnits, msatPerUnit, peerPubKey,
acceptedQuote.Scid)
}

expectedStatus := expectedPayStatus.UnwrapOr(lnrpc.Payment_SUCCEEDED)

result, err := getAssetPaymentResult(stream, expectedPayStatus.IsSome())
result, err := getAssetPaymentResult(
stream, expectedStatus == lnrpc.Payment_IN_FLIGHT,
)
require.NoError(t, err)
require.Equal(t, expectedStatus, result.Status)

return numUnits, *rate
return numUnits, rateVal
}

func createAssetInvoice(t *testing.T, dstRfqPeer, dst *HarnessNode,
Expand Down
7 changes: 7 additions & 0 deletions itest/litd_accounts_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,13 @@ func getAssetPaymentResult(
return nil, err
}

// Ignore RFQ quote acceptance messages read from the send
// payment stream, as they are not relevant.
quote := msg.GetAcceptedSellOrder()
if quote != nil {
continue
}

payment := msg.GetPaymentResult()
if payment == nil {
return nil, fmt.Errorf("unexpected message: %v", msg)
Expand Down
Loading

0 comments on commit 82c8511

Please sign in to comment.