3

I'm trying to do the signature verification in an ink! contract. I'm using ink_env::ecdsa_recover for this purpose.

It is returning Compressed Public Key of type [u8; 33]. I have the AccountId of the signer in the contract storage.

Is there a way I can get the AccountId from the Compressed Public Key to verify the signer? or is there a better way to approach this?

2 Answers 2

7

A compressed public key can be represented by the ECDSAPublicKey struct from the eth_compatibility crate from ink.

Try to create an ECDSAPublicKey struct from your uncompressed public key and then invoke the to_default_account_id() function from it which is defined here.

Try the following:

  1. Add the eth_compatibility crate to your project
  2. Import eth_compatibility::ECDSAPublicKey
  3. Define an ecdsa_key from your compressed_pub_key with: let ecdsa_key=ECDSAPublicKey::from(compressed_pub_key);
  4. Derive an account_id of type AccountId with: let account_id=ecdsa_key.to_default_account_id();
7
  • 1
    AccountId::from() takes in [u8; 32]. Since ink_env::ecdsa_recover returns [u8; 33], it is throwing an error. My understanding of a compressed public key is limited. Is there a way to get the pub_key from compressed_pub_key?
    – Kanishka
    Apr 5, 2022 at 6:19
  • 1
    Yes, as I realized by myself, the compressed public key obtained by ecdsa_recover is not identical with the AccountId, but it should be possible to derive it by hashing or by invoking the corresponding function from the the_compatibility crate. I updated my answer above accordingly.
    – Achim
    Apr 5, 2022 at 7:27
  • When I do AccountId::from(pub_key) it's throwing an error saying the trait From<ink_env::types::AccountId> is not implemented for ink_env::AccountId
    – Kanishka
    Apr 5, 2022 at 8:21
  • Can you try the 4 steps outlined above?
    – Achim
    Apr 5, 2022 at 8:47
  • 1
    Indeed, to_default_account_id() already returns an AccountId struct, you don't need AccountId::from. The new error is due to different versions of your crates, since you are obtaining eth_compatibility from GitHub. Just remove the git = ... from your Cargo.toml for eth_compatibility
    – Achim
    Apr 5, 2022 at 9:30
4

You could get the Public key (hex) using the inspect command of subkey --> Take a look at this link: enter link description here

If you already have it (for example 0xd6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746), add hex-literal = "0.3.4" in your Cargo.toml, and then in your ink contract, your account Id will be:

AccountId = hex_literal::hex!["d6a3105d6768e956e9e5d41050ac29843f98561410d3a47f9dd5b3b227ab8746"].into();
3
  • Let me clarify, I'm getting the compressed public key back from ink_env::ecdsa_recover and I wanna use that to compare it to an AccountId in the ink contract. hex_literal::hex! only works on string literals.
    – Kanishka
    Apr 5, 2022 at 3:58
  • I believe it's not possible to do that with subkey inspect. This is what it says in it's --help : Gets a public key and a SS58 address from the provided Secret URI.
    – Kanishka
    Apr 5, 2022 at 4:56
  • 1
    Got it! Sorry, I tried... Apr 5, 2022 at 8:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.