-
Notifications
You must be signed in to change notification settings - Fork 93
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat : Added Signature verification (#176)
* feat : Added Signature verification * feat : Added deployed contract instance link * feat : Changed the topic from ch01 to ch02
- Loading branch information
1 parent
32b8abc
commit b2c8e07
Showing
10 changed files
with
210 additions
and
30 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
target |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
# Code generated by scarb DO NOT EDIT. | ||
version = 1 | ||
|
||
[[package]] | ||
name = "ecdsa_verification" | ||
version = "0.1.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
[package] | ||
name = "ecdsa_verification" | ||
version.workspace = true | ||
edition = '2023_11' | ||
|
||
|
||
[dependencies] | ||
starknet.workspace = true | ||
|
||
[scripts] | ||
test.workspace = true | ||
|
||
[[target.starknet-contract]] |
98 changes: 98 additions & 0 deletions
98
listings/advanced-concepts/ecdsa_verification/src/ecdsa_verification.cairo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
// How to Sign and Verify | ||
// # Signing | ||
// 1. Create message to sign | ||
// 2. Hash the message | ||
// 3. Sign the hash (off chain, keep your private key secret) | ||
|
||
use core::starknet::eth_address::EthAddress; | ||
use starknet::secp256_trait::{Signature}; | ||
#[starknet::interface] | ||
trait IVerifySignature<TContractState> { | ||
fn get_signature(self: @TContractState, r: u256, s: u256, v: u32,) -> Signature; | ||
fn verify_eth_signature( | ||
self: @TContractState, eth_address: EthAddress, msg_hash: u256, r: u256, s: u256, v: u32, | ||
); | ||
fn recover_public_key( | ||
self: @TContractState, eth_address: EthAddress, msg_hash: u256, r: u256, s: u256, v: u32 | ||
); | ||
} | ||
|
||
#[starknet::contract] | ||
mod verifySignature { | ||
use super::IVerifySignature; | ||
use core::starknet::eth_address::EthAddress; | ||
use starknet::get_caller_address; | ||
use starknet::secp256_trait; | ||
use starknet::secp256k1::{Secp256k1Point}; | ||
use starknet::{SyscallResult, SyscallResultTrait}; | ||
use starknet::secp256_trait::{ | ||
Secp256Trait, Secp256PointTrait, Signature, signature_from_vrs, recover_public_key, | ||
is_signature_entry_valid | ||
}; | ||
use core::traits::{TryInto, Into}; | ||
use starknet::eth_signature::{verify_eth_signature, public_key_point_to_eth_address}; | ||
|
||
#[storage] | ||
struct Storage { | ||
msg_hash: u256, | ||
signature: Signature, | ||
eth_address: EthAddress, | ||
} | ||
|
||
#[abi(embed_v0)] | ||
impl VerifySignature of IVerifySignature<ContractState> { | ||
/// This function returns the signature struct for the given parameters. | ||
/// | ||
/// # Arguments | ||
/// | ||
/// * `r` - The R component of the signature. | ||
/// * `s` - The S component of the signature. | ||
/// * `v` - The V component of the signature. | ||
/// | ||
/// # Returns | ||
/// | ||
/// * `Signature` - The signature struct. | ||
fn get_signature(self: @ContractState, r: u256, s: u256, v: u32,) -> Signature { | ||
// Create a Signature object from the given v, r, and s values. | ||
let signature: Signature = signature_from_vrs(v, r, s); | ||
signature | ||
} | ||
|
||
|
||
/// Verifies an Ethereum signature. | ||
/// | ||
/// # Arguments | ||
/// | ||
/// * `eth_address` - The Ethereum address to verify the signature against. | ||
/// * `msg_hash` - The hash of the message that was signed. | ||
/// * `r` - The R component of the signature. | ||
/// * `s` - The S component of the signature. | ||
/// * `v` - The V component of the signature. | ||
fn verify_eth_signature( | ||
self: @ContractState, eth_address: EthAddress, msg_hash: u256, r: u256, s: u256, v: u32 | ||
) { | ||
let signature = self.get_signature(r, s, v); | ||
verify_eth_signature(:msg_hash, :signature, :eth_address); | ||
} | ||
|
||
/// Recovers the public key from an Ethereum signature and verifies that it matches the given Ethereum address. | ||
/// | ||
/// # Arguments | ||
/// | ||
/// * `eth_address` - The Ethereum address to verify the signature against. | ||
/// * `msg_hash` - The hash of the message that was signed. | ||
/// * `r` - The R component of the signature. | ||
/// * `s` - The S component of the signature. | ||
/// * `v` - The V component of the signature. | ||
fn recover_public_key( | ||
self: @ContractState, eth_address: EthAddress, msg_hash: u256, r: u256, s: u256, v: u32 | ||
) { | ||
let signature = self.get_signature(r, s, v); | ||
let public_key_point = recover_public_key::<Secp256k1Point>(msg_hash, signature) | ||
.unwrap(); | ||
let calculated_eth_address = public_key_point_to_eth_address(:public_key_point); | ||
assert(calculated_eth_address == eth_address, 'Invalid Address'); | ||
} | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
mod ecdsa_verification; | ||
|
||
#[cfg(test)] | ||
mod tests; |
41 changes: 41 additions & 0 deletions
41
listings/advanced-concepts/ecdsa_verification/src/tests.cairo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
#[cfg(test)] | ||
mod tests { | ||
use starknet::secp256_trait::{ | ||
Secp256Trait, Secp256PointTrait, Signature, signature_from_vrs, recover_public_key, | ||
is_signature_entry_valid | ||
}; | ||
|
||
use starknet::EthAddress; | ||
use starknet::secp256k1::{Secp256k1Point}; | ||
use core::traits::{TryInto, Into}; | ||
use starknet::eth_signature::{verify_eth_signature, public_key_point_to_eth_address}; | ||
|
||
|
||
fn get_message_and_signature() -> (u256, Signature, EthAddress) { | ||
let msg_hash = 0x546ec3fa4f7d3308931816fafd47fa297afe9ac9a09651f77acc13c05a84734f; | ||
let r = 0xc0f30bcef72974dedaf165cf7848a83b0b9eb6a65167a14643df96698d753efb; | ||
let s = 0x7f189e3cb5eb992d8cd26e287a13e900326b87f58da2b7fb48fbd3977e3cab1c; | ||
let v = 27; | ||
|
||
let eth_address = 0x5F04693482cfC121FF244cB3c3733aF712F9df02_u256.into(); | ||
let signature: Signature = signature_from_vrs(v, r, s); | ||
|
||
(msg_hash, signature, eth_address) | ||
} | ||
|
||
#[test] | ||
#[available_gas(100000000)] | ||
fn test_verify_eth_signature() { | ||
let (msg_hash, signature, eth_address) = get_message_and_signature(); | ||
verify_eth_signature(:msg_hash, :signature, :eth_address); | ||
} | ||
|
||
#[test] | ||
#[available_gas(100000000)] | ||
fn test_secp256k1_recover_public_key() { | ||
let (msg_hash, signature, eth_address) = get_message_and_signature(); | ||
let public_key_point = recover_public_key::<Secp256k1Point>(msg_hash, signature).unwrap(); | ||
let calculated_eth_address = public_key_point_to_eth_address(:public_key_point); | ||
assert(calculated_eth_address == eth_address, 'Invalid Address'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# Signature Verification |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
# ECDSA Verification | ||
|
||
This is the Cairo adaptation of the [Solidity by example Verifying Signature](https://solidity-by-example.org/signature/) | ||
Messages can be signed off chain and then verified on chain using a smart contract. | ||
|
||
```rust | ||
{{#include ../../listings/advanced-concepts/ecdsa_verification/src/ecdsa_verification.cairo}} | ||
``` | ||
|
||
[Click here to interact with the deployed contract on Voyager](https://goerli.voyager.online/contract/0x070bad62072d2a30fd08a95e9de99828955cfcffc40eac8adf3b21e9970590be#writeContract) |