Blocky Attestation Service (Blocky AS) allows you to run custom functions in a Trusted Execution Environment (TEE) and receive attestations over their execution. In the Attesting Function Calls example, we showed how to attest a simple "Hello, World!" function call using the Blocky AS CLI. In this example, we show you how verify that attestation in a smart contract allowing it to take onchain actions based on the attested function output.
Install
npmby following these instructions.Clone the Blocky AS examples repository and navigate to the
on_chaindirectory by running:git clone --branch v0.1.0-beta.12 git@github.com:blocky/attestation-service-examples.git cd attestation-service-examples/on_chainInstall project dependencies by running:
npm install
In the Attesting a Function Calls example, we used Blocky AS to attest a simple "Hello, World!" function call and saved the attestations in out.json. Download it into the on_chain directory by running:
curl -o out.json https://docs.blocky.rocks/v0.1.0-beta.12/out.jsonFor this example, we have created a simple user contract in contracts/User.sol to verify a transitive attestation over a function call and emit its output.
contract User {
event AttestedFunctionCallOutput(string output);
address private enclAttAppPubKeyAddress;
function setEnclaveAttestedAppPubKey(
bytes calldata enclAttAppPubKey
)
public
{
enclAttAppPubKeyAddress = TAParserLib.publicKeyToAddress(
enclAttAppPubKey
);
}
function processTransitiveAttestedFunctionCall(
bytes calldata transitiveAttestation
)
public
{
TAParserLib.FnCallClaims memory claims;
claims = TAParserLib.verifyTransitiveAttestedFnCall(
enclAttAppPubKeyAddress,
transitiveAttestation
);
emit AttestedFunctionCallOutput(string(claims.Output));
}
}The User contract complements process of verifying function execution, where verify the properties of a Blocky AS server and its enclave attested application public key used to sign transitive attestations. The setEnclaveAttestedAppPubKey converts an enclave attested application public key into an address and stores it in the enclAttAppPubKeyAddress variable. Once the enclave attested application public key is set, the processTransitiveAttestedFunctionCall function uses the TAParserLib.verifyTransitiveAttestedFnCall function to verify that the transitiveAttestation was signed by enclAttAppPubKeyAddress and to parse out its claims. Finally, the processTransitiveAttestedFunctionCall emits claims.Output through the AttestedFunctionCallOutput event. At this point, you can extend the User contract to use the value of claims.Output to take further onchain actions.
Note that you can extend
setEnclaveAttestedAppPubKeyfunction to set other elements of the verification process your smart contract will accept such as,hash_of_codeorfunctionname. TheprocessTransitiveAttestedFunctionCallcan then check these against the verifiedclaimsof thetransitiveAttestationas described in Step 5 of the Attesting Function Calls example.
To verify the output of the WASM function call in a smart contract, we extract from out.json the enclave attested application public key of the Blocky AS server and the transitive attestation of function call and pass them to the User contract functions executed in a local Hardhat testnet.
We define the "User contract test" in test/user.ts, which deploys the User contract, calls its functions with the enclave attested application public key and transitive attestation extracted from out.json, and checks that the contract emits the AttestedFunctionCallOutput event with "Hello, World!" as input.
You can invoke the test by running:
TA_FILE=$(realpath out.json) npx hardhat test --grep "User contract"Compiled 3 Solidity files successfully (evm target: paris).
User contract test
processTransitiveAttestedFunctionCall emitted AttestedFunctionCallOutput(Hello, World!)
✔ Verify transitive attested function call (637ms)
1 passing (639ms)