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
1 change: 1 addition & 0 deletions contracts/ILCPClientErrors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ interface ILCPClientErrors {
error LCPClientZKDCAPRisc0ImageIdNotSet();
error LCPClientZKDCAPUnexpectedIntelRootCAHash();
error LCPClientZKDCAPOutputReportUnexpectedOperator(address actual, address expected);
error LCPClientZKDCAPInvalidOperator();

error LCPClientZKDCAPDisallowedTCBStatus();
error LCPClientZKDCAPDisallowedAdvisoryID();
Expand Down
25 changes: 25 additions & 0 deletions contracts/LCPClientZKDCAPBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,15 @@ abstract contract LCPClientZKDCAPBase is LCPClientBase {
message.operator_signature
);
}

// if the operators are set, the operator address must be non-zero and active
if (
clientStorage.clientState.operators.length != 0
&& !ensureActiveOperator(clientStorage.clientState, operator)
) {
revert LCPClientZKDCAPInvalidOperator();
}

if (output.operator != address(0) && output.operator != operator) {
revert LCPClientZKDCAPOutputReportUnexpectedOperator(operator, output.operator);
}
Expand Down Expand Up @@ -379,4 +388,20 @@ abstract contract LCPClientZKDCAPBase is LCPClientBase {
return (currentUpdated, false);
}
}

function ensureActiveOperator(ProtoClientState.Data storage clientState, address operator)
internal
view
returns (bool)
{
if (operator == address(0)) {
return false;
}
for (uint256 i = 0; i < clientState.operators.length; i++) {
if (address(bytes20(clientState.operators[i])) == operator) {
return true;
}
}
return false;
}
}
2 changes: 1 addition & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ src = 'contracts'
out = 'out'
libs = ['lib', 'node_modules']
optimizer = true
optimizer_runs = 8000
optimizer_runs = 2000
via-ir = false
ffi = true
ast = true
Expand Down
2 changes: 1 addition & 1 deletion lib/risc0-ethereum
Submodule risc0-ethereum updated 221 files
45 changes: 38 additions & 7 deletions test/LCPClientZKDCAPTest.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -575,11 +575,42 @@ contract LCPClientZKDCAPTest is BasicTest {
DCAPValidator.Output memory output = ZKDCAPTestHelper.qvOutput();
output.operator = op1.addr;
IbcLightclientsLcpV1ZKDCAPRegisterEnclaveKeyMessage.Data memory message = registerEnclaveKeyMessage(output);
vm.expectRevert(
abi.encodeWithSelector(
ILCPClientErrors.LCPClientZKDCAPOutputReportUnexpectedOperator.selector, address(0), output.operator
vm.expectRevert(abi.encodeWithSelector(ILCPClientErrors.LCPClientZKDCAPInvalidOperator.selector));
lc.zkDCAPRegisterEnclaveKey(clientId, message);
}

{
// if the operator signature is set by an unregistered operator, it should fail
DCAPValidator.Output memory output = ZKDCAPTestHelper.qvOutput();
IbcLightclientsLcpV1ZKDCAPRegisterEnclaveKeyMessage.Data memory message = registerEnclaveKeyMessage(output);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(
op2,
keccak256(
LCPOperator.computeEIP712ZKDCAPRegisterEnclaveKey(
clientState.zkdcap_verifier_infos[0], keccak256(ZKDCAPTestHelper.toBytes(output))
)
)
);
message.operator_signature = abi.encodePacked(r, s, v);
vm.expectRevert(abi.encodeWithSelector(ILCPClientErrors.LCPClientZKDCAPInvalidOperator.selector));
lc.zkDCAPRegisterEnclaveKey(clientId, message);
}

{
// if the operator signature and operator are set by an unregistered operator, it should fail
DCAPValidator.Output memory output = ZKDCAPTestHelper.qvOutput();
output.operator = op2.addr;
IbcLightclientsLcpV1ZKDCAPRegisterEnclaveKeyMessage.Data memory message = registerEnclaveKeyMessage(output);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(
op2,
keccak256(
LCPOperator.computeEIP712ZKDCAPRegisterEnclaveKey(
clientState.zkdcap_verifier_infos[0], keccak256(ZKDCAPTestHelper.toBytes(output))
)
)
);
message.operator_signature = abi.encodePacked(r, s, v);
vm.expectRevert(abi.encodeWithSelector(ILCPClientErrors.LCPClientZKDCAPInvalidOperator.selector));
lc.zkDCAPRegisterEnclaveKey(clientId, message);
}

Expand All @@ -589,7 +620,7 @@ contract LCPClientZKDCAPTest is BasicTest {
output.operator = op1.addr;
IbcLightclientsLcpV1ZKDCAPRegisterEnclaveKeyMessage.Data memory message = registerEnclaveKeyMessage(output);
(uint8 v, bytes32 r, bytes32 s) = vm.sign(
op2,
op3,
keccak256(
LCPOperator.computeEIP712ZKDCAPRegisterEnclaveKey(
clientState.zkdcap_verifier_infos[0], keccak256(ZKDCAPTestHelper.toBytes(output))
Expand All @@ -599,7 +630,7 @@ contract LCPClientZKDCAPTest is BasicTest {
message.operator_signature = abi.encodePacked(r, s, v);
vm.expectRevert(
abi.encodeWithSelector(
ILCPClientErrors.LCPClientZKDCAPOutputReportUnexpectedOperator.selector, op2.addr, op1.addr
ILCPClientErrors.LCPClientZKDCAPOutputReportUnexpectedOperator.selector, op3.addr, op1.addr
)
);
lc.zkDCAPRegisterEnclaveKey(clientId, message);
Expand All @@ -625,12 +656,12 @@ contract LCPClientZKDCAPTest is BasicTest {
}

{
// if both operator and operator signature are not set, it should succeed
// if both operator and operator signature are not set, it should fail
DCAPValidator.Output memory output = ZKDCAPTestHelper.qvOutput();
output.enclaveKey = address(2);
IbcLightclientsLcpV1ZKDCAPRegisterEnclaveKeyMessage.Data memory message = registerEnclaveKeyMessage(output);
vm.expectRevert(abi.encodeWithSelector(ILCPClientErrors.LCPClientZKDCAPInvalidOperator.selector));
lc.zkDCAPRegisterEnclaveKey(clientId, message);
assertEq(lc.getEKInfo(clientId, output.enclaveKey).operator, address(0));
}

{
Expand Down
29 changes: 27 additions & 2 deletions test/ZKDCAPVerifier.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {DCAPValidator} from "../contracts/DCAPValidator.sol";
contract ZKDCAPVerifierTest is BasicTest {
IRiscZeroVerifier verifier_rz11;
IRiscZeroVerifier verifier_rz12;
IRiscZeroVerifier verifier_rz30;

function setUp() public {
// ref. https://github.com/risc0/risc0-ethereum/blob/4fa7de055d461b7fa948eb56107b7a172459e8fc/contracts/src/groth16/ControlID.sol#L22
Expand All @@ -21,6 +22,11 @@ contract ZKDCAPVerifierTest is BasicTest {
hex"8cdad9242664be3112aba377c5425a4df735eb1c6966472b561d2855932c0469",
hex"04446e66d300eb7fb45c9726bb53c793dda407a62e9601618bb43c5c14657ac0"
);
// https://github.com/risc0/risc0/blob/61cfbaf57615b83854424f972f23e026970b4201/risc0/circuit/recursion/src/control_id.rs#L53-L59
verifier_rz30 = new RiscZeroGroth16Verifier(
hex"a54dc85ac99f851c92d7c96d7318af41dbe7c0194edfcc37eb4d422a998c1f56",
hex"04446e66d300eb7fb45c9726bb53c793dda407a62e9601618bb43c5c14657ac0"
);
}

/*
Expand All @@ -30,7 +36,7 @@ contract ZKDCAPVerifierTest is BasicTest {
"commit":"00000003000000000500906ed50000a1acc73eb45794fa1734f14d882e91925b6006f79d3bb2460df9d01b333d700900000000679885950000000067c00a9c15150b07ff800e000000000000000000000000000000000000000000000000000000000000000000000000000000000005000000000000000700000000000000813c146e403f203f2784fa222b3edeac70727dee21c0b08f74883aa189e7b0ed000000000000000000000000000000000000000000000000000000000000000083d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017dcf7408c72ebe9076aebbb208d2c85e62050db4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000e494e54454c2d53412d3030333334000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e494e54454c2d53412d3030363135000000000000000000000000000000000000"
}}
*/
function testVerify1() public view {
function testVerify11() public view {
verifier_rz11.verify(
hex"50bd1769039405f7898272862594bc436f08dab3e5c1200e0c44b542b462fe09bb2655b700ae0374f99c5b30f8580605267de7b5d121758ae405b5b378b588deca3042a70e22eefd598a4638d7c039ffb737f45dbee0152559f25c4dc0854ab7fd7cc2f52704dc9991d84e00c48d155b0d7fbfe2d307d1fb1a573c38083d86bea39e60191110517565779f631fc0028b82ff9b224bcc627bd6fd3ee1c1ffcea67e9e921c281abaaeacabff9fb74232c9ca2914ce6fe3ec9a4584c68a888339f2e6865c9f2bb57d5a38759c09ecb3f9f9f80fd582f23b7fb47495f783a8cc2eedb99ca18b0337102df4a2e325367d954ea5154f11c03f459551f849763d75ccad9d6665c5",
hex"200d1f40b5733d31e4f3bfb1f106351e878aea304b5c9e73690b9e18e2e77bb6",
Expand All @@ -49,7 +55,7 @@ contract ZKDCAPVerifierTest is BasicTest {
}
}
*/
function testVerify2() public view {
function testVerify12() public view {
verifier_rz12.verify(
hex"c101b42b2178a72a844649d14328eb6b7a650d6fe1640c1ef2fa887bcc755597229713fb2360369704b1c06c610e6a83dbdc31bb04e1cb5a8def9c7354fc34be7e74844301db3e4f8c2cef2a91df93e191e3138ac27dac03d1a2d2bc2e18330f712e65021d34cf95c2ff4134df2a04a726de5a8d8e535f10225f00046295f8b3d3b939a626e424d04c48c94aef79267457e375ce4670ef5eb5af2c3e8fea40c4905228e617130a7a0c1ac16ed030103b02f94c89f6f5935d8a581198df573c050ea63e331b6c494238c02ff85040e720621dd81fa6d1191098cf40ac05923398e58b213c197e62e6a4394b5b5134f9770ba31805e57c2c8635e921472936bab23a56c824",
hex"a7b6d5b9a35f9c4e9364e69728c87a4818fe56b361b5f5ff25bab7494074b50b",
Expand All @@ -59,6 +65,25 @@ contract ZKDCAPVerifierTest is BasicTest {
);
}

/*
{
"Risc0":{
"image_id":"27a8d21b54ce10b06901dca7de504f7421cfcad47bae69e8783e449519d99635",
"selector":"73c457ba",
"seal":"2708b796ffbe2beafb20f3c313f4e8c05f8b2c1d5320a10e0e40a38f44584b9d2f1f2b0dc953ab24d707b5664bf4a4ab4b7c13ce7303f46af3ce10021fbbe3950df800fe0b015d9ece18c61a1095dbf9b9043a4fd5d7ab0593532e727c9d48a80d0bc9a26dcc2e2426bfa7747dda3a64a563d14596d9ef81b3807b958492ba13164020246d455ce5c7864b7e98af1c19c593b3e4b1723384f17a9e272e52d9cf0ef7eea2b3f3ad8622099b96b2950c304c3acb826daf42456a6e858a8c56ae7c1b295ab9e1b12107427031951322955ba7a30c613797a82ae9ffdcef77d06d4924ba37eeb963abb404775a498a34bc2d2f9222482a9e69124858e69d6ee8ccdc",
"output":"0000000300000000050000000100606a000000d61f4e3d30011899d16131d4c940ef1f75ec53d7f9a70cbb3aab1f5ab0235b2b0000000068aea64900000000e8aea6484820f3376ae6b2f2034d3b7a4b48a778000000000000000000000000000000000000000000000000000000000000000005000000000000000700000000000000568b2634f9e30ab3df84ccc8a1fab58d87dcd02e02cbb62172ed4734215f0f38000000000000000000000000000000000000000000000000000000000000000083d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011770f0a82157d84d369a1935277fb8cca8b34e18000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000e494e54454c2d53412d3030333334000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e494e54454c2d53412d3030363135000000000000000000000000000000000000"
}
*/
function testVerify30() public view {
verifier_rz30.verify(
hex"73c457ba2708b796ffbe2beafb20f3c313f4e8c05f8b2c1d5320a10e0e40a38f44584b9d2f1f2b0dc953ab24d707b5664bf4a4ab4b7c13ce7303f46af3ce10021fbbe3950df800fe0b015d9ece18c61a1095dbf9b9043a4fd5d7ab0593532e727c9d48a80d0bc9a26dcc2e2426bfa7747dda3a64a563d14596d9ef81b3807b958492ba13164020246d455ce5c7864b7e98af1c19c593b3e4b1723384f17a9e272e52d9cf0ef7eea2b3f3ad8622099b96b2950c304c3acb826daf42456a6e858a8c56ae7c1b295ab9e1b12107427031951322955ba7a30c613797a82ae9ffdcef77d06d4924ba37eeb963abb404775a498a34bc2d2f9222482a9e69124858e69d6ee8ccdc",
hex"27a8d21b54ce10b06901dca7de504f7421cfcad47bae69e8783e449519d99635",
sha256(
hex"0000000300000000050000000100606a000000d61f4e3d30011899d16131d4c940ef1f75ec53d7f9a70cbb3aab1f5ab0235b2b0000000068aea64900000000e8aea6484820f3376ae6b2f2034d3b7a4b48a778000000000000000000000000000000000000000000000000000000000000000005000000000000000700000000000000568b2634f9e30ab3df84ccc8a1fab58d87dcd02e02cbb62172ed4734215f0f38000000000000000000000000000000000000000000000000000000000000000083d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011770f0a82157d84d369a1935277fb8cca8b34e18000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000e494e54454c2d53412d3030333334000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e494e54454c2d53412d3030363135000000000000000000000000000000000000"
)
);
}

function testParseOutputSWHardeningNeeded() public pure {
bytes memory outputBytes =
hex"0000000300000000050000001200906ed50000a1acc73eb45794fa1734f14d882e91925b6006f79d3bb2460df9d01b333d70090000000067b3f1fa0000000067db736115150b07ff800e00000000000000000000000000000000000000000000000000000000000000000000000000000000000500000000000000070000000000000026ae825ffce1cf9dcdf682614f4d36704e7bca087bbb5264aca9301d7824cec8000000000000000000000000000000000000000000000000000000000000000083d719e77deaca1470f6baf62a4d774303c899db69020f9c70ee1dfc08c7ce9e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001c170f98628b3a01b15654fbfaad1aaf3419b2c3c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000e494e54454c2d53412d3030333334000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e494e54454c2d53412d3030363135000000000000000000000000000000000000";
Expand Down