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 20-byte account id to subxt_core #1638

Merged
merged 3 commits into from
Jun 19, 2024
Merged

Add 20-byte account id to subxt_core #1638

merged 3 commits into from
Jun 19, 2024

Conversation

pkhry
Copy link
Contributor

@pkhry pkhry commented Jun 11, 2024

Description:

see #1576. This mr just moves the AccountId20 implementation to subxt_core and adds serde's Serialize and Deserialize implementations for it.

closes #1576

@pkhry pkhry requested a review from a team as a code owner June 11, 2024 08:16
core/src/utils/account_id20.rs Outdated Show resolved Hide resolved
core/Cargo.toml Outdated Show resolved Hide resolved
signer/Cargo.toml Outdated Show resolved Hide resolved
impl AccountId20 {
/// Convert to a public key hash
pub fn checksum(&self) -> String {
let hex_address = hex::encode(self.0);
Copy link
Member

Choose a reason for hiding this comment

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

I think this code is just moved but we think we could get rid of this hex::encode call it should be possible to iterate over the bytes instead of allocating a String.

This probably doesn't matter in practice but just a thought :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

is it really that important?

Copy link
Member

Choose a reason for hiding this comment

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

no, I don't think it matters just an unnecessary allocation :)

@pkhry pkhry requested a review from niklasad1 June 13, 2024 08:51
@@ -33,7 +33,7 @@ std = [
# https://github.com/rust-bitcoin/rust-bitcoin/issues/930#issuecomment-1215538699
sr25519 = ["schnorrkel"]
ecdsa = ["secp256k1"]
unstable-eth = ["keccak-hash", "ecdsa", "secp256k1", "bip32"]
unstable-eth = ["dep:subxt-core", "keccak-hash", "ecdsa", "secp256k1", "bip32"]
Copy link
Member

@niklasad1 niklasad1 Jun 13, 2024

Choose a reason for hiding this comment

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

do we need the keccak-hash depdendency now when it's dependency in subxt-core?

Copy link
Collaborator

Choose a reason for hiding this comment

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

From my prev comment, let's remove the subxt-core dep here :)

Copy link
Member

@niklasad1 niklasad1 left a comment

Choose a reason for hiding this comment

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

LGTM, nice to have this for sure.

I guess when the new metadata v16 then the codegen can be smart enough to use AccountId20 instead of AccountId32 from ethereum-style metadata/chains?

@pkhry
Copy link
Contributor Author

pkhry commented Jun 13, 2024

LGTM, nice to have this for sure.

I guess when the new metadata v16 then codegen can smart enough to use AccountId20 instead of AccountId32 from ethereum-style metadata/chains?

We need to know the path for the accountId20 to provide a substitution in this case, If anyone can tag in with it we can add it to the substitution rules inside codegen/lib.

EDIT: added substitution inside codegen for fp_account::AccountId20 and updated frontier example accordingly

@pkhry pkhry requested a review from niklasad1 June 13, 2024 12:45
@@ -371,6 +371,10 @@ fn default_substitutes(crate_path: &syn::Path) -> TypeSubstitutes {
parse_quote!(sp_core::crypto::AccountId32),
parse_quote!(#crate_path::utils::AccountId32),
),
(
parse_quote!(fp_account::AccountId20),
Copy link
Member

@niklasad1 niklasad1 Jun 13, 2024

Choose a reason for hiding this comment

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

Maybe add a comment that the type comes from frontier which probably works for frontier/moonbeam but probably not for all ethereum-based chains.

I have no strong opinions whether to support this override or not, doesn't hurt I guess...

Copy link
Collaborator

Choose a reason for hiding this comment

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

Mmm it might be that we can add a few overrides if needed to cater for the common chains, but otherwise the user can do this themselves.

I was hesitent but don't see a reason not to add this since its super unlikely to ever break anything that doesn't care :)

use core::fmt::{Display, Formatter};
use core::str::FromStr;
use keccak_hash::keccak;
use secp256k1::Message;
use subxt_core::utils::AccountId20;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's avoid importing subxt-core here, and instead copy the pattern from eg sr25519.rs where we have a standalong PublicKey struct and then in the subxt_compat section we pull in subxt-core and have the relevant From impls etc to make PublicKey play nice with subxt's AccountId20 :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

what about the tests for eth? they will be enable only if "subxt" feature is also enabled

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah the tests are no problem; currently we just assume the default features are enabled for them, which allows subxt-core anyways. I just think that we can avoid needing subxt-core by default for "eth" signing to fall in line with the other algorithms :)

@jsdw
Copy link
Collaborator

jsdw commented Jun 14, 2024

Looks good to me! Only things to do are fixing the CI issues and removing the subxt-core dep from subxt-signer's eth feature by following the same pattern as sr25519.rs etc :)

@pkhry pkhry requested a review from jsdw June 16, 2024 18:53
@pkhry
Copy link
Contributor Author

pkhry commented Jun 16, 2024

issues with subxt-macro related, to clippy

@niklasad1
Copy link
Member

issues with subxt-macro related, to clippy

Just add a lint #![allow(clippy::manual_unwrap_or_default)] in macros then, it's the darling dependency that causes that and just silly thing.....

I guess we could file an issue in darling but still quite opinionated lint IMHO :)

use subxt_core::utils::AccountId20;
use subxt_core::utils::MultiAddress;

impl Keypair {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah this isn't quite what I had in mind; I was hitnking you could do something more like sr25519.rs and have eg:

/// The public key for an [`Keypair`] key pair. This is equivalent to an `AccountId20`.
pub struct PublicKey(pub [u8; 20]);

pub struct Keypair(..)

// Impl here; not gated by subxt-compat feature:
impl Keypair {
    // ...
}

#[cfg(feature = "subxt")]
mod subxt_compat {
    use super::*;

    // Only in this block do we now need to import subxt-core to
    // describe how to convert our PublicKey above into an AccountId20:
    use subxt_core::utils::AccountId20;

    impl From<PublicKey> for AccountId20 {
        fn from(value: PublicKey) -> Self {
            value.to_account_id()
        }
    }

    impl PublicKey {
        /// A shortcut to obtain an [`AccountId20`] from a [`PublicKey`].
        /// We often want this type, and using this method avoids any
        /// ambiguous type resolution issues.
        pub fn to_account_id(self) -> AccountId20 {
            AccountId20(self.0)
        }
    }

    impl<T: Config> SignerT<T> for Keypair
    where
        T::AccountId: From<PublicKey>,
        // looks like T::Address is also AcocuntId20 so the one From impl above works,
        // but this allows other address types to be used as long as there's a way to convert:
        T::Address: From<PublicKey>, 
        // sameish: we just use the Signature type above so I think this Just Works, but
        // also leaves door open for people to use other Signature types in their Config as 
        // long as they provide a From impl:
        T::Signature: From<Signature>,
    {
        fn account_id(&self) -> T::AccountId {
            self.public_key().into()
        }

        fn address(&self) -> T::Address {
            self.public_key().into()
        }

        fn sign(&self, signer_payload: &[u8]) -> T::Signature {
            self.sign(signer_payload).into()
        }
    }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah, ok, will push the change shortly

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated in line with the suggestion

@pkhry pkhry requested a review from jsdw June 17, 2024 10:29
@pkhry pkhry force-pushed the pkhry/accountid20 branch from bc24b52 to b0e36af Compare June 18, 2024 22:26
/// of the Keccak-256 hash of the public key.
pub fn account_id(&self) -> AccountId20 {
/// Obtain the [`eth::PublicKey`] of this keypair.
pub fn public_key(&self) -> PublicKey {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah yeah ok; it's a bit different from sr25519 etc because the public key isn't directly the bytes we want for the acocuntId. I like this wrapper type though; I suppose it could just contain the ecdsa::PublicKey at this point, but I'm not too bothered either way :)

Copy link
Collaborator

@jsdw jsdw left a comment

Choose a reason for hiding this comment

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

LGTM, nice job @pkhry!

@pkhry pkhry merged commit 5a5c5fc into master Jun 19, 2024
9 of 13 checks passed
@pkhry pkhry deleted the pkhry/accountid20 branch June 19, 2024 11:31
@muraca
Copy link
Contributor

muraca commented Jun 19, 2024

Lovely, thank you!

@jsdw
Copy link
Collaborator

jsdw commented Jun 19, 2024

Next time we should make sure the CI is passing before merging (which in this case means fixing the failing test); just incase something else was broken in the other CI steps that we missed :)

@jsdw jsdw mentioned this pull request Oct 24, 2024
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.

AccountId20 does not implement Serialize
4 participants