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

Add precompiles for key generation and signing #1176

Merged
merged 1 commit into from
Dec 13, 2022

Conversation

jberci
Copy link
Contributor

@jberci jberci commented Oct 21, 2022

No description provided.

@kostko kostko requested a review from nhynes October 21, 2022 15:43
@codecov
Copy link

codecov bot commented Oct 21, 2022

Codecov Report

Merging #1176 (7b1e85e) into main (cdb79f9) will increase coverage by 1.35%.
The diff coverage is 90.50%.

❗ Current head 7b1e85e differs from pull request most recent head be27674. Consider uploading reports for the commit be27674 to get more accurate results

@@            Coverage Diff             @@
##             main    #1176      +/-   ##
==========================================
+ Coverage   64.65%   66.01%   +1.35%     
==========================================
  Files         135      136       +1     
  Lines       12384    12960     +576     
==========================================
+ Hits         8007     8555     +548     
- Misses       4345     4373      +28     
  Partials       32       32              
Impacted Files Coverage Δ
runtime-sdk/src/crypto/signature/digests.rs 78.26% <78.26%> (ø)
runtime-sdk/src/crypto/signature/secp256k1.rs 67.14% <84.37%> (+41.50%) ⬆️
runtime-sdk/src/crypto/signature/mod.rs 79.58% <87.09%> (+43.47%) ⬆️
runtime-sdk/src/crypto/signature/ed25519.rs 87.14% <92.10%> (+43.39%) ⬆️
...ime-sdk/modules/evm/src/precompile/confidential.rs 92.01% <93.27%> (+2.68%) ⬆️
runtime-sdk/modules/evm/src/precompile/mod.rs 89.13% <100.00%> (+0.75%) ⬆️

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

nhynes
nhynes previously requested changes Oct 31, 2022
Copy link
Contributor

@nhynes nhynes left a comment

Choose a reason for hiding this comment

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

Thanks for this PR. I think the functionality overall looks solid, but it seems quite like there's some abstraction that describes all three variants in a way that ties them all together and reduces the need for tests.

One approach is to just have the one enum and its impl but have big ol' match arms that handle each case. This keeps things easy to understand and high performance with a slight decrease in readability.

Another approach create a trait called trait MemorySigner (or something) containing provided implementations of all of these methods with associated types type Signer: Signer and type Digest: Digest (so like let mut digest = Self::Digest::new()). You could then pass around a Box<dyn MemorySigner> for polymorphism. This comes with cleaner separation of implementations, but less efficiency (not that it really matters when you're only calling the thing once).

A third approach that mixes the two above and is quite like what you're already doing here: enum dispatch for performance but a trait to keep the APIs in sync. There's even a macro for it (enum_dispatch)! I'm not sure if this one works with associated types, though.

I'd suggest:

  1. take a look at the different kinds of digests and signers you'll need (e.g., k256+sha3, ed25519_dalek+sha2) and see if they all implement a common trait (e.g., digest::Digest). If they do, you can simplify the implementation using associated types.
  2. Try to collect everything into a trait and use Box<dyn Signer> for polymorphism to keep things simple. If you find that doesn't work, then you can bring back your enum but also bind the implementations together using a trait.
  3. Look at enum_dispatch for your own edification. A tiny performance benefit isn't worth the supply chain risk of an extra dependency.

runtime-sdk/modules/evm/src/precompile/confidential.rs Outdated Show resolved Hide resolved
runtime-sdk/modules/evm/src/precompile/confidential.rs Outdated Show resolved Hide resolved
runtime-sdk/src/crypto/signature/ed25519.rs Show resolved Hide resolved
runtime-sdk/src/crypto/signature/ed25519.rs Outdated Show resolved Hide resolved
runtime-sdk/src/crypto/signature/ed25519.rs Outdated Show resolved Hide resolved
runtime-sdk/src/crypto/signature/secp256k1.rs Outdated Show resolved Hide resolved
runtime-sdk/src/crypto/signature/secp256k1.rs Show resolved Hide resolved
@jberci jberci force-pushed the jberci/feature/signing-precompiles branch from 50a301d to 5e32ee7 Compare November 2, 2022 14:52
@jberci jberci force-pushed the jberci/feature/signing-precompiles branch from 5e32ee7 to 7a9b60b Compare November 9, 2022 16:02
@jberci jberci force-pushed the jberci/feature/signing-precompiles branch from 47fb41d to bdfffb0 Compare November 22, 2022 15:47
/// Length of an EVM word, in bytes.
pub const WORD: usize = 32;

pub fn round_up(what: usize) -> usize {
Copy link
Contributor

@nhynes nhynes Nov 23, 2022

Choose a reason for hiding this comment

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

Suggested change
pub fn round_up(what: usize) -> usize {
pub fn round_up_u5(what: usize) -> usize {

is this a correct interpretation?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Depends on what you mean by the u5. The function should round the number up to the nearest multiple of 32, so the bottom 5 bits are cleared.

Copy link
Contributor

@nhynes nhynes left a comment

Choose a reason for hiding this comment

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

This looks overall good. Just one main question, though: I see that the precompile is still about signing messages rather than signing digests using separate digest functions. Am I mistaken in thinking this? @kostko

runtime-sdk/src/crypto/signature/digests.rs Outdated Show resolved Hide resolved
runtime-sdk/src/crypto/signature/ed25519.rs Show resolved Hide resolved
runtime-sdk/modules/evm/src/precompile/confidential.rs Outdated Show resolved Hide resolved
@jberci jberci force-pushed the jberci/feature/signing-precompiles branch 2 times, most recently from d66242c to 95b5c2d Compare December 6, 2022 22:19
runtime-sdk/src/crypto/signature/mod.rs Outdated Show resolved Hide resolved
runtime-sdk/src/crypto/signature/mod.rs Outdated Show resolved Hide resolved
@kostko kostko mentioned this pull request Dec 9, 2022
@nhynes nhynes force-pushed the jberci/feature/signing-precompiles branch from 95b5c2d to 6fdafee Compare December 10, 2022 08:20
@jberci jberci force-pushed the jberci/feature/signing-precompiles branch from 6fdafee to efbc21d Compare December 12, 2022 23:24
@jberci jberci force-pushed the jberci/feature/signing-precompiles branch from 7b1e85e to be27674 Compare December 13, 2022 13:10
@jberci jberci merged commit c43daf9 into main Dec 13, 2022
@jberci jberci deleted the jberci/feature/signing-precompiles branch December 13, 2022 14:20
const WORD: usize = 32;

/// The cost of a key pair generation operation, per method.
static KEYPAIR_GENERATE_BASE_COST: Lazy<HashMap<SignatureType, u64>> = Lazy::new(|| {
Copy link
Contributor

Choose a reason for hiding this comment

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

please inline this as an if ... else if ... else (or match)

});

/// The costs of a message signing operation.
static SIGN_MESSAGE_COST: Lazy<HashMap<SignatureType, (u64, u64)>> = Lazy::new(|| {
Copy link
Contributor

Choose a reason for hiding this comment

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

please inline this as an if ... else if ... else (or match)

impl SignatureType {
pub fn as_int(&self) -> u8 {
match self {
Self::Ed25519_Oasis => 0,
Copy link
Contributor

Choose a reason for hiding this comment

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

I suggest that 0 be nothing for the same reason protobuf makes the zeroth item Unknown (especially good for solidity where you can't test for presence).

}

impl super::Signer for MemorySigner {
fn new_from_seed(seed: &[u8]) -> Result<Self, Error> {
Copy link
Contributor

Choose a reason for hiding this comment

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

this isn't really so much of generate as derivePublicKey. Maybe this should invoke random_bytes with seed as the pers str?

@nhynes
Copy link
Contributor

nhynes commented Dec 13, 2022

guess I was too late

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants