-
Notifications
You must be signed in to change notification settings - Fork 710
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
Make polkadot behave correctly if node changes peer-id at restart #3673
Comments
The first link is not really a problem. Just more the explanation why these people could not connect to all the other validators. polkadot-sdk/polkadot/node/network/gossip-support/src/lib.rs Lines 327 to 352 in 809d466
This function needs to be called multiple times per session. Currently we don't call this once and if a validator address was not known at this point, we will never resolve it in this session. |
Messed up the links, fixed it in the description. |
Looked a bit more closer at
Both 1) & 3) will happen until the old record TTL is met which currently is 36 hours, after that the new record will be the only one in the network. Why does this happen ?The way What can we do ?At least as far as I can tell this behaviour is entrenched in the So, I'm inclined to think changing the network key(PeerID) while a node is in the active set should not be considered a safe operation, to perform, hence what I'm proposing is:
@bkchr @dmitry-markin @eskimor Thoughts ? |
Here are my notes from last week that I wanted to put into an issue actually:
This assumes the same as you are writing. However, I would like to try to optimize the current implementation given the points above. We can also go further and extend the record with a timestamp to find out which one is newer. We also don't verify the data in the DHT storage. The verification is only done in the authority discovery. This means that the DHT may could still contain invalid values.
Could be done as well, but should only be done for validators. Generally we probably need to improve docs around this stuff. There also exists |
Ok, I see what you mean, so basically if we let the query continue we could probably end up discovering both more often than not and have them both stored in authorithy-discovery. Let me check how that behaves. |
…e robust In the case when nodes don't persist their node-key or they want to generate a new one while being in the active set, things go wrong because both the old addresses and the new ones will still be present in DHT, so because of the distributed nature of the DHT both will survive in the network untill the old ones expires which is 36 hours. Nodes in the network will randomly resolve the authorithy-id to the old address or the new one. More details in: #3673 This PR proposes we mitigate this problem, by: 1. Let the query for a DHT key retrieve all the results, that is usually bounded by the replication factor which is 20, currently we interrupt the querry on the first result. 2. Modify the authority-discovery service to keep all the discovered addresses around for 24h since they last seen an address. 3. Plumb through other subsystems where the assumption was that an authorithy-id will resolve only to one PeerId. Currently, the authorithy-discovery keeps just the last record it received from DHT and queries the DHT every 10 minutes. But they could always receive only the old address, only the new address or a flip-flop between them depending on what node wins the race to provide the record 4. Update gossip-support to try resolve authorities more often than every session. This would gives us a lot more chances for the nodes in the networks to also discover not only the old address of the node but also the new one and should improve the time it takes for a node to be properly connected in the network. The behaviour won't be deterministic because there is no guarantee the all nodes will see the new record at least once, since they could query only nodes that have the old one. Signed-off-by: Alexandru Gheorghe <alexandru.gheorghe@parity.io>
Posted a draft PR with all the plumbing that would need to happen to make this a bit better than the way it currently is: #3786, let me know what you guys think, don't be nitpicky it is in a very rough form :D. |
I don't understand why people regenerate the PeerIDs of validators in the first place. Obviously, a validator should have the actual database, so the contents of Generally I'm for not-regenerating PeerIDs of the validators without a sound reason (is there one?)
May be make this default for validators only? This would change the interface and force operators to update their procedures, but we can print a nice error message if somebody starts a validator without network key file present.
IMO, this should be an explicit cli command like |
Likewise, we could fix this in the CLI and require validators to use
I think this sounds like a reasonable solution to me. We'd need to extend the polkadot-sdk/substrate/client/network/src/discovery.rs Lines 475 to 478 in e88d1cb
Then, in the authority-discovery, we could store only the most recent records, since we know that older records might contain stale addresses. While at it, we could also have a look at the |
I've been down that road, it won't work because expiry is actually a function of the distance from the key to the node answering the request: https://github.com/libp2p/rust-libp2p/blob/master/protocols/kad/src/behaviour.rs#L1816. Expiry doesn't tell how old the record is because if you get it from nodes farther from the key they would have a close expiry they should not store the record for too much time. |
In this case a large validator set >50, were mount individually the keystore and db in their pod, so they missed persisting the network:
|
I was thinking to name it more like --i-know-i-m-getting-0-rewards-but-auto-generate-node-key :D |
PR to not allow auto generate of network key unless it is explicitly required: #3852. |
As discovered during investigation of #3314 and #3673 there are active validators which accidentally might change their network key during restart, that's not a safe operation when you are in the active set because of distributed nature of DHT, so the old records would still exist in the network until they expire 36h, so unless they have a good reason validators should avoid changing their key when they restart their nodes. There is an effort in parallel to improve this situation #3786, but those changes are way more intrusive and will need more rigorous testing, additionally they will reduce the time to less than 36h, but the propagation won't be instant anyway, so not changing your network during restart should be the safest way to run your node, unless you have a really good reason to change it. ## Proposal 1. Do not auto-generate the network if the network file does not exist in the provided path. Nodes where the key file does not exist will get the following error: ``` Error: 0: Starting an authorithy without network key in /home/alexggh/.local/share/polkadot/chains/ksmcc3/network/secret_ed25519. This is not a safe operation because the old identity still lives in the dht for 36 hours. Because of it your node might suffer from not being properly connected to other nodes for validation purposes. If it is the first time running your node you could use one of the following methods. 1. Pass --unsafe-force-node-key-generation and make sure you remove it for subsequent node restarts 2. Separetly generate the key with: polkadot key generate-node-key --file <YOUR_PATH_TO_NODE_KEY> ``` 2. Add an explicit parameters for nodes that do want to change their network despite the warnings or if they run the node for the first time. `--unsafe-force-node-key-generation` 3. For `polkadot key generate-node-key` add two new mutually exclusive parameters `base_path` and `default_base_path` to help with the key generation in the same path the polkadot main command would expect it. 4. Modify the installation scripts to auto-generate a key in default path if one was not present already there, this should help with making the executable work out of the box after an instalation. ## Notes Nodes that do not have already the key persisted will fail to start after this change, however I do consider that better than the current situation where they start but they silently hide that they might not be properly connected to their peers. ## TODO - [x] Make sure only nodes that are authorities on producation chains will be affected by this restrictions. - [x] Proper PRDOC, to make sure node operators are aware this is coming. --------- Signed-off-by: Alexandru Gheorghe <alexandru.gheorghe@parity.io> Co-authored-by: Dmitry Markin <dmitry@markin.tech> Co-authored-by: s0me0ne-unkn0wn <48632512+s0me0ne-unkn0wn@users.noreply.github.com> Co-authored-by: Bastian Köcher <git@kchr.de>
…e robust (#3786) In the case when nodes don't persist their node-key or they want to generate a new one while being in the active set, things go wrong because both the old addresses and the new ones will still be present in DHT, so because of the distributed nature of the DHT both will survive in the network untill the old ones expires which is 36 hours. Nodes in the network will randomly resolve the authorithy-id to the old address or the new one. More details in: #3673 This PR proposes we mitigate this problem, by: 1. Let the query for a DHT key retrieve more than one results(4), that is also bounded by the replication factor which is 20, currently we interrupt the querry on the first result. ~2. Modify the authority-discovery service to keep all the discovered addresses around for 24h since they last seen an address.~ ~3. Plumb through other subsystems where the assumption was that an authorithy-id will resolve only to one PeerId. Currently, the authorithy-discovery keeps just the last record it received from DHT and queries the DHT every 10 minutes. But they could always receive only the old address, only the new address or a flip-flop between them depending on what node wins the race to provide the record~ 2. Extend the `SignedAuthorityRecord` with a signed creation_time. 3. Modify authority discovery to keep track of nodes that sent us old record and once we are made aware of a new record update the nodes we know about with the new record. 4. Update gossip-support to try resolve authorities more often than every session. ~This would gives us a lot more chances for the nodes in the networks to also discover not only the old address of the node but also the new one and should improve the time it takes for a node to be properly connected in the network. The behaviour won't be deterministic because there is no guarantee the all nodes will see the new record at least once, since they could query only nodes that have the old one.~ ## TODO - [x] Add unittests for the new paths. - [x] Make sure the implementation is backwards compatible - [x] Evaluate if there are any bad consequence of letting the query continue rather than finish it at first record found. - [x] Bake in versi the new changes. --------- Signed-off-by: Alexandru Gheorghe <alexandru.gheorghe@parity.io> Co-authored-by: Dmitry Markin <dmitry@markin.tech> Co-authored-by: Alexandru Vasile <60601340+lexnv@users.noreply.github.com>
Problem mitigated with: 6720279 |
…e robust (paritytech#3786) In the case when nodes don't persist their node-key or they want to generate a new one while being in the active set, things go wrong because both the old addresses and the new ones will still be present in DHT, so because of the distributed nature of the DHT both will survive in the network untill the old ones expires which is 36 hours. Nodes in the network will randomly resolve the authorithy-id to the old address or the new one. More details in: paritytech#3673 This PR proposes we mitigate this problem, by: 1. Let the query for a DHT key retrieve more than one results(4), that is also bounded by the replication factor which is 20, currently we interrupt the querry on the first result. ~2. Modify the authority-discovery service to keep all the discovered addresses around for 24h since they last seen an address.~ ~3. Plumb through other subsystems where the assumption was that an authorithy-id will resolve only to one PeerId. Currently, the authorithy-discovery keeps just the last record it received from DHT and queries the DHT every 10 minutes. But they could always receive only the old address, only the new address or a flip-flop between them depending on what node wins the race to provide the record~ 2. Extend the `SignedAuthorityRecord` with a signed creation_time. 3. Modify authority discovery to keep track of nodes that sent us old record and once we are made aware of a new record update the nodes we know about with the new record. 4. Update gossip-support to try resolve authorities more often than every session. ~This would gives us a lot more chances for the nodes in the networks to also discover not only the old address of the node but also the new one and should improve the time it takes for a node to be properly connected in the network. The behaviour won't be deterministic because there is no guarantee the all nodes will see the new record at least once, since they could query only nodes that have the old one.~ ## TODO - [x] Add unittests for the new paths. - [x] Make sure the implementation is backwards compatible - [x] Evaluate if there are any bad consequence of letting the query continue rather than finish it at first record found. - [x] Bake in versi the new changes. --------- Signed-off-by: Alexandru Gheorghe <alexandru.gheorghe@parity.io> Co-authored-by: Dmitry Markin <dmitry@markin.tech> Co-authored-by: Alexandru Vasile <60601340+lexnv@users.noreply.github.com>
During the investigation for #3314 we discovered there is a number of validators that change their PeerId at every restart, that seems not work properly right now.
Work-arrounds
network
folder, so you can simply reuse that by always providing--base-path
argument and making sure the network folder is present where you restart the node.[WIP] Things that need fixing
In general all the assumptions where we think we have just one PeerID per AuthorithyId are breaking this on a quick scan by me and @bkchr:
With kusama size nodes won't be able to connect to nodes if they aren't in the reserved set.
polkadot-sdk/polkadot/node/network/protocol/src/peer_set.rs
Lines 95 to 96 in 809d466
Some places where the assumption that just one peerID per authority exist.
polkadot-sdk/polkadot/node/network/gossip-support/src/lib.rs
Line 408 in 809d466
polkadot-sdk/polkadot/node/network/statement-distribution/src/v2/mod.rs
Line 451 in a756baf
Another thing that I observed that is probably off while testing on versi is that
ConnectToResolvedValidators
gets called sometime with the new address and sometimes with old-address.The text was updated successfully, but these errors were encountered: