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

Asyncify BareCryptoStore trait #5940

Closed
wants to merge 4 commits into from

Conversation

rakanalh
Copy link
Contributor

@rakanalh rakanalh commented May 7, 2020

This is part of #4689.
Resolves #5931

@rakanalh rakanalh added the A3-in_progress Pull request is in progress. No review needed at this stage. label May 7, 2020
@rakanalh rakanalh marked this pull request as ready for review May 7, 2020 11:29
@rakanalh rakanalh added A0-please_review Pull request needs code review. and removed A3-in_progress Pull request is in progress. No review needed at this stage. labels May 7, 2020
Copy link
Member

@gavofyork gavofyork left a comment

Choose a reason for hiding this comment

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

looks like a harmless enough refactor to me...

@gavofyork gavofyork modified the milestone: Polkadot May 7, 2020
Copy link
Contributor

@tomusdrw tomusdrw left a comment

Choose a reason for hiding this comment

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

lgtm!

pub trait BareCryptoStore: Send + Sync {
/// Returns all sr25519 public keys for the given key type.
fn sr25519_public_keys(&self, id: KeyTypeId) -> Vec<sr25519::Public>;
async fn sr25519_public_keys(&self, id: KeyTypeId) -> Vec<sr25519::Public>;
Copy link
Contributor

Choose a reason for hiding this comment

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

Note that all methods here will most likely end up returning a Result so that we can handle potential remote signer issues (unless we want them to fall back to some defaults).

@@ -64,8 +67,9 @@ impl KeyStore {
}

#[cfg(feature = "std")]
#[async_trait]
impl crate::traits::BareCryptoStore for KeyStore {
Copy link
Contributor

@tomusdrw tomusdrw May 7, 2020

Choose a reason for hiding this comment

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

Might be good to simply introduce a blocking wrapper for BareCryptoStore instead of sprinkling block_on everywhere. You can do that without introducing any new structs, just adding an extra trait that maintains current API something like this:

pub trait BlockingBareCryptoStore {
  fn keys() -> Vec<...>
}

impl<T: BareCryptoStore> BlockingBareCryptoStore for T {
  fn keys() -> Vec<...> { block_on(BareCryptoStore::keys(self)) }
}

Unless we plan to asyncify more parts of the code in the future, in that case a blockign variant is not worth it.

@tomusdrw tomusdrw added A6-mustntgrumble and removed A0-please_review Pull request needs code review. labels May 7, 2020
Copy link
Contributor

@mxinden mxinden left a comment

Choose a reason for hiding this comment

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

I doubt using block_on is the right way to go here. I think this is a lot more involved. Let me know in case I am missing something.

)
.map_err(|_| Error::Signing)?;
let keystore = key_store.read();
let signatures = block_on(keystore.sign_with_all(
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think blocking on async logic is an option. Instead this should properly pass a context and return Poll::Pending in case the future is not yet ready.

Why not use block_on:

Logic further below might expect to be called in a preemptive non-blocking fashion. Making that assumption in a blocking environment is problematic.

Say e.g. one executes on a single hardware thread. The logic below needs to wait for something, thus returns Poll::Pending. Given that one uses block_on here the thread is stalled and thus the dependency (the thing the logic below is waiting for) never gets any compute time. Thus one has a deadlock.

Copy link
Contributor

Choose a reason for hiding this comment

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

Rather than passing a context, I think a better solution is to turn publish_ext_addresses into an async function and adjusting poll to poll it progressively.
That involves extracting publish_ext_addresses into a freestanding function and passing copies of client, network, etc. but I don't think that's a problem.

@@ -105,7 +105,7 @@ impl<P, Client> AuthorApi<TxHash<P>, BlockHash<P>> for Author<P, Client>

let key_type = key_type.as_str().try_into().map_err(|_| Error::BadKeyType)?;
let mut keystore = self.keystore.write();
keystore.insert_unknown(key_type, &suri, &public[..])
block_on(keystore.insert_unknown(key_type, &suri, &public[..]))
Copy link
Contributor

Choose a reason for hiding this comment

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

We could change the RPC to return a future instead (i.e. asyncify it)

@@ -28,6 +28,9 @@

use sp_std::vec::Vec;

#[cfg(feature = "std")]
use futures::executor::block_on;
Copy link
Contributor

Choose a reason for hiding this comment

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

Is it ok to totally block a runtime execution on potentially some long-duration I/O?

@rakanalh rakanalh self-assigned this May 13, 2020
@rakanalh
Copy link
Contributor Author

Closing this and putting it on hold to implement a different approach.

@rakanalh rakanalh closed this May 15, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Asyncify keystore
6 participants