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

User can participate in signing protocol #362

Closed
ameba23 opened this issue Jun 19, 2023 · 2 comments
Closed

User can participate in signing protocol #362

ameba23 opened this issue Jun 19, 2023 · 2 comments
Assignees
Labels
Feature introduces a new feature

Comments

@ameba23
Copy link
Contributor

ameba23 commented Jun 19, 2023

User participates in signing protocol - Feature Design Notes

Currently the user sends all shares to the threshold servers. In this feature, the user could keep one share to store themselves, and participate in the signing protocol together with the threshold servers.

  • It should be optional - user may or may not be a signing party.

Things we need:

  1. entropy-core - A way for the threshold servers to know whether or not the user is a signing party.
  2. entropy-core - A way for the threshold servers to communicate with the user when undertaking the signing protocol.
  3. synedrion-wasm - needs bindings to the sessions API.
  4. entropy-js a way for the user to execute the signing protocol and communicate with threshold servers.

1. entropy-core - A way for threshold servers to know whether the user is a signing party

The simplest way to do this would be that that the user indicates that they are going to participate in signing in a boolean passed in the UserTransactionRequest whenever they sign a message.

But probably better is if the chain tracks that the user has a key-share. This could be done as follows:

  • In the staking extension, ThresholdServers is renamed as SigningParties
  • ServerInfo is renamed as SigningPartyInfo and would look like this:
pub struct SigningPartyInfo<AccountId> {
    pub account: AccountId,
    pub signing_party_type: SigningPartyType,
}

pub enum SigningPartyType {
    User,
    ThresholdServer {
        endpoint: TssServerUrl,
        x25519_public_key: X25519PublicKey,
    },
}
  • On user registration, the relayer pallet register function should additionally take a boolean to indicate the user has a keyshare. If true, this function should internally call the staking extention's validate to declare the user as a signing party and store their SigningPartyInfo.

  • The staking pallet's new_session_handler function would need to check which signing parties are users, and put them in a signing sub-group of their own (containing only the user themselves).

  • A possible problem - SIGNING_PARTY_SIZE is declared as a constant. If the user participates we might want more signers, eg: 1 user and 2 validators.

2. entropy-core - The threshold servers communicate with the user to carry out the signing protocol

  • Use Websockets rather than Server Sent Events for protocol messages.
  • Because websockets are bidirectional, whereas SSE is one direction, we need one connection for each pair of signing parties (rather than everyone subscribes to everyone)
  • To decide who connects to who, follow this rule: (this logic would replace subscribe_to_them)
    • Iterate over signing parties
      • If the signing party is a user, do not initiate a connection (we don't have an IP address for them)
      • If the signing party is another threshold server, deterministically decide whether to initiate a connection - eg: by comparing account IDs or socket addresses.
      • If we do not initiate a connection, we wait for a connection from the remote party and accept it.
  • We split the websocket connection into read and write components, and use them to build our Channels. To do this we would need to modify Listener.
  • Once we have Channels which should send and receive SigningMessage from the respective read and write halves of the websocket connection, we should not need to modify the rest of the signing client code - execute_sign should stay just as it is.

3. synedrion-wasm needs bindings to the sessions API

Need to cover make_interactive_signing_session and its output type Session<InteractiveSigningState>.

4. entropy-js - the user executes the signing protocol and communicates with threshold servers

  • In the register method, we need to indicate whether or not we have stored a share locally.
  • If the user holds a share, they can pass it to the sign method. If a key-share is passed, we need to open a websocket connection to each threshold server, call make_interactive_signing_session, and relay messages between the Session and our set of websocket connections.
  • We no longer need to poll for a signature - we get it as a result of the session.
@ameba23 ameba23 converted this from a draft issue Jun 19, 2023
@ameba23 ameba23 changed the title User can participates in signing protocol User can participate in signing protocol Jun 19, 2023
@ameba23 ameba23 added the Feature introduces a new feature label Jun 19, 2023
@ameba23 ameba23 moved this from 📋 Backlog to 🏗 In progress in Entropy Core Jul 26, 2023
@ameba23 ameba23 self-assigned this Jul 26, 2023
@ameba23
Copy link
Contributor Author

ameba23 commented Aug 18, 2023

I am planning to move the signing (and DKG) protocol logic, as well has the handshaking and encryption logic, into a separate crate that can be used by both the SDK and server - so the same code can be called by validator nodes and users to execute the signing and DKG protocols.

The tricky part of this is the different websocket implementations. Already we are using axum::extract::ws for handling incoming connections, and tokio-tungstenite for outgoing connections. In wasm we would use the native JS websocket implementation, eg: from bindings provided by the gloo-net crate.

Since we have channels which relay messages between the encrypted websocket connections and the signing / DKG protocols, one option would be to move the handshaking and encryption logic to the other side of these channels.

The other option is using the Stream and Sink traits, or some other trait giving us a way of accessing an arbitrary websocket implementation.

I think for both these options, error handling is going to be the hardest part.

@ameba23
Copy link
Contributor Author

ameba23 commented Dec 6, 2023

Completed

@ameba23 ameba23 closed this as completed Dec 6, 2023
@github-project-automation github-project-automation bot moved this from 🏗 In progress to ✅ Done in Entropy Core Dec 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature introduces a new feature
Projects
Archived in project
Development

No branches or pull requests

1 participant