peerswap
peerswap copied to clipboard
Premium
This PR adds premium to peerswap. design doc
Usage
doing swap
A premium limit will be added to the existing swap command. If not set, default is 0.
cln
lightning-cli peerswap-swap-out [short channel id] [amount in sats] [asset: btc or lbtc] [premium limit in sats]
lnd
pscli swapout --sat_amt=[sat amount] --channel_id=[chan_id from above] --asset=btc --premium_limit=[premium limit]
configure premium rate
The premium rate is pert per million and can be set for swapin and swapout respectively.
swap_amount * premium_rate_ppm / 1000000 is the premium.
Negative values can also be set to give a discount
policy.conf
swap_in_premium_rate_ppm=10000
swap_out_premium_rate_ppm=20000
You can check the premium rate set for each peer by using listpeers.
pscli listpeers
{
"peers": [
{
"node_id": "0322d434b1f90b1ca1c35f2ecf3d250bd3884f5d2809156eb76929b91d73322bf0",
"swaps_allowed": true,
"supported_assets": [
"btc",
"lbtc"
],
"channels": [
{
"channel_id": "120946279120897",
"local_balance": "99996530",
"remote_balance": "0",
"active": true
}
],
"as_sender": {
"swaps_out": "0",
"swaps_in": "0",
"sats_out": "0",
"sats_in": "0"
},
"as_receiver": {
"swaps_out": "0",
"swaps_in": "0",
"sats_out": "0",
"sats_in": "0"
},
"paid_fee": "0",
"swap_in_premium_rate_ppm": "100",
"swap_out_premium_rate_ppm": "100"
}
]
}
examples
If the max_acceptable_premium is lower than responder.
./bin/pscli peerswap1 swapout --channel_id $CHANID --sat_amt 1000000 --asset btc --premium_limit 1
2023/12/23 02:02:36 rpc error: code = Unknown desc = from the LND peer: unacceptable premium: 100, limit: 1
success
./bin/pscli peerswap1 swapout --channel_id $CHANID --sat_amt 1000000 --asset btc --premium_limit 100
{
"swap": {
"id": "eb5f41a515f737956300a38ab1f5286a67d580c4d3f838afdf48537c1133ed69",
"created_at": "1702532654",
"asset": "btc",
"type": "swap-out",
"role": "sender",
"state": "State_SwapOutSender_AwaitTxConfirmation",
"initiator_node_id": "02ea1fd791bb1b639e7119ac54505e3f553a7bb942877ccbb359affa8547046988",
"peer_node_id": "034066fecfcdad7cb2f002c8c4234dbab26688db9617509ede4c7372c79ab94d0d",
"amount": "1000000",
"channel_id": "110:1:1",
"opening_tx_id": "83f0b1174a3c55934ca9fa60398dbdfa76394db1450cbe2c1d2369ef80095b15",
"claim_tx_id": "",
"cancel_message": "",
"lnd_chan_id": "120946279120897",
"premium": "100"
}
}
Asking for opinions: Should we have fine grained configuration to allow for setting certain peers a different premium fee rate? I suppose that would complicate things a lot and make the configuration look ugly. But is this a highly desirable feature?
Asking for opinions: Should we have fine grained configuration to allow for setting certain peers a different premium fee rate? I suppose that would complicate things a lot and make the configuration look ugly. But is this a highly desirable feature?
I think no. But allow separate premiums for received swap ins and swap outs, including negative values. This will allow managing liquidity among BTC, LBTC and Lightning.
Asking for opinions: Should we have fine grained configuration to allow for setting certain peers a different premium fee rate? I suppose that would complicate things a lot and make the configuration look ugly. But is this a highly desirable feature?
In the future, it may be better to allow premiums to be set according to the degree of use, such as channels that flow easily in both directions or channels that flow only in one direction. However, since this has nothing to do with protocol changes, I think there is an option to not implement it in this PR and consider it later.
But allow separate premiums for received swap ins and swap outs, including negative values. This will allow managing liquidity among BTC, LBTC and Lightning.
It is possible to configure swap in and swap out in policy.conf, including negative values.
Asking for opinions: Should we have fine grained configuration to allow for setting certain peers a different premium fee rate? I suppose that would complicate things a lot and make the configuration look ugly. But is this a highly desirable feature?
Yes I think so. Channels may have different characteristics that would benefit from having individual premium/discount rates to incentivize swapping in one direction or the other, similar to how routing fee rates can be used to influence how a channel is used?
Looks like the premium info is missing from the CLN listpeers:
$ lightning-cli --signet peerswap-listpeers
[
{
"nodeid": "035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923",
"swaps_allowed": true,
"supported_assets": [
"btc",
"lbtc"
],
"channels": [
{
"short_channel_id": "140490x1x0",
"local_balance": 224000900,
"remote_balance": 75999100,
"state": "CHANNELD_NORMAL"
},
{
"short_channel_id": "162922x1x0",
"local_balance": 201341,
"remote_balance": 18668659,
"state": "CHANNELD_NORMAL"
}
],
"sent": {
"total_swaps_out": 0,
"total_swaps_in": 0,
"total_sats_swapped_out": 0,
"total_sats_swapped_in": 0
},
"received": {
"total_swaps_out": 10,
"total_swaps_in": 12,
"total_sats_swapped_out": 238000000,
"total_sats_swapped_in": 144000000
}
}
]
Would it be useful to have the premium rate limit be a config option in policy.conf too?
Hitting this with CLN as sender:
$ lightning-cli --signet peerswap-swap-out 140490x1x0 100000000 lbtc 1000000
{
"code": -32603,
"message": "-32603: Incompatible types: SwapOut.bool (bool) != float64"
}
CLN plugin crashed when trying a listswaps:
$ lightning-cli --signet peerswap-listswaps
{
"code": -4,
"message": "Plugin terminated before replying to RPC call."
}
Looks like peerswapd segfaulted when trying listswaps too:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0xdb1460]
goroutine 142825 [running]:
github.com/elementsproject/peerswap/swap.(*SwapData).GetPremium(...)
/home/user/builds/master_peerswap/swap/swap.go:239
github.com/elementsproject/peerswap/peerswaprpc.PrettyprintFromServiceSwap(0xc0002c5600)
/home/user/builds/master_peerswap/peerswaprpc/server.go:576 +0x300
github.com/elementsproject/peerswap/peerswaprpc.(*PeerswapServer).ListSwaps(0xf6cf00?, {0xc0006f4120?, 0x498fe6?}, 0x0?)
/home/user/builds/master_peerswap/peerswaprpc/server.go:321 +0xfd
github.com/elementsproject/peerswap/peerswaprpc._PeerSwap_ListSwaps_Handler({0x10505a0?, 0xc000400840}, {0x12b8dd8, 0xc0006f40f0}, 0xc00043e620, 0x0)
/home/user/builds/master_peerswap/peerswaprpc/peerswaprpc_grpc.pb.go:357 +0x169
google.golang.org/grpc.(*Server).processUnaryRPC(0xc000320b40, {0x12c0880, 0xc00040e820}, 0xc0006e6360, 0xc00001f8f0, 0x199ffc8, 0x0)
/home/user/go/pkg/mod/google.golang.org/[email protected]/server.go:1318 +0xb18
google.golang.org/grpc.(*Server).handleStream(0xc000320b40, {0x12c0880, 0xc00040e820}, 0xc0006e6360, 0x0)
/home/user/go/pkg/mod/google.golang.org/[email protected]/server.go:1659 +0x9e7
google.golang.org/grpc.(*Server).serveStreams.func1.2()
/home/user/go/pkg/mod/google.golang.org/[email protected]/server.go:955 +0x8d
created by google.golang.org/grpc.(*Server).serveStreams.func1 in goroutine 142824
/home/user/go/pkg/mod/google.golang.org/[email protected]/server.go:953 +0x246
The logs appear to show that the swap I attempted succeeded however.
2024/01/26 19:03:15 [INFO] [Swap:cdd8bff7205897ad5ed687e830c434a31abf80fdca1f011d32e256bbab836057] Swap claimed with preimage 6fb9a8eb04df189ffe3f78772ff74b29c36ab55ef3923edf5a6b56999cd8cc09
Thanks for the test. Perhaps some of the behavior is a bug. I'll investigate and fix it.
FIXED.
SwapInPremiumRatePPM and SwapInPremiumRatePPM are added to the ListPeers.
This is an additional information, we are currently managing the peerswapd and the cln-plugin in duplicate, but this will be fixed by https://github.com/ElementsProject/peerswap/pull/231.
I rearranged the order of commands. I think it is natural that the force flag should be at the end.
The source of the information was an error, which I corrected.
@YusukeShimizu Hello. Do you plan RPC endpoints to configure premium rates?
Hello. Do you plan RPC endpoints to configure premium rates?
I have no definite plan.
There are some opinions that a fine-grained premium setting is needed, so I may need to think about an appropriate design for that (such as having RPC endpoints, etc.)
At 9c34c47 my peerswapd segfaults when attempting a swap-out.
2024/01/31 15:31:22 [INFO] [Swap:69d53116566e72ac131f343a7dfc492879042c02752c0557369cbd8674703eee] Start new swap-out: peer: 036e680823a129ac9a2eeb8c43514a5b6cb09ae28e3e698a0e34aaa8865d6cc344 chanId: 140490:1:0 initiator: 035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923 amount 100000000
2024/01/31 15:31:22 [DEBUG] [FSM] event:id: 69d53116566e72ac131f343a7dfc492879042c02752c0557369cbd8674703eee, Event_ActionSucceeded on State_SwapOutSender_CreateSwap
2024/01/31 15:31:22 [DEBUG] [FSM] event:id: 69d53116566e72ac131f343a7dfc492879042c02752c0557369cbd8674703eee, Event_ActionSucceeded on State_SwapOutSender_SendRequest
2024/01/31 15:31:22 [DEBUG] [Messenger] From: 036e680823a129ac9a2eeb8c43514a5b6cb09ae28e3e698a0e34aaa8865d6cc344 got msgtype: a45b for swap: 69d53116566e72ac131f343a7dfc492879042c02752c0557369cbd8674703eee
2024/01/31 15:31:22 [DEBUG] [FSM] event:id: 69d53116566e72ac131f343a7dfc492879042c02752c0557369cbd8674703eee, Event_OnFeeInvoiceReceived on State_SwapOutSender_AwaitAgreement
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x58 pc=0xcb6c9f]
goroutine 69 [running]:
github.com/elementsproject/peerswap/swap.(*CheckPremiumAmount).Execute(0xc0006bd600?, 0x10ad8bb?, 0xc000318780)
/home/user/builds/master_peerswap/swap/actions.go:215 +0x11f
github.com/elementsproject/peerswap/swap.(*SwapStateMachine).SendEvent(0xc0006bd600, {0x10a2a12, 0x1a}, {0x12b42d0?, 0xc0001b8e00})
/home/user/builds/master_peerswap/swap/fsm.go:233 +0x7ae
github.com/elementsproject/peerswap/swap.(*SwapService).OnSwapOutAgreementReceived(0xc00055c2c0?, 0xc0001b8e00)
/home/user/builds/master_peerswap/swap/service.go:695 +0x92
github.com/elementsproject/peerswap/swap.(*SwapService).OnMessageReceived(0xc0001cfee0?, {0xc000841c20, 0x42}, {0xc0005f5028, 0x4}, {0xc00055c2c0, 0x2b9, 0x2c0})
/home/user/builds/master_peerswap/swap/service.go:218 +0x906
github.com/elementsproject/peerswap/lnd.(*MessageListener).Start.func1()
/home/user/builds/master_peerswap/lnd/messagelistener.go:84 +0x473
created by github.com/elementsproject/peerswap/lnd.(*MessageListener).Start in goroutine 1
/home/user/builds/master_peerswap/lnd/messagelistener.go:60 +0x10b
I fixed it on https://github.com/ElementsProject/peerswap/pull/264/commits/d8b683d478332794947be52c42e84fccd470ee89
For CLN swap-in sender it hits the incompatible type error:
$ lightning-cli --signet peerswap-swap-in 140490x1x0 100000000 lbtc 2000000
{
"code": -32603,
"message": "-32603: Incompatible types: SwapIn.bool (bool) != float64"
}
I fixed it on https://github.com/ElementsProject/peerswap/pull/264/commits/2b9dfa303d09fba18da9b510e318d1813f45b408 same as swapout
After editing policy.conf to change the swap premium rates while CLN / peerswap are running, CLN peerswap does not output the correct values for the premium rates when running peerswap-reloadpolicy. In this example the correct values would be swap_in_premium_rate_ppm = 40000 and swap_out_premium_rate_ppm rate = 60000:
$ lightning-cli --signet peerswap-reloadpolicy
{
"reserve_onchain_msat": 0,
"allowlisted_peers": [
"035ca2fe4793a5e789ce846062eb4834f573c060d9200ce77544a29b48a0aa5923"
],
"suspicious_peers": [],
"accept_all_peers": false,
"min_swap_amount_msat": 100000000,
"allow_new_swaps": true,
"swap_in_premium_rate_ppm": 0, <------
"swap_out_premium_rate_ppm": 0 <------
}
Though the remote peer receives a poll from the CLN peerswap with the correct new rates:
2024/02/21 00:09:22 [DEBUG] Received poll from peer 036e680823a129ac9a2eeb8c43514a5b6cb09ae28e3e698a0e34aaa8865d6cc344: {"version":5,"assets":["lbtc","btc"],"peer_allowed":true,"swap_in_premium_rate_ppm":40000,"swap_out_premium_rate_ppm":60000}
For LND peerswap, when doing the same thing as above, the premium rates aren't included in the json output at all:
$ ./builds/peerswap/out/pscli reloadpolicy
{
"reserve_onchain_msat": "0",
"min_swap_amount_msat": "100000000",
"accept_all_peers": false,
"allow_new_swaps": true,
"allowlisted_peers": [
"036e680823a129ac9a2eeb8c43514a5b6cb09ae28e3e698a0e34aaa8865d6cc344"
],
"suspicious_peer_list": []
}
https://github.com/ElementsProject/peerswap/pull/264#issuecomment-1955572416
When the reload policy was executed, the configuration values were updated, but they were not being displayed, which was causing this behavior.
Definitions are being added so that they are displayed. https://github.com/ElementsProject/peerswap/pull/264/commits/82d3121a03aa94cc37c6517267c06f823466f348
Idea: being able to set separate premiums for BTC and L-BTC. If I receive BTC from swaps, maybe I want to add a higher premium to offset the cost of moving it in the future?
Idea: being able to set separate premiums for BTC and L-BTC. If I receive BTC from swaps, maybe I want to add a higher premium to offset the cost of moving it in the future?
I think we need configurable premium different for each peer.
It would make sense to have different premiums for different assets too. And, for different peers as well. With defaults to fall back on.
The required premium rates for in and out swaps should be advertised by the receiver in its response to REQUEST_POLL message. So that the initiator can see these rates in listpeers output.
Attempting swaps blindly with 'max acceptable premium rate' is a no go. Peerswap is already suffering from uncertainty about available balances, additional uncertainty about fees will kill it. People hate attempting and seeing constant probing in swaps history.
The required premium rates for in and out swaps should be advertised by the receiver in its response to REQUEST_POLL message. So that the initiator can see these rates in
listpeersoutput.Attempting swaps blindly with 'max acceptable premium rate' is a no go. Peerswap is already suffering from uncertainty about available balances, additional uncertainty about fees will kill it. People hate attempting and seeing constant probing in swaps history.
I totally agree here!
Hello. Is this PR abandoned, or still in the works? No one keeps any Liquid balance because it can be snatched cheaply. There is a need for a swap out premium.
Thank you for the feedback. This PR is in progress.
I have made it possible to set premiums individually for BTC and LBTC.
Additionally, it is now possible to configure settings on a per-peer basis.
You can set it up as shown below.
allowlisted_peers=peer1
allowlisted_peers=peer2
allowlisted_peers=peer3
accept_all_peers=0
# swap_amount * premium_rate_ppm / 1000000 is the premium
# Negative values can also be set to give a discount
# * The value specified by `btc_swap_in_premium_rate_ppm` is the premium rate for BTC swap in
# * The value specified by `btc_swap_out_premium_rate_ppm` is the premium rate for BTC swap out
# * The value specified by `lbtc_swap_in_premium_rate_ppm` is the premium rate for LBTC swap in
# * The value specified by `lbtc_swap_out_premium_rate_ppm` is the premium rate for LBTC swap out
[base_premium_rate]
btc_swap_in_premium_rate_ppm=100
# Set the premium rate for each peer
# * The value specified by `peer1.btc_swap_in_premium_rate_ppm` is the premium rate for BTC swap in for peer1
# * The value specified by `peer1.btc_swap_out_premium_rate_ppm` is the premium rate for BTC swap out for peer1
# * The value specified by `peer1.lbtc_swap_in_premium_rate_ppm` is the premium rate for LBTC swap in for peer1
# * The value specified by `peer1.lbtc_swap_out_premium_rate_ppm` is the premium rate for LBTC swap out for peer1
[peers_premium_rate]
peer1.btc_swap_in_premium_rate_ppm=1000
peer2.btc_swap_out_premium_rate_ppm=2000
@YusukeShimizu
- Will we set these params via API/cli calls or must edit the policy.conf directly (poor UX)?
- What is
reserve_onchain_msat? Keep min balance for onchain BTC? Any chance to have one for LBTC as well?
The current code only supports direct editing of policy.conf.
However, it is also possible to make edits, such as modifying the allow list, through API or CLI calls.
I plan to add this functionality.
The reserve_onchain_msat setting was my mistake and has been removed as it was an unnecessary and meaningless configuration.
Although it was defined as a parameter in peerswap, it was not used in the logic.
I did not specify anything in policy yet, but listpeers shows 10000 ppm for my other node. I think 0 is a better default.
"premium": {
"btc_swap_in_premium_rate_ppm": "10000",
"btc_swap_out_premium_rate_ppm": "10000",
"lbtc_swap_in_premium_rate_ppm": "10000",
"lbtc_swap_out_premium_rate_ppm": "10000"
}