Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement swap watcher nodes. #1431

Open
artemii235 opened this issue Aug 4, 2022 · 8 comments · Fixed by #1859
Open

Implement swap watcher nodes. #1431

artemii235 opened this issue Aug 4, 2022 · 8 comments · Fixed by #1859
Assignees
Labels
enhancement New feature or request

Comments

@artemii235
Copy link
Member

As of now, we require trading parties to always be online during swap process. Going offline is specifically dangerous for takers due to how swap protocol works. To help them refund their payments or spend maker's in time, we need to add "watcher nodes" that will track swap transactions statuses and trigger the required action if the trading party doesn't seem to do it itself. It will be a concept similar to Lightning watchtower nodes.

@artemii235 artemii235 added the enhancement New feature or request label Aug 4, 2022
@artemii235 artemii235 self-assigned this Aug 4, 2022
@artemii235
Copy link
Member Author

artemii235 commented Aug 4, 2022

For the beginning, I drew the diagram on how I envision this to work for UTXO case
AtomicDEX architecture watcher nodes

cc @caglaryucekaya

@artemii235
Copy link
Member Author

For other protocols like ETH, simply generating a refund transaction won't work: adversary watcher node can broadcast it right away - it will fail due to lock time not expired burning taker ETH for gas fees. We will likely have to rework our swap smart contracts, allowing 3rd parties to call refund/spend fns for other nodes swaps. However, there should be a financial benefit or at least gas fees coverage for smart contract calls by watchers. So I think we should focus on UTXO first, and then figure out how we can do the same for other protocols.

@caglaryucekaya
Copy link

caglaryucekaya commented Sep 8, 2022

TODO List:

  • Switch to the state machine pattern instead of using the same design as the existing swap implementation
  • Add watcher refund functionality
  • Before running a watcher, check if the maker payment is already spent by the taker or another watcher
  • Watcher might give the taker some time to spend the maker payment before spending it itself.
  • Use TimeCache to keep track of running watchers instead of a hashset
  • Add a WatcherValidatesTakerPayment error
  • Think about a spam prevention mechanism for different swap uuids
  • Add tests covering different cases
  • Swap watcher functionality for makers
  • Implement swap watchers for Ethereum
  • Find out if it is possible to implement watchers for lightning swaps (low priority)
  • Add the ability for the watcher nodes to ban certain public keys (maybe)
  • Consider native mode watchers
  • Add save swap state functionality (low priority)

@artemii235
Copy link
Member Author

@caglaryucekaya @smk762 New WatcherMessageSent was added in the #1457 PR. The new event might be a breaking change for some GUIs, so it should be documented. Could you do it, please?

@caglaryucekaya
Copy link

WatcherMessageSent event is triggered when a taker node sends a WatcherMessage right after it sends the taker payment. For this to happen, a node must run with the use_watchers configuration set to true and it must start a taker swap. If the WatcherMessage cannot be sent due to an error, the WatcherMessageSent event is not triggered but the taker swap continues as usual.

@caglaryucekaya
Copy link

caglaryucekaya commented Dec 22, 2022

@smk762 here's some test scenarios based on the integration tests I wrote:

Swap set-up:

  1. Start a taker as a seed node with the use_watchers config set to true. Enable MYCOIN and MYCOIN1 with some funds.
  2. Start a maker as a light node. Enable MYCOIN and MYCOIN1 with some funds.
  3. Start a watcher as a light node with the is_watcher config set to true. Enable MYCOIN and MYCOIN1. To not wait for the actual locktime durations and get immediate results, the configurations wait_maker_payment_spend_factor, refund_start_factor, search_interval, wait_taker_payment are used. The values for each case are written belov. If these configs are not set, then everything works with default values, i.e. actual locktime durations.
  4. Maker calls the setprice mehod with MYCOIN and MYCOIN1.
  5. Taker calls the buy method with MYCOIN and MYCOIN1.

a) Watcher spends maker payment spend (https://github.com/KomodoPlatform/atomicDEX-API/blob/dev/mm2src/mm2_main/tests/docker_tests/docker_tests_inner.rs#L829):
3) Watcher configurations:
wait_maker_payment_spend_factor: 0.
refund_start_factor: 1.5
search_interval: 1.
wait_taker_payment: 0.
6) Taker runs until sending the taker payment and watcher message and stops after logging the WATCHER_MESSAGE_SENT_LOG. Maker keeps running for the whole swap.
7) The swap will be completed successfully a few seconds after the watcher sends the maker payment spend Tx and logs the MAKER_PAYMENT_SPEND_SENT_LOG.
8) The success of the swap can be verified by checking the final balances of the taker and the maker.

b) Watcher waits for taker: (https://github.com/KomodoPlatform/atomicDEX-API/blob/dev/mm2src/mm2_main/tests/docker_tests/docker_tests_inner.rs#L953)
3) Watcher configurations:
wait_maker_payment_spend_factor: 1.
refund_start_factor: 1.5
search_interval: 1.
wait_taker_payment: 0.
6) After the taker spends the maker payment, the watcher will log MAKER_PAYMENT_SPEND_FOUND_LOG message and stop without sending the maker payment spend Tx itself.

c) Watcher refunds taker payment: (https://github.com/KomodoPlatform/atomicDEX-API/blob/dev/mm2src/mm2_main/tests/docker_tests/docker_tests_inner.rs#L1019)
1 - Same as the step 1 above, but also set an environment variable for the taker, "USE_TEST_LOCKTIME" = "". The value doesn't matter.
3 - Watcher configurations:
wait_maker_payment_spend_factor: 1.
refund_start_factor: 0.
search_interval: 1.
wait_taker_payment: 0.

6 - Maker sends the maker payment, logs the MAKER_PAYMENT_SENT_LOG message and stops.
7 - Taker sends the taker payment, logs the WATCHER_MESSAGE_SENT_LOG and stops.
8 - Refund will be successfully completed a few seconds after the watcher sends the taker payment refund Tx and logs the TAKER_PAYMENT_REFUND_SENT_LOG.

@caglaryucekaya
Copy link

caglaryucekaya commented Jan 10, 2023

TODO for Ethereum Swap Watchers:

  • Reuse the validate_payment method
  • Reuse the validate_fee method
  • Use global constants for passphrases
  • Add activation parameter for watcher support
  • Write a unit test for watcher_validate_taker_payment
  • Stabilize the integration tests
  • Ensure that failed attempts to spend/refund payments do not cost any gas to the watchers. If it's not possible, prevent simultaneous attempts of watchers to spend/refund payments.
  • Think of different attacks which can cause the watchers to spend gas for failed spend/refund attempts. Secure the implementation accordingly.
  • All nodes should validate the result of the watcher reward functions by comparing it to a certain percentage of the trade amount (comment)
  • Watcher nodes should validate the watcher reward in UTXO transactions.
  • Convert from u64 to u256 in watcher_common and other places where possible, instead of doing the opposite (comment)
  • Save the watcher reward information in saved swaps, and use it when validating watcher spends and refunds.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants