# Attesting Function Calls

Blocky Attestation Service (Blocky AS) allows you to run custom functions in a
Trusted Execution Environment (TEE) and receive attestations over their
execution. In this example, we show you how to attest a simple
"Hello, World!" function call using the Blocky AS CLI.

## Prerequisites

- Install the [Blocky AS CLI](/attestation-service/v0.1.0-beta.11/setup)
- Install the [Blocky Compiler](https://github.com/blocky/compiler)
- Make sure you have
[Docker](https://www.docker.com/),
[jq](https://jqlang.org/), and
[openssl dgst](https://docs.openssl.org/3.4/man1/openssl-dgst/)
installed on your system.
- Clone the Blocky AS
[examples repository](https://github.com/blocky/attestation-service-examples/tree/release/v0.1.0-beta.11)
and navigate to the `attest_fn_call` directory.

```bash
git clone git@github.com:blocky/attestation-service-examples.git
cd attestation-service-examples/attest_fn_call
```


## Quick Start

To attest a simple function call using Blocky AS, follow these steps:

1. Define a `helloWorld` function in
[main.go](https://github.com/blocky/attestation-service-examples/tree/release/v0.1.0-beta.11/attest_fn_call/main.go):

2. Compile
[main.go](https://github.com/blocky/attestation-service-examples/tree/release/v0.1.0-beta.11/attest_fn_call/main.go)
to WebAssembly (WASM):

```bash
bky-c build --reproducible . ./main.wasm
```
3. Invoke the function on a Blocky AS server with the `bky-as` CLI and save
its response to `out.json`:

```bash
cat fn-call.json | bky-as attest-fn-call > out.json
```
4. Parse the attested function call output from `out.json`:

```bash
jq -r '.transitive_attested_function_call.claims.output | @base64d ' out.json
```
which will print the output of the `helloWorld` function:

```
Hello, World!
```


## Full Walkthrough

### Step 1: Create a function that returns a "Hello, World!" message.

Let's create a simple function that returns a `"Hello, World!"`
message. We will write this function in Go and compile it to WebAssembly (WASM)
to run on the Blocky AS server. If you look at
[main.go](https://github.com/blocky/attestation-service-examples/tree/release/v0.1.0-beta.11/attest_fn_call/main.go)
in this example's repository folder, you'll see our function there:

helloWorld
A few things to notice:

- The `helloWorld` function is tagged with the `//export` comment, so that it
can be invoked by the Blocky AS server in a WASM runtime.
- The function takes two `uint64` arguments and returns a `uint64`. These are
fat pointers to shared memory managed by the Blocky AS server, where the first
32 bits are a memory address and the second 32 bits are the size of the data.
The memory space is sandboxed and shared between the TEE host program (Blocky
AS server) and the WASM runtime (your function). The `inputPtr` and
`secretPtr` arguments carry user-defined function input and secrets,
though we don't make use of them in this example. The output of the function
is also a memory pointer, whose value will be returned to the user.
- The function calls the `basm`
[Blocky Attestation Service WASM Go SDK](https://github.com/blocky/basm-go-sdk/tree/v0.1.0-beta.11)
`WriteToHost` function to write a byte array (serialized from
`msg`) to shared memory. The host (Blocky AS server) will create an
attestation over that array as a part of its response.


### Step 2: Compile the function to WebAssembly (WASM)

To invoke our function in the Blocky AS server, we need to compile
it to WASM. If you inspect the `main.wasm` target in the
[Makefile](https://github.com/blocky/attestation-service-examples/tree/release/v0.1.0-beta.11/attest_fn_call/Makefile),
you'll see a series of commands that compile
[main.go](https://github.com/blocky/attestation-service-examples/tree/release/v0.1.0-beta.11/attest_fn_call/main.go)
to the `main.wasm` binary. You can build our function by calling:


```bash
bky-c build --reproducible . ./main.wasm
```

> Note that you can speed up the build time during development by dropping the
`--reproducible` flag, which will allow
`bky-c` to cache certain artifacts at the cost of reproducibility.


### Step 3: Invoke the function on the Blocky AS server

To invoke our function, we need to define an invocation template.
We set up the template in
[fn-call.json](https://github.com/blocky/attestation-service-examples/tree/release/v0.1.0-beta.11/attest_fn_call/fn-call.json),
which contains:


```json
{
  "code_file": "main.wasm",
  "function": "helloWorld"
}
```

where `code_file` is the path to the WASM we built in the previous step, and
`function` is the name of the exported function we want to call.

To invoke our function, we need to pass the invocation template to `bky-as` CLI
by calling:


```bash
cat fn-call.json | bky-as attest-fn-call > out.json
```

where we read and pipe the contents of
[fn-call.json](https://github.com/blocky/attestation-service-examples/tree/release/v0.1.0-beta.11/attest_fn_call/fn-call.json)
to the `bky-as attest-fn-call` command. The `bky-as` CLI will invoke
our function on a Blocky AS server and save its response to `out.json`.

> Note that the call to `bky-as attest-fn-call` will use the
[config.toml](https://github.com/blocky/attestation-service-examples/tree/release/v0.1.0-beta.11/attest_fn_call/config.toml)
configuration file. Its `host` field, set to `local-server`, will direct
`bky-as` to start a local, non-TEE instance of the Blocky AS server to run our
function in dev mode. You can confirm this by finding the following output:

```
🚀 Starting local server at http://127.0.0.1:8081 ...success
```
If you'd like to send our function for execution on a Blocky AS server hosted
on a TEE, you can follow the
[`bky-as` configuration instructions](/attestation-service/v0.1.0-beta.11/setup#configuration)
in our documentation.


### Step 4: Extract function output from the Blocky AS attestation

To extract the attested output of our `helloWorld` function, we need to parse
the `out.json` file generated in the previous step. The `out.json` file will
contain data similar to:


```json
{
  "enclave_attested_application_public_key": {
    "enclave_attestation": "eyJQbGF0Zm9ybSI6InBsY...",
    "claims": {
      "enclave_measurement": {
        "platform": "plain",
        "code": "plain"
      },
      "public_key": {
        "curve_type": "p256k1",
        "data": "BCwe5u7yz27GmJ4AakUAfDJHV7MRZnmvUh3apJ7HIuao2T/bh01pC20/h5SIhJGrCRV/znFAeh2XTJ/PyneJ5yA="
      }
    }
  },
  "transitive_attested_function_call": {
    "transitive_attestation": "AAAAAAAAAAAAAAAAAAAA...",
    "claims": {
      "hash_of_code": "9f644e9815fd94b44a0376718563353376b99feafd8fafe8ba1f59e746e073ea16388afb9be633566158dc62bc472ab8eaa39e44d4e0702797be34bc04f61fec",
      "function": "helloWorld",
      "hash_of_input": "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26",
      "output": "SGVsbG8sIFdvcmxkIQ==",
      "hash_of_secrets": "9375447cd5307bf7473b8200f039b60a3be491282f852df9f42ce31a8a43f6f8e916c4f8264e7d233add48746a40166eec588be8b7b9b16a5eb698d4c3b06e00"
    }
  }
}
```

The `enclave_attested_application_public_key` contains the `enclave_attestation`
over the Blocky AS server public key. The `transitive_attested_function_call`
section contains the `transitive_attestation` over the function call. The
`bky-as attest-fn-call` command verifies that the `enclave_attestation` has been
signed by either the TEE hardware manufacturer's private key, when the Blocky
AS server is running on an AWS Nitro Enclave TEE, or by a hardcoded development
private key, when the Blocky AS server is running locally. In this example, we
have set up
[config.toml](https://github.com/blocky/attestation-service-examples/tree/release/v0.1.0-beta.11/attest_fn_call/config.toml)
with `host = "local-server"`, which directs the `bky-as` to start a local
server. As a part of the verification process, the `bky-as` lists
`enclave_attested_application_public_key.claims` attested by the
`enclave_attestation`. You can confirm that `enclave_attestation` was produced
by a local Blocky AS server by seeing that
`enclave_attested_application_public_key.claims.enclave_measurement.platform`
is reported as `plain`. The `bky-as` CLI also checks that the measurement of
the Blocky AS server code, attested by the `enclave_attestation`, matches one in
the `acceptable_measurements` list in
[config.toml](https://github.com/blocky/attestation-service-examples/tree/release/v0.1.0-beta.11/attest_fn_call/config.toml).
Again, since we are running the Blocky AS server locally in this example, the
`enclave_attested_application_public_key.claims.enclave_measurement.code` is
reported as `plain`. Finally, the `bky-as` CLI extracts the enclave attested
application public key, generated by the Blocky AS server on startup, and uses
it to verify the signature of the `transitive_attestation` (ABI-encoded in the
above example) and extract its `claims`.
You can learn more about this process in the
[Attestations in the Blocky Attestation Service](/attestation-service/v0.1.0-beta.11/concepts#attestations-in-the-blocky-attestation-service)
and
[Verification Process](/attestation-service/v0.1.0-beta.11/verification#verification-process)
sections in our documentation.

## Step 5: Verify transitive attested function call output

The `claims` section contains attested information about the execution of
the function.
You can see:

- `hash_of_code`: The hash of the WASM code executed by the Blocky AS server.
In this example, this is the hash of the `main.wasm` file we compiled in
[Step 2](#step-2-compile-the-function-to-webassembly-wasm). You can verify
this by running:

```bash
BUILT_WASM_HASH=$(openssl dgst -sha3-512 main.wasm | awk '{print $2}')
ATTESTED_WASM_HASH=$(jq -r '.transitive_attested_function_call.claims.hash_of_code' out.json)
diff <(echo "$BUILT_WASM_HASH") <(echo "$ATTESTED_WASM_HASH")
```
When the `diff` command returns no output, it means that the hashes match.
> If the hashes don't match, check that you've used the `--reproducible` flag
during the `bky-c` WASM build process.
- `function`: The name of the function executed by the Blocky AS server.
To parse out the function name from `out.json`, run:

```bash
jq -r '.transitive_attested_function_call.claims.function' out.json
```
- `hash_of_input`: The hash of the input data used by the function. In this
example this is the hash of the empty string, since we didn't specify any
input. You can verify this by running:

```bash
BUILT_INPUT_HASH=$(echo -n "" | openssl dgst -sha3-512 | awk '{print $2}')
ATTESTED_INPUT_HASH=$(jq -r '.transitive_attested_function_call.claims.hash_of_input' out.json)
diff <(echo "$BUILT_INPUT_HASH") <(echo "$ATTESTED_INPUT_HASH")
```
- `hash_of_secrets`: The hash of the decrypted secrets used by the function. In
this example this is the hash of the serialized JSON empty value, `null`,
since we didn't specify any secrets. You can verify this by running:

```bash
BUILT_SECRETS_HASH=$(echo -n 'null' | openssl dgst -sha3-512 | awk '{print $2}')
ATTESTED_SECRETS_HASH=$(jq -r '.transitive_attested_function_call.claims.hash_of_secrets' out.json)
diff <(echo "$BUILT_SECRETS_HASH") <(echo "$ATTESTED_SECRETS_HASH")
```
- `output`: The output of the function encoded in base64. To parse out the
output of our `helloWorld` function, call:

```bash
jq -r '.transitive_attested_function_call.claims.output | @base64d ' out.json
```
You should see the expected output of out `helloWorld` function:

```
Hello, World!
```