A language for collaboratively summoning computations.
Based on ValueScript.
cargo build
export PATH="$PATH:$PWD/target/debug"
summonc main.ts
This will generate the circuit in bristol format at output/circuit.txt
and a description of the inputs, outputs, and constants at output/circuit_info.json
.
You can also produce boolean circuits by adding --boolify-width 16
. (See boolify for more about boolean circuits.)
// examples/loopAdd.ts
const iterations = 3;
export default function main(input: number) {
let res = 0;
for (let i = 0; i < iterations; i++) {
res += input;
}
return res;
}
summonc examples/loopAdd.ts
# output/circuit.txt
2 3
1 1
1 1
2 1 0 0 1 AAdd
2 1 1 0 2 AAdd
// output/circuit_info.json
{
"input_name_to_wire_index": {
"input": 0
},
"constants": {},
"output_name_to_wire_index": {
"main": 2
}
}
Building a circuit from a program with a fixed path is relatively straightforward. The real power of Summon is its ability to handle signal-dependent branches - where the program follows a different path depending on the input. For example:
// examples/greaterThan10.ts
export default function main(x: number) {
if (x > 10) {
return 10;
}
return 0;
}
2 1 0 1 2 AGt
2 1 2 1 3 AMul
Above, the constant 10 is used for wire 1, so the circuit is output = (x > 10) * 10
.
Summon can also handle more complex branching, so you can use loops and even things like
continue
, break
, and switch
. You can also conditionally throw exceptions as long as you
catch them.
To achieve this, Summon has a general solution to handle any conditional jump instruction. A conditional jump generates a new evaluation branch, and each branch tracks a multiplier signal. Summon dynamically manages these branches and merges them when they reach the same location.
However, it is easy to write programs which branch indefinitely and never consolidate into a single fixed circuit. Programs like this become infinite loops:
for (let i = 0; i < input; i++) {
sum += i;
}
A traditional runtime can terminate shortly after i
reaches input
, but because input
isn't
known during compilation, Summon will get stuck in a loop as it adds more and more circuitry
to handle larger and larger values of input
forever.
- You can't use a signal as an array index
- Compile-time number operations use f64
- Math functions don't work with signals
- You have to write your own versions of
Math.min
,Math.max
, etc
- You have to write your own versions of
If you'd like to try your hand at Summon but you're not sure where to start, I have prepared some exercises you might find interesting:
- Check Supermajority
- Approval Voting
- TODO: exercise with in-between difficulty
- Sneaky Tic-Tac-Toe
- Asset Swap
- Poker Hands
The circuits generated by Summon are intended for MPC. When performing MPC, you use cryptography to collaboratively compute the output of a function without anyone seeing each other's inputs or any of the intermediary calculations. It's like summoning the result with magic.