Skip to content
Closed
Show file tree
Hide file tree
Changes from 5 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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,6 @@ lcov.info

Prover.toml
raw_inputs.json
target/
# ignore target dir contents but keep generated .sol verifiers (e.g. HonkVerifier.sol)
**/target/*
!**/target/*.sol
5 changes: 2 additions & 3 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ coverage/
node_modules/
out/

# circuit generated files
test/fixtures/handleCommand/circuit/target
test/fixtures/redditHandleCommand/circuit/target
# ignore circuit generated files (target directories under fixtures)
test/fixtures/**/target

# files
.env
Expand Down
5 changes: 2 additions & 3 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ quote_style = "double"
tab_width = 4
wrap_comments = true
ignore = [
# ignore circuit generated files
"test/fixtures/handleCommand/circuit/target/*.sol",
"test/fixtures/redditHandleCommand/circuit/target/*.sol",
# ignore circuit generated files (target directories under fixtures)
"test/fixtures/**/target/*.sol",
]
2 changes: 1 addition & 1 deletion script/DeployAllDiscord.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Script, console } from "forge-std/Script.sol";
import { HandleRegistrar } from "../src/entrypoints/HandleRegistrar.sol";
import { HandleResolver } from "../src/resolvers/HandleResolver.sol";
import { ClaimHandleCommandVerifier } from "../src/verifiers/ClaimHandleCommandVerifier.sol";
import { HonkVerifier } from "../test/fixtures/handleCommand/HonkVerifier.sol";
import { HonkVerifier } from "../test/fixtures/linkHandleCommand/twitter/target/HonkVerifier.sol";
Comment thread
coderabbitai[bot] marked this conversation as resolved.
import { EnsUtils } from "../src/utils/EnsUtils.sol";

contract DeployAllDiscordScript is Script {
Expand Down
2 changes: 1 addition & 1 deletion script/DeployAllX.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Script, console } from "forge-std/Script.sol";
import { HandleRegistrar } from "../src/entrypoints/HandleRegistrar.sol";
import { HandleResolver } from "../src/resolvers/HandleResolver.sol";
import { ClaimHandleCommandVerifier } from "../src/verifiers/ClaimHandleCommandVerifier.sol";
import { HonkVerifier } from "../test/fixtures/handleCommand/HonkVerifier.sol";
import { HonkVerifier } from "../test/fixtures/linkHandleCommand/twitter/target/HonkVerifier.sol";
import { EnsUtils } from "../src/utils/EnsUtils.sol";

contract DeployAllXScript is Script {
Expand Down
2 changes: 1 addition & 1 deletion script/DeployHandleRegistrar.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity ^0.8.30;
import { Script, console } from "forge-std/Script.sol";
import { HandleRegistrar } from "../src/entrypoints/HandleRegistrar.sol";
import { ClaimHandleCommandVerifier } from "../src/verifiers/ClaimHandleCommandVerifier.sol";
import { HonkVerifier } from "../test/fixtures/handleCommand/HonkVerifier.sol";
import { HonkVerifier } from "../test/fixtures/linkHandleCommand/twitter/target/HonkVerifier.sol";
import { EnsUtils } from "../src/utils/EnsUtils.sol";

contract DeployHandleRegistrarScript is Script {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;

import { DeployLinkHandleEntrypointScript } from "./_DeployLinkHandleEntrypoint.s.sol";
import { HonkVerifier } from "../../test/fixtures/handleCommand/HonkVerifier.sol";

contract DeployLinkHandleEntrypointTwitterScript is DeployLinkHandleEntrypointScript {
function _deployHonkVerifier() internal override returns (address) {
return address(new HonkVerifier());
}

function _dkimRegistry() internal pure override returns (address) {
// sepolia always valid dkim registry
return 0xc4f628496b8c474096650C8f9023954643cC614F;
}

function _keyName() internal pure override returns (string memory) {
return "com.twitter";
}
}
Comment thread
benceharomi marked this conversation as resolved.
Outdated
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;

import { DeployLinkHandleEntrypointScript } from "./_DeployLinkHandleEntrypoint.s.sol";
import { HonkVerifier } from "../../test/fixtures/linkHandleCommand/twitter/target/HonkVerifier.sol";

contract DeployLinkHandleEntrypointTwitterScript is DeployLinkHandleEntrypointScript {
function _getHonkVerifierAddress() internal override returns (address) {
return address(new HonkVerifier());
}

function _getDkimRegistryAddress() internal pure override returns (address) {
// sepolia always valid dkim registry
return 0xc4f628496b8c474096650C8f9023954643cC614F;
}

function _getPlatformName() internal pure override returns (string memory) {
return "x";
}

function _getRecordName() internal pure override returns (string memory) {
return "com.twitter";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.30;

import { Script, console } from "forge-std/Script.sol";
import { LinkHandleEntrypoint } from "../../src/entrypoints/LinkHandleEntrypoint.sol";
import { LinkHandleCommandVerifier } from "../../src/verifiers/LinkHandleCommandVerifier.sol";

abstract contract DeployLinkHandleEntrypointScript is Script {
function run() external {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");

vm.startBroadcast(deployerPrivateKey);

console.log("\n=== Step 1: Deploy LinkHandleCommandVerifier ===");
LinkHandleCommandVerifier commandVerifier =
new LinkHandleCommandVerifier(_getHonkVerifierAddress(), _getDkimRegistryAddress());
console.log("LinkHandleCommandVerifier deployed at:", address(commandVerifier));

console.log("\n=== Step 2: Deploy LinkHandleEntrypoint ===");
LinkHandleEntrypoint entrypoint =
new LinkHandleEntrypoint(address(commandVerifier), _getRecordName(), _getPlatformName());
console.log("LinkHandleEntrypoint deployed at:", address(entrypoint));

vm.stopBroadcast();

console.log("\n=== Deployment Complete ===");
console.log("HONK_VERIFIER=", _getHonkVerifierAddress());
console.log("DKIM_REGISTRY=", _getDkimRegistryAddress());
console.log("LINK_HANDLE_COMMAND_VERIFIER=", address(commandVerifier));
console.log("RECORD_NAME=", _getRecordName());
console.log("PLATFORM_NAME=", _getPlatformName());
console.log("LINK_HANDLE_ENTRYPOINT=", address(entrypoint));
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

/**
* @notice The HonkVerifier address.
* @dev TODO: ideally ths would be pure and would only return the address of the HonkVerifier deployed by the
* registry. Currently this is deployed inside this function. Remove it once the registry deploys the
* HonkVerifier.
* @return The address of the HonkVerifier
*/
function _getHonkVerifierAddress() internal virtual returns (address);

/**
* @notice The DKIM registry address.
* @dev Example (sepolia): return 0xe24c24Ab94c93D5754De1cbE61b777e47cc57723;
* Example (sepolia always valid): return 0xc4f628496b8c474096650C8f9023954643cC614F;
* @return The address of the DKIM registry
*/
function _getDkimRegistryAddress() internal pure virtual returns (address);

/**
* @notice The platform name in the command (e.g. "x").
* @return The platform name used in the command
*/
function _getPlatformName() internal pure virtual returns (string memory);

/**
* @notice ENS text record name (e.g. "com.twitter") — the key in setText(node, key, value).
* @return The record name for the text record
*/
function _getRecordName() internal pure virtual returns (string memory);
}
27 changes: 0 additions & 27 deletions script/DeployLinkHandleVerifier.s.sol

This file was deleted.

4 changes: 2 additions & 2 deletions script/LinkHandleWithFixture.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pragma solidity ^0.8.30;
import { Script } from "forge-std/Script.sol";
import { LinkHandleEntrypoint } from "../src/entrypoints/LinkHandleEntrypoint.sol";
import { LinkHandleCommand } from "../src/verifiers/HandleVerifier.sol";
import { HandleCommandTestFixture } from "../test/fixtures/handleCommand/HandleCommandTestFixture.sol";
import { LinkHandleCommandTestFixture } from "../test/fixtures/linkHandleCommand/LinkHandleCommandTestFixture.sol";

contract LinkHandleWithFixtureScript is Script {
// sepolia mock
Expand All @@ -16,7 +16,7 @@ contract LinkHandleWithFixtureScript is Script {
uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");

LinkHandleEntrypoint verifier = LinkHandleEntrypoint(LINK_X_HANDLE_VERIFIER);
(LinkHandleCommand memory command,) = HandleCommandTestFixture.getLinkXFixture();
(LinkHandleCommand memory command,) = LinkHandleCommandTestFixture.getTwitterFixture();

vm.startBroadcast(deployerPrivateKey);

Expand Down
2 changes: 1 addition & 1 deletion src/entrypoints/LinkEmailEntrypoint.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { LinkEmailCommand } from "../verifiers/LinkEmailCommandVerifier.sol";
* @dev The verifier can be updated via the entrypoint function.
*/
contract LinkEmailEntrypoint is LinkTextRecordEntrypoint {
constructor(address verifier) LinkTextRecordEntrypoint(verifier, "email") { }
constructor(address verifier) LinkTextRecordEntrypoint(verifier, "email", "email") { }

/**
* @inheritdoc LinkTextRecordEntrypoint
Expand Down
14 changes: 13 additions & 1 deletion src/entrypoints/LinkHandleEntrypoint.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,19 @@ import { LinkHandleCommand } from "../verifiers/HandleVerifier.sol";
* @dev The verifier can be updated via the entrypoint function.
*/
contract LinkHandleEntrypoint is LinkTextRecordEntrypoint {
constructor(address verifier) LinkTextRecordEntrypoint(verifier, "com.twitter") { }
/**
* @notice Constructor
* @param verifier The LinkHandleCommandVerifier contract address
* @param recordName ENS text record name (e.g. "com.twitter") — the key in setText(node, key, value)
* @param platformName The platform name in the command (e.g. "Twitter")
*/
constructor(
address verifier,
string memory recordName,
string memory platformName
)
LinkTextRecordEntrypoint(verifier, recordName, platformName)
{ }

/**
* @inheritdoc LinkTextRecordEntrypoint
Expand Down
19 changes: 14 additions & 5 deletions src/entrypoints/LinkTextRecordEntrypoint.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { IVerifier } from "../interfaces/IVerifier.sol";
import { EnsUtils } from "../utils/EnsUtils.sol";

struct TextRecord {
string platformName;
string ensName;
string value;
bytes32 nullifier;
Expand All @@ -20,7 +21,8 @@ struct TextRecord {
abstract contract LinkTextRecordEntrypoint is IEntryPoint, ITextRecordVerifier {
using EnsUtils for bytes;

bytes32 private immutable _KEY;
bytes32 private immutable _recordNameHash;
bytes32 private immutable _platformNameHash;

// link text record command verifier
address public immutable VERIFIER;
Expand All @@ -34,9 +36,12 @@ abstract contract LinkTextRecordEntrypoint is IEntryPoint, ITextRecordVerifier {
error InvalidCommand();
error NullifierUsed();

constructor(address verifier, string memory keyName) {
/// @param recordName ENS text record name (e.g. "com.twitter") — the key in setText(node, key, value)
/// @param platformName Platform name in the command (e.g. "x")
constructor(address verifier, string memory recordName, string memory platformName) {
VERIFIER = verifier;
_KEY = keccak256(bytes(keyName));
_recordNameHash = keccak256(bytes(recordName));
_platformNameHash = bytes(platformName).length == 0 ? bytes32(0) : keccak256(bytes(platformName));
}

/**
Expand All @@ -47,6 +52,10 @@ abstract contract LinkTextRecordEntrypoint is IEntryPoint, ITextRecordVerifier {
function entrypoint(bytes memory data) external {
TextRecord memory record = _extractTextRecord(data);

if (_platformNameHash != bytes32(0) && keccak256(bytes(record.platformName)) != _platformNameHash) {
revert InvalidCommand();
}

if (_isUsed[record.nullifier]) {
revert NullifierUsed();
}
Expand Down Expand Up @@ -81,8 +90,8 @@ abstract contract LinkTextRecordEntrypoint is IEntryPoint, ITextRecordVerifier {
* @inheritdoc ITextRecordVerifier
*/
function verifyTextRecord(bytes32 node, string memory key, string memory value) external view returns (bool) {
// this verifier only supports this specific text record
if (keccak256(bytes(key)) != _KEY) {
// this verifier only supports this specific text record (key must match constructor recordName)
if (keccak256(bytes(key)) != _recordNameHash) {
revert UnsupportedKey();
}
string memory storedTextRecord = textRecord[node];
Expand Down
17 changes: 13 additions & 4 deletions src/verifiers/LinkEmailCommandVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ import { TextRecord } from "../entrypoints/LinkTextRecordEntrypoint.sol";
/**
* @notice Enum representing the indices of command parameters in the command template
* @dev Used to specify which parameter to extract from the command string
* @param ENS_NAME = 0
* @param PLATFORM_NAME = 0
* @param ENS_NAME = 1
*/
enum CommandParamIndex {
PLATFORM_NAME,
ENS_NAME
}

Expand Down Expand Up @@ -79,6 +81,11 @@ contract LinkEmailCommandVerifier is EmailAuthVerifier {
PublicInputs memory publicInputs = _unpackPublicInputs(publicInputsFields);
return LinkEmailCommand({
textRecord: TextRecord({
platformName: string(
CommandUtils.extractCommandParamByIndex(
_getTemplate(), publicInputs.maskedCommand, uint256(CommandParamIndex.PLATFORM_NAME)
)
),
// ensName is extracted from the command
ensName: string(
CommandUtils.extractCommandParamByIndex(
Expand All @@ -95,8 +102,10 @@ contract LinkEmailCommandVerifier is EmailAuthVerifier {
}

function _getMaskedCommand(LinkEmailCommand memory command) private pure returns (string memory) {
bytes[] memory commandParams = new bytes[](1);
commandParams[0] = abi.encode(command.textRecord.ensName);
bytes[] memory commandParams = new bytes[](2);
commandParams[0] = abi.encode(command.textRecord.platformName);
commandParams[1] = abi.encode(command.textRecord.ensName);

return CommandUtils.computeExpectedCommand(commandParams, _getTemplate(), 0);
}

Expand All @@ -105,7 +114,7 @@ contract LinkEmailCommandVerifier is EmailAuthVerifier {

template[0] = "Link";
template[1] = "my";
template[2] = "email";
template[2] = CommandUtils.STRING_MATCHER;
template[3] = "to";
template[4] = CommandUtils.STRING_MATCHER;

Expand Down
16 changes: 12 additions & 4 deletions src/verifiers/LinkHandleCommandVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@ import { HandleVerifier, LinkHandleCommand, PublicInputs, TextRecord } from "./H
/**
* @notice Enum representing the indices of command parameters in the command template
* @dev Used to specify which parameter to extract from the command string
* @param ENS_NAME = 0
* @param PLATFORM_NAME = 0
* @param ENS_NAME = 1
*/
enum CommandParamIndex {
PLATFORM_NAME,
ENS_NAME
}

Expand Down Expand Up @@ -65,6 +67,11 @@ contract LinkHandleCommandVerifier is HandleVerifier {
PublicInputs memory publicInputs = _unpackPublicInputs(publicInputsFields);
return LinkHandleCommand({
textRecord: TextRecord({
platformName: string(
CommandUtils.extractCommandParamByIndex(
_getTemplate(), publicInputs.command, uint256(CommandParamIndex.PLATFORM_NAME)
)
),
// ensName is extracted from the command
ensName: string(
CommandUtils.extractCommandParamByIndex(
Expand All @@ -81,8 +88,9 @@ contract LinkHandleCommandVerifier is HandleVerifier {
}

function _getCommand(LinkHandleCommand memory command) private pure returns (string memory) {
bytes[] memory commandParams = new bytes[](1);
commandParams[0] = abi.encode(command.textRecord.ensName);
bytes[] memory commandParams = new bytes[](2);
commandParams[0] = abi.encode(command.textRecord.platformName);
commandParams[1] = abi.encode(command.textRecord.ensName);

return CommandUtils.computeExpectedCommand(commandParams, _getTemplate(), 0);
}
Expand All @@ -92,7 +100,7 @@ contract LinkHandleCommandVerifier is HandleVerifier {

template[0] = "Link";
template[1] = "my";
template[2] = "x";
template[2] = CommandUtils.STRING_MATCHER;
template[3] = "handle";
template[4] = "to";
template[5] = CommandUtils.STRING_MATCHER;
Expand Down
Loading
Loading