Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: sol-ts parity checks for decoder-encoder #412

Merged
merged 5 commits into from
May 2, 2023
Merged
Show file tree
Hide file tree
Changes from 2 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
171 changes: 91 additions & 80 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,25 +64,25 @@ 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);
}

Expand All @@ -86,17 +92,16 @@ contract Decoder {
* @return sha256(header[0x4:0x16c], 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 Down Expand Up @@ -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,16 @@ contract Decoder {
mstore8(add(temp, 0x23), _l2BlockNumber)
}
assembly {
calldatacopy(add(temp, 0x24), add(_l2Block.offset, _offset), 0xb4)
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 +158,45 @@ 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);
uint256 srcCommitmentOffset = 0x1b0;
Maddiaa0 marked this conversation as resolved.
Show resolved Hide 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 +207,60 @@ 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);
bytes memory baseLeaf = new bytes(0x4c0);
Maddiaa0 marked this conversation as resolved.
Show resolved Hide resolved
// @todo I am messing something up here, at least the second time running something, it is getting fucked

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Kernel1.contract.aztecaddress
// Kernel1.contract.aztecAddress

calldatacopy(add(baseLeaf, dstOffset), add(_l2Block.offset, srcContractDataOffset), 0x20)
dstOffset := add(dstOffset, 0x20)

// Kernel1.contract.ethAddress padded to 32 bytes
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
)
dstOffset := add(dstOffset, 0x20)

// Kernel2.contract.aztecaddress
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Kernel2.contract.aztecaddress
// 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
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