Skip to content

Commit

Permalink
fix(ark-contracts): use poseidon hash function (#200)
Browse files Browse the repository at this point in the history
  • Loading branch information
remiroyc authored Nov 28, 2023
1 parent 47724ad commit ad9b859
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 93 deletions.
31 changes: 2 additions & 29 deletions crates/ark-contracts/arkchain/src/crypto/hash.cairo
Original file line number Diff line number Diff line change
@@ -1,34 +1,7 @@
//! Crypto hashes computation.

/// Computes the starknet keccak on the input data.
/// Starknet keccak is used to fit into one felt, and being easily
/// computed with off-chain components using starknet-rs or starknetjs.
///
/// # Arguments
///
/// * `data` - Data to hash.
fn starknet_keccak(data: Span<felt252>) -> felt252 {
let mut u256_data: Array<u256> = array![];

let mut i = 0_usize;
loop {
if i == data.len() {
break;
}
u256_data.append((*data[i]).into());
i += 1;
};

let mut hash = keccak::keccak_u256s_be_inputs(u256_data.span());
let low = integer::u128_byte_reverse(hash.high);
let high = integer::u128_byte_reverse(hash.low);
hash = u256 { low, high };
hash = hash & 0x03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_u256;
hash.try_into().expect('starknet keccak overflow')
}
use poseidon::poseidon_hash_span;

fn serialized_hash<T, +Serde<T>, +Drop<T>>(value: T) -> felt252 {
let mut buf = array![];
value.serialize(ref buf);
starknet_keccak(buf.span())
poseidon_hash_span(buf.span())
}
7 changes: 3 additions & 4 deletions crates/ark-contracts/arkchain/src/order/order_v1.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ use core::option::OptionTrait;
use starknet::ContractAddress;
use starknet::contract_address_to_felt252;
use arkchain::order::types::{OrderTrait, OrderValidationError, OrderType, RouteType};
use arkchain::crypto::hash::starknet_keccak;
use arkchain::order::types::FulfillInfo;

use poseidon::poseidon_hash_span;
const ORDER_VERSION_V1: felt252 = 'v1';
// Auction -> end_amount (reserve price) > start_amount (starting price).
// Auction -> ERC721_ERC20.
Expand Down Expand Up @@ -147,12 +146,12 @@ impl OrderTraitOrderV1 of OrderTrait<OrderV1> {
buf.append((token_id.high).into());
buf.append((*self.token_address).into());
buf.append(*self.token_chain_id);
starknet_keccak(buf.span())
poseidon_hash_span(buf.span())
}

fn compute_order_hash(self: @OrderV1) -> felt252 {
let mut buf = array![];
self.serialize(ref buf);
starknet_keccak(buf.span())
poseidon_hash_span(buf.span())
}
}
2 changes: 1 addition & 1 deletion crates/ark-contracts/arkchain/src/order/types.cairo
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Order generic variables.
use starknet::ContractAddress;
use arkchain::crypto::hash::starknet_keccak;
use poseidon::poseidon_hash_span;

/// Order types.
#[derive(Serde, Drop, PartialEq, Copy)]
Expand Down
4 changes: 2 additions & 2 deletions crates/ark-contracts/arkchain/src/orderbook.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ mod orderbook {
};
use arkchain::crypto::signer::{SignInfo, Signer, SignerValidator};
use arkchain::order::types::OrderStatus;
use arkchain::crypto::hash::{starknet_keccak, serialized_hash};

use arkchain::crypto::hash::{serialized_hash};
use poseidon::poseidon_hash_span;
const EXTENSION_TIME_IN_SECONDS: u64 = 600;
const AUCTION_ACCEPTING_TIME_SECS: u64 = 172800;
/// Storage struct for the Orderbook contract.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,12 @@ fn test_validate_common_data_with_valid_order() {
fn test_order_signature() {
let block_timestamp = 1700069210;
let (order_listing, order_offer, order_auction, order_collection_offer) = setup_orders();

let order_hash = order_listing.compute_order_hash();

let signer = Signer::WEIERSTRESS_STARKNET(
SignInfo {
user_pubkey: 0x20c29f1c98f3320d56f01c13372c923123c35828bce54f2153aa1cfe61c44f2,
user_sig_r: 1489698813778371355144251950338771124997774846063061621537328046839877802074,
user_sig_s: 3108595483860555652530443442785498132521754673633088480599648397307624361634,
user_sig_r: 1604505843266718300714627301508508239046631480436842114329682515156485708769,
user_sig_s: 61902183293821228744451698818869796262719190329925918953383999133206977961,
}
);
SignerValidator::verify(order_hash, signer);
Expand Down
61 changes: 31 additions & 30 deletions scripts/signature/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ec, encode } from "starknet";
import { OrderV1, RouteType, ExecutionInfo } from "./types";
import { hashOrder, hashExecutionInfo } from "./utils";
import { poseidonHashOrder } from "./utils";

function main() {
const privateKey = "0x1234567890987654321";
Expand All @@ -24,13 +24,13 @@ function main() {
quantity: { high: 0, low: 1 },
startAmount: { high: 0, low: 600000000000000000 },
endAmount: { high: 0, low: 0 },
startDate: 1699556878,
endDate: 1702148878,
startDate: 1699556828,
endDate: 1702148828,
brokerId: 123,
additionalData: [],
};

const orderMessageHash = hashOrder(order);
const orderMessageHash = poseidonHashOrder(order);
const signature = ec.starkCurve.sign(orderMessageHash, privateKey);

console.log("Order Message Hash:", orderMessageHash);
Expand All @@ -40,35 +40,36 @@ function main() {
console.log("Signature S:", signature.s.toString());
}

function execution() {
const privateKey = "0x1234567890987654321";
const starknetPublicKey = ec.starkCurve.getStarkKey(privateKey);
const fullPublicKey = encode.addHexPrefix(
encode.buf2hex(ec.starkCurve.getPublicKey(privateKey, false))
);
// function execution() {
// const privateKey = "0x1234567890987654321";
// const starknetPublicKey = ec.starkCurve.getStarkKey(privateKey);
// const fullPublicKey = encode.addHexPrefix(
// encode.buf2hex(ec.starkCurve.getPublicKey(privateKey, false))
// );

const executionInfo: ExecutionInfo = {
orderHash:
"0x00E4769a444F7FF9C70951A333eBA5c32707Cef3CdfB6B27cA63567f51cdd078",
fulfiller:
"0x00E4769a4d2F7F69C70951A333eBA5c32707Cef3CdfB6B27cA63567f51cdd078",
tokenChainId: "0x534e5f4d41494e",
tokenAddress:
"0x01435498bf393da86b4733b9264a86b58a42b31f8d8b8ba309593e5c17847672",
tokenId: { high: 0, low: 10 },
};
// const executionInfo: ExecutionInfo = {
// orderHash:
// "0x00E4769a444F7FF9C70951A333eBA5c32707Cef3CdfB6B27cA63567f51cdd078",
// fulfiller:
// "0x00E4769a4d2F7F69C70951A333eBA5c32707Cef3CdfB6B27cA63567f51cdd078",
// tokenChainId: "0x534e5f4d41494e",
// tokenAddress:
// "0x01435498bf393da86b4733b9264a86b58a42b31f8d8b8ba309593e5c17847672",
// tokenId: { high: 0, low: 10 },
// };

const executionInfoMessageHash = hashExecutionInfo(executionInfo);
const signature = ec.starkCurve.sign(executionInfoMessageHash, privateKey);
// const executionInfoMessageHash = hashExecutionInfo(executionInfo);
// const signature = ec.starkCurve.sign(executionInfoMessageHash, privateKey);

console.log("Order Message Hash:", executionInfoMessageHash);
console.log("StarkNet Public Key:", starknetPublicKey);
console.log("Full Public Key:", fullPublicKey);
console.log("Signature R:", signature.r.toString());
console.log("Signature S:", signature.s.toString());
}
// console.log("Order Message Hash:", executionInfoMessageHash);
// console.log("StarkNet Public Key:", starknetPublicKey);
// console.log("Full Public Key:", fullPublicKey);
// console.log("Signature R:", signature.r.toString());
// console.log("Signature S:", signature.s.toString());
// }

console.log("------ ORDER -------");
main();
console.log("------ Execution ------");
execution();

// console.log("------ Execution ------");
// execution();
74 changes: 51 additions & 23 deletions scripts/signature/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,41 @@ export function bigNumberishToUint8Array(value: BigNumberish): Uint8Array {
return num.hexToBytes(`0x${hex}`);
}

export function poseidonHashOrder(order: OrderV1): string {
const elements: bigint[] = [
BigInt(order.route),
BigInt(order.currencyAddress),
BigInt(order.currencyChainId),
BigInt(order.salt),
BigInt(order.offerer),
BigInt(order.tokenChainId),
BigInt(order.tokenAddress),
...(order.tokenId
? [BigInt(0), BigInt(order.tokenId.low), BigInt(order.tokenId.high)]
: [BigInt(1)]),
BigInt(order.quantity.low),
BigInt(order.quantity.high),
BigInt(order.startAmount.low),
BigInt(order.startAmount.high),
BigInt(order.endAmount.low),
BigInt(order.endAmount.high),
BigInt(order.startDate),
BigInt(order.endDate),
BigInt(order.brokerId),
BigInt(order.additionalData.length),
];

const generatedHash = starknet.poseidonHashMany(elements);
return num.toHex(generatedHash);
}

/**
* Constructs a Keccak hash from the order's properties.
* Property order is important as it determines the hash output.
* @param {OrderV1} order - The order to hash.
* @returns {string} The Keccak hash of the order as a hex string.
*/
export function hashOrder(order: OrderV1): string {
export function keccakHashOrder(order: OrderV1): string {
// Convert order properties to Uint8Array and concatenate them.
// The array is initialized with a fixed set of properties.
let results = Uint8Array.from([
Expand Down Expand Up @@ -63,27 +91,27 @@ export function hashOrder(order: OrderV1): string {
* @param {OrderV1} order - The order to hash.
* @returns {string} The Keccak hash of the order as a hex string.
*/
export function hashExecutionInfo(execution: ExecutionInfo): string {
// Convert order properties to Uint8Array and concatenate them.
// The array is initialized with a fixed set of properties.
let results = Uint8Array.from([
...bigNumberishToUint8Array(execution.orderHash),
...bigNumberishToUint8Array(execution.fulfiller),
...bigNumberishToUint8Array(execution.offerHash || 1),
...bigNumberishToUint8Array(execution.tokenChainId),
...bigNumberishToUint8Array(execution.tokenAddress),
...(execution.tokenId
? [
...bigNumberishToUint8Array(0),
...bigNumberishToUint8Array(execution.tokenId.low),
...bigNumberishToUint8Array(execution.tokenId.high),
]
: [...bigNumberishToUint8Array(1)]),
]);
// export function hashExecutionInfo(execution: ExecutionInfo): string {
// // Convert order properties to Uint8Array and concatenate them.
// // The array is initialized with a fixed set of properties.
// let results = Uint8Array.from([
// ...bigNumberishToUint8Array(execution.orderHash),
// ...bigNumberishToUint8Array(execution.fulfiller),
// ...bigNumberishToUint8Array(execution.offerHash || 1),
// ...bigNumberishToUint8Array(execution.tokenChainId),
// ...bigNumberishToUint8Array(execution.tokenAddress),
// ...(execution.tokenId
// ? [
// ...bigNumberishToUint8Array(0),
// ...bigNumberishToUint8Array(execution.tokenId.low),
// ...bigNumberishToUint8Array(execution.tokenId.high),
// ]
// : [...bigNumberishToUint8Array(1)]),
// ]);

// Generate the hash from the concatenated Uint8Arrays.
const generatedHash = starknet.keccak(results);
// // Generate the hash from the concatenated Uint8Arrays.
// const generatedHash = starknet.keccak(results);

// Convert the generated hash to a hexadecimal string.
return num.toHex(generatedHash);
}
// // Convert the generated hash to a hexadecimal string.
// return num.toHex(generatedHash);
// }

0 comments on commit ad9b859

Please sign in to comment.