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

refactor: pad when needed and not sooner #5482

Merged
merged 21 commits into from
Apr 3, 2024
48 changes: 38 additions & 10 deletions l1-contracts/src/core/libraries/decoders/TxsDecoder.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {Hash} from "../Hash.sol";
* @dev Assumes the input trees to be padded.
*
* -------------------
* You can use scripts/l2_block_data_specification_comment.py to generate the below outline.
* You can use scripts/l2_block_data_specification_comment.py to generate the below outline. --> SCRIPT STALE NOW!
* -------------------
* L2 Body Data Specification
* -------------------
Expand Down Expand Up @@ -68,25 +68,25 @@ library TxsDecoder {
}

/**
* @notice Computes consumables for the block
* @param _body - The L2 block calldata.
* @return diffRoot - The root of the diff tree (new note hashes, nullifiers etc)
* @notice Computes txs effects hash
* @param _body - The L2 block body calldata.
* @return The txs effects hash.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was all outdated so I sneaked the fix in.

*/
function decode(bytes calldata _body) internal pure returns (bytes32) {
ArrayOffsets memory offsets;
Counts memory counts;
ConsumablesVars memory vars;
uint256 offset = 0;

{
uint256 count = read4(_body, offset); // number of tx effects
offset += 0x4;
vars.baseLeaves = new bytes32[](count);
}
uint32 numTxEffects = uint32(read4(_body, offset));
uint256 numTxEffectsToPad = computeNumTxEffectsToPad(numTxEffects);

offset += 0x4;
vars.baseLeaves = new bytes32[](numTxEffects + numTxEffectsToPad);

// Data starts after header. Look at L2 Block Data specification at the top of this file.
{
for (uint256 i = 0; i < vars.baseLeaves.length; i++) {
for (uint256 i = 0; i < numTxEffects; i++) {
/*
* Compute the leaf to insert.
* Leaf_i = (
Expand Down Expand Up @@ -179,6 +179,12 @@ library TxsDecoder {

vars.baseLeaves[i] = Hash.sha256ToField(vars.baseLeaf);
}

// We pad base leaves with hashes of empty tx effect.
for (uint256 i = numTxEffects; i < vars.baseLeaves.length; i++) {
// Value taken from tx_effect.test.ts "hash of empty tx effect matches snapshot" test case
vars.baseLeaves[i] = hex"0071f7630d28ce02cc1ca8b15c44953f84a39e1478445395247ae04dfa213c0e";
}
}

return computeRoot(vars.baseLeaves);
Expand Down Expand Up @@ -344,4 +350,26 @@ library TxsDecoder {
function read4(bytes calldata _data, uint256 _offset) internal pure returns (uint256) {
return uint256(uint32(bytes4(slice(_data, _offset, 4))));
}

function computeNumTxEffectsToPad(uint32 _numTxEffects) internal pure returns (uint32) {
// 2 is the minimum number of tx effects so we have to handle the following 2 cases separately
if (_numTxEffects == 0) {
return 2;
} else if (_numTxEffects == 1) {
return 1;
}

uint32 v = _numTxEffects;

// the following rounds _numTxEffects up to the next power of 2 (works only for 4 bytes value!)
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;

return v - _numTxEffects;
}
}
22 changes: 17 additions & 5 deletions l1-contracts/test/Rollup.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pragma solidity >=0.8.18;
import {DecoderBase} from "./decoders/Base.sol";

import {DataStructures} from "../src/core/libraries/DataStructures.sol";
import {Constants} from "../src/core/libraries/ConstantsGen.sol";

import {Registry} from "../src/core/messagebridge/Registry.sol";
import {Inbox} from "../src/core/messagebridge/Inbox.sol";
Expand All @@ -15,6 +16,8 @@ import {AvailabilityOracle} from "../src/core/availability_oracle/AvailabilityOr
import {NaiveMerkle} from "./merkle/Naive.sol";
import {MerkleTestUtil} from "./merkle/TestUtil.sol";

import {TxsDecoderHelper} from "./decoders/helpers/TxsDecoderHelper.sol";

/**
* Blocks are generated using the `integration_l1_publisher.test.ts` tests.
* Main use of these test is shorter cycles when updating the decoder contract.
Expand All @@ -25,6 +28,7 @@ contract RollupTest is DecoderBase {
Outbox internal outbox;
Rollup internal rollup;
MerkleTestUtil internal merkleTestUtil;
TxsDecoderHelper internal txsHelper;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added the helper here because I needed the computeNumTxEffectsToPad here to correctly pad l2 to l1 messages.


AvailabilityOracle internal availabilityOracle;

Expand All @@ -38,6 +42,7 @@ contract RollupTest is DecoderBase {
registry.upgrade(address(rollup), address(inbox), address(outbox));

merkleTestUtil = new MerkleTestUtil();
txsHelper = new TxsDecoderHelper();
}

function testMixedBlock() public {
Expand Down Expand Up @@ -128,6 +133,7 @@ contract RollupTest is DecoderBase {
bytes memory header = full.block.header;
bytes32 archive = full.block.archive;
bytes memory body = full.block.body;
uint32 numTxs = full.block.numTxs;

// We jump to the time of the block.
vm.warp(full.block.decodedHeader.globalVariables.timestamp);
Expand All @@ -145,19 +151,25 @@ contract RollupTest is DecoderBase {

bytes32 l2ToL1MessageTreeRoot;
{
uint256 treeHeight =
merkleTestUtil.calculateTreeHeightFromSize(full.messages.l2ToL1Messages.length);
uint256 numTxsWithPadding = txsHelper.computeNumTxEffectsToPad(numTxs) + numTxs;
uint256 numMessagesWithPadding = numTxsWithPadding * Constants.MAX_NEW_L2_TO_L1_MSGS_PER_TX;

uint256 treeHeight = merkleTestUtil.calculateTreeHeightFromSize(numMessagesWithPadding);
NaiveMerkle tree = new NaiveMerkle(treeHeight);
for (uint256 i = 0; i < full.messages.l2ToL1Messages.length; i++) {
tree.insertLeaf(full.messages.l2ToL1Messages[i]);
for (uint256 i = 0; i < numMessagesWithPadding; i++) {
if (i < full.messages.l2ToL1Messages.length) {
tree.insertLeaf(full.messages.l2ToL1Messages[i]);
} else {
tree.insertLeaf(bytes32(0));
}
}

l2ToL1MessageTreeRoot = tree.computeRoot();
}

(bytes32 root,) = outbox.roots(full.block.decodedHeader.globalVariables.blockNumber);

assertEq(l2ToL1MessageTreeRoot, root);
assertEq(l2ToL1MessageTreeRoot, root, "Invalid l2 to l1 message tree root");

assertEq(rollup.archive(), archive, "Invalid archive");
}
Expand Down
3 changes: 3 additions & 0 deletions l1-contracts/test/decoders/Base.sol
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ contract DecoderBase is Test {
bytes body;
DecodedHeader decodedHeader;
bytes header;
// Note: The following could be decoded from body but having it explicitaly here makes tests more robust against
// decoder changes
uint32 numTxs;
bytes32 publicInputsHash;
bytes32 txsEffectsHash;
}
Expand Down
35 changes: 35 additions & 0 deletions l1-contracts/test/decoders/Decoders.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -277,4 +277,39 @@ contract DecodersTest is DecoderBase {
assertEq(bytesAdvanced, encodedLogs.length, "Advanced by an incorrect number of bytes");
assertEq(logsHash, referenceLogsHashFromIteration3, "Incorrect logs hash");
}

function testTxsDecoderCorrectlyComputesNumTxEffectsToPad() public {
// Minimum num txs is 2 so when there are no real txs we need to pad to 2
uint32 numTxEffects = 0;
uint32 paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects);
assertEq(paddedNumTxEffects, 2, "Incorrect number of tx effects to pad");

numTxEffects = 1;
paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects);
assertEq(paddedNumTxEffects, 2 ** 1 - numTxEffects, "Incorrect number of tx effects to pad");

numTxEffects = 3;
paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects);
assertEq(paddedNumTxEffects, 2 ** 2 - numTxEffects, "Incorrect number of tx effects to pad");

numTxEffects = 5;
paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects);
assertEq(paddedNumTxEffects, 2 ** 3 - numTxEffects, "Incorrect number of tx effects to pad");

numTxEffects = 8;
paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects);
assertEq(paddedNumTxEffects, 2 ** 3 - numTxEffects, "Incorrect number of tx effects to pad");

numTxEffects = 10;
paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects);
assertEq(paddedNumTxEffects, 2 ** 4 - numTxEffects, "Incorrect number of tx effects to pad");

numTxEffects = 16;
paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects);
assertEq(paddedNumTxEffects, 2 ** 4 - numTxEffects, "Incorrect number of tx effects to pad");

numTxEffects = 17;
paddedNumTxEffects = txsHelper.computeNumTxEffectsToPad(numTxEffects);
assertEq(paddedNumTxEffects, 2 ** 5 - numTxEffects, "Incorrect number of tx effects to pad");
}
}
4 changes: 4 additions & 0 deletions l1-contracts/test/decoders/helpers/TxsDecoderHelper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,8 @@ contract TxsDecoderHelper {
{
return TxsDecoder.computeKernelLogsHash(0, _kernelLogs);
}

function computeNumTxEffectsToPad(uint32 _numTxEffects) external pure returns (uint32) {
return TxsDecoder.computeNumTxEffectsToPad(_numTxEffects);
}
}
38 changes: 15 additions & 23 deletions l1-contracts/test/fixtures/empty_block_0.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,26 @@
"sender": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc"
},
"messages": {
"l2ToL1Messages": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000"
]
"l2ToL1Messages": []
},
"block": {
"archive": "0x29598370fa40a50b7fbb99e501f11527a69e104a43c8eefbfe66888f137e7e49",
"body": "0x0000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"txsEffectsHash": "0x008194e3dd375d5d878dcf9546bb5c2c77e165c6b1bef9aead8ceb35c3762bd5",
"archive": "0x122e56310a16134c202e94b3ba9cb74de123f7ec493e601d2f0b6da00cf57a4a",
"body": "0x00000000",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Body is now even smaller because empty tx effects are not included. We could shrink this value even more because we will probably never need 4 bytes for num tx effects but that's not so important now.

"txsEffectsHash": "0x00df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d2493896",
"decodedHeader": {
"contentCommitment": {
"inHash": "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c",
"outHash": "0x00efcbdb79553ae6863646bf36441755bc344a9a4af335fadc6659594faa4316",
"txTreeHeight": 2,
"txsEffectsHash": "0x008194e3dd375d5d878dcf9546bb5c2c77e165c6b1bef9aead8ceb35c3762bd5"
"outHash": "0x0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c3",
"txTreeHeight": 1,
"txsEffectsHash": "0x00df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d2493896"
},
"globalVariables": {
"blockNumber": 1,
"chainId": 31337,
"timestamp": 0,
"version": 1,
"coinbase": "0x5e65711eaf5606f1f42dd36579261833e54595ee",
"feeRecipient": "0x00eafbad09eab548a89726e2a735bdcadc37aa4c318ed7a12d9be6a7542e517e"
"coinbase": "0x66440eb666440eb666440eb666440eb666440eb6",
"feeRecipient": "0x061ca689507c7f1ccc68c2ad086c9d5d94f50869cb1b718c6a46aaf77a4500ba"
},
"lastArchive": {
"nextAvailableLeafIndex": 1,
Expand All @@ -46,21 +37,22 @@
},
"partialStateReference": {
"noteHashTree": {
"nextAvailableLeafIndex": 256,
"nextAvailableLeafIndex": 128,
"root": "0x16642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb"
},
"nullifierTree": {
"nextAvailableLeafIndex": 384,
"nextAvailableLeafIndex": 256,
"root": "0x0bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278"
},
"publicDataTree": {
"nextAvailableLeafIndex": 192,
"nextAvailableLeafIndex": 128,
"root": "0x0572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b"
}
}
}
},
"header": "0x1e3523d3bd50ae6204e1ec2ee1bdf8af4c6217ec80900052d2cf4259379dd130000000010000000000000000000000000000000000000000000000000000000000000002008194e3dd375d5d878dcf9546bb5c2c77e165c6b1bef9aead8ceb35c3762bd500089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00efcbdb79553ae6863646bf36441755bc344a9a4af335fadc6659594faa43161864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000c00000000000000000000000000000000000000000000000000000000000007a690000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000005e65711eaf5606f1f42dd36579261833e54595ee00eafbad09eab548a89726e2a735bdcadc37aa4c318ed7a12d9be6a7542e517e",
"publicInputsHash": "0x009e67eb54715bba61c94f475f6d4bf81b775da316c2c9a6a12506851f760bf0"
"header": "0x1e3523d3bd50ae6204e1ec2ee1bdf8af4c6217ec80900052d2cf4259379dd13000000001000000000000000000000000000000000000000000000000000000000000000100df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d249389600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000001016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000000800bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001000572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000800000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000066440eb666440eb666440eb666440eb666440eb6061ca689507c7f1ccc68c2ad086c9d5d94f50869cb1b718c6a46aaf77a4500ba",
"publicInputsHash": "0x00b833c76dd93572e83879eeb4085a3cd71f24831384fb4d3fe531ed87b859e3",
"numTxs": 0
}
}
42 changes: 17 additions & 25 deletions l1-contracts/test/fixtures/empty_block_1.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,39 +5,30 @@
"sender": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc"
},
"messages": {
"l2ToL1Messages": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000"
]
"l2ToL1Messages": []
},
"block": {
"archive": "0x045487d0ec498eb3f7f027715db8d67cc060604058bc5dd3e2e39fb47fe0ea17",
"body": "0x0000000400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"txsEffectsHash": "0x008194e3dd375d5d878dcf9546bb5c2c77e165c6b1bef9aead8ceb35c3762bd5",
"archive": "0x0d53ab5014f578345d853cd208bda74db64358fef8e5f646240db05893f6e780",
"body": "0x00000000",
"txsEffectsHash": "0x00df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d2493896",
"decodedHeader": {
"contentCommitment": {
"inHash": "0x00089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c",
"outHash": "0x00efcbdb79553ae6863646bf36441755bc344a9a4af335fadc6659594faa4316",
"txTreeHeight": 2,
"txsEffectsHash": "0x008194e3dd375d5d878dcf9546bb5c2c77e165c6b1bef9aead8ceb35c3762bd5"
"outHash": "0x0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c3",
"txTreeHeight": 1,
"txsEffectsHash": "0x00df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d2493896"
},
"globalVariables": {
"blockNumber": 2,
"chainId": 31337,
"timestamp": 1711036059,
"timestamp": 1711637579,
"version": 1,
"coinbase": "0x5e65711eaf5606f1f42dd36579261833e54595ee",
"feeRecipient": "0x00eafbad09eab548a89726e2a735bdcadc37aa4c318ed7a12d9be6a7542e517e"
"coinbase": "0x66440eb666440eb666440eb666440eb666440eb6",
"feeRecipient": "0x061ca689507c7f1ccc68c2ad086c9d5d94f50869cb1b718c6a46aaf77a4500ba"
},
"lastArchive": {
"nextAvailableLeafIndex": 2,
"root": "0x29598370fa40a50b7fbb99e501f11527a69e104a43c8eefbfe66888f137e7e49"
"root": "0x122e56310a16134c202e94b3ba9cb74de123f7ec493e601d2f0b6da00cf57a4a"
},
"stateReference": {
"l1ToL2MessageTree": {
Expand All @@ -46,21 +37,22 @@
},
"partialStateReference": {
"noteHashTree": {
"nextAvailableLeafIndex": 512,
"nextAvailableLeafIndex": 256,
"root": "0x16642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb"
},
"nullifierTree": {
"nextAvailableLeafIndex": 640,
"nextAvailableLeafIndex": 384,
"root": "0x0bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278"
},
"publicDataTree": {
"nextAvailableLeafIndex": 320,
"nextAvailableLeafIndex": 192,
"root": "0x0572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b"
}
}
}
},
"header": "0x29598370fa40a50b7fbb99e501f11527a69e104a43c8eefbfe66888f137e7e49000000020000000000000000000000000000000000000000000000000000000000000002008194e3dd375d5d878dcf9546bb5c2c77e165c6b1bef9aead8ceb35c3762bd500089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c00efcbdb79553ae6863646bf36441755bc344a9a4af335fadc6659594faa43161864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000002000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000002800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000001400000000000000000000000000000000000000000000000000000000000007a69000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000065fc569b5e65711eaf5606f1f42dd36579261833e54595ee00eafbad09eab548a89726e2a735bdcadc37aa4c318ed7a12d9be6a7542e517e",
"publicInputsHash": "0x00e9cfdd839060c90c216e1cecd24c5570a84e380e2bc640fd9dbbb5b2dd0718"
"header": "0x122e56310a16134c202e94b3ba9cb74de123f7ec493e601d2f0b6da00cf57a4a00000002000000000000000000000000000000000000000000000000000000000000000100df6b1c97b9e01113fa0363d9ff71c85addc74e92b22d433b2fb082d249389600089a9d421a82c4a25f7acbebe69e638d5b064fa8a60e018793dcb0be53752c0007638bb56b6dda2b64b8f76841114ac3a87a1820030e2e16772c4d294879c31864fcdaa80ff2719154fa7c8a9050662972707168d69eac9db6fd3110829f800000002016642d9ccd8346c403aa4c3fa451178b22534a27035cdaa6ec34ae53b29c50cb000001000bcfa3e9f1a8922ee92c6dc964d6595907c1804a86753774322b468f69d4f278000001800572c8db882674dd026b8877fbba1b700a4407da3ae9ce5fa43215a28163362b000000c00000000000000000000000000000000000000000000000000000000000007a6900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000006605844b66440eb666440eb666440eb666440eb666440eb6061ca689507c7f1ccc68c2ad086c9d5d94f50869cb1b718c6a46aaf77a4500ba",
"publicInputsHash": "0x00035031752fa374209f1ec4bc08613cae25ba65779c10130681421f6e71c6d9",
"numTxs": 0
}
}
17 changes: 9 additions & 8 deletions l1-contracts/test/fixtures/mixed_block_0.json

Large diffs are not rendered by default.

21 changes: 11 additions & 10 deletions l1-contracts/test/fixtures/mixed_block_1.json

Large diffs are not rendered by default.

Loading
Loading