---
title: ADR-006
id: adr-006
displayed_sidebar: resourcesSidebar
---
- **Author(s):** [Josh Long](https://github.com/joshLong145)
- **Last Updated:** June 21, 2022
- **Status:** Draft
- **Deployment:** `integrate/adr-006`
# ADR-006: Deployable Functions
## Introduction
Implement user defined functions invokable over HTTP within Highway.
## Abstract
The goal of user-defined functions is to allow for custom-defined behavior, defined by users which are accessible via `HTTP`.
These functions will all be accessible over a single endpoint, predefined within the highway.
When a request is sent to a static endpoint, containing the desired name of the invokable function, the function will be then invoked, with a single parameter queried from `ipfs` by the given `CID` in the declaration of the url.
## User functions
A User `Defined Function` is repersented by a single `binary` file which is assumed to be executable, and corresponding `callback Urls` associated with said executable file. Said functions are not permitted to return data to the caller directly, but rather the outer managment of the defined function will provide data to the given `urls` as `base64 encoded` representations as to not permit users to modify the system state of any `highway` node directly.
### Function definition format
The user's defined function is assumed to be precompiled into binary format. Said Binary is `jailed` as to resrtrict privileges on the execution enviorment to the host.
Currently, the executable options are more appealing as it is easier to sandbox a plain binary into a ‘jail’ rather than implementing sandboxing around a reflection execution implementation.
Below is a primitive definition for a user-defined function.
Said binary is stored within the highway node's `ipfs` storage with the following file contents as a blob of `JSON`
```go=
UserFunction {
did string // did from defintion
file []bytes // file as a byte encoding
parameters: map[string]string // not the value string is the "type"
}
```
> In the above definition, the total size of the file stored for a user function would be the total bytes of the array and the did string of the owner.
> This data would be stored on IPFS incurring the cost of file storage and passing that on to the uploader of the function.
Once a function is associated with a name and provided to the highway, a function will then have the association of label → function.
Each function will be a single relation to the user-given function.
Meaning a function can be resolved via its name `name` but a function cannot resolve its name, as the function is not explicitly required to have an associative name that matches its function name.
```go=
{
did: string
ref: cid
isActive: boolean
}
```
> The above model will be stored within the chain upon `creation` and `update`. This chain store will incur a cost on the uploader. Later changing the function to inactive will also incur a cost on chain.
The above model is then stored as a file in `IPFS` queriable by the returned `CID`.
## URL Schema
User Defined functions within the Highway will have a single entry point.
`/sonr/functions/invoke/{version}/{label}`
Where `label` is defined when the definition of the function is created.
### params to a user defined function over URL
callback? (base64 encoding).
cid? (id of the content from a highway node you wish to provide to a function)
the above URL has two params
| Name | Type | Description |
| --- | --- | --- |
| queryCid | string | Content ID to be retrieved from file storage (object, blob) |
| returnData | string | A `URL` that will be called and given the returned data from a function|
## Function Parameters
Parameters to functions will be nameless and of type `string`. the provided data will be deserailized to the described types and given to functions as what they are specified to be in the delceration upon creation. Parameters to functions will be applied in the order as they are provided, content queried by the `CID` provided URL when the function is invoked will be the last parameter to the function. The function implementor is responsible for the mapping of the parameters based on the index when implementing.
## Returning data from a user defined function
User defined functions cannot modify the state of `highways`, meaning data stored within the network. Instead one or many `callback URLs` are specifiable, allowing for data to be sent to said urls through `url encoding` data return by any function must be `encodable` to `Base64` standard or data will not be sent.
The `callback URLs` can be either an external resource outside of the network of highways, or can be another function defined on the highway.
## Invoking a User Defined Function
A function that's invoked should have the following defined within the `body` of the `HTTP` request
```=
{
did string // owner did
label: string // file as a byte encoding
cid: string // identifier of the function stored within ipfs.
parameters: map[string]string
callbackURLS: string[]
}
```
The return value will simply be an empty response body with an `HTTP` status.
When a function is "invoked" we will use one of the following strategies for calulating cost for a given function's invokation.
<table>
<tr>
<th></th>
<th>Description</th>
<th>Formula</th>
<th>User Pays</th>
<th>Highway Runner Gets</th>
<th>Function Writer Gets</th>
</tr>
<tr>
<td>Static Cost Functions</td>
<td>Cost is staticly defined at function creation time. The run time cost is added in addition to the cost paid by the caller</td>
<td>total_cost = static_cost + runtime_fees</td>
<td>total_cost</td>
<td>runtime_fees</td>
<td>static_cost</td>
</tr>
<tr>
<td>Variable Cost Functions</td>
<td>
Cost is defined when the function is running. There is a max and min cost that can be paid from the caller's wallet predefined in the function definition. The caller will also need to fund a transaction to refund the remainder
of the gas fees to caller.
</td>
<td>total_cost = variable_cost + runtime_fees + gas_fees</td>
<td>total_cost</td>
<td>runtime_fees</td>
<td>variable_cost</td>
</tr>
<tr>
<td>"Free" Functions</td>
<td>The function only costs as much as the runtime_fees</td>
<td>total_cost = runtime_fees</td>
<td>total_cost</td>
<td>runtime_fees</td>
<td>N/A</td>
</tr>
</table>
> Static and Varible functions are useful when the function needs to make its own interaction with the chain or fund calls within.
## Models and Methods (Highway)
The following methods will be added to `Highway` as a module within `x`
### Methods
#### CreateFunction()
Creates a new function with the provided `label` and `definition` (function converted to `bytes`)
```go=
type FunctionDefiniton struct {
label string
did string
definition []byte
parameters: map[string]type
}
```
**Returns**
```json=
{
"code": int,
"did": "string"
"cid": "string"
}
```
#### UpdateFunction()
```go=
type FunctionDefiniton struct {
label string
did string
definition []byte
}
```
> Updating a function does not remove the previous function defintion, as there could be reliance on said function. Updating a function creates a new instance of an already defined function by requiring a new version specified in the URL.
**Returns**
```json
{
"code": int,
"did": "string"
"cid": "string"
}
```
## CLI Commands
The CLI will need a single root level command called `function`. function will have the following two sub commands
| Name | params | Description |
| --- | --- | --- |
| add | "name" "path-to-binary" | Adds a single function to a defined name |
| remove | "name" | Removes user defined function from the function table |
## Diagrams
[
](https://www.figma.com/embed?embed_host=share&url=https%3A%2F%2Fwww.figma.com%2Ffile%2Fv9E6Om23rm80JROFHVnr31%2FHighway-sdk-user-defined-functions-(non-faas)%3Fnode-id%3D0%253A1)