From f991163ec36c6860cb022bf4eda0bc7aa11709e7 Mon Sep 17 00:00:00 2001 From: OkoliEvans Date: Sun, 30 Jun 2024 12:16:29 +0100 Subject: [PATCH 1/6] draft PR for issue 191 --- Scarb.lock | 4 + .../account_abstraction/.gitignore | 1 + .../account_abstraction/Scarb.toml | 14 ++ .../src/account_abstraction.cairo | 133 ++++++++++++++++++ .../account_abstraction/src/lib.cairo | 1 + src/advanced-concepts/account-abstraction.md | 40 ++++++ 6 files changed, 193 insertions(+) create mode 100644 listings/advanced-concepts/account_abstraction/.gitignore create mode 100644 listings/advanced-concepts/account_abstraction/Scarb.toml create mode 100644 listings/advanced-concepts/account_abstraction/src/account_abstraction.cairo create mode 100644 listings/advanced-concepts/account_abstraction/src/lib.cairo create mode 100644 src/advanced-concepts/account-abstraction.md diff --git a/Scarb.lock b/Scarb.lock index a055e8a9..c48cd663 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -1,6 +1,10 @@ # Code generated by scarb DO NOT EDIT. version = 1 +[[package]] +name = "account_abstraction" +version = "0.1.0" + [[package]] name = "advanced_factory" version = "0.1.0" diff --git a/listings/advanced-concepts/account_abstraction/.gitignore b/listings/advanced-concepts/account_abstraction/.gitignore new file mode 100644 index 00000000..eb5a316c --- /dev/null +++ b/listings/advanced-concepts/account_abstraction/.gitignore @@ -0,0 +1 @@ +target diff --git a/listings/advanced-concepts/account_abstraction/Scarb.toml b/listings/advanced-concepts/account_abstraction/Scarb.toml new file mode 100644 index 00000000..83a29d49 --- /dev/null +++ b/listings/advanced-concepts/account_abstraction/Scarb.toml @@ -0,0 +1,14 @@ +[package] +name = "account_abstraction" +version = "0.1.0" +edition = "2023_11" + +# See more keys and their definitions at https://docs.swmansion.com/scarb/docs/reference/manifest.html + +[dependencies] +starknet.workspace = true + +[scripts] +test.workspace = true + +[[target.starknet-contract]] diff --git a/listings/advanced-concepts/account_abstraction/src/account_abstraction.cairo b/listings/advanced-concepts/account_abstraction/src/account_abstraction.cairo new file mode 100644 index 00000000..ae338cd1 --- /dev/null +++ b/listings/advanced-concepts/account_abstraction/src/account_abstraction.cairo @@ -0,0 +1,133 @@ +use starknet::secp256_trait::{ + Secp256PointTrait, Signature as Secp256Signature, recover_public_key, is_signature_entry_valid +}; +use starknet::secp256r1::Secp256r1Point; +use starknet::secp256k1::Secp256k1Point; +use starknet::{ EthAddress, eth_signature::is_eth_signature_valid }; +use core::traits::TryInto; + + +const SECP256R1_SIGNER_TYPE: felt252 = 'Secp256r1 Signer'; +const SECP256K1_SIGNER_TYPE: felt252 = 'Secp256k1 Signer'; +const SECP_256_R1_HALF: u256 = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 / 2; +const SECP_256_K1_HALF: u256 = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 / 2; + + + +#[derive(Drop, Copy, PartialEq, Serde, Default)] +enum SignerType { + #[default] + Secp256r1, + Secp256k1, +} + +#[derive(Drop, Copy, Serde)] +enum SignerSignature { + Secp256r1: (Secp256r1Signer, Secp256Signature), + Secp256k1: (Secp256k1Signer, Secp256Signature), +} + +#[derive(Drop, Copy, Serde)] +enum Signer { + Secp256r1: Secp256r1Signer, + Secp256k1: Secp256k1Signer, +} + +#[derive(Drop, Copy, Serde, PartialEq)] +struct Secp256r1Signer { + pubkey: NonZero +} + +#[derive(Drop, Copy, PartialEq)] +struct Secp256k1Signer { + pubkey_hash: EthAddress +} + + +// To ensure the pubkey hash is not zero +impl Secp256k1SignerSerde of Serde { + #[inline(always)] + fn serialize(self: @Secp256k1Signer, ref output: Array) { + self.pubkey_hash.serialize(ref output); + } + + #[inline(always)] + fn deserialize(ref serialized: Span) -> Option { + let pubkey_hash = Serde::::deserialize(ref serialized)?; + assert(pubkey_hash.address != 0, 'zero pub key hash' ); + Option::Some(Secp256k1Signer { pubkey_hash }) + } +} + +// To check if secp256k1 and secp256r1 signatures are valid +trait Secp256SignatureTrait { + fn is_valid_signature(self: SignerSignature, hash: felt252) -> bool; + fn signer(self: SignerSignature) -> Signer; +} + +impl Secp256SignatureImpl of Secp256SignatureTrait { + #[inline(always)] + fn is_valid_signature(self: SignerSignature, hash: felt252) -> bool { + match self { + SignerSignature::Secp256r1(( + signer, signature + )) => is_valid_secp256r1_signature(hash.into(), signer, signature), + SignerSignature::Secp256k1(( + signer, signature + )) => is_valid_secp256k1_signature(hash.into(), signer.pubkey_hash.into(), signature), + } + } + + #[inline(always)] + fn signer(self: SignerSignature) -> Signer { + match self { + SignerSignature::Secp256k1((signer, _)) => Signer::Secp256k1(signer), + SignerSignature::Secp256r1((signer, _)) => Signer::Secp256r1(signer), + } + } +} + +// To validate secp256k1 signature +#[inline(always)] +fn is_valid_secp256k1_signature(hash: u256, pubkey_hash: EthAddress, signature: Secp256Signature) -> bool { + assert(signature.s <= SECP_256_K1_HALF, 'malleable signature'); + is_eth_signature_valid(hash, signature, pubkey_hash).is_ok() +} + +// To validate secp256r1 signature +#[inline(always)] +fn is_valid_secp256r1_signature(hash: u256, signer: Secp256r1Signer, signature: Secp256Signature) -> bool { + assert(is_signature_entry_valid::(signature.s), 'invalid s-value'); + assert(is_signature_entry_valid::(signature.r), 'invalid r-value'); + assert(signature.s <= SECP_256_R1_HALF, 'malleable signature'); + let recovered_pubkey = recover_public_key::(hash, signature).expect('invalid sign format'); + let (recovered_signer, _) = recovered_pubkey.get_coordinates().expect('invalid sig format'); + recovered_signer == signer.pubkey.into() +} + +// impl to convert signer type into felt252 using into() +impl SignerTypeIntoFelt252 of Into { + #[inline(always)] + fn into(self: SignerType) -> felt252 { + match self { + SignerType::Secp256k1 => 1, + SignerType::Secp256r1 => 2, + } + } +} + + +// impl to convert u256 type into SignerType using try_into() +impl U256TryIntoSignerType of TryInto { + #[inline(always)] + fn try_into(self: u256) -> Option { + if self == 1 { + Option::Some(SignerType::Secp256k1) + } else if self == 2 { + Option::Some(SignerType::Secp256r1) + } else { + Option::None + } + } +} + diff --git a/listings/advanced-concepts/account_abstraction/src/lib.cairo b/listings/advanced-concepts/account_abstraction/src/lib.cairo new file mode 100644 index 00000000..50d5caab --- /dev/null +++ b/listings/advanced-concepts/account_abstraction/src/lib.cairo @@ -0,0 +1 @@ +mod account_abstraction; \ No newline at end of file diff --git a/src/advanced-concepts/account-abstraction.md b/src/advanced-concepts/account-abstraction.md new file mode 100644 index 00000000..3c33100f --- /dev/null +++ b/src/advanced-concepts/account-abstraction.md @@ -0,0 +1,40 @@ +# Account Abstraction + +### Understanding Ethereum Account System + +Traditionally, there are two types of account on Ethereum: Externally Owned Accounts known as EOAs and smart contract Accounts. + +EOAs are normal accounts used by individuals, they have private keys and can sign transactions. Smart contract accounts do not have private keys, therefore they cannot initiate or sign transactions. All transactions on Ethereum must be initiated by an EOA. + +Ethereum accounts have many challenges such as: + +i. Key Management: Users must secure and never lose their seed phrase and private keys, otherwise they risk losing access to their accounts and assets forever. + +Also, once a thief gains access to your private keys or seed phrase, he gains complete access to your account and its assets. + +ii. Bad User Experience: The account system used on Ethereum makes it difficult for newbies to use crypto applications as they are always complicated to use. +Lack of account recovery options also makes it unappealing to users. + +iii. Lack of Flexibility: Ethereum account system restricts custom transaction validation schemes, limiting potential enhancements on access control and security. + + +### What is Account Abstraction? + +Account Abstraction is the concept of modifying accounts and enhancing transactions on blockchain networks. +Account Abstraction replaces EOAs with a broader model where all accounts are smart contracts, each with its own unique rules and behaviors. + +Account Abstraction makes it possible for innovative account management system such as custom signature types, session keys, 2 Factor Authentication (2FA), fingerprint or facial recognition account signing, ability to pay for gas using other tokens such as USDT, ability to recover accounts without seed phrase, email recovery of accounts and so on. + +### The Most Important Concepts + +i. **Account:** All accounts are smart contracts that can hold assets and execute transactions on Starknet protocol, these account contracts however must implement some specific methods outlined in SNIP-6. + +ii. **Signers:** These are responsible for digitally signing transactions and provide the authorization needed to initiate transactions. +Digital signatures are cryptographic proofs that transactions are authorized by corresponding accounts. + +In summary, Starknet accounts are normal blockchain accounts that hold assets and initiate transactions onchain, while signers provide the authorization required to ensure that transactions originating from these accounts are secure, valid and executed. + +To implement custom validation method on Starknet you have to ensure that the contract contains these three methods: `is_valid_signature`, `__validate__` and `__execute__`. These are the building block for account contracts on Starknet as contained in the SNIP-6. + + + From 60e7a6e7ce0c7c3b8164e1cb73b687498fded5fa Mon Sep 17 00:00:00 2001 From: OkoliEvans Date: Tue, 16 Jul 2024 12:52:26 +0100 Subject: [PATCH 2/6] edited custom-signature.md file --- Scarb.lock | 8 ++-- .../account_abstraction/src/lib.cairo | 1 - .../.gitignore | 0 .../Scarb.toml | 2 +- .../src/custom_signature.cairo} | 0 .../custom_signature_validation/src/lib.cairo | 1 + src/advanced-concepts/account-abstraction.md | 40 ------------------- .../custom_signature_validation.md | 17 ++++++++ 8 files changed, 23 insertions(+), 46 deletions(-) delete mode 100644 listings/advanced-concepts/account_abstraction/src/lib.cairo rename listings/advanced-concepts/{account_abstraction => custom_signature_validation}/.gitignore (100%) rename listings/advanced-concepts/{account_abstraction => custom_signature_validation}/Scarb.toml (87%) rename listings/advanced-concepts/{account_abstraction/src/account_abstraction.cairo => custom_signature_validation/src/custom_signature.cairo} (100%) create mode 100644 listings/advanced-concepts/custom_signature_validation/src/lib.cairo delete mode 100644 src/advanced-concepts/account-abstraction.md create mode 100644 src/advanced-concepts/custom_signature_validation.md diff --git a/Scarb.lock b/Scarb.lock index c48cd663..4499ad1c 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -1,10 +1,6 @@ # Code generated by scarb DO NOT EDIT. version = 1 -[[package]] -name = "account_abstraction" -version = "0.1.0" - [[package]] name = "advanced_factory" version = "0.1.0" @@ -67,6 +63,10 @@ dependencies = [ "snforge_std", ] +[[package]] +name = "custom_signature_validation" +version = "0.1.0" + [[package]] name = "custom_type_serde" version = "0.1.0" diff --git a/listings/advanced-concepts/account_abstraction/src/lib.cairo b/listings/advanced-concepts/account_abstraction/src/lib.cairo deleted file mode 100644 index 50d5caab..00000000 --- a/listings/advanced-concepts/account_abstraction/src/lib.cairo +++ /dev/null @@ -1 +0,0 @@ -mod account_abstraction; \ No newline at end of file diff --git a/listings/advanced-concepts/account_abstraction/.gitignore b/listings/advanced-concepts/custom_signature_validation/.gitignore similarity index 100% rename from listings/advanced-concepts/account_abstraction/.gitignore rename to listings/advanced-concepts/custom_signature_validation/.gitignore diff --git a/listings/advanced-concepts/account_abstraction/Scarb.toml b/listings/advanced-concepts/custom_signature_validation/Scarb.toml similarity index 87% rename from listings/advanced-concepts/account_abstraction/Scarb.toml rename to listings/advanced-concepts/custom_signature_validation/Scarb.toml index 83a29d49..3b7e2452 100644 --- a/listings/advanced-concepts/account_abstraction/Scarb.toml +++ b/listings/advanced-concepts/custom_signature_validation/Scarb.toml @@ -1,5 +1,5 @@ [package] -name = "account_abstraction" +name = "custom_signature_validation" version = "0.1.0" edition = "2023_11" diff --git a/listings/advanced-concepts/account_abstraction/src/account_abstraction.cairo b/listings/advanced-concepts/custom_signature_validation/src/custom_signature.cairo similarity index 100% rename from listings/advanced-concepts/account_abstraction/src/account_abstraction.cairo rename to listings/advanced-concepts/custom_signature_validation/src/custom_signature.cairo diff --git a/listings/advanced-concepts/custom_signature_validation/src/lib.cairo b/listings/advanced-concepts/custom_signature_validation/src/lib.cairo new file mode 100644 index 00000000..1e39ca20 --- /dev/null +++ b/listings/advanced-concepts/custom_signature_validation/src/lib.cairo @@ -0,0 +1 @@ +mod custom_signature; \ No newline at end of file diff --git a/src/advanced-concepts/account-abstraction.md b/src/advanced-concepts/account-abstraction.md deleted file mode 100644 index 3c33100f..00000000 --- a/src/advanced-concepts/account-abstraction.md +++ /dev/null @@ -1,40 +0,0 @@ -# Account Abstraction - -### Understanding Ethereum Account System - -Traditionally, there are two types of account on Ethereum: Externally Owned Accounts known as EOAs and smart contract Accounts. - -EOAs are normal accounts used by individuals, they have private keys and can sign transactions. Smart contract accounts do not have private keys, therefore they cannot initiate or sign transactions. All transactions on Ethereum must be initiated by an EOA. - -Ethereum accounts have many challenges such as: - -i. Key Management: Users must secure and never lose their seed phrase and private keys, otherwise they risk losing access to their accounts and assets forever. - -Also, once a thief gains access to your private keys or seed phrase, he gains complete access to your account and its assets. - -ii. Bad User Experience: The account system used on Ethereum makes it difficult for newbies to use crypto applications as they are always complicated to use. -Lack of account recovery options also makes it unappealing to users. - -iii. Lack of Flexibility: Ethereum account system restricts custom transaction validation schemes, limiting potential enhancements on access control and security. - - -### What is Account Abstraction? - -Account Abstraction is the concept of modifying accounts and enhancing transactions on blockchain networks. -Account Abstraction replaces EOAs with a broader model where all accounts are smart contracts, each with its own unique rules and behaviors. - -Account Abstraction makes it possible for innovative account management system such as custom signature types, session keys, 2 Factor Authentication (2FA), fingerprint or facial recognition account signing, ability to pay for gas using other tokens such as USDT, ability to recover accounts without seed phrase, email recovery of accounts and so on. - -### The Most Important Concepts - -i. **Account:** All accounts are smart contracts that can hold assets and execute transactions on Starknet protocol, these account contracts however must implement some specific methods outlined in SNIP-6. - -ii. **Signers:** These are responsible for digitally signing transactions and provide the authorization needed to initiate transactions. -Digital signatures are cryptographic proofs that transactions are authorized by corresponding accounts. - -In summary, Starknet accounts are normal blockchain accounts that hold assets and initiate transactions onchain, while signers provide the authorization required to ensure that transactions originating from these accounts are secure, valid and executed. - -To implement custom validation method on Starknet you have to ensure that the contract contains these three methods: `is_valid_signature`, `__validate__` and `__execute__`. These are the building block for account contracts on Starknet as contained in the SNIP-6. - - - diff --git a/src/advanced-concepts/custom_signature_validation.md b/src/advanced-concepts/custom_signature_validation.md new file mode 100644 index 00000000..ae9cdf0b --- /dev/null +++ b/src/advanced-concepts/custom_signature_validation.md @@ -0,0 +1,17 @@ +# Custom Signature Validation Scheme + +Account Abstraction on Starknet supports various signature schemes. This means that signature schemes on Starknet are not limited to just one, any standard signature scheme can be validated, for example Starknet signature, Secp256k1, Secp256r1, Eip191 et al are some of the custom signatures that can be validated on Starknet currently. + +### The Concepts of Accounts and Signers + +i. **Account:** All accounts are smart contracts that can hold assets and execute transactions on Starknet protocol, these account contracts however must implement some specific methods outlined in SNIP-6. + +ii. **Signers:** These are responsible for digitally signing transactions and provide the authorization needed to initiate transactions. +Digital signatures are cryptographic proofs that transactions are authorized by corresponding accounts. + +In summary, Starknet accounts are normal blockchain accounts that hold assets and initiate transactions onchain, while signers provide the authorization required to ensure that transactions originating from these accounts are secure, valid and executed. + +To implement custom validation method on Starknet you have to ensure that the contract contains these three methods: `is_valid_signature`, `__validate__` and `__execute__`. These are the building block for account contracts on Starknet as contained in the SNIP-6. + + + From cd066bb24ec6f48de7a7b4b51d71af4c1630509d Mon Sep 17 00:00:00 2001 From: OkoliEvans Date: Tue, 16 Jul 2024 12:55:00 +0100 Subject: [PATCH 3/6] edited custom-signature.md file --- Scarb.lock | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Scarb.lock b/Scarb.lock index 7509ed71..4084bbd1 100644 --- a/Scarb.lock +++ b/Scarb.lock @@ -135,6 +135,10 @@ dependencies = [ "openzeppelin", ] +[[package]] +name = "simple_storage" +version = "0.1.0" + [[package]] name = "simple_vault" version = "0.1.0" From cbbb89fed8ef09adb34534d02b88592f583ac363 Mon Sep 17 00:00:00 2001 From: OkoliEvans Date: Sun, 21 Jul 2024 13:12:27 +0100 Subject: [PATCH 4/6] added more details to custom signature scheme --- .../src/custom_signature.cairo | 2 ++ .../custom_signature_validation.md | 29 ++++++++++++++++--- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/listings/advanced-concepts/custom_signature_validation/src/custom_signature.cairo b/listings/advanced-concepts/custom_signature_validation/src/custom_signature.cairo index ae338cd1..bc61e9ae 100644 --- a/listings/advanced-concepts/custom_signature_validation/src/custom_signature.cairo +++ b/listings/advanced-concepts/custom_signature_validation/src/custom_signature.cairo @@ -1,3 +1,4 @@ +// ANCHOR: custom_signature_scheme use starknet::secp256_trait::{ Secp256PointTrait, Signature as Secp256Signature, recover_public_key, is_signature_entry_valid }; @@ -131,3 +132,4 @@ impl U256TryIntoSignerType of TryInto { } } +// ANCHOR_END: custom_signature_scheme \ No newline at end of file diff --git a/src/advanced-concepts/custom_signature_validation.md b/src/advanced-concepts/custom_signature_validation.md index ae9cdf0b..7b8d4e88 100644 --- a/src/advanced-concepts/custom_signature_validation.md +++ b/src/advanced-concepts/custom_signature_validation.md @@ -1,17 +1,38 @@ # Custom Signature Validation Scheme -Account Abstraction on Starknet supports various signature schemes. This means that signature schemes on Starknet are not limited to just one, any standard signature scheme can be validated, for example Starknet signature, Secp256k1, Secp256r1, Eip191 et al are some of the custom signatures that can be validated on Starknet currently. +Account Abstraction is a native feature on Starknet, this makes it possible for anyone to implement custom signature schemes. The implication is that signature schemes on Starknet are not limited to just one, any standard signature scheme can be validated, for example Starknet signature, Secp256k1, Secp256r1, Eip191 etc are some of the custom signatures that can be validated on Starknet currently. ### The Concepts of Accounts and Signers -i. **Account:** All accounts are smart contracts that can hold assets and execute transactions on Starknet protocol, these account contracts however must implement some specific methods outlined in SNIP-6. +i. **Account:** All accounts are smart contracts that can hold assets and execute transactions on Starknet, these account contracts however must implement some specific methods outlined in SNIP-6. For further reading: [Account contract](https://starknet-by-example.voyager.online/advanced-concepts/account_abstraction/account_contract.html). ii. **Signers:** These are responsible for digitally signing transactions and provide the authorization needed to initiate transactions. Digital signatures are cryptographic proofs that transactions are authorized by corresponding accounts. -In summary, Starknet accounts are normal blockchain accounts that hold assets and initiate transactions onchain, while signers provide the authorization required to ensure that transactions originating from these accounts are secure, valid and executed. +### Signature validation on Starknet -To implement custom validation method on Starknet you have to ensure that the contract contains these three methods: `is_valid_signature`, `__validate__` and `__execute__`. These are the building block for account contracts on Starknet as contained in the SNIP-6. +On Starknet transactions are signed offchain, which means that the signature process happens outside the blockchain. The signed transaction is then submitted to Starknet network for verification and execution. Read more: [Starknet-js docs](https://www.starknetjs.com/docs/guides/signature/) +All Account contracts on Starknet must implement the SNIP-6 standard as mentioned earlier. The methods implemented in the SNIP-6 standard provide means to move offchain signatures onchain and execute them. +`is_valid_signature` returns true if the signature is valid, `__validate__` validates the signature and marks them as 'VALIDATED', while `__execute__` executes the validated transaction. Sample implementation of SNIP-6 standard: [Sample SNIP-6 Implementation](https://starknet-by-example.voyager.online/advanced-concepts/account_abstraction/account_contract.html#minimal-account-contract-executing-transactions) + +On Ethereum, EOAs directly sign transactions onchain using their private keys. This onchain signing of transactions is more secure and straightforward but less flexible. Offchain signing employed on Starknet gives room for more flexibility aside the ability to implement custom signature schemes, however, care must be taken to validate all signatures meticulously to ensure that: + +a. the message has not been altered. +b. the signer owns the private key corresponding to the public key. + + +In summary, Starknet accounts are normal blockchain accounts that hold assets and initiate transactions onchain, while signers provide the authorization required to ensure that transactions originating from these accounts are secure and valid. + +Digital signatures are a fundamental aspect of modern cryptography, used to verify the authenticity and integrity of digital messages or transactions. They are based on public-key cryptography, where a pair of keys (a public key and a private key) are used to create and verify signatures. +Private keys are kept secret and secure by the owner, and are used to sign the message or transaction, while the public key can be used by anyone to verify the signature. + +### Custom signature validation sample + +The example below shows a sample implementation of `Secp256r1` and `Secp256k1` signature schemes: + +```rust +{{#rustdoc_include ../../listings/advanced-concepts/custom_signature_validation/src/custom_signature.cairo:custom_signature_scheme}} +``` From bd156317a090e037c260497800fb0097670df41a Mon Sep 17 00:00:00 2001 From: OkoliEvans Date: Wed, 24 Jul 2024 12:37:43 +0100 Subject: [PATCH 5/6] made some adjustments based on PR review --- .../custom_signature_validation.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/advanced-concepts/custom_signature_validation.md b/src/advanced-concepts/custom_signature_validation.md index 7b8d4e88..bb6a95dc 100644 --- a/src/advanced-concepts/custom_signature_validation.md +++ b/src/advanced-concepts/custom_signature_validation.md @@ -1,12 +1,15 @@ # Custom Signature Validation Scheme -Account Abstraction is a native feature on Starknet, this makes it possible for anyone to implement custom signature schemes. The implication is that signature schemes on Starknet are not limited to just one, any standard signature scheme can be validated, for example Starknet signature, Secp256k1, Secp256r1, Eip191 etc are some of the custom signatures that can be validated on Starknet currently. +Digital signatures are a fundamental aspect of modern cryptography, used to verify the authenticity and integrity of digital messages or transactions. They are based on public-key cryptography, where a pair of keys (a public key and a private key) are used to create and verify signatures. +Private keys are kept secret and secure by the owner, and are used to sign the message or transaction, while the public key can be used by anyone to verify the signature. + +Account Abstraction is a native feature on Starknet, this makes it possible for anyone to implement custom signature schemes. The implication is that signature schemes on Starknet are not limited to just one, any standard signature scheme can be validated, for example Starknet signature, Secp256k1, Secp256r1, Eip191 etc are some of the custom signatures that can be validated on Starknet currently. ### The Concepts of Accounts and Signers i. **Account:** All accounts are smart contracts that can hold assets and execute transactions on Starknet, these account contracts however must implement some specific methods outlined in SNIP-6. For further reading: [Account contract](https://starknet-by-example.voyager.online/advanced-concepts/account_abstraction/account_contract.html). -ii. **Signers:** These are responsible for digitally signing transactions and provide the authorization needed to initiate transactions. +ii. **Signers:** These are responsible for digitally signing transactions and provide the authorization needed to initiate transactions. Digital signatures are cryptographic proofs that transactions are authorized by corresponding accounts. ### Signature validation on Starknet @@ -17,18 +20,14 @@ All Account contracts on Starknet must implement the SNIP-6 standard as mentione `is_valid_signature` returns true if the signature is valid, `__validate__` validates the signature and marks them as 'VALIDATED', while `__execute__` executes the validated transaction. Sample implementation of SNIP-6 standard: [Sample SNIP-6 Implementation](https://starknet-by-example.voyager.online/advanced-concepts/account_abstraction/account_contract.html#minimal-account-contract-executing-transactions) - -On Ethereum, EOAs directly sign transactions onchain using their private keys. This onchain signing of transactions is more secure and straightforward but less flexible. Offchain signing employed on Starknet gives room for more flexibility aside the ability to implement custom signature schemes, however, care must be taken to validate all signatures meticulously to ensure that: +On Ethereum, only **one** signature scheme is used for signing messages and transactions, and also for signature authentications: the Elliptic Curve Digital Signature Algorithm (ECDSA). That means that no other signature algorithms can be validated on Ethereum, making it more secure but less flexible. +Custom signature validation employed on Starknet gives room for more flexibility, however, care must be taken to validate all signatures meticulously to ensure that: a. the message has not been altered. b. the signer owns the private key corresponding to the public key. - In summary, Starknet accounts are normal blockchain accounts that hold assets and initiate transactions onchain, while signers provide the authorization required to ensure that transactions originating from these accounts are secure and valid. -Digital signatures are a fundamental aspect of modern cryptography, used to verify the authenticity and integrity of digital messages or transactions. They are based on public-key cryptography, where a pair of keys (a public key and a private key) are used to create and verify signatures. -Private keys are kept secret and secure by the owner, and are used to sign the message or transaction, while the public key can be used by anyone to verify the signature. - ### Custom signature validation sample The example below shows a sample implementation of `Secp256r1` and `Secp256k1` signature schemes: From d531ed6cd845aae6c1a36a86e6bb300820f25cb1 Mon Sep 17 00:00:00 2001 From: OkoliEvans Date: Tue, 13 Aug 2024 21:39:02 +0100 Subject: [PATCH 6/6] Edited draft PR on Custom signature validation --- .../src/custom_signature.cairo | 12 +++-- .../src/simple_account.cairo | 51 +++++++++++++++++++ .../custom_signature_validation.md | 29 ++++++----- 3 files changed, 76 insertions(+), 16 deletions(-) create mode 100644 listings/advanced-concepts/custom_signature_validation/src/simple_account.cairo diff --git a/listings/advanced-concepts/custom_signature_validation/src/custom_signature.cairo b/listings/advanced-concepts/custom_signature_validation/src/custom_signature.cairo index bc61e9ae..310c15e0 100644 --- a/listings/advanced-concepts/custom_signature_validation/src/custom_signature.cairo +++ b/listings/advanced-concepts/custom_signature_validation/src/custom_signature.cairo @@ -24,7 +24,7 @@ enum SignerType { #[derive(Drop, Copy, Serde)] enum SignerSignature { - Secp256r1: (Secp256r1Signer, Secp256Signature), + Secp256r1: (Secp256r1Signer, Secp2newAccount56Signature), Secp256k1: (Secp256k1Signer, Secp256Signature), } @@ -64,8 +64,10 @@ impl Secp256k1SignerSerde of Serde { trait Secp256SignatureTrait { fn is_valid_signature(self: SignerSignature, hash: felt252) -> bool; fn signer(self: SignerSignature) -> Signer; -} - + } + + // ANCHOR: is_valid_signature +// To check if secp256k1 and secp256r1 signatures are valid impl Secp256SignatureImpl of Secp256SignatureTrait { #[inline(always)] fn is_valid_signature(self: SignerSignature, hash: felt252) -> bool { @@ -78,7 +80,8 @@ impl Secp256SignatureImpl of Secp256SignatureTrait { )) => is_valid_secp256k1_signature(hash.into(), signer.pubkey_hash.into(), signature), } } - + + #[inline(always)] fn signer(self: SignerSignature) -> Signer { match self { @@ -105,6 +108,7 @@ fn is_valid_secp256r1_signature(hash: u256, signer: Secp256r1Signer, signature: let (recovered_signer, _) = recovered_pubkey.get_coordinates().expect('invalid sig format'); recovered_signer == signer.pubkey.into() } +// ANCHOR_END: is_valid_signature // impl to convert signer type into felt252 using into() impl SignerTypeIntoFelt252 of Into { diff --git a/listings/advanced-concepts/custom_signature_validation/src/simple_account.cairo b/listings/advanced-concepts/custom_signature_validation/src/simple_account.cairo new file mode 100644 index 00000000..0f32f6eb --- /dev/null +++ b/listings/advanced-concepts/custom_signature_validation/src/simple_account.cairo @@ -0,0 +1,51 @@ + +#[starknet::contract] +mod SimpleAccount { + + +// ANCHOR: validate +fn __validate__(ref self: ContractState, calls: Array) -> felt252 { + let exec_info = get_execution_info().unbox(); + let tx_info = exec_info.tx_info.unbox(); + assert_only_protocol(exec_info.caller_address); + assert_correct_invoke_version(tx_info.version); + assert(tx_info.paymaster_data.is_empty(), 'unsupported-paymaster'); + if self.session.is_session(tx_info.signature) { + self.session.assert_valid_session(calls.span(), tx_info.transaction_hash, tx_info.signature,); + } else { + self + .assert_valid_calls_and_signature( + calls.span(), + tx_info.transaction_hash, + tx_info.signature, + is_from_outside: false, + account_address: exec_info.contract_address, + ); + } + VALIDATED +} +// ANCHOR_END: validate + +// ANCHOR: execute +fn __execute__(ref self: ContractState, calls: Array) -> Array> { + self.reentrancy_guard.start(); + let exec_info = get_execution_info().unbox(); + let tx_info = exec_info.tx_info.unbox(); + assert_only_protocol(exec_info.caller_address); + assert_correct_invoke_version(tx_info.version); + let signature = tx_info.signature; + if self.session.is_session(signature) { + let session_timestamp = *signature[1]; + // can call unwrap safely as the session has already been deserialized + let session_timestamp_u64 = session_timestamp.try_into().unwrap(); + assert(session_timestamp_u64 >= exec_info.block_info.unbox().block_timestamp, 'session/expired'); + } + + let retdata = execute_multicall(calls.span()); + + self.emit(TransactionExecuted { hash: tx_info.transaction_hash, response: retdata.span() }); + self.reentrancy_guard.end(); + retdata +} +// ANCHOR_END: execute +} \ No newline at end of file diff --git a/src/advanced-concepts/custom_signature_validation.md b/src/advanced-concepts/custom_signature_validation.md index bb6a95dc..9e0a42a0 100644 --- a/src/advanced-concepts/custom_signature_validation.md +++ b/src/advanced-concepts/custom_signature_validation.md @@ -1,37 +1,42 @@ # Custom Signature Validation Scheme -Digital signatures are a fundamental aspect of modern cryptography, used to verify the authenticity and integrity of digital messages or transactions. They are based on public-key cryptography, where a pair of keys (a public key and a private key) are used to create and verify signatures. -Private keys are kept secret and secure by the owner, and are used to sign the message or transaction, while the public key can be used by anyone to verify the signature. +Digital signatures are a fundamental aspect of modern cryptography used to verify the authenticity and integrity of digital messages or transactions. They are based on public-key cryptography, where a pair of keys (a public key and a private key) are used to create and verify signatures. -Account Abstraction is a native feature on Starknet, this makes it possible for anyone to implement custom signature schemes. The implication is that signature schemes on Starknet are not limited to just one, any standard signature scheme can be validated, for example Starknet signature, Secp256k1, Secp256r1, Eip191 etc are some of the custom signatures that can be validated on Starknet currently. +Private keys are kept secret and secured by the owner. They are used to sign data such as messages or transactions, which can be verified by anyone with the public key. + +Account Abstraction is a native feature on Starknet, this makes it possible for anyone to implement custom signature schemes and use it to validate transactions with the implementation of the signature validation logic. ### The Concepts of Accounts and Signers -i. **Account:** All accounts are smart contracts that can hold assets and execute transactions on Starknet, these account contracts however must implement some specific methods outlined in SNIP-6. For further reading: [Account contract](https://starknet-by-example.voyager.online/advanced-concepts/account_abstraction/account_contract.html). +i. **Account:** All accounts are smart contracts that can hold assets and execute transactions on Starknet, these account contracts however must implement some specific methods outlined in [SNIP-6.](https://github.com/starknet-io/SNIPs/blob/main/SNIPS/snip-6.md) + +ii. **Signers:** These are responsible for digitally signing transactions and also provide the authorization needed to initiate transactions. Transaction signing is done offchain on Starknet. -ii. **Signers:** These are responsible for digitally signing transactions and provide the authorization needed to initiate transactions. Digital signatures are cryptographic proofs that transactions are authorized by corresponding accounts. ### Signature validation on Starknet On Starknet transactions are signed offchain, which means that the signature process happens outside the blockchain. The signed transaction is then submitted to Starknet network for verification and execution. Read more: [Starknet-js docs](https://www.starknetjs.com/docs/guides/signature/) -All Account contracts on Starknet must implement the SNIP-6 standard as mentioned earlier. The methods implemented in the SNIP-6 standard provide means to move offchain signatures onchain and execute them. +All Account contracts on Starknet must implement the SNIP-6 standard as mentioned earlier. The methods outlined in the standard provide means to move offchain signatures onchain and execute them. + +`is_valid_signature` returns true if the signature is valid, `__validate__` validates the signature and marks them as 'VALIDATED', while `__execute__` executes the validated transaction. Sample implementation of SNIP-6 standard: -`is_valid_signature` returns true if the signature is valid, `__validate__` validates the signature and marks them as 'VALIDATED', while `__execute__` executes the validated transaction. Sample implementation of SNIP-6 standard: [Sample SNIP-6 Implementation](https://starknet-by-example.voyager.online/advanced-concepts/account_abstraction/account_contract.html#minimal-account-contract-executing-transactions) +```rust +{{#rustdoc_include ../../listings/advanced-concepts/simple_account/src/simple_account.cairo}} +``` -On Ethereum, only **one** signature scheme is used for signing messages and transactions, and also for signature authentications: the Elliptic Curve Digital Signature Algorithm (ECDSA). That means that no other signature algorithms can be validated on Ethereum, making it more secure but less flexible. -Custom signature validation employed on Starknet gives room for more flexibility, however, care must be taken to validate all signatures meticulously to ensure that: +On Ethereum, only **one** signature scheme is used: ECDSA. It makes Ethereum more secure but less flexible. +Custom signature validation used on Starknet gives room for more flexibility, however, care must be taken to validate all signatures meticulously to ensure that: a. the message has not been altered. b. the signer owns the private key corresponding to the public key. -In summary, Starknet accounts are normal blockchain accounts that hold assets and initiate transactions onchain, while signers provide the authorization required to ensure that transactions originating from these accounts are secure and valid. ### Custom signature validation sample -The example below shows a sample implementation of `Secp256r1` and `Secp256k1` signature schemes: +The example below shows a sample validation of `Secp256r1` and `Secp256k1` signature schemes: ```rust -{{#rustdoc_include ../../listings/advanced-concepts/custom_signature_validation/src/custom_signature.cairo:custom_signature_scheme}} +{{#rustdoc_include ../../listings/advanced-concepts/custom_signature_validation/src/custom_signature.cairo:is_valid_signature}} ```