-
Notifications
You must be signed in to change notification settings - Fork 2.7k
Refactor key management #3213
Refactor key management #3213
Conversation
|
This could potentially deprecate the Just needs some test-fixing as well, with which I could help if needed. |
|
yeah that'd be good. can also merge |
|
Signed-Extension-related tests should work fine now; I have the logic needed to throw out |
| #[derive(Clone, Copy, PartialEq, Eq, Encode, Decode)] | ||
| #[cfg_attr(feature = "std", derive(Debug))] | ||
| #[repr(u32)] | ||
| pub enum Kind { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason to avoid using an enum is that we will never be able to exhaustively define all crypto types. This change makes it impossible to introduce custom crypto without requiring an upstream pull request
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not convinced it would be otherwise trivial to add new kinds of crypto. Realistically, that crypto would need extern and/or off-chain crypto support which would necessitate alterations to core. There could be a crypto Kind of User, which would basically mean "core doesn't know anything about it". In any case, this would not be needed any time soon so can go in a separate PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why should core need to know anything about any of the kinds of crypto?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mainly for offchain worker stuff. Hopefully we can remove this.
|
It would also be helpful to ensure that the model does not make this less possible: #3063 (comment) . Ideally the slashing subsystems don't have to make any assumption about what kind of crypto is used for transactions, and we should make sure that this PR doesn't introduce anything in that direction. One reason that I've wanted |
|
@kianenigma If it can be applied here, then I don't see why not. @rphmeier The store shouldn't be searched for keys of a certain type of crypto, it should be keys from a certain subsystem. If two subsystems happen to use the same underlying crypto, then it should not entail them sharing the same keys. This appears to be a recurring point and it was a Big Problem with the previous design.
|
core/primitives/src/crypto.rs
Outdated
| /// Key type for controlling an account in a Substrate runtime, built-in. | ||
| pub const ACCOUNT: KeyTypeId = *b"acco"; | ||
| /// Key type for Aura module, built-in. | ||
| pub const AURA: KeyTypeId = *b"acco"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo, should be *b"aura"
|
So does the keystore have to persist keys to disk or not? I was under the impression that that was not the case, since the only keys in the keystore are session keys which should only be stored in memory according to a discussion on riot. |
When you generate new session keys and only know the public key, what will you do when your node crashes? Let's say the node crashes and you already send the transaction to change the session key. You could not participate with this session key, as you have lost it. Sounds like we should persist them? |
|
The previous thinking was that the client generates/persists the session keys and configures them via rpc. |
Seems not to be wanted anymore. |
Oh? Why? |
|
Maybe I misunderstood @dvc94ch, but didn't he talked about sending the private key via RPC? Or is client the As I understood your comment, you call |
|
I read the PR text, I was just wondering why the change. I believe @joepetrowski and @gavofyork used to be of the opinion that offloading key management to the client is a good idea for security reasons, although I'm not really sure why that was. |
|
I still don't know what you referring to when you talk about "client"^^ |
|
Wallet if you prefer... |
I'm slowly working on this, but considering the amount of changes I'm waiting for all PRs that touch the service to land before actually doing that. |
Cleanup some naming
|
the idea is that both models are supported (user pushing private keys via RPC to the node and having the user pull public keys from node over RPC). |
This will eventually allow for dynamic determination of authority keys and avoid having to set them directly on CLI.
Experiment with modular consensus API.
dab7203 to
caa07e4
Compare
| + HeaderBackend<<Self::Client as BlockOf>::Type>; | ||
|
|
||
| /// Initialize the consensus service. | ||
| fn initialize(client: &'a Self::Client, keystore: Arc<Store>) -> Self; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There doesn't seem to be a good reason why we should have service objects at all.
The design of the pluggable consensus system was intended to avoid over-assumption about what resources a consensus system might need access to, and I'm afraid that's exactly what this trait function is -- it's omitting at a bare minimum network and event-loop access.
The primitive of "some thing that can be driven to completion" (i.e. a Future) is much less fragile.
I understand the motivation of wanting to avoid users having to write any consensus-specific initialization in their service files, but it should be 1 line per consensus engine at most, if we instead go the route of consensus crates exposing an initialize function (without fixed type signature!).
That is much more anti-fragile compared to a bunch of trait machinery/macro magic trying to create an idealized declarative system that will almost certainly have to be ripped up later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Additionally, considering that this PR is pressing, let's please not introduce API changes that aren't strictly necessary, because discussions around such API changes shouldn't get rushed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was really just a draft design to get people thinking, I'm not familiar enough with the details of the overall consensus framework to do much more. That said...
My concern is that it actually is "1 line per consensus engine at most".
Right now it's a load of incoherent boilerplate babble that chain creators can neither write nor understand. Enforcing a coherent API that clearly provides the functions and hooks that a consensus service may use in a single place would dramatically improve devex.
Right now as a developer looking to create a new consensus system in Substrate, I'm faced with an incoherent mashup of randomly assorted crates that I'm expected to magically understand which I should be using where, how they get initialised, referenced and driven.
Over-generalising might technically enable everything, but unless you take care to provide an appropriate environment and API rails, you'll end up with nothing.
|
Closed in favour of #3296 |
This PR is turning into a major refactoring over the crypto and key management system, which seems both long overdue and somewhat inescapable.
I'll want to integrate the general changes in (but not merge) #3034 and possibly #3193 together with #3137.
The main issues that this PR aims to solve are:
fn fg_authority_key()all the way through the codebase). Though they do now, they won't forever and it shouldn't be an assumption that we bake in to internal APIs.TODO:
Refactor
ImOnline:Dynamic key selection:
--validatorto enable active validation process; remove any validator key-management stuff from the CLI (--key). (A second--workerarg can enable off-chain workers.)--keyall the way down to key-choice).authority_key/fg_authority_keyAPIs completely.--passwordwork (should accept a manually-entered password and use it for everything in the keystore).author_rotateKeyswhich creates a new set of session keys, saves them to the key-store and returns their public keys, so that a rotation-transaction can be constructed. There should be no pollution of the APIs with session keys: the rotation API should be wholly independent of each of the individual keys. This may mean new APIs in theOpaqueKeystrait.Refactor
Client:Clienttrait that provides all the basic APIs and hasBlockas an associated item.I would also like to solve the fact that service construction is highly monolithic and polluted by consensus-module-specific code. Really it should just be a case of specifying the block production and finality systems and letting it do the rest. Code for set-up, take-down, RPC and key-store integration should be provided through traits that the consensus modules (Babe, Aura, Grandpa and eventually Rho and PoW) implement within their module's scope. There shouldn't be any consensus-module-specific logic dirtying up
service.rs. That might be a different PR, though.service:service.rsinto the respective consensus modules. Provide a single API endpoint (i.e. a type that implements someConsensusSystemtrait and have that as the only resource that service needs know of.This also adds:
swapto allow two storage items in the same map to be swapped.