From 224b66af273552cd54834be3a888632266ed49d3 Mon Sep 17 00:00:00 2001 From: yoavGrs <97383386+yoavGrs@users.noreply.github.com> Date: Thu, 31 Aug 2023 16:24:26 +0300 Subject: [PATCH] feat(common): calculate declare transaction hash (#1124) --- .../resources/transaction_hash.json | 50 ++++++++++++- crates/papyrus_common/src/transaction_hash.rs | 72 +++++++++++++++++-- 2 files changed, 116 insertions(+), 6 deletions(-) diff --git a/crates/papyrus_common/resources/transaction_hash.json b/crates/papyrus_common/resources/transaction_hash.json index 6273b9dcd5..ea20263ba5 100644 --- a/crates/papyrus_common/resources/transaction_hash.json +++ b/crates/papyrus_common/resources/transaction_hash.json @@ -79,6 +79,54 @@ } }, "transaction_hash": "0xa5eeb0d17fe3262c2b7b95bd934c5a5ee7243b0e7584a8d2a3fbb9bd456241" + }, + { + "transaction": { + "Declare": { + "V0": { + "max_fee": "0x0", + "signature": [], + "nonce": "0x0", + "class_hash": "0x70ffba803149d9cfe1762b5099d15ec129de0e998d1cbd2a29c2abca40c2ce1", + "sender_address": "0x1" + } + } + }, + "transaction_hash": "0x5a5e819664c7550d60d9e4bce8da3478a133602b81e4d0bfdbbc4bb30125a96" + }, + { + "transaction": { + "Declare": { + "V1": { + "max_fee": "0x174876e8000", + "signature": [ + "0x6b2c99aac0e375ecca77d5056be39c00328e45c541045d89aeb7458acaffbdb", + "0x732e2b1604487609fdabd9be05ea0e2d828f50bca1e5dd86ca0beabf4670866" + ], + "nonce": "0x5", + "class_hash": "0x4da612e187f8ea1508ca96c726e1da9891bc480f97a157df25568f9dc8ea1dc", + "sender_address": "0x92e02752e4309de75f8f07f4a9efca32649ba83d798f13897714b1a5acd93d" + } + } + }, + "transaction_hash": "0x64b91efce5648a65b950d3aa560b4e265eedd9b49b232a85170510c4c77e9bc" + }, + { + "transaction": { + "Declare": { + "V2": { + "max_fee": "0xb7efe7b25236", + "signature": [ + "0x2a1abe101f6651801e5faf2adab17feb726d440fb19a0f1d75e3ea7786b9459", + "0x2fda52f14100da5d87ddffdbc2b48981947285bb549a7760d4f472ce06dba5e" + ], + "nonce": "0x17", + "class_hash": "0x702a9e80c74a214caf0e77326180e72ba3bd3f53dbd5519ede339eb3ae9eed4", + "compiled_class_hash": "0x1be58ebac8e3bc17ae4b7de633ed9c78f2d6dd1acd49c12985bcd5002bdb824", + "sender_address": "0x349d9bdae264d4d613f34a7bcb68e287417e4cd3651e1ff7a89fd75ff04b662" + } + } + }, + "transaction_hash": "0x29410c3ab8d8a7d593e915f3051b9c71e48626cf688c7c8c526f400648cf24c" } - ] diff --git a/crates/papyrus_common/src/transaction_hash.rs b/crates/papyrus_common/src/transaction_hash.rs index bc68680164..8caf0047fc 100644 --- a/crates/papyrus_common/src/transaction_hash.rs +++ b/crates/papyrus_common/src/transaction_hash.rs @@ -6,6 +6,9 @@ use lazy_static::lazy_static; use starknet_api::core::{calculate_contract_address, ChainId, ContractAddress}; use starknet_api::hash::{StarkFelt, StarkHash}; use starknet_api::transaction::{ + DeclareTransaction, + DeclareTransactionV0V1, + DeclareTransactionV2, DeployAccountTransaction, DeployTransaction, InvokeTransaction, @@ -18,6 +21,7 @@ use starknet_api::StarknetApiError; use starknet_crypto::{pedersen_hash, FieldElement}; lazy_static! { + static ref DECLARE: StarkFelt = ascii_as_felt("declare").unwrap(); static ref DEPLOY: StarkFelt = ascii_as_felt("deploy").unwrap(); static ref DEPLOY_ACCOUNT: StarkFelt = ascii_as_felt("deploy_account").unwrap(); static ref INVOKE: StarkFelt = ascii_as_felt("invoke").unwrap(); @@ -30,6 +34,7 @@ lazy_static! { static ref ZERO: StarkFelt = StarkFelt::from(0_u8); static ref ONE: StarkFelt = StarkFelt::from(1_u8); + static ref TWO: StarkFelt = StarkFelt::from(2_u8); } /// Calculates hash of a Starknet transaction. @@ -38,7 +43,17 @@ pub fn get_transaction_hash( chain_id: &ChainId, ) -> Result { match transaction { - Transaction::Declare(_) => unimplemented!(), + Transaction::Declare(declare) => match declare { + DeclareTransaction::V0(declare_v0) => { + get_declare_transaction_v0_hash(declare_v0, chain_id) + } + DeclareTransaction::V1(declare_v1) => { + get_declare_transaction_v1_hash(declare_v1, chain_id) + } + DeclareTransaction::V2(declare_v2) => { + get_declare_transaction_v2_hash(declare_v2, chain_id) + } + }, Transaction::Deploy(deploy) => get_deploy_transaction_hash(deploy, chain_id), Transaction::DeployAccount(deploy_account) => { get_deploy_account_transaction_hash(deploy_account, chain_id) @@ -60,13 +75,11 @@ pub fn validate_transaction_hash( expected_hash: StarkHash, ) -> Result { let mut possible_hashes = match transaction { - Transaction::Declare(_) => unimplemented!(), + Transaction::Declare(_) => vec![], Transaction::Deploy(deploy) => { vec![get_deprecated_deploy_transaction_hash(deploy, chain_id)?] } - Transaction::DeployAccount(_) => { - vec![] - } + Transaction::DeployAccount(_) => vec![], Transaction::Invoke(invoke) => match invoke { InvokeTransaction::V0(invoke_v0) => { vec![get_deprecated_invoke_transaction_v0_hash(invoke_v0, chain_id)?] @@ -265,3 +278,52 @@ fn get_common_l1_handler_transaction_hash( .chain(&transaction.nonce.0) .get_hash()) } + +fn get_declare_transaction_v0_hash( + transaction: &DeclareTransactionV0V1, + chain_id: &ChainId, +) -> Result { + Ok(PedersenHashChain::new() + .chain(&DECLARE) + .chain(&ZERO) // Version + .chain(transaction.sender_address.0.key()) + .chain(&ZERO ) // No entry point selector in declare transaction. + .chain(&PedersenHashChain::new().get_hash()) + .chain(&transaction.max_fee.0.into()) + .chain(&ascii_as_felt(chain_id.0.as_str())?) + .chain(&transaction.class_hash.0) + .get_hash()) +} + +fn get_declare_transaction_v1_hash( + transaction: &DeclareTransactionV0V1, + chain_id: &ChainId, +) -> Result { + Ok(PedersenHashChain::new() + .chain(&DECLARE) + .chain(&ONE) // Version + .chain(transaction.sender_address.0.key()) + .chain(&ZERO) // No entry point selector in declare transaction. + .chain(&PedersenHashChain::new().chain(&transaction.class_hash.0).get_hash()) + .chain(&transaction.max_fee.0.into()) + .chain(&ascii_as_felt(chain_id.0.as_str())?) + .chain(&transaction.nonce.0) + .get_hash()) +} + +fn get_declare_transaction_v2_hash( + transaction: &DeclareTransactionV2, + chain_id: &ChainId, +) -> Result { + Ok(PedersenHashChain::new() + .chain(&DECLARE) + .chain(&TWO) // Version + .chain(transaction.sender_address.0.key()) + .chain(&ZERO) // No entry point selector in declare transaction. + .chain(&PedersenHashChain::new().chain(&transaction.class_hash.0).get_hash()) + .chain(&transaction.max_fee.0.into()) + .chain(&ascii_as_felt(chain_id.0.as_str())?) + .chain(&transaction.nonce.0) + .chain(&transaction.compiled_class_hash.0) + .get_hash()) +}