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

Add support for lists of peers in the config #16376

Conversation

felixbrucker
Copy link
Contributor

@felixbrucker felixbrucker commented Sep 20, 2023

Purpose:

Currently it is possible to connect to a single peer via the peer info in the config.yaml, for example:

full_node_peer:
  host: *self_hostname
  port: 8444

It is currently not possible to connect to multiple predefined peers, one has to use the cli/rpc to connect to additional peers after startup.

This PR adds support for a list of peers in the config.yaml, the key name just gets a s added, for example:

full_node_peers:
  - host: *self_hostname
    port: 8444
  - host: some.other.host
    port: 8444

Note: This is currently only supported for farmer and full node peers, as imho those are the only ones where multiple peers make sense at the moment.

Current Behavior:

Connecting to multiple predefined peers is not possible.

New Behavior:

When a singular peer info is present in the config it is used as is, same as before, it just gets wrapped into a set with it being the only member. In case the peer list should be present as well both get merged together.
When no singular peer info is present, the peer list is retrieved with a default of an empty set.

Testing Notes:

I added tests for the new get_unresolved_peer_infos() function. Its usages in the start_<service>.py files are not currently tested as im unsure on how to best test those as they use globals and are generally hard to work with (async_main() that is). If there is a recommended way to test those please let me know and i'll happily add tests for those as well.

It's also important to note that i did not change the configure cli, it will continue to write to the singular entry in the config. I added support for farmer and full node node types. In the config there are some more peer infos (harvester, wallet, timelord, introducer) which currently are either unused or rely on being a singular value to set service wide values (enable_private_networks).

@aqk
Copy link
Contributor

aqk commented Sep 20, 2023

This looks like a good idea, and low risk. Thanks, Felix, and good luck with this PR.

@xearl4
Copy link
Contributor

xearl4 commented Sep 20, 2023

I'd love to see this. I run several nodes which I want to keep in a fully connected mesh with each other. Currently, I achieve this with the peer whitelist and a cronjob that connects a node manually to the desired peers via the CLI. Being able to get rid of that cronjob and directly have this in the config would be great.

Second use-case: since another of Felix' recent PRs was merged, I run my farmer processes connected to two full nodes, for redundancy. Have to manually connect to the second full node, though. And if the farmer loses connection to the secondary node, it does not automatically re-connect (which it does for the primary full node peer from the config) -- so, same cronjob to stay connected to the secondary.

@felixbrucker felixbrucker force-pushed the add-support-for-lists-of-peers-in-config branch from 13b2b73 to 75fe673 Compare October 1, 2023 05:33
@felixbrucker felixbrucker marked this pull request as ready for review October 1, 2023 05:40
@felixbrucker felixbrucker requested a review from a team as a code owner October 1, 2023 05:40
@wallentx wallentx added the Added Required label for PR that categorizes merge commit message as "Added" for changelog label Oct 2, 2023
@felixbrucker felixbrucker force-pushed the add-support-for-lists-of-peers-in-config branch from 75fe673 to 713dfb4 Compare October 2, 2023 04:11
Copy link
Contributor

@altendky altendky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that this feature addition makes sense and is valuable. Thanks Felix for both suggesting it and providing the implementation! Bonus, while reviewing this I found we needed to fix some mutable default parameter values. #16472


When a singular peer info is present in the config it is used as is, same as before, it just gets wrapped into a list with it being the only member. In this case the peer list should it be present as well gets ignored. When no singular peer info is present, the peer list is retrieved with a default of an empty list.

Is there a particular reason for this behavior? The first thing that popped into my head was to have the singular peer entry just treated as if it were another entry in the plural peers list. I was thinking that leaving the singular peer entry at all is mostly a backwards compatibility feature (which is good, thanks).


For the tests, maybe look at uses o @datacases, a small @pytest.mark.parametrize wrapper we use some, to provide a single parametrized test with the many cases.

@felixbrucker
Copy link
Contributor Author

Is there a particular reason for this behavior? The first thing that popped into my head was to have the singular peer entry just treated as if it were another entry in the plural peers list. I was thinking that leaving the singular peer entry at all is mostly a backwards compatibility feature (which is good, thanks).

No, it would probably make sense to merge them in this case yes 👍

@felixbrucker
Copy link
Contributor Author

For the tests, maybe look at uses o @datacases, a small @pytest.mark.parametrize wrapper we use some, to provide a single parametrized test with the many cases.

This is only for the tests i wrote, right? Together with the change to assert a set of unresolved peer infos this will work nicely

Do you have suggestions regarding testing the async_main()s?

@altendky
Copy link
Contributor

altendky commented Oct 2, 2023

For the tests, maybe look at uses o @datacases, a small @pytest.mark.parametrize wrapper we use some, to provide a single parametrized test with the many cases.

This is only for the tests i wrote, right? Together with the change to assert a set of unresolved peer infos this will work nicely

Yes, that comment is just about the pattern for coding the tests.

Do you have suggestions regarding testing the async_main()s?

If you really want to go for this, you could setup a temporary root (we have a fixture), edit the config (we have helper functions and patterns) then setup the services you want it to connect (we have fixtures), call the async_main() (probably in a separate task) and make sure it connects to the desired peers (presumably we can look at some objects directly and not have to parse logs etc). I won't require you achieve coverage for this PR to get merged, but if you want to then I can try to piece together some reference links and think through some of the details. Note that if you do this right now there's room for some issues related to #16472 potentially. They may or may not show up, I didn't look in detail.

@felixbrucker
Copy link
Contributor Author

Yeah, testing the async_main()s feels like a lot of pain, i actually tried something similar to what you described, but it didn't work properly (the async_main uses the DEFAULT_ROOT, and i couldn't overwrite it)

i'll omit tests for those for now 👍

@felixbrucker felixbrucker requested a review from altendky October 2, 2023 15:07
@altendky
Copy link
Contributor

altendky commented Oct 2, 2023

Yep, plenty of corners and we might need to adjust some params etc.

Copy link
Contributor

@altendky altendky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be good to have this new configuration in the initial-config.yaml file. I think we can remove the existing singular case and add the peer listed there as the only entry in the new plural list.

Once we have this ready, I'll create an ephemeral testnet to make sure everything still launches ok. This will be a partial stop gap for the lack of top level integration test coverage.

@felixbrucker
Copy link
Contributor Author

felixbrucker commented Oct 2, 2023

I think we can remove the existing singular case and add the peer listed there as the only entry in the new plural list.

Seems like some tests are failing, because the configure command assumes the key is present

What should be its behaviour when only a list is present?

@altendky
Copy link
Contributor

altendky commented Oct 2, 2023

It reads to me like that code should be updated to set the plural list value for the if case and remove both for the else case. Maybe use the pop method with a default of None instead of del to avoid failures when either key is not there.

@felixbrucker
Copy link
Contributor Author

set the plural list value

which entry in the list would you update, the first?

for the if case and remove both for the else case.

Sadly im not following here, why would we remove anything?

@altendky
Copy link
Contributor

altendky commented Oct 2, 2023

At a glance, this is what I was thinking.

diff --git a/chia/simulator/setup_services.py b/chia/simulator/setup_services.py
index 799134941..6582b7ee4 100644
--- a/chia/simulator/setup_services.py
+++ b/chia/simulator/setup_services.py
@@ -309,11 +309,15 @@ async def setup_wallet_node(
             service_config["introducer_peer"] = None
 
         if full_node_port is not None:
-            service_config["full_node_peer"] = {}
-            service_config["full_node_peer"]["host"] = self_hostname
-            service_config["full_node_peer"]["port"] = full_node_port
+            service_config["full_node_peers"] = [
+                {
+                    "host": self_hostname,
+                    "port": full_node_port,
+                },
+            ]
         else:
-            del service_config["full_node_peer"]
+            service_config.pop("full_node_peer", None)
+            service_config.pop("full_node_peers", None)
 
         service = create_wallet_service(
             local_bt.root_path,
@@ -413,11 +417,16 @@ async def setup_farmer(
     service_config["rpc_port"] = uint16(0)
     config_pool["xch_target_address"] = encode_puzzle_hash(b_tools.pool_ph, "xch")
 
-    if full_node_port:
-        service_config["full_node_peer"]["host"] = self_hostname
-        service_config["full_node_peer"]["port"] = full_node_port
+    if full_node_port is not None:
+        service_config["full_node_peers"] = [
+            {
+                "host": self_hostname,
+                "port": full_node_port,
+            },
+        ]
     else:
-        del service_config["full_node_peer"]
+        service_config.pop("full_node_peer", None)
+        service_config.pop("full_node_peers", None)
 
     service = create_farmer_service(
         root_path,

@felixbrucker
Copy link
Contributor Author

Oh you are talking about the simulator, yeah, that looks good

i was talking about the configure cmd used on the cli, which currently will break as well

im unsure how this command should work with a list, as we probably cant uniquely identify the "self" peer

@altendky
Copy link
Contributor

altendky commented Oct 3, 2023

I'm going to chat around about this. Maybe ping me tomorrow if I haven't gotten an answer to you here.

@emlowe
Copy link
Contributor

emlowe commented Oct 3, 2023

I think this might make some sense for wallet as well if you want to "hardcode" some nodes for a wallet to use.

I believe you are referring to chia configure --set-fullnode-port. I might make it work as follows:
Change the port in full_node_peer if present, otherwise, change the port for the first entry in full_node_peers.

It's seems mostly a testing option, and I don't know how much it's really used.

@altendky
Copy link
Contributor

altendky commented Oct 3, 2023

Chris pointed out --set-farmer-peer.

@felixbrucker
Copy link
Contributor Author

I think this might make some sense for wallet as well if you want to "hardcode" some nodes for a wallet to use.

That is already done yeah 👍

I believe you are referring to chia configure --set-fullnode-port. I might make it work as follows:
Change the port in full_node_peer if present, otherwise, change the port for the first entry in full_node_peers.

Yeah, setting the first entries port was my first thought as well, as that is very likely the self peer in most cases

Chris pointed out --set-farmer-peer.

I'd probably handle it the same here, for the full node it just gets updated same as before as that did not change, and for the harvester its the first entry as well

@felixbrucker felixbrucker requested a review from altendky October 4, 2023 10:51
@felixbrucker felixbrucker force-pushed the add-support-for-lists-of-peers-in-config branch from 65a3646 to b38a3a3 Compare October 7, 2023 06:09
@felixbrucker
Copy link
Contributor Author

Rebased to current main to hopefully get rid of test flakes

@felixbrucker felixbrucker requested a review from altendky October 7, 2023 06:10
@github-actions github-actions bot added the merge_conflict Branch has conflicts that prevent merge to main label Oct 10, 2023
@github-actions
Copy link
Contributor

This pull request has conflicts, please resolve those before we can evaluate the pull request.

…onfig

# Conflicts:
#	chia/cmds/configure.py
#	chia/cmds/sim_funcs.py
#	chia/util/config.py
#	chia/util/initial-config.yaml
@github-actions github-actions bot removed the merge_conflict Branch has conflicts that prevent merge to main label Oct 11, 2023
@github-actions
Copy link
Contributor

Conflicts have been resolved. A maintainer will review the pull request shortly.

@github-actions github-actions bot added the merge_conflict Branch has conflicts that prevent merge to main label Oct 17, 2023
@github-actions
Copy link
Contributor

This pull request has conflicts, please resolve those before we can evaluate the pull request.

…onfig

# Conflicts:
#	chia/server/start_farmer.py
@github-actions github-actions bot removed the merge_conflict Branch has conflicts that prevent merge to main label Oct 17, 2023
@github-actions
Copy link
Contributor

Conflicts have been resolved. A maintainer will review the pull request shortly.

@altendky altendky requested review from emlowe and removed request for xdustinface October 20, 2023 23:15
@emlowe
Copy link
Contributor

emlowe commented Oct 24, 2023

Coverage diff exemption

Much thanks for the PR

@cmmarslender cmmarslender merged commit ef98949 into Chia-Network:main Oct 24, 2023
@felixbrucker felixbrucker deleted the add-support-for-lists-of-peers-in-config branch October 24, 2023 18:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Added Required label for PR that categorizes merge commit message as "Added" for changelog
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants