diff --git a/docs/docs/concepts/foundation/communication/cross_chain_calls.md b/docs/docs/concepts/foundation/communication/cross_chain_calls.md index 86554a82090..abd37f84fcf 100644 --- a/docs/docs/concepts/foundation/communication/cross_chain_calls.md +++ b/docs/docs/concepts/foundation/communication/cross_chain_calls.md @@ -96,7 +96,7 @@ For the sake of cross-chain messages, this means inserting and nullifying L1 $\r ### Messages -While a message could theoretically be arbitrary long, we want to limit the cost of the insertion on L1 as much as possible. Therefore, we allow the users to send 32 bytes of "content" between L1 and L2. If 32 suffices, no packing required. If the 32 is too "small" for the message directly, the sender should simply pass along a `sha256(content)` instead of the content directly. The content can then either be emitted as an event on L2 or kept by the sender, who should then be the only entity that can "unpack" the message. +While a message could theoretically be arbitrary long, we want to limit the cost of the insertion on L1 as much as possible. Therefore, we allow the users to send 32 bytes of "content" between L1 and L2. If 32 suffices, no packing required. If the 32 is too "small" for the message directly, the sender should simply pass along a `sha256(content)` instead of the content directly (note that this hash should fit in a field element which is ~254 bits. More info on this below). The content can then either be emitted as an event on L2 or kept by the sender, who should then be the only entity that can "unpack" the message. In this manner, there is some way to "unpack" the content on the receiving domain. The message that is passed along, require the `sender/recipient` pair to be communicated as well (we need to know who should receive the message and be able to check). By having the pending messages be a contract on L1, we can ensure that the `sender = msg.sender` and let only `content` and `recipient` be provided by the caller. Summing up, we can use the struct's seen below, and only store the commitment (`sha256(LxToLyMsg)`) on chain or in the trees, this way, we need only update a single storage slot per message. diff --git a/docs/docs/dev_docs/contracts/portals/main.md b/docs/docs/dev_docs/contracts/portals/main.md index 0ff0bc24d40..e1450b98140 100644 --- a/docs/docs/dev_docs/contracts/portals/main.md +++ b/docs/docs/dev_docs/contracts/portals/main.md @@ -47,6 +47,20 @@ Computing the `content` must be done manually in its current form, as we are sti #include_code claim_public /yarn-project/noir-contracts/src/contracts/token_bridge_contract/src/main.nr rust +:::info +The `content_hash` is a sha256 truncated to a field element (~ 254 bits). In Aztec-nr, you can use our `sha256_to_field()` to do a sha256 hash which fits in one field element: + +#include_code mint_public_content_hash_nr /yarn-project/noir-contracts/src/contracts/token_bridge_contract/src/util.nr rust + +In solidity, you can use our `Hash.sha256ToField()` method: + +#include_code content_hash_sol_import l1-contracts/test/portals/TokenPortal.sol solidity + +#include_code deposit_public l1-contracts/test/portals/TokenPortal.sol solidity + +The `secret_hash` uses the pederson hash which fits in a field element. You can use the utility method `computeMessageSecretHash()`in `@aztec/aztec.js` npm package to generate a secret and its corresponding hash. +::: + After the transaction has been mined, the message is consumed, a nullifier is emitted and the tokens have been minted on Aztec and are ready for claiming. Since the message consumption is emitting a nullifier the same message cannot be consumed again. The index in the message tree is used as part of the nullifier computation, ensuring that the same content and secret being inserted will be distinct messages that can each be consumed. Without the index in the nullifier, it would be possible to perform a kind of attack known as `Faerie Gold` attacks where two seemingly good messages are inserted, but only one of them can be consumed later. diff --git a/docs/docs/dev_docs/tutorials/writing_dapp/contract_deployment.md b/docs/docs/dev_docs/tutorials/writing_dapp/contract_deployment.md index 9155fd48be1..d91c0b3db30 100644 --- a/docs/docs/dev_docs/tutorials/writing_dapp/contract_deployment.md +++ b/docs/docs/dev_docs/tutorials/writing_dapp/contract_deployment.md @@ -28,16 +28,12 @@ Last, copy-paste the code from the `Token` contract into `contracts/token/main.n #include_code token_all yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr rust -The `Token` contract also requires two helper files. Copy-them too: +The `Token` contract also requires a helper file. Copy it too: Create `contracts/token/types.nr` and copy-paste the following: #include_code token_types_all yarn-project/noir-contracts/src/contracts/token_contract/src/types/transparent_note.nr rust -Finally, create `contracts/token/util.nr` and copy-paste the following: - -#include_code token_util_all yarn-project/noir-contracts/src/contracts/token_contract/src/util.nr rust - ## Compile your contract We'll now use the [Aztec CLI](../../cli/main.md) to [compile](../../contracts/compiling.md) our project. If you haven't installed the CLI already, you can install it locally to your project running: diff --git a/l1-contracts/test/portals/TokenPortal.sol b/l1-contracts/test/portals/TokenPortal.sol index 37d5f5cb472..ed04aa8dd60 100644 --- a/l1-contracts/test/portals/TokenPortal.sol +++ b/l1-contracts/test/portals/TokenPortal.sol @@ -7,7 +7,9 @@ import {SafeERC20} from "@oz/token/ERC20/utils/SafeERC20.sol"; import {IRegistry} from "@aztec/core/interfaces/messagebridge/IRegistry.sol"; import {IInbox} from "@aztec/core/interfaces/messagebridge/IInbox.sol"; import {DataStructures} from "@aztec/core/libraries/DataStructures.sol"; +// docs:start:content_hash_sol_import import {Hash} from "@aztec/core/libraries/Hash.sol"; +// docs:end:content_hash_sol_import contract TokenPortal { using SafeERC20 for IERC20; diff --git a/yarn-project/aztec-nr/aztec/src/hash.nr b/yarn-project/aztec-nr/aztec/src/hash.nr new file mode 100644 index 00000000000..09bdd46f0d3 --- /dev/null +++ b/yarn-project/aztec-nr/aztec/src/hash.nr @@ -0,0 +1,36 @@ +use dep::std::hash::{pedersen_with_separator, sha256}; +use crate::constants_gen::{ + GENERATOR_INDEX__SIGNATURE_PAYLOAD, + GENERATOR_INDEX__L1_TO_L2_MESSAGE_SECRET, +}; + +fn sha256_to_field(bytes_to_hash: [u8; N]) -> Field { + let sha256_hashed = sha256(bytes_to_hash); + + // Convert it to a field element + let mut v = 1; + let mut high = 0 as Field; + let mut low = 0 as Field; + + for i in 0..16 { + high = high + (sha256_hashed[15 - i] as Field) * v; + low = low + (sha256_hashed[16 + 15 - i] as Field) * v; + v = v * 256; + } + + // Abuse that a % p + b % p = (a + b) % p and that low < p + let hash_in_a_field = low + high * v; + + hash_in_a_field +} + +fn compute_message_hash(args: [Field; N]) -> Field { + // @todo @lherskind We should probably use a separate generator for this, + // to avoid any potential collisions with payloads. + pedersen_with_separator(args, GENERATOR_INDEX__SIGNATURE_PAYLOAD)[0] +} + +fn compute_secret_hash(secret: Field) -> Field { + // TODO(#1205) This is probably not the right index to use + pedersen_with_separator([secret], GENERATOR_INDEX__L1_TO_L2_MESSAGE_SECRET)[0] +} \ No newline at end of file diff --git a/yarn-project/aztec-nr/aztec/src/lib.nr b/yarn-project/aztec-nr/aztec/src/lib.nr index 72ebcd052f8..98c8e638bb0 100644 --- a/yarn-project/aztec-nr/aztec/src/lib.nr +++ b/yarn-project/aztec-nr/aztec/src/lib.nr @@ -5,6 +5,7 @@ mod auth; mod constants_gen; mod context; mod entrypoint; +mod hash; mod log; mod messaging; mod note; diff --git a/yarn-project/aztec-nr/aztec/src/messaging/l1_to_l2_message.nr b/yarn-project/aztec-nr/aztec/src/messaging/l1_to_l2_message.nr index 70e5f6efc23..8ac1a932490 100644 --- a/yarn-project/aztec-nr/aztec/src/messaging/l1_to_l2_message.nr +++ b/yarn-project/aztec-nr/aztec/src/messaging/l1_to_l2_message.nr @@ -3,6 +3,7 @@ use crate::constants_gen::{ GENERATOR_INDEX__NULLIFIER, GENERATOR_INDEX__L1_TO_L2_MESSAGE_SECRET, }; +use crate::hash::{sha256_to_field}; struct L1ToL2Message { sender: Field, @@ -64,20 +65,7 @@ impl L1ToL2Message { hash_bytes[i + 224] = fee_bytes[i]; } - let message_sha256 = dep::std::hash::sha256(hash_bytes); - - // Convert the message_sha256 to a field element - let mut v = 1; - let mut high = 0 as Field; - let mut low = 0 as Field; - - for i in 0..16 { - high = high + (message_sha256[15 - i] as Field) * v; - low = low + (message_sha256[16 + 15 - i] as Field) * v; - v = v * 256; - } - - let message_hash = low + high * v; + let message_hash = sha256_to_field(hash_bytes); message_hash } diff --git a/yarn-project/noir-contracts/src/contracts/ecdsa_account_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/ecdsa_account_contract/src/main.nr index be516af65a3..d9ddd592801 100644 --- a/yarn-project/noir-contracts/src/contracts/ecdsa_account_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/ecdsa_account_contract/src/main.nr @@ -7,7 +7,6 @@ contract EcdsaAccount { use dep::std::option::Option; use dep::aztec::{ abi::CallContext, - constants_gen::GENERATOR_INDEX__SIGNATURE_PAYLOAD, context::{PrivateContext, PublicContext, Context}, entrypoint::{EntrypointPayload, ENTRYPOINT_PAYLOAD_SIZE}, log::emit_encrypted_log, diff --git a/yarn-project/noir-contracts/src/contracts/schnorr_hardcoded_account_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/schnorr_hardcoded_account_contract/src/main.nr index ad591369e08..562e403d1f7 100644 --- a/yarn-project/noir-contracts/src/contracts/schnorr_hardcoded_account_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/schnorr_hardcoded_account_contract/src/main.nr @@ -6,7 +6,6 @@ contract SchnorrHardcodedAccount { entrypoint::{ EntrypointPayload, ENTRYPOINT_PAYLOAD_SIZE }, abi::{ PrivateCircuitPublicInputs, PrivateContextInputs, Hasher }, types::{ vec::BoundedVec, point::Point }, - constants_gen::GENERATOR_INDEX__SIGNATURE_PAYLOAD, context::PrivateContext, account::AccountActions, oracle::auth_witness::get_auth_witness, diff --git a/yarn-project/noir-contracts/src/contracts/token_bridge_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/token_bridge_contract/src/main.nr index 88b854ed1e3..ac5563fa835 100644 --- a/yarn-project/noir-contracts/src/contracts/token_bridge_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/token_bridge_contract/src/main.nr @@ -9,6 +9,7 @@ mod token_interface; contract TokenBridge { use dep::aztec::{ context::{Context}, + hash::{compute_secret_hash}, state_vars::{public_state::PublicState}, types::type_serialization::field_serialization::{ FieldSerializationMethods, FIELD_SERIALIZED_LEN, @@ -18,7 +19,7 @@ contract TokenBridge { }; use crate::token_interface::Token; - use crate::util::{get_mint_public_content_hash, get_mint_private_content_hash, get_withdraw_content_hash, compute_secret_hash}; + use crate::util::{get_mint_public_content_hash, get_mint_private_content_hash, get_withdraw_content_hash}; // Storage structure, containing all storage, and specifying what slots they use. struct Storage { diff --git a/yarn-project/noir-contracts/src/contracts/token_bridge_contract/src/util.nr b/yarn-project/noir-contracts/src/contracts/token_bridge_contract/src/util.nr index 7ecb7d547cd..f03bed15094 100644 --- a/yarn-project/noir-contracts/src/contracts/token_bridge_contract/src/util.nr +++ b/yarn-project/noir-contracts/src/contracts/token_bridge_contract/src/util.nr @@ -1,87 +1,54 @@ -use dep::std::hash::{pedersen_with_separator, sha256}; -use dep::aztec::constants_gen::{ - GENERATOR_INDEX__SIGNATURE_PAYLOAD, - GENERATOR_INDEX__L1_TO_L2_MESSAGE_SECRET, -}; +use dep::std::hash::pedersen_with_separator; +// docs:start:mint_public_content_hash_nr +use dep::aztec::hash::{sha256_to_field}; -fn compute_secret_hash(secret: Field) -> Field { - // TODO(#1205) This is probably not the right index to use - pedersen_with_separator([secret], GENERATOR_INDEX__L1_TO_L2_MESSAGE_SECRET)[0] -} - -// Computes a content hash of a deposit/mint_private message. +// Computes a content hash of a deposit/mint_public message. // Refer TokenPortal.sol for reference on L1. -fn get_mint_private_content_hash(amount: Field, secret_hash_for_redeeming_minted_notes: Field, canceller: Field) -> Field { +fn get_mint_public_content_hash(owner_address: Field, amount: Field, canceller: Field) -> Field { + let mut hash_bytes: [u8; 100] = [0; 100]; let amount_bytes = amount.to_be_bytes(32); - let secret_hash_bytes = secret_hash_for_redeeming_minted_notes.to_be_bytes(32); + let recipient_bytes = owner_address.to_be_bytes(32); let canceller_bytes = canceller.to_be_bytes(32); for i in 0..32 { hash_bytes[i + 4] = amount_bytes[i]; - hash_bytes[i + 36] = secret_hash_bytes[i]; + hash_bytes[i + 36] = recipient_bytes[i]; hash_bytes[i + 68] = canceller_bytes[i]; } - // Function selector: 0x25d46b0f keccak256('mint_private(uint256,bytes32,address)') - hash_bytes[0] = 0x25; - hash_bytes[1] = 0xd4; - hash_bytes[2] = 0x6b; - hash_bytes[3] = 0x0f; - - let content_sha256 = sha256(hash_bytes); - - // // Convert the content_sha256 to a field element - let mut v = 1; - let mut high = 0 as Field; - let mut low = 0 as Field; - - for i in 0..16 { - high = high + (content_sha256[15 - i] as Field) * v; - low = low + (content_sha256[16 + 15 - i] as Field) * v; - v = v * 256; - } + // Function selector: 0x63c9440d keccak256('mint_public(uint256,bytes32,address)') + hash_bytes[0] = 0x63; + hash_bytes[1] = 0xc9; + hash_bytes[2] = 0x44; + hash_bytes[3] = 0x0d; - // Abuse that a % p + b % p = (a + b) % p and that low < p - let content_hash = low + high * v; + let content_hash = sha256_to_field(hash_bytes); content_hash } +// docs:end:mint_public_content_hash_nr -// Computes a content hash of a deposit/mint_public message. +// Computes a content hash of a deposit/mint_private message. // Refer TokenPortal.sol for reference on L1. -fn get_mint_public_content_hash(owner_address: Field, amount: Field, canceller: Field) -> Field { +fn get_mint_private_content_hash(amount: Field, secret_hash_for_redeeming_minted_notes: Field, canceller: Field) -> Field { let mut hash_bytes: [u8; 100] = [0; 100]; let amount_bytes = amount.to_be_bytes(32); - let recipient_bytes = owner_address.to_be_bytes(32); + let secret_hash_bytes = secret_hash_for_redeeming_minted_notes.to_be_bytes(32); let canceller_bytes = canceller.to_be_bytes(32); for i in 0..32 { hash_bytes[i + 4] = amount_bytes[i]; - hash_bytes[i + 36] = recipient_bytes[i]; + hash_bytes[i + 36] = secret_hash_bytes[i]; hash_bytes[i + 68] = canceller_bytes[i]; } - // Function selector: 0x63c9440d keccak256('mint_public(uint256,bytes32,address)') - hash_bytes[0] = 0x63; - hash_bytes[1] = 0xc9; - hash_bytes[2] = 0x44; - hash_bytes[3] = 0x0d; - - let content_sha256 = sha256(hash_bytes); - - // // Convert the content_sha256 to a field element - let mut v = 1; - let mut high = 0 as Field; - let mut low = 0 as Field; - - for i in 0..16 { - high = high + (content_sha256[15 - i] as Field) * v; - low = low + (content_sha256[16 + 15 - i] as Field) * v; - v = v * 256; - } + // Function selector: 0x25d46b0f keccak256('mint_private(uint256,bytes32,address)') + hash_bytes[0] = 0x25; + hash_bytes[1] = 0xd4; + hash_bytes[2] = 0x6b; + hash_bytes[3] = 0x0f; - // Abuse that a % p + b % p = (a + b) % p and that low < p - let content_hash = low + high * v; + let content_hash = sha256_to_field(hash_bytes); content_hash } @@ -107,20 +74,6 @@ fn get_withdraw_content_hash(recipient: Field, amount: Field, callerOnL1: Field) hash_bytes[i + 36] = recipient_bytes[i]; hash_bytes[i + 68] = callerOnL1_bytes[i]; } - let content_sha256 = sha256(hash_bytes); - - // Convert the content_sha256 to a field element - let mut v = 1; - let mut high = 0 as Field; - let mut low = 0 as Field; - - for i in 0..16 { - high = high + (content_sha256[15 - i] as Field) * v; - low = low + (content_sha256[16 + 15 - i] as Field) * v; - v = v * 256; - } - - // Abuse that a % p + b % p = (a + b) % p and that low < p - let content = low + high * v; - content + let content_hash = sha256_to_field(hash_bytes); + content_hash } \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr index 2cf48a52994..3d8cc7e1b44 100644 --- a/yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/token_contract/src/main.nr @@ -1,7 +1,6 @@ // docs:start:token_all // docs:start:imports mod types; -mod util; // Minimal token implementation that supports `AuthWit` accounts. // The auth message follows a similar pattern to the cross-chain message and includes a designated caller. @@ -22,6 +21,7 @@ contract Token { utils as note_utils, }, context::{PrivateContext, PublicContext, Context}, + hash::{compute_message_hash}, state_vars::{map::Map, public_state::PublicState, set::Set}, types::type_serialization::{ field_serialization::{FieldSerializationMethods, FIELD_SERIALIZED_LEN}, @@ -39,7 +39,6 @@ contract Token { balances_map::{BalancesMap}, safe_u120_serialization::{SafeU120SerializationMethods, SAFE_U120_SERIALIZED_LEN} }; - use crate::util::{compute_message_hash}; // docs:end::imports // docs:start:storage_struct @@ -454,4 +453,4 @@ contract Token { // docs:end:compute_note_hash_and_nullifier } -// docs:end:token_all +// docs:end:token_all \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/token_contract/src/types/transparent_note.nr b/yarn-project/noir-contracts/src/contracts/token_contract/src/types/transparent_note.nr index ae32796f2bd..bce35b24660 100644 --- a/yarn-project/noir-contracts/src/contracts/token_contract/src/types/transparent_note.nr +++ b/yarn-project/noir-contracts/src/contracts/token_contract/src/types/transparent_note.nr @@ -1,12 +1,11 @@ // docs:start:token_types_all use dep::std::hash::pedersen; -use dep::std::hash::pedersen_with_separator; use dep::aztec::note::{ note_header::NoteHeader, note_interface::NoteInterface, utils::compute_siloed_note_hash, }; -use dep::aztec::constants_gen::GENERATOR_INDEX__L1_TO_L2_MESSAGE_SECRET; +use dep::aztec::hash::{compute_secret_hash}; global TRANSPARENT_NOTE_LEN: Field = 2; @@ -39,7 +38,7 @@ impl TransparentNote { fn new_from_secret(amount: Field, secret: Field) -> Self { TransparentNote { amount: amount, - secret_hash: TransparentNote::compute_secret_hash(secret), + secret_hash: compute_secret_hash(secret), secret: secret, header: NoteHeader::empty(), } @@ -83,13 +82,8 @@ impl TransparentNote { // CUSTOM FUNCTIONS FOR THIS NOTE TYPE - fn compute_secret_hash(secret: Field) -> Field { - // TODO(#1205) This is probably not the right index to use - pedersen_with_separator([secret], GENERATOR_INDEX__L1_TO_L2_MESSAGE_SECRET)[0] - } - fn knows_secret(self, secret: Field) { - let hash = TransparentNote::compute_secret_hash(secret); + let hash = compute_secret_hash(secret); assert(self.secret_hash == hash); } } diff --git a/yarn-project/noir-contracts/src/contracts/token_contract/src/util.nr b/yarn-project/noir-contracts/src/contracts/token_contract/src/util.nr deleted file mode 100644 index 701d0dd0527..00000000000 --- a/yarn-project/noir-contracts/src/contracts/token_contract/src/util.nr +++ /dev/null @@ -1,10 +0,0 @@ -// docs:start:token_util_all -use dep::std::hash::{pedersen_with_separator}; -use dep::aztec::constants_gen::GENERATOR_INDEX__SIGNATURE_PAYLOAD; - -fn compute_message_hash(args: [Field; N]) -> Field { - // @todo @lherskind We should probably use a separate generator for this, - // to avoid any potential collisions with payloads. - pedersen_with_separator(args, GENERATOR_INDEX__SIGNATURE_PAYLOAD)[0] -} -// docs:end:token_util_all \ No newline at end of file diff --git a/yarn-project/noir-contracts/src/contracts/uniswap_contract/src/main.nr b/yarn-project/noir-contracts/src/contracts/uniswap_contract/src/main.nr index 2b01f224802..e92dd734d17 100644 --- a/yarn-project/noir-contracts/src/contracts/uniswap_contract/src/main.nr +++ b/yarn-project/noir-contracts/src/contracts/uniswap_contract/src/main.nr @@ -8,6 +8,7 @@ contract Uniswap { use dep::aztec::{ auth::{IS_VALID_SELECTOR, assert_valid_public_message_for}, context::{PrivateContext, PublicContext, Context}, + hash::compute_message_hash, oracle::compute_selector::compute_selector, oracle::context::get_portal_address, state_vars::{map::Map, public_state::PublicState}, @@ -21,7 +22,7 @@ contract Uniswap { }; use crate::interfaces::{Token, TokenBridge}; - use crate::util::{compute_message_hash, compute_swap_private_content_hash, compute_swap_public_content_hash}; + use crate::util::{compute_swap_private_content_hash, compute_swap_public_content_hash}; struct Storage { // like with account contracts, stores the approval message on a slot and tracks if they are active diff --git a/yarn-project/noir-contracts/src/contracts/uniswap_contract/src/util.nr b/yarn-project/noir-contracts/src/contracts/uniswap_contract/src/util.nr index 4e578587e4a..8d51e11679b 100644 --- a/yarn-project/noir-contracts/src/contracts/uniswap_contract/src/util.nr +++ b/yarn-project/noir-contracts/src/contracts/uniswap_contract/src/util.nr @@ -1,11 +1,4 @@ -use dep::std::hash::{pedersen_with_separator, sha256}; -use dep::aztec::constants_gen::GENERATOR_INDEX__SIGNATURE_PAYLOAD; - -fn compute_message_hash(args: [Field; N]) -> Field { - // @todo @lherskind We should probably use a separate generator for this, - // to avoid any potential collisions with payloads. - pedersen_with_separator(args, GENERATOR_INDEX__SIGNATURE_PAYLOAD)[0] -} +use dep::aztec::hash::sha256_to_field; // This method computes the L2 to L1 message content hash for the private // refer `l1-contracts/test/portals/UniswapPortal.sol` on how L2 to L1 message is expected @@ -52,23 +45,7 @@ fn compute_swap_private_content_hash( hash_bytes[i + 260] = canceller_bytes[i]; hash_bytes[i + 292] = caller_on_L1_bytes[i]; } - - let content_sha256 = sha256(hash_bytes); - - // Convert the content_sha256 to a field element - let mut v = 1; - let mut high = 0 as Field; - let mut low = 0 as Field; - - for i in 0..16 { - high = high + (content_sha256[15 - i] as Field) * v; - low = low + (content_sha256[16 + 15 - i] as Field) * v; - v = v * 256; - } - - // Abuse that a % p + b % p = (a + b) % p and that low < p - let content_hash = low + high * v; - + let content_hash = sha256_to_field(hash_bytes); content_hash } @@ -118,21 +95,6 @@ fn compute_swap_public_content_hash( hash_bytes[i + 292] = caller_on_L1_bytes[i]; } - let content_sha256 = sha256(hash_bytes); - - // Convert the content_sha256 to a field element - let mut v = 1; - let mut high = 0 as Field; - let mut low = 0 as Field; - - for i in 0..16 { - high = high + (content_sha256[15 - i] as Field) * v; - low = low + (content_sha256[16 + 15 - i] as Field) * v; - v = v * 256; - } - - // Abuse that a % p + b % p = (a + b) % p and that low < p - let content_hash = low + high * v; - + let content_hash = sha256_to_field(hash_bytes); content_hash }