Allow sending transactions from an Ethereum address derived account id#8757
Allow sending transactions from an Ethereum address derived account id#8757
Conversation
Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com>
|
/cmd prdoc --audience runtime_dev --bump major |
…time_dev --bump major'
|
This seems to be important for the foundry-forge project as well. with paritytech/foundry-polkadot#130, the project is trying to upload the code on chain ahead of time so that we can interact with the code hash directly. To do that, foundry will have to sign a pallet-revive::upload-code substrate transaction with an Ethererum private key. cc @soul022 |
bkchr
left a comment
There was a problem hiding this comment.
Not a cryptographic expert, but looks reasonable.
| impl CryptoType for KeccakSignature { | ||
| type Pair = KeccakPair; | ||
| } |
There was a problem hiding this comment.
For the public key it will report the wrong Pair. Not actually sure where we use this stuff and if that is that important for the public key.
There was a problem hiding this comment.
Yeah I think it should return the correct Pair. Will need to make the Public generic, too.
There was a problem hiding this comment.
Made Public generic in order to fix that. Not sure if really necessary but let's be safe here.
Actually, I just realized that there is no need to actually check against both options... Instead, simply check if the last 12 bytes of the account-id are padded with I think that could be preferable to having the following enum: pub enum MultiSignature {
/// An Ed25519 signature.
Ed25519(ed25519::Signature),
/// An Sr25519 signature.
Sr25519(sr25519::Signature),
/// An ECDSA/SECP256k1 signature.
Ecdsa(ecdsa::Signature),
/// An ECDSA/SECP256k1 signature but with a different address derivation.
Eth(ecdsa::KeccakSignature),
}TBH EDIT:Just to be clear: it's not that I actually have a super-strong opinion about this. I can see the tradeoffs for both options... To be fair: both feel a bit hacky, but in different ways. I just found it a bit surprising that this option was never discussed/considered, that's all. |
|
It just seems more straightforward in theory. In the actual code you would need to touch the unchecked extrinsic implementation. While this is neatly self contained. |
|
Nothing severe was found in the audit. Going ahead. |
|
All GitHub workflows were cancelled due to failure one of the required jobs. |
#8757) We always allowed signing transactions using an Bitcoin/Eth style SECP256k1 key. The account in this case is simply the blake2 hash of the public key. This address derivation is problematic: It requires the public key in order to derive the account id. On Ethereum you simply can't know the public key of an address. This is why the mapping in pallet_revive is defined as `address <-> account_id`. This PR adds a new signature variant that allows signing a transaction with an account id as origin that matches this mapping. ## Why is this important? ### Example1 A wallet contains an SECP256k1 key and wants to interact with native Polkadot APIs. It can sign the transaction using this key. However, without this change the origin of that transaction will be different than the one it would appear under if it had signed an Ethereum transaction. ### Example2 A chain using an Ethereum style address (like Mythical) wants to send some tokens to one of their users account on AssetHub. How would they know what is the address of that user on AssetHub? With this change they can just pad the address with `0xEE` and rely on the fact that the user can interact with AssetHub using their existing key. ## Why a new variant? We can't modify the existing variant. Otherwise the same signature would suddenly map to a different account making people lose access to their funds. Instead, we add a new variant that adds control over an additional account for the same signature. ## A new `KeccakSigner` and `KeccakSignature` After considering feedback by @moliholy I am convinced that we should use keccak instead of blake2b for this new `MultiSignature` variant. Reasoning is that this will make it much simpler for Ethereum tooling to generate such signatures. Since this signature is specifically created for Ethereum interop it just makes sense to also use keccak here. To that end I made the `ecdsa::{KeccakSigner, KeccakSignature}` generic over their hash algorithm. Please note that I am using tags here and not the `Hasher` trait directly. This makes things more complicated but it was necessary: All Hasher implementations are in higher level crates and can't be directly referenced here. But I would have to reference it in order to make this a non breaking change. The `Signer` and `Signature` types behave exactly the same way as before. --------- Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
#8757) We always allowed signing transactions using an Bitcoin/Eth style SECP256k1 key. The account in this case is simply the blake2 hash of the public key. This address derivation is problematic: It requires the public key in order to derive the account id. On Ethereum you simply can't know the public key of an address. This is why the mapping in pallet_revive is defined as `address <-> account_id`. This PR adds a new signature variant that allows signing a transaction with an account id as origin that matches this mapping. ## Why is this important? ### Example1 A wallet contains an SECP256k1 key and wants to interact with native Polkadot APIs. It can sign the transaction using this key. However, without this change the origin of that transaction will be different than the one it would appear under if it had signed an Ethereum transaction. ### Example2 A chain using an Ethereum style address (like Mythical) wants to send some tokens to one of their users account on AssetHub. How would they know what is the address of that user on AssetHub? With this change they can just pad the address with `0xEE` and rely on the fact that the user can interact with AssetHub using their existing key. ## Why a new variant? We can't modify the existing variant. Otherwise the same signature would suddenly map to a different account making people lose access to their funds. Instead, we add a new variant that adds control over an additional account for the same signature. ## A new `KeccakSigner` and `KeccakSignature` After considering feedback by @moliholy I am convinced that we should use keccak instead of blake2b for this new `MultiSignature` variant. Reasoning is that this will make it much simpler for Ethereum tooling to generate such signatures. Since this signature is specifically created for Ethereum interop it just makes sense to also use keccak here. To that end I made the `ecdsa::{KeccakSigner, KeccakSignature}` generic over their hash algorithm. Please note that I am using tags here and not the `Hasher` trait directly. This makes things more complicated but it was necessary: All Hasher implementations are in higher level crates and can't be directly referenced here. But I would have to reference it in order to make this a non breaking change. The `Signer` and `Signature` types behave exactly the same way as before. --------- Co-authored-by: joe petrowski <25483142+joepetrowski@users.noreply.github.com> Co-authored-by: cmd[bot] <41898282+github-actions[bot]@users.noreply.github.com>
We always allowed signing transactions using an Bitcoin/Eth style SECP256k1 key. The account in this case is simply the blake2 hash of the public key.
This address derivation is problematic: It requires the public key in order to derive the account id. On Ethereum you simply can't know the public key of an address. This is why the mapping in pallet_revive is defined as
address <-> account_id.This PR adds a new signature variant that allows signing a transaction with an account id as origin that matches this mapping.
Why is this important?
Example1
A wallet contains an SECP256k1 key and wants to interact with native Polkadot APIs. It can sign the transaction using this key. However, without this change the origin of that transaction will be different than the one it would appear under if it had signed an Ethereum transaction.
Example2
A chain using an Ethereum style address (like Mythical) wants to send some tokens to one of their users account on AssetHub. How would they know what is the address of that user on AssetHub? With this change they can just pad the address with
0xEEand rely on the fact that the user can interact with AssetHub using their existing key.Why a new variant?
We can't modify the existing variant. Otherwise the same signature would suddenly map to a different account making people lose access to their funds. Instead, we add a new variant that adds control over an additional account for the same signature.
A new
KeccakSignerandKeccakSignatureAfter considering feedback by @moliholy I am convinced that we should use keccak instead of blake2b for this new
MultiSignaturevariant. Reasoning is that this will make it much simpler for Ethereum tooling to generate such signatures. Since this signature is specifically created for Ethereum interop it just makes sense to also use keccak here.To that end I made the
ecdsa::{KeccakSigner, KeccakSignature}generic over their hash algorithm. Please note that I am using tags here and not theHashertrait directly. This makes things more complicated but it was necessary: All Hasher implementations are in higher level crates and can't be directly referenced here. But I would have to reference it in order to make this a non breaking change. TheSignerandSignaturetypes behave exactly the same way as before.