-
Notifications
You must be signed in to change notification settings - Fork 72
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Added hashing * Fixed typo and used ANCHOR * added hash_trait * added hash_trait tests * removed text for link to remix url * fix: hashing --------- Co-authored-by: Giuseppe Fontanella <gfont@MacBook-Pro-M1-di-Giuseppe.local> Co-authored-by: Evans <mr.evans0075@gmail.com>
- Loading branch information
1 parent
d1924c4
commit 28a2599
Showing
7 changed files
with
179 additions
and
28 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,11 @@ | ||
[package] | ||
name = "hash_trait" | ||
version.workspace = true | ||
|
||
[dependencies] | ||
starknet.workspace = true | ||
|
||
[scripts] | ||
test.workspace = true | ||
|
||
[[target.starknet-contract]] |
118 changes: 118 additions & 0 deletions
118
listings/advanced-concepts/hash_trait/src/hash_trait.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,118 @@ | ||
#[starknet::interface] | ||
trait IHashTrait<T> { | ||
fn save_user_with_poseidon( | ||
ref self: T, id: felt252, username: felt252, password: felt252 | ||
) -> felt252; | ||
fn save_user_with_pedersen( | ||
ref self: T, id: felt252, username: felt252, password: felt252 | ||
) -> felt252; | ||
} | ||
|
||
// ANCHOR: hash | ||
#[starknet::contract] | ||
mod HashTraits { | ||
use core::hash::{HashStateTrait, HashStateExTrait}; | ||
use core::{pedersen::PedersenTrait, poseidon::PoseidonTrait}; | ||
|
||
#[storage] | ||
struct Storage { | ||
user_hash_poseidon: felt252, | ||
user_hash_pedersen: felt252, | ||
} | ||
|
||
#[derive(Drop, Hash)] | ||
struct LoginDetails { | ||
username: felt252, | ||
password: felt252, | ||
} | ||
|
||
#[derive(Drop, Hash)] | ||
struct UserDetails { | ||
id: felt252, | ||
login: LoginDetails, | ||
} | ||
|
||
#[abi(embed_v0)] | ||
impl HashTrait of super::IHashTrait<ContractState> { | ||
fn save_user_with_poseidon( | ||
ref self: ContractState, id: felt252, username: felt252, password: felt252 | ||
) -> felt252 { | ||
let login = LoginDetails { username, password }; | ||
let user = UserDetails { id, login }; | ||
|
||
let poseidon_hash = PoseidonTrait::new().update_with(user).finalize(); | ||
|
||
self.user_hash_poseidon.write(poseidon_hash); | ||
poseidon_hash | ||
} | ||
|
||
fn save_user_with_pedersen( | ||
ref self: ContractState, id: felt252, username: felt252, password: felt252 | ||
) -> felt252 { | ||
let login = LoginDetails { username, password }; | ||
let user = UserDetails { id, login }; | ||
|
||
let pedersen_hash = PedersenTrait::new(0).update_with(user).finalize(); | ||
|
||
self.user_hash_pedersen.write(pedersen_hash); | ||
pedersen_hash | ||
} | ||
} | ||
} | ||
// ANCHOR_END: hash | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::{HashTraits, IHashTraitDispatcher, IHashTraitDispatcherTrait}; | ||
|
||
use core::hash::{HashStateTrait, HashStateExTrait}; | ||
use core::{pedersen::PedersenTrait, poseidon::PoseidonTrait}; | ||
use starknet::{deploy_syscall}; | ||
|
||
use debug::PrintTrait; | ||
|
||
fn deploy() -> IHashTraitDispatcher { | ||
let mut calldata = ArrayTrait::new(); | ||
let (address, _) = deploy_syscall( | ||
HashTraits::TEST_CLASS_HASH.try_into().unwrap(), 0, calldata.span(), false | ||
) | ||
.unwrap(); | ||
IHashTraitDispatcher { contract_address: address } | ||
} | ||
|
||
|
||
#[test] | ||
#[available_gas(20000000)] | ||
fn test_pedersen_hash() { | ||
let mut contract = deploy(); | ||
|
||
let id = 0x1; | ||
let username = 'A.stark'; | ||
let password = 'password.stark'; | ||
let test_hash = contract.save_user_with_pedersen(id, username, password); | ||
|
||
assert( | ||
test_hash == 0x6da4b4d0489989f5483d179643dafb3405b0e3b883a6c8efe5beb824ba9055a, | ||
'Incorrect hash output' | ||
); | ||
} | ||
|
||
#[test] | ||
#[available_gas(20000000)] | ||
fn test_poseidon_hash() { | ||
let mut contract = deploy(); | ||
|
||
let id = 0x1; | ||
let username = 'A.stark'; | ||
let password = 'password.stark'; | ||
|
||
let test_hash = contract.save_user_with_poseidon(id, username, password); | ||
|
||
test_hash.print(); | ||
|
||
assert( | ||
test_hash == 0x4d165e1d398ae4864854518d3c58c3d7a21ed9c1f8f3618fbb0031d208aab7b, | ||
'Incorrect hash output' | ||
); | ||
} | ||
} |
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 @@ | ||
mod hash_trait; |
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,16 @@ | ||
# Hashing | ||
|
||
Hashing is a cryptographic technique that allows you to transform a variable length input into a fixed length output. | ||
The resulting output is called a hash and it's completely different from the input. | ||
Hash functions are deterministic, meaning that the same input will always produce the same output. | ||
|
||
The two hash functions provided by the Cairo library are `Poseidon` and `Pedersen`. | ||
Pedersen hashes were used in the past (but still used in some scenario for backward compatibility) while Poseidon hashes are the standard nowadays since they were designed to be very efficient for Zero Knowledge proof systems. | ||
|
||
In Cairo it's possible to hash all the types that can be converted to `felt252` since they implement natively the `Hash` trait. It's also possible to hash more complex types like structs by deriving the Hash trait with the attribute `#[derive(Hash)]` but only if all the struct's fields are themselves hashable. | ||
|
||
You first need to initialize a hash state with the `new` method of the `HashStateTrait` and then you can update it with the `update` method. You can accumulate multiple updates. Then, the `finalize` method returns the final hash value as a `felt252`. | ||
|
||
```rust | ||
{{#rustdoc_include ../../listings/advanced-concepts/hash_trait/src/hash_trait.cairo:hash}} | ||
``` |