Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions l1-contracts/src/core/libraries/Hash.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: Apache-2.0
// Copyright 2023 Aztec Labs.
pragma solidity >=0.8.18;

import {Constants} from "./Constants.sol";
import {DataStructures} from "./DataStructures.sol";

/**
* @title Hash library
* @author Aztec
* @notice A small library of functions to compute hashes for data structures and convert to field elements
*/
library Hash {
/**
* @notice Computes the sha256 hash of the L1 to L2 message and converts it to a field element
* @param _message - The L1 to L2 message to hash
* @return The hash of the provided message as a field element
*/
function sha256ToField(DataStructures.L1ToL2Msg memory _message) internal pure returns (bytes32) {
return sha256ToField(
abi.encode(
_message.sender,
_message.recipient,
_message.content,
_message.secretHash,
_message.deadline,
_message.fee
)
);
}

/**
* @notice Computes the sha256 hash of the L2 to L1 message and converts it to a field element
* @param _message - The L2 to L1 message to hash
* @return The hash of the provided message as a field element
*/
function sha256ToField(DataStructures.L2ToL1Msg memory _message) internal pure returns (bytes32) {
return sha256ToField(abi.encode(_message.sender, _message.recipient, _message.content));
}

/**
* @notice Computes the sha256 hash of the provided data and converts it to a field element
* @dev Using modulo to convert the hash to a field element.
* @param _data - The bytes to hash
* @return The hash of the provided data as a field element
*/
function sha256ToField(bytes memory _data) internal pure returns (bytes32) {
return bytes32(uint256(sha256(_data)) % Constants.P);
}
}
20 changes: 4 additions & 16 deletions l1-contracts/src/core/messagebridge/Inbox.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
pragma solidity >=0.8.18;

import {IInbox} from "@aztec/core/interfaces/messagebridge/IInbox.sol";
import {Constants} from "@aztec/core/libraries/Constants.sol";
import {DataStructures} from "@aztec/core/libraries/DataStructures.sol";
import {Hash} from "@aztec/core/libraries/Hash.sol";
import {MessageBox} from "@aztec/core/libraries/MessageBox.sol";
import {Errors} from "@aztec/core/libraries/Errors.sol";
import {IRegistry} from "@aztec/core/interfaces/messagebridge/IRegistry.sol";
Expand All @@ -16,6 +16,7 @@ import {IRegistry} from "@aztec/core/interfaces/messagebridge/IRegistry.sol";
*/
contract Inbox is IInbox {
using MessageBox for mapping(bytes32 entryKey => DataStructures.Entry entry);
using Hash for DataStructures.L1ToL2Msg;

IRegistry immutable REGISTRY;

Expand All @@ -37,28 +38,15 @@ contract Inbox is IInbox {
* @return The hash of the message (used as the key of the entry in the set)
*/
function computeEntryKey(DataStructures.L1ToL2Msg memory _message) public pure returns (bytes32) {
return bytes32(
uint256(
sha256(
abi.encode(
_message.sender,
_message.recipient,
_message.content,
_message.secretHash,
_message.deadline,
_message.fee
)
)
) % Constants.P
);
return _message.sha256ToField();
}

/**
* @notice Inserts an entry into the Inbox
* @dev Will emit `MessageAdded` with data for easy access by the sequencer
* @dev msg.value - The fee provided to sequencer for including the entry
* @param _recipient - The recipient of the entry
* @param _deadline - The deadline to consume a message. Only after it, can a message be cancalled.
* @param _deadline - The deadline to consume a message. Only after it, can a message be cancelled.
* it is uint32 to for slot packing of the Entry struct. Should work until Feb 2106.
* @param _content - The content of the entry (application specific)
* @param _secretHash - The secret hash of the entry (make it possible to hide when a specific entry is consumed on L2)
Expand Down
9 changes: 3 additions & 6 deletions l1-contracts/src/core/messagebridge/Outbox.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
pragma solidity >=0.8.18;

import {IOutbox} from "@aztec/core/interfaces/messagebridge/IOutbox.sol";
import {Constants} from "@aztec/core/libraries/Constants.sol";
import {DataStructures} from "@aztec/core/libraries/DataStructures.sol";
import {Hash} from "@aztec/core/libraries/Hash.sol";
import {Errors} from "@aztec/core/libraries/Errors.sol";
import {MessageBox} from "@aztec/core/libraries/MessageBox.sol";
import {IRegistry} from "@aztec/core/interfaces/messagebridge/IRegistry.sol";
Expand All @@ -17,6 +17,7 @@ import {IRegistry} from "@aztec/core/interfaces/messagebridge/IRegistry.sol";
*/
contract Outbox is IOutbox {
using MessageBox for mapping(bytes32 entryKey => DataStructures.Entry entry);
using Hash for DataStructures.L2ToL1Msg;

IRegistry immutable REGISTRY;

Expand All @@ -37,11 +38,7 @@ contract Outbox is IOutbox {
* @return The key of the entry in the set
*/
function computeEntryKey(DataStructures.L2ToL1Msg memory _message) public pure returns (bytes32) {
// TODO: Replace mod P later on when we have a better idea of how to handle Fields.
return bytes32(
uint256(sha256(abi.encode(_message.sender, _message.recipient, _message.content)))
% Constants.P
);
return _message.sha256ToField();
}

/**
Expand Down
10 changes: 4 additions & 6 deletions l1-contracts/test/portals/RollupNativeAsset.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity >=0.8.18;

import {ERC20} from "@oz/token/ERC20/ERC20.sol";
import {DataStructures} from "@aztec/core/libraries/DataStructures.sol";
import {Constants} from "@aztec/core/libraries/Constants.sol";
import {Hash} from "@aztec/core/libraries/Hash.sol";
import {Registry} from "@aztec/core/messagebridge/Registry.sol";

contract RollupNativeAsset is ERC20 {
Expand All @@ -19,14 +19,12 @@ contract RollupNativeAsset is ERC20 {
}

function withdraw(uint256 _amount, address _recipient) external returns (bytes32) {
bytes memory contentBytes =
abi.encodeWithSignature("withdraw(uint256,address)", _amount, _recipient);
bytes32 content = bytes32(uint256(sha256(contentBytes)) % Constants.P);

DataStructures.L2ToL1Msg memory message = DataStructures.L2ToL1Msg({
sender: DataStructures.L2Actor(aztecAddress, 1),
recipient: DataStructures.L1Actor(address(this), block.chainid),
content: content
content: Hash.sha256ToField(
abi.encodeWithSignature("withdraw(uint256,address)", _amount, _recipient)
)
});

bytes32 entryKey = registry.getOutbox().consume(message);
Expand Down
6 changes: 3 additions & 3 deletions l1-contracts/test/portals/TokenPortal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ 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";
import {Constants} from "@aztec/core/libraries/Constants.sol";
import {Hash} from "@aztec/core/libraries/Hash.sol";

contract TokenPortal {
using SafeERC20 for IERC20;
Expand Down Expand Up @@ -40,8 +40,8 @@ contract TokenPortal {
DataStructures.L2Actor memory actor = DataStructures.L2Actor(l2TokenAddress, 1);

// Hash the message content to be reconstructed in the receiving contract
bytes memory content = abi.encodeWithSignature("mint(uint256,bytes32)", _amount, _to);
bytes32 contentHash = bytes32(uint256(sha256(content)) % Constants.P);
bytes32 contentHash =
Hash.sha256ToField(abi.encodeWithSignature("mint(uint256,bytes32)", _amount, _to));

// Hold the tokens in the portal
underlying.safeTransferFrom(msg.sender, address(this), _amount);
Expand Down
6 changes: 2 additions & 4 deletions l1-contracts/test/portals/TokenPortal.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {Inbox} from "@aztec/core/messagebridge/Inbox.sol";
import {Registry} from "@aztec/core/messagebridge/Registry.sol";
import {Outbox} from "@aztec/core/messagebridge/Outbox.sol";
import {DataStructures} from "@aztec/core/libraries/DataStructures.sol";
import {Constants} from "@aztec/core/libraries/Constants.sol";
import {Hash} from "@aztec/core/libraries/Hash.sol";

// Interfaces
import {IRegistry} from "@aztec/core/interfaces/messagebridge/IRegistry.sol";
Expand Down Expand Up @@ -71,9 +71,7 @@ contract TokenPortalTest is Test {
DataStructures.L1ToL2Msg memory expectedMessage = DataStructures.L1ToL2Msg({
sender: DataStructures.L1Actor(address(tokenPortal), 1),
recipient: DataStructures.L2Actor(l2TokenAddress, 1),
content: bytes32(
uint256(sha256(abi.encodeWithSignature("mint(uint256,bytes32)", amount, to))) % Constants.P
),
content: Hash.sha256ToField(abi.encodeWithSignature("mint(uint256,bytes32)", amount, to)),
secretHash: secretHash,
deadline: deadline,
fee: bid
Expand Down