{"id":13648662,"url":"https://github.com/GuildOfWeavers/distaff","last_synced_at":"2025-04-22T11:32:55.459Z","repository":{"id":41498555,"uuid":"248854163","full_name":"GuildOfWeavers/distaff","owner":"GuildOfWeavers","description":"Zero-knowledge virtual machine written in Rust","archived":false,"fork":false,"pushed_at":"2023-03-17T11:40:11.000Z","size":1309,"stargazers_count":243,"open_issues_count":11,"forks_count":44,"subscribers_count":17,"default_branch":"master","last_synced_at":"2024-11-09T23:36:21.297Z","etag":null,"topics":["cryptography","stack-based","virtual-machine","zero-knowledge"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/GuildOfWeavers.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2020-03-20T21:20:11.000Z","updated_at":"2024-10-23T16:13:33.000Z","dependencies_parsed_at":"2024-01-14T10:59:32.010Z","dependency_job_id":"d5760dd7-5c3d-4924-8716-fd23df8019ea","html_url":"https://github.com/GuildOfWeavers/distaff","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GuildOfWeavers%2Fdistaff","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GuildOfWeavers%2Fdistaff/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GuildOfWeavers%2Fdistaff/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GuildOfWeavers%2Fdistaff/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GuildOfWeavers","download_url":"https://codeload.github.com/GuildOfWeavers/distaff/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250232411,"owners_count":21396640,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cryptography","stack-based","virtual-machine","zero-knowledge"],"created_at":"2024-08-02T01:04:26.265Z","updated_at":"2025-04-22T11:32:55.094Z","avatar_url":"https://github.com/GuildOfWeavers.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"# Distaff\nDistaff is a zero-knowledge virtual machine written in Rust. For any program executed on Distaff VM, a STARK-based proof of execution is automatically generated. This proof can then be used by anyone to verify that a program was executed correctly without the need for re-executing the program or even knowing what the program was.\n\n### Status\n**DO NOT USE IN PRODUCTION.** Distaff is in an alpha stage. This means that current functionality is incomplete, and there are known and unknown bugs and security flaws.\n\n## Usage\nDistaff crate exposes `execute()` and `verify()` functions which can be used to execute programs and verify their execution. Both are explained below, but you can also take a look at several working examples [here](https://github.com/GuildOfWeavers/distaff/blob/master/src/main.rs).\n\n### Executing a program \nTo execute a program on Distaff VM, you can use `execute()` function. The function takes the following parameters:\n\n* `program: \u0026Program` - the program to be executed. A program can be constructed manually by building a program execution graph, or compiled from Distaff assembly (see [here](#Writing-programs)).\n* `inputs: \u0026ProgramInputs` - inputs for the program. These include public inputs used to initialize the stack, as well as secret inputs consumed during program execution (see [here](#Program-inputs)).\n* `num_outputs: usize` - number of items on the stack to be returned as program output. Currently, at most 8 outputs can be returned.\n* `options: \u0026ProofOptions` - config parameters for proof generation. The default options target 120-bit security level.\n\nIf the program is executed successfully, the function returns a tuple with 2 elements:\n\n* `outputs: Vec\u003cu128\u003e` - the outputs generated by the program. The number of elements in the vector will be equal to the `num_outputs` parameter.\n* `proof: StarkProof` - proof of program execution. `StarkProof` implements `serde`'s `Serialize` and `Deserialize` traits - so, it can be easily serialized and de-serialized.\n\n#### Program inputs\nTo provide inputs for a program, you must create a [ProgramInputs](https://github.com/GuildOfWeavers/distaff/blob/master/src/programs/inputs.rs) object which can contain the following:\n\n* A list of public inputs which will be used to initialize the stack. Currently, at most 8 public inputs can be provided.\n* Two lists of secret inputs. These lists can be thought of as tapes `A` and `B`. You can use `read` operations to read values from these tapes and push them onto the stack.\n\nBesides the `ProgramInputs::new()` function, you can also use `ProgramInputs::from_public()` and `ProgramInputs:none()` convenience functions to construct the inputs object.\n\n#### Writing programs\nTo execute a program, Distaff VM consumes a [Program](https://github.com/GuildOfWeavers/distaff/blob/master/src/programs/mod.rs) object. This object contains an execution graph for the program, as well as other info needed to execute the program. There are two way of constructing a `Program` object:\n\n1. You can construct a `Program` object by manually building program execution graph from raw Distaff VM [instructions](docs/isa.md).\n2. You can compile [Distaff assembly](docs/assembly.md) source code into a `Program` object.\n\nThe latter approach is strongly encouraged because building programs from raw Distaff VM instructions is tedious, error-prone, and requires an in-depth understanding of VM internals. All examples throughout these docs use assembly syntax.\n\nA general description of Distaff VM is also provided 👉 [here](docs) 👈. If you are trying to learn how to write programs for Distaff VM, this would be a good place to start.\n\n#### Program execution example\nHere is a simple example of executing a program which pushes two numbers onto the stack and computes their sum:\n```Rust\nuse distaff::{ self, ProofOptions, ProgramInputs, assembly };\n\n// this is our program, we compile it from assembly code\nlet program = assembly::compile(\"begin push.3 push.5 add end\").unwrap();\n\n// let's execute it\nlet (outputs, proof) = distaff::execute(\n        \u0026program,\n        \u0026ProgramInputs::none(),     // we won't provide any inputs\n        1,                          // we'll return one item from the stack\n        \u0026ProofOptions::default());  // we'll be using default options\n\n// the output should be 8\nassert_eq!(vec![8], outputs);\n```\n\n### Verifying program execution\nTo verify program execution, you can use `verify()` function. The function takes the following parameters:\n\n* `program_hash: \u0026[u8; 32]` - an array of 32 bytes representing a hash of the program to be verified.\n* `public_inputs: \u0026[u128]` - a list of public inputs against which the program was executed.\n* `outputs: \u0026[u128]` - a list of outputs generated by the program.\n* `proof: \u0026StarkProof` - the proof generated during program execution.\n\nThe function returns `Result\u003cbool, String\u003e` which will be `Ok\u003ctrue\u003e` if verification passes, or `Err\u003cmessage\u003e` if verification fails, with `message` describing the reason for the failure.\n\nVerifying execution proof of a program basically means the following:\n\n\u003e If a program with the provided hash is executed against some secret inputs and the provided public inputs, it will produce the provided outputs.\n\nNotice how the verifier needs to know only the hash of the program - not what the actual program was.\n\n#### Verifying execution example\nHere is a simple example of verifying execution of the program from the previous example:\n```Rust\nuse distaff;\n\nlet program =   /* value from previous example */;\nlet proof =     /* value from previous example */;\n\n// let's verify program execution\nmatch distaff::verify(program.hash(), \u0026[], \u0026[8], \u0026proof) {\n    Ok(_) =\u003e println!(\"Execution verified!\"),\n    Err(msg) =\u003e println!(\"Execution verification failed: {}\", msg)\n}\n```\n\n## Fibonacci calculator\nLet's write a simple program for Distaff VM (using [Distaff assembly](docs/assembly.md)). Our program will compute the 5-th [Fibonacci number](https://en.wikipedia.org/wiki/Fibonacci_number):\n\n```\npush.0      // stack state: 0\npush.1      // stack state: 1 0\nswap        // stack state: 0 1\ndup.2       // stack state: 0 1 0 1\ndrop        // stack state: 1 0 1\nadd         // stack state: 1 1\nswap        // stack state: 1 1\ndup.2       // stack state: 1 1 1 1\ndrop        // stack state: 1 1 1\nadd         // stack state: 2 1\nswap        // stack state: 1 2\ndup.2       // stack state: 1 2 1 2\ndrop        // stack state: 2 1 2\nadd         // stack state: 3 2\n```\nNotice that except for the first 2 operations which initialize the stack, the sequence of `swap dup.2 drop add` operations repeats over and over. In fact, we can repeat these operations an arbitrary number of times to compute an arbitrary Fibonacci number. In Rust, it would like like this (this is actually a simplified version of the example in [fibonacci.rs](https://github.com/GuildOfWeavers/distaff/blob/master/src/examples/fibonacci.rs)):\n```Rust\nuse distaff::{ self, ProofOptions, ProgramInputs, assembly };\n\n// use default proof options\nlet options = ProofOptions::default();\n\n// set the number of terms to compute\nlet n = 50;\n\n// build the program\nlet mut source = format!(\"\n    begin \n        repeat.{}\n            swap dup.2 drop add\n        end\n    end\", n - 1);\nlet program = assembly::compile(\u0026source).unwrap();\n\n// initialize the stack with values 0 and 1\nlet inputs = ProgramInputs::from_public(\u0026[1, 0]);\n\n// execute the program\nlet (outputs, proof) = distaff::execute(\n        \u0026program,\n        \u0026inputs,\n        1,          // top stack item is the output\n        \u0026options);\n\n// the output should be the 50th Fibonacci number\nassert_eq!(vec![12586269025], outputs);\n```\nAbove, we used public inputs to initialize the stack rather than using `push` operations. This makes the program a bit simpler, and also allows us to run the program from arbitrary starting points without changing program hash.\n\nThis program is rather efficient: the stack never gets more than 4 items deep.\n\n## Performance\nHere are some very informal benchmarks of running the Fibonacci calculator on Intel Core i5-7300U @ 2.60GHz (single thread) for a given number of operations:\n\n| Operation Count | Execution time | Execution RAM  | Verification time | Proof size |\n| --------------- | :------------: | :------------: | :---------------: | :--------: |\n| 2\u003csup\u003e8\u003c/sup\u003e   | 190 ms         | negligible     | 2 ms              | 62 KB      |\n| 2\u003csup\u003e10\u003c/sup\u003e  | 350 ms         | negligible     | 2 ms              | 80 KB      |\n| 2\u003csup\u003e12\u003c/sup\u003e  | 1 sec          | \u003c 100 MB       | 2 ms              | 104 KB     |\n| 2\u003csup\u003e14\u003c/sup\u003e  | 4.5 sec        | ~ 250 MB       | 3 ms              | 132 KB     |\n| 2\u003csup\u003e16\u003c/sup\u003e  | 18 sec         | 1.1 GB         | 3 ms              | 161 KB     |\n| 2\u003csup\u003e18\u003c/sup\u003e  | 1.3 min        | 5.5 GB         | 3 ms              | 193 KB     |\n| 2\u003csup\u003e20\u003c/sup\u003e  | 18 min         | \u003e 5.6 GB       | 4 ms              | 230 KB     |\n\nA few notes about the results:\n1. Execution time is dominated by the proof generation time. In fact, the time needed to run the program is only about 0.05% of the time needed to generate the proof.\n2. For 2\u003csup\u003e20\u003c/sup\u003e case, RAM on my machine maxed out at 5.6 GB, but for efficient execution ~20 GB would be needed. This probably explains why proving time is so poor in this case as compared to other cases. If there was sufficient RAM available, execution time would have likely been around 5 mins.\n3. The benchmarks use default proof options which target 120-bit security level. The security level can be increased by either increasing execution time or proof size. In general, there is a trade-off between proof time and proof size (i.e. for a given security level, you can reduce proof size by increasing execution time, up to a point).\n\n## References\nProofs of execution generated by Distaff VM are based on STARKs. A STARK is a novel proof-of-computation scheme that allows you to create an efficiently verifiable proof that a computation was executed correctly. The scheme was developed by Eli-Ben Sasson and team at Technion - Israel Institute of Technology. STARKs do not require an initial trusted setup, and rely on very few cryptographic assumptions.\n\nHere are some resources to learn more about STARKs:\n\n* STARKs whitepaper: [Scalable, transparent, and post-quantum secure computational integrity](https://eprint.iacr.org/2018/046)\n* STARKs vs. SNARKs: [A Cambrian Explosion of Crypto Proofs](https://nakamoto.com/cambrian-explosion-of-crypto-proofs/)\n\nVitalik Buterin's blog series on zk-STARKs:\n* [STARKs, part 1: Proofs with Polynomials](https://vitalik.ca/general/2017/11/09/starks_part_1.html)\n* [STARKs, part 2: Thank Goodness it's FRI-day](https://vitalik.ca/general/2017/11/22/starks_part_2.html)\n* [STARKs, part 3: Into the Weeds](https://vitalik.ca/general/2018/07/21/starks_part_3.html)\n\nStarkWare's STARK Math blog series:\n* [STARK Math: The Journey Begins](https://medium.com/starkware/stark-math-the-journey-begins-51bd2b063c71)\n* [Arithmetization I](https://medium.com/starkware/arithmetization-i-15c046390862)\n* [Arithmetization II](https://medium.com/starkware/arithmetization-ii-403c3b3f4355)\n* [Low Degree Testing](https://medium.com/starkware/low-degree-testing-f7614f5172db)\n* [A Framework for Efficient STARKs](https://medium.com/starkware/a-framework-for-efficient-starks-19608ba06fbe)\n\n# License\n[MIT](/LICENSE) © 2020 Guild of Weavers","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGuildOfWeavers%2Fdistaff","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FGuildOfWeavers%2Fdistaff","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FGuildOfWeavers%2Fdistaff/lists"}