Skip to content

Commit

Permalink
zk verifier contract interface compatible with risczero, succinct, ot…
Browse files Browse the repository at this point in the history
…her zk-coprocessors we may support in the future
  • Loading branch information
preston4896 committed Nov 6, 2024
1 parent 0dc5733 commit 17faa2d
Show file tree
Hide file tree
Showing 10 changed files with 222 additions and 67 deletions.
80 changes: 50 additions & 30 deletions contracts/AutomataDcapAttestation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,56 @@
pragma solidity ^0.8.0;

import {IAttestation} from "./interfaces/IAttestation.sol";
import {BELE} from "./utils/BELE.sol";
import {IQuoteVerifier} from "./interfaces/IQuoteVerifier.sol";
import {IZKVerifier} from "./interfaces/IZKVerifier.sol";

import {Header} from "./types/CommonStruct.sol";
import {BELE} from "./utils/BELE.sol";
import "./types/Constants.sol";
import {Header} from "./types/CommonStruct.sol";
import {Ownable} from "solady/auth/Ownable.sol";

// ZK-Coprocessor imports:
import {IRiscZeroVerifier} from "risc0/IRiscZeroVerifier.sol";
import {Ownable} from "solady/auth/Ownable.sol";
import {ISP1Verifier} from "@sp1-contracts/ISP1Verifier.sol";

contract AutomataDcapAttestation is IAttestation, Ownable {
/// @notice RISC Zero verifier contract address.
IRiscZeroVerifier public riscZeroVerifier;
enum ZkCoProcessorType {
Unknown,
RiscZero,
Succinct
}

/// @notice The ImageID of the Risc0 DCAP Guest ELF
bytes32 public DCAP_RISC0_IMAGE_ID;
struct ZkCoProcessorConfig {
bytes32 dcapProgramIdentifier;
address zkVerifier;
}

contract AutomataDcapAttestation is IAttestation, IZKVerifier, Ownable {
mapping(ZkCoProcessorType => ZkCoProcessorConfig) _zkConfig;

mapping(uint16 quoteVersion => IQuoteVerifier verifier) public quoteVerifiers;

constructor(address risc0Verifier, bytes32 imageId) {
constructor() {
_initializeOwner(msg.sender);
riscZeroVerifier = IRiscZeroVerifier(risc0Verifier);
DCAP_RISC0_IMAGE_ID = imageId;
}

function setQuoteVerifier(address verifier) external onlyOwner {
IQuoteVerifier quoteVerifier = IQuoteVerifier(verifier);
quoteVerifiers[quoteVerifier.quoteVersion()] = quoteVerifier;
}

function updateRisc0Config(address risc0Verifier, bytes32 imageId) external onlyOwner {
riscZeroVerifier = IRiscZeroVerifier(risc0Verifier);
DCAP_RISC0_IMAGE_ID = imageId;
function setZkConfiguration(ZkCoProcessorType zkCoProcessor, ZkCoProcessorConfig memory config)
external
onlyOwner
{
_zkConfig[zkCoProcessor] = config;
}

function programIdentifier(uint8 zkCoProcessorType) external view override returns (bytes32) {
return _zkConfig[ZkCoProcessorType(zkCoProcessorType)].dcapProgramIdentifier;
}

function zkVerifier(uint8 zkCoProcessorType) external view returns (address) {
return _zkConfig[ZkCoProcessorType(zkCoProcessorType)].zkVerifier;
}

function verifyAndAttestOnChain(bytes calldata rawQuote)
Expand All @@ -55,30 +73,32 @@ contract AutomataDcapAttestation is IAttestation, Ownable {
(success, output) = quoteVerifier.verifyQuote(header, rawQuote);
}

// the journal output has the following format:
// serial_output_len (2 bytes)
// serial_output (VerifiedOutput) (SGX: 397 bytes, TDX: 597 bytes)
// current_time (8 bytes)
// tcbinfov2_hash
// qeidentityv2_hash
// sgx_intel_root_ca_cert_hash
// sgx_tcb_signing_cert_hash
// sgx_tcb_intel_root_ca_crl_hash
// sgx_pck_platform_crl_hash or sgx_pck_processor_crl_hash
function verifyAndAttestWithZKProof(bytes calldata journal, bytes calldata seal)
function verifyAndAttestWithZKProof(bytes calldata output, bytes calldata proofBytes)
external
view
override
returns (bool success, bytes memory output)
returns (bool success, bytes memory verifiedOutput)
{
riscZeroVerifier.verify(seal, DCAP_RISC0_IMAGE_ID, sha256(journal));
uint16 version = uint16(bytes2(journal[2:4]));
ZkCoProcessorType zkCoprocessor = ZkCoProcessorType(uint8(bytes1(proofBytes[0:1])));
ZkCoProcessorConfig memory zkConfig = _zkConfig[zkCoprocessor];

if (zkCoprocessor == ZkCoProcessorType.RiscZero) {
IRiscZeroVerifier(zkConfig.zkVerifier).verify(
proofBytes[1:], zkConfig.dcapProgramIdentifier, sha256(output)
);
} else if (zkCoprocessor == ZkCoProcessorType.Succinct) {
ISP1Verifier(zkConfig.zkVerifier).verifyProof(zkConfig.dcapProgramIdentifier, output, proofBytes[1:]);
} else {
revert Unknown_Zk_Coprocessor();
}

// verifies the output
uint16 version = uint16(bytes2(output[2:4]));
IQuoteVerifier quoteVerifier = quoteVerifiers[version];
if (address(quoteVerifier) == address(0)) {
return (false, bytes("Unsupported quote version"));
}

(success, output) = quoteVerifier.verifyJournal(journal);
(success, verifiedOutput) = quoteVerifier.verifyZkOutput(output);
}

function _parseQuoteHeader(bytes calldata rawQuote) private pure returns (Header memory header) {
Expand Down
16 changes: 0 additions & 16 deletions contracts/interfaces/IAttestation.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,4 @@ interface IAttestation {
* @dev can directly type cast the failed output as a string
*/
function verifyAndAttestOnChain(bytes calldata input) external returns (bool success, bytes memory output);

/**
* @param journal - The output of the Guest program, this includes:
* - VerifiedOutput struct
* - TcbInfo hash
* - QEID hash
* - RootCA hash
* - TCB Signing CA hash
* - Root CRL hash
* - Platform CRL hash
* - Processor CRL hash
* @param seal - The encoded cryptographic proof (i.e. SNARK).
*/
function verifyAndAttestWithZKProof(bytes calldata journal, bytes calldata seal)
external
returns (bool success, bytes memory output);
}
2 changes: 1 addition & 1 deletion contracts/interfaces/IQuoteVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ interface IQuoteVerifier {

function verifyQuote(Header calldata, bytes calldata) external view returns (bool, bytes memory);

function verifyJournal(bytes calldata) external view returns (bool, bytes memory);
function verifyZkOutput(bytes calldata) external view returns (bool, bytes memory);
}
34 changes: 34 additions & 0 deletions contracts/interfaces/IZKVerifier.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;

interface IZKVerifier {
// 51abd95c
error Unknown_Zk_Coprocessor();

/**
* @param zkCoprocessorType 0 - RiscZero, 1 - Succinct... etc.
* @return this is either the IMAGE_ID for RiscZero Guest Program or
* Succiinct Program Verifying Key
*/
function programIdentifier(uint8 zkCoprocessorType) external view returns (bytes32);

/**
* @notice get the contract verifier for the provided ZK Co-processor
*/
function zkVerifier(uint8 zkCoprocessorType) external view returns (address);

/**
* @param output - The output of the Guest program, this includes:
* - VerifiedOutput struct
* - RootCA hash
* - TCB Signing CA hash
* - Root CRL hash
* - Platform or Processor CRL hash
* @param proofBytes - abi-encoded tuple of:
* - The ZK Co-Processor Type
* - The encoded cryptographic proof (i.e. SNARK)).
*/
function verifyAndAttestWithZKProof(bytes calldata output, bytes calldata proofBytes)
external
returns (bool success, bytes memory verifiedOutput);
}
6 changes: 3 additions & 3 deletions contracts/verifiers/V3QuoteVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import "../bases/tcb/TCBInfoV2Base.sol";
contract V3QuoteVerifier is QuoteVerifierBase, TCBInfoV2Base {
constructor(address _router) QuoteVerifierBase(_router, 3) {}

function verifyJournal(bytes calldata journal) external view override returns (bool success, bytes memory output) {
function verifyZkOutput(bytes calldata outputBytes) external view override returns (bool success, bytes memory output) {
uint256 offset = 2 + MINIMUM_OUTPUT_LENGTH + ENCLAVE_REPORT_LENGTH;
success = checkCollateralHashes(offset + 72, journal);
success = checkCollateralHashes(offset + 72, outputBytes);
if (success) {
output = journal[2: offset];
output = outputBytes[2: offset];
} else {
output = bytes("Found one or more collaterals mismatch");
}
Expand Down
8 changes: 4 additions & 4 deletions contracts/verifiers/V4QuoteVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,19 @@ contract V4QuoteVerifier is QuoteVerifierBase, TCBInfoV3Base, TDXModuleBase {

constructor(address _router) QuoteVerifierBase(_router, 4) {}

function verifyJournal(bytes calldata journal) external view override returns (bool success, bytes memory output) {
function verifyZkOutput(bytes calldata outputBytes) external view override returns (bool success, bytes memory output) {
uint256 offset = 2;

bytes4 teeType = bytes4(journal[4:8]);
bytes4 teeType = bytes4(outputBytes[4:8]);
if (teeType == SGX_TEE) {
offset += MINIMUM_OUTPUT_LENGTH + ENCLAVE_REPORT_LENGTH;
} else if (teeType == TDX_TEE) {
offset += MINIMUM_OUTPUT_LENGTH + TD_REPORT10_LENGTH;
} else return (false, bytes("Unknown TEE type"));

success = checkCollateralHashes(offset + 72, journal);
success = checkCollateralHashes(offset + 72, outputBytes);
if (success) {
output = journal[2:offset];
output = outputBytes[2:offset];
} else {
output = bytes("Found one or more collaterals mismatch");
}
Expand Down
12 changes: 9 additions & 3 deletions forge-script/AttestationScript.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ contract AttestationScript is Script {
function deployEntrypoint() public {
vm.startBroadcast(deployerKey);

AutomataDcapAttestation attestation = new AutomataDcapAttestation(riscZeroVerifier, riscZeroImageId);
AutomataDcapAttestation attestation = new AutomataDcapAttestation();

console.log("Automata Dcap Attestation deployed at: ", address(attestation));

Expand All @@ -27,9 +27,15 @@ contract AttestationScript is Script {
AutomataDcapAttestation(attestationAddr).setQuoteVerifier(verifier);
}

function risc0Config(address risc0Verifier, bytes32 imageId) public {
function configureZk(uint8 zk, address verifierGateway, bytes32 programId) public {
address attestationAddr = vm.envAddress("DCAP_ATTESTATION");

ZkCoProcessorConfig memory config = ZkCoProcessorConfig({
dcapProgramIdentifier: programId,
zkVerifier: verifierGateway
});

vm.broadcast(deployerKey);
AutomataDcapAttestation(attestationAddr).updateRisc0Config(risc0Verifier, imageId);
AutomataDcapAttestation(attestationAddr).setZkConfiguration(ZkCoProcessorType(zk), config);
}
}
Loading

0 comments on commit 17faa2d

Please sign in to comment.