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
184 changes: 101 additions & 83 deletions l1-contracts/src/core/Decoder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,35 @@ pragma solidity >=0.8.18;
* | 0x90 | 0x04 | startTreeOfHistoricPrivateDataTreeRootsSnapshot.nextAvailableLeafIndex
* | 0x94 | 0x20 | startTreeOfHistoricContractTreeRootsSnapshot.root
* | 0xb4 | 0x04 | startTreeOfHistoricContractTreeRootsSnapshot.nextAvailableLeafIndex
* | 0xb8 | 0x20 | endPrivateDataTreeSnapshot.root
* | 0xd8 | 0x04 | endPrivateDataTreeSnapshot.nextAvailableLeafIndex
* | 0xdc | 0x20 | endNullifierTreeSnapshot.root
* | 0xfc | 0x04 | endNullifierTreeSnapshot.nextAvailableLeafIndex
* | 0x100 | 0x20 | endContractTreeSnapshot.root
* | 0x120 | 0x04 | endContractTreeSnapshot.nextAvailableLeafIndex
* | 0x124 | 0x20 | endTreeOfHistoricPrivateDataTreeRootsSnapshot.root
* | 0x144 | 0x04 | endTreeOfHistoricPrivateDataTreeRootsSnapshot.nextAvailableLeafIndex
* | 0x148 | 0x20 | endTreeOfHistoricContractTreeRootsSnapshot.root
* | 0x168 | 0x04 | endTreeOfHistoricContractTreeRootsSnapshot.nextAvailableLeafIndex
* | 0x16c | 0x04 | len(newCommitments) denoted x
* | 0x170 | x | newCommits
* | 0x170 + x | 0x04 | len(newNullifiers) denoted y
* | 0x174 + x | y | newNullifiers
* | 0x174 + x + y | 0x04 | len(newContracts) denoted z
* | 0x178 + x + y | z | newContracts
* | 0x178 + x + y + z | z | newContractData
* | 0xb8 | 0x20 | startPublicDataTreeRoot
* | 0xd8 | 0x20 | endPrivateDataTreeSnapshot.root
* | 0xf8 | 0x04 | endPrivateDataTreeSnapshot.nextAvailableLeafIndex
* | 0xfc | 0x20 | endNullifierTreeSnapshot.root
* | 0x11c | 0x04 | endNullifierTreeSnapshot.nextAvailableLeafIndex
* | 0x120 | 0x20 | endContractTreeSnapshot.root
* | 0x140 | 0x04 | endContractTreeSnapshot.nextAvailableLeafIndex
* | 0x144 | 0x20 | endTreeOfHistoricPrivateDataTreeRootsSnapshot.root
* | 0x164 | 0x04 | endTreeOfHistoricPrivateDataTreeRootsSnapshot.nextAvailableLeafIndex
* | 0x168 | 0x20 | endTreeOfHistoricContractTreeRootsSnapshot.root
* | 0x188 | 0x04 | endTreeOfHistoricContractTreeRootsSnapshot.nextAvailableLeafIndex
* | 0x18c | 0x20 | endPublicDataTreeRoot
* | 0x1ac | 0x04 | len(newCommitments) denoted a
* | 0x1b0 | a | newCommitments (each element 32 bytes)
* | 0x1b0 + a | 0x04 | len(newNullifiers) denoted b
* | 0x1b4 + a | b | newNullifiers (each element 32 bytes)
* | 0x1b4 + a + b | 0x04 | len(newPublicDataWrites) denoted c
* | 0x1b8 + a + b | c | newPublicDataWrites (each element 64 bytes)
* | 0x1b8 + a + b + c | 0x04 | len(newContracts) denoted d
* | 0x1bc + a + b + c | v | newContracts (each element 32 bytes)
* | 0x1bc + a + b + c + d | v | newContractData (each element 52 bytes)
* |--- |--- | ---
*
* TODO: a,b,c,d are number of elements and not bytes, need to be multiplied by the length of the elements.
*/
contract Decoder {
uint256 internal constant COMMITMENTS_PER_KERNEL = 4;
uint256 internal constant NULLIFIERS_PER_KERNEL = 4;
uint256 internal constant PUBLIC_DATA_WRITES_PER_KERNEL = 4;
uint256 internal constant CONTRACTS_PER_KERNEL = 1;

// Prime field order
uint256 internal constant P =
Expand All @@ -58,45 +64,44 @@ contract Decoder {
* @notice Decodes the inputs and computes values to check state against
* @param _l2Block - The L2 block calldata.
* @return l2BlockNumber - The L2 block number.
* @return oldStateHash - The state hash expected prior the execution.
* @return newStateHash - The state hash expected after the execution.
* @return startStateHash - The state hash expected prior the execution.
* @return endStateHash - The state hash expected after the execution.
* @return publicInputHash - The hash of the public inputs
*/
function _decode(bytes calldata _l2Block)
internal
pure
returns (
uint256 l2BlockNumber,
bytes32 oldStateHash,
bytes32 newStateHash,
bytes32 startStateHash,
bytes32 endStateHash,
bytes32 publicInputHash
)
{
l2BlockNumber = _getL2BlockNumber(_l2Block);
// Note, for oldStateHash to match the storage, the l2 block number must be new - 1.
// Note, for startStateHash to match the storage, the l2 block number must be new - 1.
// Only jumping 1 block at a time.
oldStateHash = _computeStateHash(l2BlockNumber - 1, 0x4, _l2Block);
newStateHash = _computeStateHash(l2BlockNumber, 0xb8, _l2Block);
startStateHash = _computeStateHash(l2BlockNumber - 1, 0x4, _l2Block);
endStateHash = _computeStateHash(l2BlockNumber, 0xd8, _l2Block);
publicInputHash = _computePublicInputsHash(_l2Block);
}

/**
* Computes a hash of the public inputs from the calldata
* @param _l2Block - The L2 block calldata.
* @return sha256(header[0x4:0x16c], diffRoot)
* @return sha256(header[0x4: 0x1ac], diffRoot)
*/
function _computePublicInputsHash(bytes calldata _l2Block) internal pure returns (bytes32) {
// Compute the public inputs hash
// header size - block number + one value for the diffRoot
uint256 size = 0x16c - 0x04 + 0x20;
// header size - block number size + one value for the diffRoot
uint256 size = 0x1ac - 0x04 + 0x20;
bytes memory temp = new bytes(size);
assembly {
calldatacopy(add(temp, 0x20), add(_l2Block.offset, 0x04), size)
}

bytes32 diffRoot = _computeDiffRoot(_l2Block);
assembly {
mstore(add(temp, add(0x20, sub(0x16c, 0x04))), diffRoot)
mstore(add(temp, add(0x20, sub(0x1ac, 0x04))), diffRoot)
}

return bytes32(uint256(sha256(temp)) % P);
Expand All @@ -116,7 +121,7 @@ contract Decoder {
/**
* @notice Computes a state hash
* @param _l2BlockNumber - The L2 block number
* @param _offset - The offset into the data, 0x04 for old, 0xb8 for next
* @param _offset - The offset into the data, 0x04 for start, 0xd8 for end
* @param _l2Block - The L2 block calldata.
* @return The state hash
*/
Expand All @@ -125,7 +130,7 @@ contract Decoder {
pure
returns (bytes32)
{
bytes memory temp = new bytes(0xb8);
bytes memory temp = new bytes(0xd8);

assembly {
mstore8(add(temp, 0x20), shr(24, _l2BlockNumber))
Expand All @@ -134,15 +139,17 @@ contract Decoder {
mstore8(add(temp, 0x23), _l2BlockNumber)
}
assembly {
calldatacopy(add(temp, 0x24), add(_l2Block.offset, _offset), 0xb4)
// Copy header elements (not including block number) for start or end (size 0xd4)
calldatacopy(add(temp, 0x24), add(_l2Block.offset, _offset), 0xd4)
}

return sha256(temp);
}

struct Vars {
uint256 commitmentCount;
uint256 kernelCount;
uint256 nullifierCount;
uint256 dataWritesCount;
uint256 contractCount;
}

Expand All @@ -152,46 +159,48 @@ contract Decoder {
* @return The root of the "diff" tree
*/
function _computeDiffRoot(bytes calldata _l2Block) internal pure returns (bytes32) {
// Find the lengths of the different inputs
Vars memory vars;
{
uint256 commitmentCount;
assembly {
commitmentCount := and(shr(224, calldataload(add(_l2Block.offset, 0x16c))), 0xffffffff)
}
vars.commitmentCount = commitmentCount;
vars.kernelCount = commitmentCount / COMMITMENTS_PER_KERNEL;
uint256 contractCountOffset =
vars.kernelCount * (COMMITMENTS_PER_KERNEL + NULLIFIERS_PER_KERNEL) * 0x20;
let offset := add(_l2Block.offset, 0x1ac)
let commitmentCount := and(shr(224, calldataload(offset)), 0xffffffff)
offset := add(add(offset, 0x4), mul(commitmentCount, 0x20))
let nullifierCount := and(shr(224, calldataload(offset)), 0xffffffff)
offset := add(add(offset, 0x4), mul(nullifierCount, 0x20))
let dataWritesCount := and(shr(224, calldataload(offset)), 0xffffffff)
offset := add(add(offset, 0x4), mul(nullifierCount, 0x40))
let contractCount := and(shr(224, calldataload(offset)), 0xffffffff)

uint256 newContractCount;
assembly {
newContractCount :=
and(
shr(224, calldataload(add(_l2Block.offset, add(0x174, contractCountOffset)))), 0xffffffff
)
// Store it in vars
mstore(vars, commitmentCount)
mstore(add(vars, 0x20), nullifierCount)
mstore(add(vars, 0x40), dataWritesCount)
mstore(add(vars, 0x60), contractCount)
}
vars.contractCount = newContractCount;
}

bytes32[] memory baseLeafs = new bytes32[](vars.kernelCount / 2);
bytes32[] memory baseLeafs = new bytes32[](
vars.commitmentCount / (COMMITMENTS_PER_KERNEL * 2)
);

uint256 dstCommitmentOffset = COMMITMENTS_PER_KERNEL * 0x20 * 0x2;
uint256 dstContractOffset = dstCommitmentOffset + NULLIFIERS_PER_KERNEL * 0x20 * 0x2;

uint256 srcCommitmentOffset = 0x170;
uint256 srcNullifierOffset = 0x174 + vars.commitmentCount * 0x20;
uint256 srcContractOffset =
0x178 + (baseLeafs.length * 2 * (NULLIFIERS_PER_KERNEL + COMMITMENTS_PER_KERNEL) * 0x20);
// Data starts after header. Look at L2 Block Data specification at the top of this file.
uint256 srcCommitmentOffset = 0x1b0;
Comment thread
Maddiaa0 marked this conversation as resolved.
uint256 srcNullifierOffset = srcCommitmentOffset + 0x4 + vars.commitmentCount * 0x20;
uint256 srcDataOffset = srcNullifierOffset + 0x4 + vars.nullifierCount * 0x20;
uint256 srcContractOffset = srcDataOffset + 0x4 + vars.dataWritesCount * 0x40;
uint256 srcContractDataOffset = srcContractOffset + vars.contractCount * 0x20;

for (uint256 i = 0; i < baseLeafs.length; i++) {
/**
* Compute the leaf to insert.
* Leaf_i = (
* newNullifiersKernel1,
* newNullifiersKernel2,
* newCommitmentsKernel1,
* newCommitmentsKernel2,
* newNullifiersKernel1,
* newNullifiersKernel2,
* newPublicDataWritesKernel1,
* newPublicDataWritesKernel2,
* newContractLeafKernel1,
* newContractLeafKernel2,
* newContractDataKernel1.aztecAddress,
Expand All @@ -202,54 +211,63 @@ contract Decoder {
* Note that we always read data, the l2Block (atm) must therefore include dummy or zero-notes for
* Zero values.
*/
bytes memory baseLeaf = new bytes(0x2c0);
// Create the leaf to contain commitments (8 * 0x20) + nullifiers (8 * 0x20)
// + new public data writes (8 * 0x40) + contract deployments (2 * 0x60)
bytes memory baseLeaf = new bytes(0x4c0);
Comment thread
Maddiaa0 marked this conversation as resolved.

assembly {
// Adding new nullifiers
calldatacopy(add(baseLeaf, 0x20), add(_l2Block.offset, srcNullifierOffset), mul(0x08, 0x20))

let dstOffset := 0x20
// Adding new commitments
calldatacopy(
add(baseLeaf, add(0x20, dstCommitmentOffset)),
add(_l2Block.offset, srcCommitmentOffset),
mul(0x08, 0x20)
add(baseLeaf, dstOffset), add(_l2Block.offset, srcCommitmentOffset), mul(0x08, 0x20)
)
dstOffset := add(dstOffset, mul(0x08, 0x20))

// Adding Contract Leafs
// Adding new nullifiers
calldatacopy(
add(baseLeaf, add(0x20, dstContractOffset)),
add(_l2Block.offset, srcContractOffset),
mul(2, 0x20)
add(baseLeaf, dstOffset), add(_l2Block.offset, srcNullifierOffset), mul(0x08, 0x20)
)
dstOffset := add(dstOffset, mul(0x08, 0x20))

// Kernel1.contract.aztecaddress
// Adding new public data writes
calldatacopy(add(baseLeaf, dstOffset), add(_l2Block.offset, srcDataOffset), mul(0x08, 0x40))
dstOffset := add(dstOffset, mul(0x08, 0x40))

// Adding Contract Leafs
calldatacopy(
add(baseLeaf, add(0x20, add(dstContractOffset, 0x40))),
add(_l2Block.offset, srcContractDataOffset),
0x20
add(baseLeaf, dstOffset), add(_l2Block.offset, srcContractOffset), mul(2, 0x20)
)
dstOffset := add(dstOffset, mul(2, 0x20))

// Kernel1.contract.aztecAddress
calldatacopy(add(baseLeaf, dstOffset), add(_l2Block.offset, srcContractDataOffset), 0x20)
dstOffset := add(dstOffset, 0x20)

// Kernel1.contract.ethAddress padded to 32 bytes
// Add 12 (0xc) bytes of padding to the ethAddress
dstOffset := add(dstOffset, 0xc)
calldatacopy(
add(baseLeaf, add(0x20, add(dstContractOffset, 0x6c))),
add(_l2Block.offset, add(srcContractDataOffset, 0x20)),
0x14
add(baseLeaf, dstOffset), add(_l2Block.offset, add(srcContractDataOffset, 0x20)), 0x14
)
// Kernel2.contract.aztecaddress
dstOffset := add(dstOffset, 0x20)

// Kernel2.contract.aztecAddress
calldatacopy(
add(baseLeaf, add(0x20, add(dstContractOffset, 0x80))),
add(_l2Block.offset, add(srcContractDataOffset, 0x34)),
0x20
add(baseLeaf, dstOffset), add(_l2Block.offset, add(srcContractDataOffset, 0x34)), 0x20
)
dstOffset := add(dstOffset, 0x20)

// Kernel2.contract.ethAddress padded to 32 bytes
// Add 12 (0xc) bytes of padding to the ethAddress
dstOffset := add(dstOffset, 0xc)
calldatacopy(
add(baseLeaf, add(0x20, add(dstContractOffset, 0xac))),
add(_l2Block.offset, add(srcContractDataOffset, 0x54)),
0x14
add(baseLeaf, dstOffset), add(_l2Block.offset, add(srcContractDataOffset, 0x54)), 0x14
)
}

srcCommitmentOffset += 2 * COMMITMENTS_PER_KERNEL * 0x20;
srcNullifierOffset += 2 * NULLIFIERS_PER_KERNEL * 0x20;
srcDataOffset += 2 * PUBLIC_DATA_WRITES_PER_KERNEL * 0x40;
srcContractOffset += 2 * 0x20;
srcContractDataOffset += 2 * 0x34;

Expand Down
7 changes: 6 additions & 1 deletion l1-contracts/src/periphery/UnverifiedDataEmitter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ contract UnverifiedDataEmitter {
* @param portalAddress - The address of the L1 counterparty
* @param acir - The acir bytecode of the L2 contract
*/
event ContractDeployment(uint256 indexed l2BlockNum, bytes32 indexed aztecAddress, address indexed portalAddress, bytes acir);
event ContractDeployment(
uint256 indexed l2BlockNum,
bytes32 indexed aztecAddress,
address indexed portalAddress,
bytes acir
);

/**
* @notice Used to share data which are not required to advance the state but are needed for other purposes
Expand Down
Loading