One of the goals I have for AirScript is to make the language fully composable and enable writing modular “gadgets”. But as I’ve been thinking of how to accomplish this, I realized that AirScript is not the right level for where code composition should happen. There are just too many high-level constructs (and more are on the way) which makes code composition non-trivial.

Enter AirAssembly, which is a low-level language for encoding Algebraic Intermediate Representation (AIR) of computations. The goal of the language is to provide a minimum number of constructs required to fully express AIR for an arbitrary computation, and to make code composition much much simpler.

Unlike AirScript, AirAssembly is intended to be a compilation target for higher-level languages (of which AirScript will be one, but maybe other languages will emerge over time). I’m also hoping that AirAssembly could become a common language understood by various STARK libraries. So, the model could be something like this:

I’ve just published the first draft of AirAssembly specifications, and would love to get feedback/comments from people working with or interested in STARKs.

Also, here is the obligatory MiMC example written in AirAssembly:

A more sophisticated example of AirAssembly for Poseidon hash function can be found here.

Next, I’m planning to integrate the runtime into genSTARK.

One thing AirAssembly doesn’t yet support is “long-range” constraints. I’d love to add support for these as I think that opens up some interesting use cases. If anyone has any thoughts about long-range constraints (or any other aspect of AirAssembly), would love to hear them.

I’ve just released a new version of AirAssembly (v0.2). Notable changes include:

A single AirAssembly module can now contain AIR for many computations. This will enable “library” modules which will export different types of computations (e.g. hash functions, signature verification etc.).

It is now possible to define module-level functions to encapsulate common algebraic expressions. This makes code much more compact.

AirAssembly specs now include initial support for “long-range” constraints - thought, the compiler/runtime doesn’t handle them yet.

Here is how AirAssembly module for MiMC computation looks like now:

genSTARK has also been updated to work with AirAssembly back-end, though, the changes haven’t been merged to the master yet (if anyone is curious, they are in this PR).

I’ve just released a new version of AirScript (v0.6) and genSTARK library (v0.7). The biggest thing is that now AirScript gets compiled into an AirAssembly module, and then genSTARK creates a STARK from this AirAssembly module.

In fact, genSTARK can now instantiate STARKs from either AirScript or AirAssembly source code. This will help with making AirScript modular/composable - which is what I’m planning to do next.

Other notable change is that now AirScript supports naming of input and readonly registers. So, for example, a MiMC STARK in AirScript can be written like this:

define MiMC over prime field (2^128 - 9 * 2^32 + 1) {
const alpha: 3;
// define cyclic readonly register
static round_constant: cycle [42, 43, 170, 2209, 16426, 78087, 279978, 823517];
// require a single secret input
secret input start_value: element[1];
// transition function definition
transition 1 register {
for each (start_value) {
init { yield start_value; }
for steps [1..8192] {
yield $r0^3 + round_constant;
}
}
}
// transition constraint definition
enforce 1 constraint {
for all steps {
enforce transition($r) = $n;
}
}
}

More sophisticated examples (hash functions, Merkle proofs) can be found here and here.

Thanks! I have some examples here but nothing like a full-blown tutorial yet.

One of the reasons for this is that the language is still evolving quite a bit and the tutorial would get obsolete pretty quickly. I think the things will stabilize after the next iteration, and I do have a tutorial on my TODO list after that