Skip to content

Commit

Permalink
adding v1 string example
Browse files Browse the repository at this point in the history
  • Loading branch information
gaetbout committed Oct 24, 2024
1 parent fc7408a commit 31d754c
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 3 deletions.
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1 +1 @@
scarb 2.7.0
scarb 2.8.3
5 changes: 3 additions & 2 deletions Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ version = "0.3.0"
sierra = true

[dependencies]
starknet = "2.7.0"
starknet = "2.8.2"

[dev-dependencies]
cairo_test = "2.7.0"
cairo_test = "2.8.2"

[scripts]
SimpleStruct = "npx ts-node scripts/v0/SimpleStruct.ts"
Expand All @@ -20,6 +20,7 @@ StructWithMerkletree = "npx ts-node scripts/v0/StructWithMerkletree.ts"
StructWithMerkletreeV1 = "npx ts-node scripts/v1/StructWithMerkletree.ts"
StructWithU256 = "npx ts-node scripts/v0/StructWithU256.ts"
StructWithU256V1 = "npx ts-node scripts/v1/StructWithU256.ts"
StructWithByteArray = "npx ts-node scripts/v1/StructWithByteArray.ts"
format = "scarb fmt && npx prettier --write ."

## TODO ADD ALL STANDARD INTERFACES
53 changes: 53 additions & 0 deletions scripts/v1/StructWithByteArray.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { byteArray, shortString, StarknetDomain, TypedData, typedData, TypedDataRevision } from "starknet";

const types = {
StarknetDomain: [
{ name: "name", type: "shortstring" },
{ name: "version", type: "shortstring" },
{ name: "chainId", type: "shortstring" },
{ name: "revision", type: "shortstring" },
],
StructWithByteArray: [
{ name: "some_felt252", type: "felt" },
{ name: "some_byte_array", type: "string" },
],
};

interface StructWithByteArray {
some_felt252: string;
some_byte_array: string;
}


function getDomain(chainId: string): StarknetDomain {
return {
name: "dappName",
version: shortString.encodeShortString("1"),
chainId,
revision: TypedDataRevision.ACTIVE,
};
}

function getTypedDataHash(myStruct: StructWithByteArray, chainId: string, owner: bigint): string {
console.log(JSON.stringify(getTypedData(myStruct, chainId)));
return typedData.getMessageHash(getTypedData(myStruct, chainId), owner);
}

// Needed to reproduce the same structure as:
// https://github.com/0xs34n/starknet.js/blob/1a63522ef71eed2ff70f82a886e503adc32d4df9/__mocks__/typedDataStructArrayExample.json
function getTypedData(myStruct: StructWithByteArray, chainId: string): TypedData {
return {
types,
primaryType: "StructWithByteArray",
domain: getDomain(chainId),
message: { ...myStruct },
};
}

console.log(byteArray.byteArrayFromString("Some long message that exceeds 31 characters"));
const structWithByteArray: StructWithByteArray = {
some_felt252: "712",
some_byte_array: "Some long message that exceeds 31 characters",
};

console.log(`test test_valid_hash ${getTypedDataHash(structWithByteArray, "0", 420n)};`);
68 changes: 68 additions & 0 deletions src/examples/v1/struct_with_byte_array.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use starknet::{get_tx_info, get_caller_address};
use poseidon::PoseidonTrait;
use hash::{HashStateTrait, HashStateExTrait};
use off_chain_signature::interfaces::{IOffChainMessageHash, IStructHash, v1::StarknetDomain};

const STRUCT_WITH_U256_TYPE_HASH: felt252 =
selector!("\"StructWithByteArray\"(\"some_felt252\":\"felt\",\"some_byte_array\":\"string\")");

#[derive(Drop)]
struct StructWithByteArray {
some_felt252: felt252,
some_byte_array: ByteArray,
}

impl OffChainMessageHashStructWithByteArray of IOffChainMessageHash<StructWithByteArray> {
fn get_message_hash(self: @StructWithByteArray) -> felt252 {
let domain = StarknetDomain {
name: 'dappName', version: '1', chain_id: get_tx_info().unbox().chain_id, revision: 1
};
let mut state = PoseidonTrait::new();
state = state.update_with('StarkNet Message');
state = state.update_with(domain.get_struct_hash());
// This can be a field within the struct, it doesn't have to be get_caller_address().
state = state.update_with(get_caller_address());
state = state.update_with(self.get_struct_hash());
// Hashing with the amount of elements being hashed
state.finalize()
}
}

impl StructHashStructWithByteArray of IStructHash<StructWithByteArray> {
fn get_struct_hash(self: @StructWithByteArray) -> felt252 {
let mut state = PoseidonTrait::new();
state = state.update_with(STRUCT_WITH_U256_TYPE_HASH);
state = state.update_with(*self.some_felt252);
state = state.update_with(self.some_byte_array.get_struct_hash());
state.finalize()
}
}

impl StructHashU256 of IStructHash<ByteArray> {
fn get_struct_hash(self: @ByteArray) -> felt252 {
let mut state = PoseidonTrait::new();
let mut output = array![];
Serde::serialize(self, ref output);
for e in output.span() {
state = state.update_with(*e);
};
state.finalize()
}
}

#[cfg(test)]
mod tests {
use super::{StructWithByteArray, IOffChainMessageHash};
use starknet::testing::set_caller_address;

#[test]
fn test_valid_hash() {
// This value was computed using StarknetJS
let message_hash = 0x3e75d70054b3e7d181949eaab082b5dab03903f08952959d46e4755b7055b5;
let simple_struct = StructWithByteArray {
some_felt252: 712, some_byte_array: "Some long message that exceeds 31 characters"
};
set_caller_address(420.try_into().unwrap());
assert_eq!(simple_struct.get_message_hash(), message_hash);
}
}
1 change: 1 addition & 0 deletions src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ mod examples {
mod struct_with_array;
mod struct_with_merkletree;
mod struct_with_u256;
mod struct_with_byte_array;
}
}

0 comments on commit 31d754c

Please sign in to comment.