# Attesting Function Calls

The Blocky Attestation Service `attest-fn-call` command allows you to submit a
function call to a TEE for execution. Below we walk you through a simple
"hello world" example to use Block AS to create an attestation for a function
call.

## Setup

- Install the Blocky AS CLI by following the
[setup instructions](/attestation-service/v0.1.0-beta.4/setup)
in the Blocky AS documentation.
- Make sure you also have
[Docker](https://www.docker.com/) and [jq](https://jqlang.org/) installed on
your system.
- Clone our
[https://github.com/blocky/attestation-service-examples/tree/release/v0.1.0-beta.4](https://github.com/blocky/attestation-service-examples/tree/release/v0.1.0-beta.4)
repository and navigate to the `hello_world_attest_fn_call` directory.

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


## Quick Start

To run this example, call:


```bash
make run
```

You will see the following output extracted from a Blocky AS response:


```
Log:
Writing "Hello, World!" to host

Output:
Hello, World!
```

## Walkthrough

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

Our first goal is to 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 open
[main.go](https://github.com/blocky/attestation-service-examples/tree/release/v0.1.0-beta.4/hello_world_attest_fn_call/main.go)
you'll see our function there:


```go
//export helloWorld
func helloWorld(inputPtr uint64, secretPtr uint64) uint64 {
	msg := "Hello, World!"

	basm.Log(fmt.Sprintf("Writing \"%s\" to host\n", msg))

	return basm.WriteToHost([]byte(msg))
}
```

You will notice a few things:

- The `helloWorld` function is exported 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 uses `basm`
[Blocky Attestation Service WASM Go SDK](https://github.com/blocky/basm-go-sdk/tree/v0.1.0-beta.4)
`basm.Log` function to write a message to the Blocky AS server log,
maintained separately for each function invocation. You can log messages
to debug or monitor your function's behavior.
- The function calls `basm.WriteToHost` 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 first need to compile
it into a WASM file. If you inspect the `build` target in the
[Makefile](https://github.com/blocky/attestation-service-examples/tree/release/v0.1.0-beta.4/hello_world_attest_fn_call/Makefile),
you'll see the build command:


```bash
@docker run --rm \
  -v .:/src \
  -w /src \
  tinygo/tinygo:0.31.2 \
  tinygo build -o tmp/x.wasm -target=wasi ./...
```

where we use `docker` to run [`tinygo`](https://tinygo.org/) to compile
[main.go](https://github.com/blocky/attestation-service-examples/tree/release/v0.1.0-beta.4/hello_world_attest_fn_call/main.go)
to WASM and save it to `tmp/x.wasm`. You can build our
function by calling:


```bash
make build
```

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

To invoke our function, we first need to define an invocation template.
We have one set up already in
[fn-call.json](https://github.com/blocky/attestation-service-examples/tree/release/v0.1.0-beta.4/hello_world_attest_fn_call/fn-call.json)
that looks like:


```json
{
  "code_file": "tmp/x.wasm",
  "function": "helloWorld"
}
```

where `code_file` is the path to the WASM file we compiled earlier, 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`.
If you inspect the `run` target in the
[Makefile](https://github.com/blocky/attestation-service-examples/tree/release/v0.1.0-beta.4/hello_world_attest_fn_call/Makefile),
you'll see the
command:


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

where we use `cat` to read the
[fn-call.json](https://github.com/blocky/attestation-service-examples/tree/release/v0.1.0-beta.4/hello_world_attest_fn_call/fn-call.json),
pipe it to `bky-as attest-fn-call`, and save the output to `tmp/out.json`.

So then to run our function, you can call:


```bash
make run
```

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.4/hello_world_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 demo 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.4/setup#configuration)
in our documentation.

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

The `run` target will extract the log and the attested output of the function
call.
After running:


```bash
make run
```

you should see:


```
Log:
Writing "Hello, World!" to host

Output:
Hello, World!
```

To dive deeper, let's again look at the `run` target in the
[Makefile](https://github.com/blocky/attestation-service-examples/tree/release/v0.1.0-beta.4/hello_world_attest_fn_call/Makefile).
There you will see that we save the output of the `bky-as attest-fn-call`
command to `tmp/out.json`, which contains:


```json
{
  "enclave_attested_application_public_key": {
    "enclave_attestation": "eyJQbGF0Zm9ybSI6InBsYWl...",
    "claims": {
      "enclave_measurement": {
        "Platform": "plain",
        "Code": "plain"
      },
      "public_key": {
        "curve_type": "p256k1",
        "data": "BN3/W1LNadnQ/AUWabtYJw0z58d4fC+oN83SlI+qUYShcUnYY67tlkE8fDnOa+pRLhaiGzvFUYguCKL/Bqo5hH0="
      }
    }
  },
  "transitive_attested_function_call": {
    "transitive_attestation": "WyJXeUpaZW14cVRucFJl...",
    "claims": {
      "hash_of_code": "c9c7439eb4aa0b3905f84654c6cf07fa9edf5730f5a5252086ece67c0b4dcc50fc7605cae70849799124aaf87332ab2a31bb1b7b9bdb52233ef4850899ebd15a",
      "function": "helloWorld",
      "hash_of_input": "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26",
      "output": "SGVsbG8sIFdvcmxkIQ==",
      "hash_of_secrets": "9375447cd5307bf7473b8200f039b60a3be491282f852df9f42ce31a8a43f6f8e916c4f8264e7d233add48746a40166eec588be8b7b9b16a5eb698d4c3b06e00"
    },
    "logs": "V3JpdGluZyAiSGVsbG8sIFdvcmxkISIgdG8gaG9zdAo="
  }
}
```

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.4/hello_world_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.4/hello_world_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` 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.4/concepts#attestations-in-the-blocky-attestation-service)
section in our documentation.

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
- `function`: The name of the function executed by the Blocky AS server
- `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.
- `hash_of_secrets`: The hash of the secrets used by the function. In this
example this is the hash of the empty string, since we didn't specify any
secrets.
- `output`: The output of the function encoded in base64.


Finally, the `logs` field contains the logs generated by the function execution
and encoded in base64. Notice that while `output` is a part of the attested
`claims`, the `logs` are not attested and are only a part of the server response.

If you look at the `run` target in the [Makefile](https://github.com/blocky/attestation-service-examples/tree/release/v0.1.0-beta.4/hello_world_attest_fn_call/Makefile)
again, you will see that we use `jq` to extract the `output` and the `logs`
fields from `tmp/out.json` and decode them from base64.