Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Mixnet integration #14207

Closed
wants to merge 20 commits into from
Closed

Mixnet integration #14207

wants to merge 20 commits into from

Conversation

zdave
Copy link
Contributor

@zdave zdave commented May 23, 2023

See #13904.

This adds all the necessary mixnet components, and puts them together in the "kitchen-sink" node/runtime. The components added are:

  • A pallet (frame/mixnet). This is responsible for determining the current mixnet session and phase, and the mixnodes to use in each session. It includes an offchain worker which attempts to automatically register validator nodes as mixnodes. The logic of this pallet is very similar to that of the im-online pallet.
  • A service (client/mixnet). This implements the core mixnet logic, building on the mixnet crate. The service communicates with other nodes using notifications sent over the "mixnet" protocol.
  • An RPC interface. This currently only supports sending transactions over the mixnet.

@zdave zdave requested review from cheme, arkpar and a team May 23, 2023 20:19
@arkpar arkpar requested a review from bkchr May 23, 2023 22:57
@zdave
Copy link
Contributor Author

zdave commented May 24, 2023

Ideally the new CLI options would only be added to the kitchen-sink node, but the best way to achieve this is not obvious to me.

@zdave zdave added B1-note_worthy Changes should be noted in the release notes C1-low PR touches the given topic and has a low impact on builders. T0-node This PR/Issue is related to the topic “node”. T1-runtime This PR/Issue is related to the topic “runtime”. T2-API This PR/Issue is related to APIs. D2-notlive 💤 PR contains changes in a runtime directory that is not deployed to a chain that requires an audit. and removed T1-runtime This PR/Issue is related to the topic “runtime”. T2-API This PR/Issue is related to APIs. labels May 24, 2023
Copy link
Contributor

@cheme cheme left a comment

Choose a reason for hiding this comment

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

Had a few question from my first reading, at this point I did not yet get the session even odd logic, but will look at it soon.

@@ -165,6 +168,7 @@ impl<T: offchain::DbExternalities + Clone + Sync + Send + 'static> DbExternaliti
pub struct ExecutionExtensions<Block: BlockT> {
strategies: ExecutionStrategies,
keystore: Option<KeystorePtr>,
mixnet_kx_public_store: Option<Arc<MixnetKxPublicStore>>,
Copy link
Contributor

Choose a reason for hiding this comment

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

Thinking out loud (no idea if better), could this have been part of existing keystore?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I didn't think the requirements overlapped enough for this to make sense. The existing keystore is (AFAICT) designed for long-lived keys that persist across node restarts. The mixnet key-exchange keys are only used for a single session (a few hours), and should be destroyed once the session ends. They intentionally do not persist across node restarts, as this would be non-trivial to implement properly:

  • When destroying keys you would have to be careful to properly erase the key data from disk.
  • The corresponding replay filters would also have to persist, or you would be vulnerable to replay attacks after a node restart.

I opened a GitHub issue about this a while back (#12595), there wasn't really any conclusion though.

client/cli/src/params/mixnet_params.rs Outdated Show resolved Hide resolved
client/mixnet/src/packet_dispatcher.rs Outdated Show resolved Hide resolved
client/api/src/execution_extensions.rs Outdated Show resolved Hide resolved
client/mixnet/src/extrinsic_queue.rs Show resolved Hide resolved

impl<MaxPeerIdSize, MaxExternalAddressSize, MaxExternalAddresses> Into<OpaqueMixnode>
for BoundedOpaqueMixnode<
BoundedVec<u8, MaxPeerIdSize>,
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure if doable but type aliasing BoundedVec<u8, MaxPeerIdSize> to PeerIdRuntime or a better name would be good.
Also for BoundedVec<u8, MaxExternalAddressSize>.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I would like to write something like impl<T: Config> Into<OpaqueMixnode> for BoundedOpaqueMixnodeFor<T> here, but the Rust compiler doesn't like this:

error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
  --> frame/mixnet/src/lib.rs:84:6
   |
84 | impl<T: Config> Into<OpaqueMixnode> for BoundedOpaqueMixnodeFor<T>
   |      ^ unconstrained type parameter

I can do something like this, but not sure it's better:

pub type BoundedPeerId<MaxSize> = BoundedVec<u8, MaxSize>;
pub type BoundedExternalAddress<MaxSize> = BoundedVec<u8, MaxSize>;
pub type BoundedExternalAddresses<MaxSizeEach, Max> =
	BoundedVec<BoundedExternalAddress<MaxSizeEach>, Max>;

impl<MaxPeerIdSize, MaxExternalAddressSize, MaxExternalAddresses> Into<OpaqueMixnode>
	for BoundedOpaqueMixnode<
		BoundedPeerId<MaxPeerIdSize>,
		BoundedExternalAddresses<MaxExternalAddressSize, MaxExternalAddresses>,
	>

frame/mixnet/src/lib.rs Outdated Show resolved Hide resolved
frame/mixnet/src/lib.rs Show resolved Hide resolved

#[pallet::call]
impl<T: Config> Pallet<T> {
/// Register a mixnode for the following session.
Copy link
Contributor

Choose a reason for hiding this comment

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

is there a way to register a change of external address for the current session?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No. Doesn't feel worthwhile to implement this to me; sessions should only be a few hours?

Copy link
Contributor

Choose a reason for hiding this comment

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

if a few hour offline is acceptable (probably is initially).

frame/mixnet/src/lib.rs Outdated Show resolved Hide resolved
@tomaka
Copy link
Contributor

tomaka commented May 25, 2023

Is there (or is there going to be) some kind of documentation for how this works at the protocol level somewhere? (source code doesn't count, since it is extremely hard to decipher for non-maintainers)

@cheme
Copy link
Contributor

cheme commented May 26, 2023

Is there (or is there going to be) some kind of documentation for how this works at the protocol level somewhere? (source code doesn't count, since it is extremely hard to decipher for non-maintainers)

That is a really good question, the design did change a lot since the first prototyping, and a high level documentation would be probably good too.
Not sure when is the right time for the effort, and the correct medium.
I mean probably what I would want is a good technical blog post to give me reading direction on the project (with frame description and more general network behaviour (delays, routings...)).
Could also wonder if the protocol could be in a Psp?

@arkpar
Copy link
Member

arkpar commented May 26, 2023

Here's a tracking issue for the documentaiton:
paritytech/mixnet#13

@zdave
Copy link
Contributor Author

zdave commented May 26, 2023

Is there (or is there going to be) some kind of documentation for how this works at the protocol level somewhere? (source code doesn't count, since it is extremely hard to decipher for non-maintainers)

There isn't really anything yet. I'll try to put something together next week. If you're interested in something to read now, the packet format is very close to what is described in the Sphinx paper.

@arkpar
Copy link
Member

arkpar commented May 30, 2023

From what I can see, after the initial sync the node will wait for the registration phase of the next session before registering. How does it it handle traffic in the meantime and what key will be used? Would it make sense to register immediatelly after the sync is completed?

primitives/io/src/lib.rs Outdated Show resolved Hide resolved
@zdave
Copy link
Contributor Author

zdave commented May 30, 2023

From what I can see, after the initial sync the node will wait for the registration phase of the next session before registering. How does it it handle traffic in the meantime and what key will be used? Would it make sense to register immediatelly after the sync is completed?

If a node isn't registered as a mixnode it should only receive reply and loop cover traffic, which it will generate a random key pair for. The public key doesn't need to be shared with any other nodes.

If a node is registered as a mixnode and then restarts, it will no longer have the private key corresponding to the public key that was registered, so it will only be able to operate as a non-mixnode until the next session.

I haven't really thought about allowing registrations after the start of a session. Maybe this could be made to work, but it seems like a bunch of extra complexity for little gain. Sessions are only a few hours long, and if a node is an active validator in a session, it should really stay online for the whole session.

@zdave zdave requested a review from a team June 1, 2023 13:40
@zdave zdave requested a review from a team as a code owner June 1, 2023 13:40
@cla-bot-2021
Copy link

cla-bot-2021 bot commented Jun 1, 2023

User @zdave-parity, please sign the CLA here.

@zdave
Copy link
Contributor Author

zdave commented Jun 5, 2023

Ideally the new CLI options would only be added to the kitchen-sink node, but the best way to achieve this is not obvious to me.

Done this now. And got rid of the client/service changes; all that stuff is just in bin/node now.

@paritytech-ci paritytech-ci requested a review from a team June 7, 2023 11:11
@zdave
Copy link
Contributor Author

zdave commented Jul 17, 2023

Been on holiday for 2 weeks, just getting back to this.

Re moving the registration stuff from an offchain worker to a separate call into the runtime: I can do this, but it will involve duplicating some of the stuff in client/offchain, or making it public. Currently I'm calling sp_io::offchain::random_seed(), sp_io::offchain::is_validator(), and sp_io::offchain::network_state() from the offchain worker. I'll have to copy across some of the Externalities implementation from client/offchain, or I guess pass this stuff in as arguments.

It's not clear to me why the offchain stuff is handled differently to the other execution extensions -- why is the Externalities implementation attached to ExecutionContext rather than ExecutionExtensions? This would be easier if the latter was the case.

Responsible for determining the mixnode set for each session.
@paritytech-ci paritytech-ci requested a review from a team July 27, 2023 18:36
@zdave
Copy link
Contributor Author

zdave commented Jul 27, 2023

I've reworked things to get rid of the offchain worker. The mixnet service now just calls the MixnetApi::maybe_register runtime function every block instead, which does basically the same thing.

@arkpar
Copy link
Member

arkpar commented Jul 31, 2023

@bkchr Could you please take another look?

client/cli/src/params/mixnet_params.rs Outdated Show resolved Hide resolved
@@ -0,0 +1,67 @@
// This file is part of Substrate.
Copy link
Member

Choose a reason for hiding this comment

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

It would also be really nice to move this into sc-mixnet.

Copy link
Contributor Author

@zdave zdave Aug 21, 2023

Choose a reason for hiding this comment

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

Hmm I'm actually thinking the kitchen-sink node would be the right place for this? It makes assumptions that are not made by sc-mixnet. For example, sc-mixnet does not assume that non-authorities cannot be mixnodes (sc-mixnet doesn't care whether nodes are authorities or not). Similarly, sc-mixnet doesn't really know anything about RPC (so the comments about RPC would be out of place).

If you agree, I'll move it there instead.

client/mixnet/src/api.rs Outdated Show resolved Hide resolved
client/mixnet/src/api.rs Outdated Show resolved Hide resolved
client/mixnet/src/config.rs Show resolved Hide resolved
frame/mixnet/src/lib.rs Show resolved Hide resolved
frame/mixnet/src/lib.rs Outdated Show resolved Hide resolved
frame/mixnet/src/lib.rs Outdated Show resolved Hide resolved
frame/mixnet/Cargo.toml Outdated Show resolved Hide resolved
frame/mixnet/src/lib.rs Outdated Show resolved Hide resolved
Not necessary; the mixnet pallet can track the session index itself.
To avoid node depending on pallet_mixnet.
In particular, avoid referring to "the register phase". Just refer to it
as the DisconnectFromPrev phase, which is the name of the enum variant.
Note that registrations are now accepted in all phases, and the previous
mixnode set is kept for the whole session.
@paritytech-cicd-pr
Copy link

The CI pipeline was cancelled due to failure one of the required jobs.
Job name: cargo-check-benches
Logs: https://gitlab.parity.io/parity/mirrors/substrate/-/jobs/3426351

@zdave zdave closed this by deleting the head repository Aug 31, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
B1-note_worthy Changes should be noted in the release notes C1-low PR touches the given topic and has a low impact on builders. D2-notlive 💤 PR contains changes in a runtime directory that is not deployed to a chain that requires an audit. T0-node This PR/Issue is related to the topic “node”.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants