Merge pull request #279 from zkemail/zkfriendly/sol-191-circuit-utils-library

feat: circuit utils library
This commit is contained in:
zkfriendly
2025-08-27 16:15:29 +02:00
committed by GitHub
16 changed files with 2828 additions and 2058 deletions

View File

@@ -48,20 +48,20 @@ jobs:
environment: development
steps:
- uses: actions/checkout@v3
- name: Set Node.js 18.x
uses: actions/setup-node@v3
with:
node-version: 18
- name: Install Yarn dependencies
working-directory: ./packages/helpers
run: yarn install --immutable
- name: Run build
working-directory: ./packages/helpers
run: yarn build
- name: Run Tests
working-directory: ./packages/helpers
run: yarn test

3
.gitignore vendored
View File

@@ -102,3 +102,6 @@ target/
# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb
# ignore build logs
thinking.log

View File

@@ -1,3 +1,5 @@
nodeLinker: node-modules
yarnPath: .yarn/releases/yarn-3.2.3.cjs
checksumBehavior: ignore

View File

@@ -43,4 +43,4 @@
]
]
}
}
}

View File

@@ -0,0 +1,236 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { Bytes } from "@openzeppelin/contracts/utils/Bytes.sol";
/**
* @title CircuitUtils
* @notice Library for ZK circuit-related utilities including field element packing and proof processing
* @dev This library provides functions for converting between byte arrays and field elements
* and other utilities needed for zero-knowledge proof circuit compatibility.
*/
library CircuitUtils {
using Bytes for bytes;
/**
* @notice Error thrown when the public signals array length is not exactly 60
* @dev The ZK circuit expects exactly 60 public signals for verification
*/
error InvalidPubSignalsLength();
/**
* @notice Error thrown when the command length is invalid
* @dev The command should have the expected format and length
*/
error InvalidCommandLength();
/**
* @notice Error thrown when the data length is greater than the padded size
* @dev The data should have the expected format and length
*/
error InvalidDataLength();
/**
* @notice Packs byte arrays into field elements for ZK circuit compatibility
* @param _bytes The byte array to pack into field elements
* @param _paddedSize The target size after padding (must be larger than or equal to _bytes.length)
* @return An array of field elements containing the packed byte data
* @dev This function packs bytes into field elements by:
* 1. Determining how many field elements are needed (31 bytes per field element)
* 2. Packing bytes in little-endian order within each field element
* 3. Padding with zeros if the input is shorter than _paddedSize
* 4. Ensuring the resulting field elements are compatible with ZK circuits
*
* Each field element can contain up to 31 bytes to ensure the result stays below
* the BN128 curve order. Bytes are packed as: byte0 + (byte1 << 8) + (byte2 << 16) + ...
*/
function packBytes2Fields(bytes memory _bytes, uint256 _paddedSize) internal pure returns (uint256[] memory) {
if (_bytes.length > _paddedSize) revert InvalidDataLength();
uint256 remain = _paddedSize % 31;
uint256 numFields = (_paddedSize - remain) / 31;
if (remain > 0) {
numFields += 1;
}
uint256[] memory fields = new uint256[](numFields);
uint256 idx = 0;
uint256 byteVal = 0;
for (uint256 i = 0; i < numFields; i++) {
for (uint256 j = 0; j < 31; j++) {
idx = i * 31 + j;
if (idx >= _paddedSize) {
break;
}
if (idx >= _bytes.length) {
byteVal = 0;
} else {
byteVal = uint256(uint8(_bytes[idx]));
}
if (j == 0) {
fields[i] = byteVal;
} else {
fields[i] += (byteVal << (8 * j));
}
}
}
return fields;
}
/**
* @notice Packs a string into field elements for ZK circuit compatibility
* @param _string The string to pack
* @param paddedSize The target size after padding
* @return fields The packed field elements
*/
function packString(string memory _string, uint256 paddedSize) internal pure returns (uint256[] memory fields) {
fields = packBytes2Fields(bytes(_string), paddedSize);
return fields;
}
/**
* @notice Packs a bytes32 value into a single field element
* @param _bytes32 The bytes32 value to pack
* @return fields The packed field element
*/
function packBytes32(bytes32 _bytes32) internal pure returns (uint256[] memory fields) {
fields = new uint256[](1);
fields[0] = uint256(_bytes32);
return fields;
}
/**
* @notice Packs a boolean value into a single field element
* @param b The boolean value to pack
* @return fields The packed field element
*/
function packBool(bool b) internal pure returns (uint256[] memory fields) {
fields = new uint256[](1);
fields[0] = b ? 1 : 0;
return fields;
}
/**
* @notice Packs a uint256 value into a single field element
* @param _uint256 The uint256 value to pack
* @return fields The packed field element
*/
function packUint256(uint256 _uint256) internal pure returns (uint256[] memory fields) {
fields = new uint256[](1);
fields[0] = _uint256;
return fields;
}
/**
* @notice Unpacks field elements back to bytes
* @param _pucSignals Array of public signals
* @param _startIndex Starting index in pubSignals
* @param _paddedSize Original padded size of the bytes
* @return The unpacked bytes
*/
function unpackFields2Bytes(
uint256[] calldata _pucSignals,
uint256 _startIndex,
uint256 _paddedSize
)
internal
pure
returns (bytes memory)
{
uint256 remain = _paddedSize % 31;
uint256 numFields = (_paddedSize - remain) / 31;
if (remain > 0) {
numFields += 1;
}
bytes memory result = new bytes(_paddedSize);
uint256 resultIndex = 0;
for (uint256 i = 0; i < numFields; i++) {
uint256 field = _pucSignals[_startIndex + i];
for (uint256 j = 0; j < 31 && resultIndex < _paddedSize; j++) {
result[resultIndex] = bytes1(uint8(field & 0xFF));
field = field >> 8;
resultIndex++;
}
}
// Trim trailing zeros
uint256 actualLength = 0;
for (uint256 i = 0; i < result.length; i++) {
if (result[i] != 0) {
actualLength = i + 1;
}
}
return result.slice(0, actualLength);
}
/**
* @notice Unpacks field elements to a string
* @param pubSignals Array of public signals
* @param startIndex Starting index in pubSignals
* @param paddedSize Original padded size of the string
* @return The unpacked string
*/
function unpackString(
uint256[] calldata pubSignals,
uint256 startIndex,
uint256 paddedSize
)
internal
pure
returns (string memory)
{
return string(unpackFields2Bytes(pubSignals, startIndex, paddedSize));
}
/**
* @notice Unpacks a bytes32 value from public signals
* @param pubSignals Array of public signals
* @param startIndex Starting index in pubSignals
* @return The unpacked bytes32 value
*/
function unpackBytes32(uint256[] calldata pubSignals, uint256 startIndex) internal pure returns (bytes32) {
return bytes32(pubSignals[startIndex]);
}
/**
* @notice Unpacks a uint256 value from public signals
* @param pubSignals Array of public signals
* @param startIndex Starting index in pubSignals
* @return The unpacked uint256 value
*/
function unpackUint256(uint256[] calldata pubSignals, uint256 startIndex) internal pure returns (uint256) {
return pubSignals[startIndex];
}
/**
* @notice Unpacks a boolean value from public signals
* @param pubSignals Array of public signals
* @param startIndex Starting index in pubSignals
* @return The unpacked boolean value
*/
function unpackBool(uint256[] calldata pubSignals, uint256 startIndex) internal pure returns (bool) {
return pubSignals[startIndex] == 1;
}
/**
* @notice Flattens multiple arrays of field elements into a single array
* @param inputs The arrays of field elements to flatten
* @param outLength The length of the flattened array
* @return out The flattened array
*/
function flattenFields(uint256[][] memory inputs, uint256 outLength) internal pure returns (uint256[] memory out) {
out = new uint256[](outLength);
uint256 k = 0;
for (uint256 i = 0; i < inputs.length; i++) {
uint256[] memory arr = inputs[i];
for (uint256 j = 0; j < arr.length; j++) {
if (k >= outLength) revert InvalidPubSignalsLength();
out[k++] = arr[j];
}
}
if (k != outLength) revert InvalidPubSignalsLength();
return out;
}
}

View File

@@ -3,4 +3,4 @@ src = './'
out = 'out'
allow_paths = ['../../node_modules']
libs = ['../../node_modules']
solc_version = '0.8.26'
solc_version = '0.8.30'

View File

@@ -7,17 +7,18 @@
"publish": "yarn npm publish --access=public"
},
"dependencies": {
"@openzeppelin/contracts": "^5.0.0",
"@openzeppelin/contracts-upgradeable": "^5.0.0",
"@openzeppelin/contracts": "5.3.0",
"@openzeppelin/contracts-upgradeable": "5.3.0",
"dotenv": "^16.3.1"
},
"files": [
"DKIMRegistry.sol",
"UserOverrideableDKIMRegistry.sol",
"CircuitUtils.sol",
"/utils",
"/interfaces"
],
"devDependencies": {
"forge-std": "https://github.com/foundry-rs/forge-std"
"forge-std": "https://github.com/foundry-rs/forge-std#v1.10.0"
}
}

View File

@@ -1,5 +1,5 @@
@openzeppelin/contracts=../../node_modules/@openzeppelin/contracts
@openzeppelin=../../node_modules/@openzeppelin/contracts
@openzeppelin/contracts-upgradeable/=../../node_modules/@openzeppelin/contracts-upgradeable
forge-std=../../node_modules/forge-std
@zk-email/email-tx-builder/=../../node_modules/@zk-email/email-tx-builder/packages/contracts/
forge-std/=../../node_modules/forge-std/src

View File

@@ -0,0 +1,90 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
import { Test } from "forge-std/Test.sol";
import { CircuitUtils } from "../../CircuitUtils.sol";
import { CircuitUtilsHelper } from "./_CircuitUtilsHelper.sol";
contract FlattenFieldsTest is Test {
CircuitUtilsHelper private _helper;
function setUp() public {
_helper = new CircuitUtilsHelper();
}
function test_expectRevert_tooManyElements() public {
uint256[][] memory inputs = new uint256[][](2);
inputs[0] = new uint256[](30);
inputs[1] = new uint256[](31);
for (uint256 i = 0; i < 30; i++) {
inputs[0][i] = i + 1;
}
for (uint256 i = 0; i < 31; i++) {
inputs[1][i] = i + 31;
}
vm.expectRevert(CircuitUtils.InvalidPubSignalsLength.selector);
_helper.callFlattenFields(inputs, 60);
}
function test_expectRevert_tooFewElements() public {
uint256[][] memory inputs = new uint256[][](2);
inputs[0] = new uint256[](30);
inputs[1] = new uint256[](29);
for (uint256 i = 0; i < 30; i++) {
inputs[0][i] = i + 1;
}
for (uint256 i = 0; i < 29; i++) {
inputs[1][i] = i + 31;
}
vm.expectRevert(CircuitUtils.InvalidPubSignalsLength.selector);
_helper.callFlattenFields(inputs, 60);
}
function test_zeroArrays() public {
uint256[][] memory inputs = new uint256[][](0);
vm.expectRevert(CircuitUtils.InvalidPubSignalsLength.selector);
_helper.callFlattenFields(inputs, 60);
}
function test_singleArray() public view {
uint256[][] memory inputs = new uint256[][](1);
inputs[0] = new uint256[](60);
for (uint256 i = 0; i < 60; i++) {
inputs[0][i] = i + 1;
}
uint256[] memory result = _helper.callFlattenFields(inputs, 60);
for (uint256 i = 0; i < 60; i++) {
assertEq(result[i], i + 1);
}
}
function test_multipleArrays() public view {
uint256[][] memory inputs = new uint256[][](3);
inputs[0] = new uint256[](20);
inputs[1] = new uint256[](20);
inputs[2] = new uint256[](20);
for (uint256 i = 0; i < 20; i++) {
inputs[0][i] = i + 1;
inputs[1][i] = i + 21;
inputs[2][i] = i + 41;
}
uint256[] memory result = _helper.callFlattenFields(inputs, 60);
for (uint256 i = 0; i < 20; i++) {
assertEq(result[i], i + 1);
assertEq(result[i + 20], i + 21);
assertEq(result[i + 40], i + 41);
}
}
function test_manySmallArrays() public view {
uint256[][] memory inputs = new uint256[][](60);
for (uint256 i = 0; i < 60; i++) {
inputs[i] = new uint256[](1);
inputs[i][0] = i + 1;
}
uint256[] memory result = _helper.callFlattenFields(inputs, 60);
for (uint256 i = 0; i < 60; i++) {
assertEq(result[i], i + 1);
}
}
}

View File

@@ -0,0 +1,124 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
import { Test } from "forge-std/Test.sol";
import { CircuitUtils } from "../../CircuitUtils.sol";
import { CircuitUtilsHelper } from "./_CircuitUtilsHelper.sol";
contract PackBytes2FieldsTest is Test {
CircuitUtilsHelper private _helper;
function setUp() public {
_helper = new CircuitUtilsHelper();
}
function test_emptyBytes() public view {
bytes memory emptyBytes = "";
uint256[] memory fields = _helper.callPackBytes2Fields(emptyBytes, 0);
assertEq(fields.length, 0);
}
function test_singleByte() public view {
bytes memory singleByte = hex"41";
uint256[] memory fields = _helper.callPackBytes2Fields(singleByte, 1);
assertEq(fields.length, 1);
assertEq(uint8(fields[0]), 0x41);
}
function test_exactly31Bytes() public view {
bytes memory data = new bytes(31);
for (uint256 i = 0; i < 31; i++) {
data[i] = bytes1(uint8(i + 1));
}
uint256[] memory fields = _helper.callPackBytes2Fields(data, 31);
assertEq(fields.length, 1);
uint256 expected = 0;
for (uint256 i = 0; i < 31; i++) {
expected += uint256(uint8(data[i])) << (8 * i);
}
assertEq(fields[0], expected);
}
function test_32Bytes() public view {
bytes memory data = new bytes(32);
for (uint256 i = 0; i < 32; i++) {
data[i] = bytes1(uint8(i + 1));
}
uint256[] memory fields = _helper.callPackBytes2Fields(data, 32);
assertEq(fields.length, 2);
uint256 expectedFirst = 0;
for (uint256 i = 0; i < 31; i++) {
expectedFirst += uint256(uint8(data[i])) << (8 * i);
}
assertEq(fields[0], expectedFirst);
assertEq(fields[1], uint256(uint8(data[31])));
}
function test_withPadding() public view {
bytes memory data = hex"414243";
uint256[] memory fields = _helper.callPackBytes2Fields(data, 10);
assertEq(fields.length, 1);
uint256 expected = 0x41 + (0x42 << 8) + (0x43 << 16);
assertEq(fields[0], expected);
}
function test_exactFieldBoundaries() public view {
bytes memory data = new bytes(62);
for (uint256 i = 0; i < 62; i++) {
data[i] = bytes1(uint8(i + 1));
}
uint256[] memory fields = _helper.callPackBytes2Fields(data, 62);
assertEq(fields.length, 2);
uint256 expectedFirst = 0;
for (uint256 i = 0; i < 31; i++) {
expectedFirst += uint256(uint8(data[i])) << (8 * i);
}
assertEq(fields[0], expectedFirst);
uint256 expectedSecond = 0;
for (uint256 i = 31; i < 62; i++) {
expectedSecond += uint256(uint8(data[i])) << (8 * (i - 31));
}
assertEq(fields[1], expectedSecond);
}
function test_allZeros() public view {
bytes memory data = new bytes(31);
uint256[] memory fields = _helper.callPackBytes2Fields(data, 31);
assertEq(fields.length, 1);
assertEq(fields[0], 0);
}
function test_maxByteValues() public view {
bytes memory data = new bytes(31);
for (uint256 i = 0; i < 31; i++) {
data[i] = 0xFF;
}
uint256[] memory fields = _helper.callPackBytes2Fields(data, 31);
assertEq(fields.length, 1);
uint256 expected = 0;
for (uint256 i = 0; i < 31; i++) {
expected += 0xFF << (8 * i);
}
assertEq(fields[0], expected);
}
function test_realisticString() public view {
bytes memory data = "gmail.com";
uint256[] memory fields = _helper.callPackBytes2Fields(data, 255);
assertEq(fields.length, 9);
uint256 expected = 0;
for (uint256 i = 0; i < data.length; i++) {
expected += uint256(uint8(data[i])) << (8 * i);
}
assertEq(fields[0], expected);
for (uint256 i = 1; i < 9; i++) {
assertEq(fields[i], 0);
}
}
function test_paddedSizeSmallerThanData() public {
bytes memory data = "This is a longer string that should revert";
vm.expectRevert(CircuitUtils.InvalidDataLength.selector);
_helper.callPackBytes2Fields(data, 10);
}
}

View File

@@ -0,0 +1,130 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
import { Test } from "forge-std/Test.sol";
import { CircuitUtilsHelper } from "./_CircuitUtilsHelper.sol";
contract UnpackFields2BytesTest is Test {
CircuitUtilsHelper private _helper;
function setUp() public {
_helper = new CircuitUtilsHelper();
}
function test_emptyFields() public view {
uint256[] memory fields = new uint256[](0);
bytes memory result = _helper.callUnpackFields2Bytes(fields, 0, 0);
assertEq(result.length, 0);
}
function test_singleFieldSingleByte() public view {
uint256[] memory fields = new uint256[](1);
fields[0] = 0x41;
bytes memory result = _helper.callUnpackFields2Bytes(fields, 0, 1);
assertEq(result.length, 1);
assertEq(uint8(result[0]), 0x41);
}
function test_singleFieldMultipleBytes() public view {
uint256[] memory fields = new uint256[](1);
fields[0] = 0x41 + (0x42 << 8) + (0x43 << 16);
bytes memory result = _helper.callUnpackFields2Bytes(fields, 0, 3);
assertEq(result.length, 3);
assertEq(uint8(result[0]), 0x41);
assertEq(uint8(result[1]), 0x42);
assertEq(uint8(result[2]), 0x43);
}
function test_multipleFields() public view {
uint256[] memory fields = new uint256[](2);
fields[0] = 0x41 + (0x42 << 8) + (0x43 << 16);
fields[1] = 0x44 + (0x45 << 8) + (0x46 << 16);
bytes memory result = _helper.callUnpackFields2Bytes(fields, 0, 6);
// Only the first 3 bytes are non-zero, the rest are zeros and will be trimmed
assertEq(result.length, 3);
assertEq(uint8(result[0]), 0x41);
assertEq(uint8(result[1]), 0x42);
assertEq(uint8(result[2]), 0x43);
}
function test_trimTrailingZeros() public view {
uint256[] memory fields = new uint256[](1);
fields[0] = 0x41 + (0x42 << 8) + (0x00 << 16);
bytes memory result = _helper.callUnpackFields2Bytes(fields, 0, 3);
assertEq(result.length, 2);
assertEq(uint8(result[0]), 0x41);
assertEq(uint8(result[1]), 0x42);
}
function test_zerosInMiddle() public view {
uint256[] memory fields = new uint256[](1);
fields[0] = 0x41 + (0x00 << 8) + (0x43 << 16);
bytes memory result = _helper.callUnpackFields2Bytes(fields, 0, 3);
assertEq(result.length, 3);
assertEq(uint8(result[0]), 0x41);
assertEq(uint8(result[1]), 0x00);
assertEq(uint8(result[2]), 0x43);
}
function test_withOffset() public view {
uint256[] memory fields = new uint256[](3);
fields[0] = 0x11 + (0x12 << 8);
fields[1] = 0x21 + (0x22 << 8) + (0x23 << 16);
fields[2] = 0x31 + (0x32 << 8);
bytes memory result = _helper.callUnpackFields2Bytes(fields, 1, 3);
assertEq(result.length, 3);
assertEq(uint8(result[0]), 0x21);
assertEq(uint8(result[1]), 0x22);
assertEq(uint8(result[2]), 0x23);
}
function test_moreFieldsThanAvailable() public view {
uint256[] memory fields = new uint256[](1);
fields[0] = 0x41 + (0x42 << 8);
bytes memory result = _helper.callUnpackFields2Bytes(fields, 0, 4);
assertEq(result.length, 2);
assertEq(uint8(result[0]), 0x41);
assertEq(uint8(result[1]), 0x42);
}
function test_allZeros() public view {
uint256[] memory fields = new uint256[](1);
fields[0] = 0;
bytes memory result = _helper.callUnpackFields2Bytes(fields, 0, 31);
assertEq(result.length, 0);
}
function test_maxFieldValue() public view {
uint256[] memory fields = new uint256[](1);
fields[0] = 0;
for (uint256 i = 0; i < 31; i++) {
fields[0] += 0xFF << (8 * i);
}
bytes memory result = _helper.callUnpackFields2Bytes(fields, 0, 31);
assertEq(result.length, 31);
for (uint256 i = 0; i < 31; i++) {
assertEq(uint8(result[i]), 0xFF);
}
}
function test_multipleFieldsWithPadding() public view {
uint256[] memory fields = new uint256[](2);
fields[0] = 0x41 + (0x42 << 8) + (0x43 << 16);
fields[1] = 0x44 + (0x45 << 8);
bytes memory result = _helper.callUnpackFields2Bytes(fields, 0, 5);
// Only the first 3 bytes are non-zero, the rest are zeros and will be trimmed
assertEq(result.length, 3);
assertEq(uint8(result[0]), 0x41);
assertEq(uint8(result[1]), 0x42);
assertEq(uint8(result[2]), 0x43);
}
function test_partialFieldUnpack() public view {
uint256[] memory fields = new uint256[](1);
fields[0] = 0x41 + (0x42 << 8) + (0x43 << 16) + (0x44 << 24);
bytes memory result = _helper.callUnpackFields2Bytes(fields, 0, 2);
assertEq(result.length, 2);
assertEq(uint8(result[0]), 0x41);
assertEq(uint8(result[1]), 0x42);
}
}

View File

@@ -0,0 +1,26 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;
import { CircuitUtils } from "../../CircuitUtils.sol";
contract CircuitUtilsHelper {
function callFlattenFields(uint256[][] memory inputs, uint256 outLength) external pure returns (uint256[] memory) {
return CircuitUtils.flattenFields(inputs, outLength);
}
function callPackBytes2Fields(bytes memory data, uint256 paddedSize) external pure returns (uint256[] memory) {
return CircuitUtils.packBytes2Fields(data, paddedSize);
}
function callUnpackFields2Bytes(
uint256[] calldata fields,
uint256 startIndex,
uint256 paddedSize
)
external
pure
returns (bytes memory)
{
return CircuitUtils.unpackFields2Bytes(fields, startIndex, paddedSize);
}
}

View File

@@ -2,8 +2,8 @@
pragma solidity ^0.8.12;
import "@openzeppelin/contracts/utils/Strings.sol";
import "forge-std/src/Test.sol";
import "forge-std/src/console.sol";
import "forge-std/Test.sol";
import "forge-std/console.sol";
import "../interfaces/IERC7969.sol";
import "../DKIMRegistry.sol";

View File

@@ -1,8 +1,8 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.12;
import "forge-std/src/Test.sol";
import "forge-std/src/console.sol";
import "forge-std/Test.sol";
import "forge-std/console.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "../UserOverrideableDKIMRegistry.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
@@ -738,27 +738,27 @@ contract UserOverrideableDKIMRegistryTest is Test {
vm.stopPrank();
}
function testExpectRevertPublicKeyHashIsAlreadyRevokedByUser1() public {
testRevokeDKIMPublicKeyHashByUser1();
vm.startPrank(user1);
function testExpectRevertPublicKeyHashIsAlreadyRevokedByUser1() public {
testRevokeDKIMPublicKeyHashByUser1();
vm.startPrank(user1);
vm.expectRevert("public key hash is already revoked");
registry.setDKIMPublicKeyHash(
domainName,
publicKeyHash,
user1,
new bytes(0)
);
vm.expectRevert("public key hash is already revoked");
registry.setDKIMPublicKeyHash(
domainName,
publicKeyHash,
user1,
new bytes(0)
);
vm.expectRevert("public key hash is already revoked");
registry.revokeDKIMPublicKeyHash(
domainName,
publicKeyHash,
user1,
new bytes(0)
);
vm.stopPrank();
}
vm.expectRevert("public key hash is already revoked");
registry.revokeDKIMPublicKeyHash(
domainName,
publicKeyHash,
user1,
new bytes(0)
);
vm.stopPrank();
}
function testExpectRevertReactivateDKIMPublicKeyHashByMainAuthorizer()
public

View File

@@ -65,7 +65,7 @@ export function generatePartialSHA({
throw new Error('Remaining body was not padded correctly with int64s');
}
bodyRemaining = padUint8ArrayWithZeros(bodyRemaining, maxRemainingBodyLength);
bodyRemaining = new Uint8Array(padUint8ArrayWithZeros(bodyRemaining, maxRemainingBodyLength));
const precomputedSha = partialSha(precomputeText, shaCutoffIndex);
return {

4204
yarn.lock

File diff suppressed because it is too large Load Diff