Skip to content

A language for building arithmetic circuits based on TypeScript

License

Notifications You must be signed in to change notification settings

voltrevo/summon

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

57 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Summon

A language for collaboratively summoning computations.

Based on ValueScript.

Setup

cargo build
export PATH="$PATH:$PWD/target/debug"

Usage

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.)

Example

// 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
  }
}

Signal-Dependent Branching

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.

Limitations

  • 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

Exercises

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:

Why "Summon"

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.

About

A language for building arithmetic circuits based on TypeScript

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages