peerswap icon indicating copy to clipboard operation
peerswap copied to clipboard

Premium

Open YusukeShimizu opened this issue 1 year ago • 26 comments

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"
  }
}

YusukeShimizu avatar Dec 23 '23 04:12 YusukeShimizu

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?

wtogami avatar Dec 25 '23 21:12 wtogami

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.

Impa10r avatar Dec 25 '23 21:12 Impa10r

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.

YusukeShimizu avatar Dec 27 '23 01:12 YusukeShimizu

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.

YusukeShimizu avatar Dec 27 '23 01:12 YusukeShimizu

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?

grubles avatar Jan 16 '24 15:01 grubles

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
      }
   }
]

grubles avatar Jan 26 '24 16:01 grubles

Would it be useful to have the premium rate limit be a config option in policy.conf too?

grubles avatar Jan 26 '24 16:01 grubles

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"
}

grubles avatar Jan 26 '24 16:01 grubles

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

grubles avatar Jan 26 '24 20:01 grubles

Thanks for the test. Perhaps some of the behavior is a bug. I'll investigate and fix it.

YusukeShimizu avatar Jan 27 '24 05:01 YusukeShimizu

FIXED.

premium info is missing from the CLN listpeers

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.

Hitting this with CLN as sender

I rearranged the order of commands. I think it is natural that the force flag should be at the end.

CLN plugin crashed when trying a listswaps.

The source of the information was an error, which I corrected.

YusukeShimizu avatar Jan 30 '24 01:01 YusukeShimizu

@YusukeShimizu Hello. Do you plan RPC endpoints to configure premium rates?

Impa10r avatar Jan 30 '24 12:01 Impa10r

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.)

YusukeShimizu avatar Jan 31 '24 12:01 YusukeShimizu

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

grubles avatar Jan 31 '24 15:01 grubles

I fixed it on https://github.com/ElementsProject/peerswap/pull/264/commits/d8b683d478332794947be52c42e84fccd470ee89

YusukeShimizu avatar Feb 01 '24 02:02 YusukeShimizu

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"                 
}

grubles avatar Feb 02 '24 15:02 grubles

I fixed it on https://github.com/ElementsProject/peerswap/pull/264/commits/2b9dfa303d09fba18da9b510e318d1813f45b408 same as swapout

YusukeShimizu avatar Feb 03 '24 04:02 YusukeShimizu

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":  []
}

grubles avatar Feb 21 '24 00:02 grubles

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

YusukeShimizu avatar Feb 21 '24 02:02 YusukeShimizu

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?

grubles avatar Mar 07 '24 15:03 grubles

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.

wtogami avatar Mar 07 '24 16:03 wtogami

It would make sense to have different premiums for different assets too. And, for different peers as well. With defaults to fall back on.

tsjk avatar Mar 07 '24 16:03 tsjk

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.

Impa10r avatar May 05 '24 20:05 Impa10r

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.

I totally agree here!

tsjk avatar May 07 '24 06:05 tsjk

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.

SwapMarket avatar Sep 17 '24 23:09 SwapMarket

Thank you for the feedback. This PR is in progress.

YusukeShimizu avatar Sep 18 '24 03:09 YusukeShimizu

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 avatar Oct 13 '24 23:10 YusukeShimizu

@YusukeShimizu

  1. Will we set these params via API/cli calls or must edit the policy.conf directly (poor UX)?
  2. What is reserve_onchain_msat? Keep min balance for onchain BTC? Any chance to have one for LBTC as well?

Impa10r avatar Oct 14 '24 19:10 Impa10r

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.

YusukeShimizu avatar Oct 15 '24 08:10 YusukeShimizu

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"
      }

Impa10r avatar Oct 15 '24 16:10 Impa10r