From 81681fda8bc049012d1a0d6ac7f384eedf73caf0 Mon Sep 17 00:00:00 2001 From: zac-williamson Date: Mon, 11 Dec 2023 16:01:48 +0000 Subject: [PATCH 01/14] initial commit --- .../docs/cryptography/_category_.json | 8 ++ .../images/proof-system-components.png | Bin 0 -> 88740 bytes .../docs/cryptography/protocol-overview.md | 103 ++++++++++++++++++ 3 files changed, 111 insertions(+) create mode 100644 yellow-paper/docs/cryptography/_category_.json create mode 100644 yellow-paper/docs/cryptography/images/proof-system-components.png create mode 100644 yellow-paper/docs/cryptography/protocol-overview.md diff --git a/yellow-paper/docs/cryptography/_category_.json b/yellow-paper/docs/cryptography/_category_.json new file mode 100644 index 000000000000..ee3fba3fe8dd --- /dev/null +++ b/yellow-paper/docs/cryptography/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Cryptography", + "position": 10, + "link": { + "type": "generated-index", + "description": "Aztec cryptography tech stack" + } +} diff --git a/yellow-paper/docs/cryptography/images/proof-system-components.png b/yellow-paper/docs/cryptography/images/proof-system-components.png new file mode 100644 index 0000000000000000000000000000000000000000..b2fcee21f4e5f0909ce2a866b9ceaa898510b9ac GIT binary patch literal 88740 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 literal 0 HcmV?d00001 diff --git a/yellow-paper/docs/cryptography/protocol-overview.md b/yellow-paper/docs/cryptography/protocol-overview.md new file mode 100644 index 000000000000..949c11195777 --- /dev/null +++ b/yellow-paper/docs/cryptography/protocol-overview.md @@ -0,0 +1,103 @@ +# Proving System Components + +# Interactive Proving Systems + +## Ultra Plonk + +UltraPlonk is a variant of the [PLONK](https://eprint.iacr.org/2019/953) protocol - a zkSNARK with a universal trusted setup. + +UltraPlonk utilizes the "Ultra" circuit arithmetisation. This is a configuration with four wires per-gate, and the following set of gate types: + +- arithmetic gate +- elliptic curve point addition/doubling gate +- range-check gate +- plookup table gate +- memory-checking gates +- non-native field arithmetic gates + +## Honk + +Honk is a variant of the PLONK protocol. Plonk performs polynomial testing via evaluating a polynomial relation is zero modulo the vanishing polynomial of a multiplicative subgroup. Honk performs the polynomial testing via evaluating, using a sumcheck protocol, that a relation over multilinear polynomials vanishes when summed over a boolean hypercube. + +The first protocol to combine Plonk and the sumcheck protocol was [HyperPlonk](https://eprint.iacr.org/2022/1355) + +Honk uses a custom arithmetisation that extends the Ultra circuit arithmetisation (not yet finalized) + +# Incrementally Verifiable Computation Subprotocols + +An Incrementally Verifiable Computation (IVC) scheme describes a protocol that enables multiple successive proofs to evolve the value taken by some defined persistent state over time. + +IVC schemes are used by Aztec in two capacities: + +1. to compute a client-side proof of one transaction execution. +2. to compute a proof of a "rollup" circuit, that updates rollup state based on a block of user transactions + +Both use IVC schemes. Client-side, each function call in a transaction is a "step" in the IVC scheme. Rollup-side, aggregating two transaction proofs is a "step" in the IVC scheme. + +The client-side IVC scheme is substantially more complex than the rollup-side scheme due to performance requiremenmts. + +Rollup-side, each "step" in the IVC scheme is a Honk proof, which are recursively verified. As a result, no protoocols other than Honk are required to execute rollup-side IVC. + +We perform one layer of "proof-system compression" in the rollup. The final proof of block-correctness is constructed as a Honk proof. An UltraPlonk circuit is used to verify the correctness of the Honk proof, so that the proof that is verified on-chain is an UltraPlonk proof (verification gas costs are lower for UltraPlonk vs Honk). + +The following sections list the protocol components required to implement client-side IVC. + +## Protogalaxy + +The [Protogalaxy](https://eprint.iacr.org/2023/1106) protocol defines a folding scheme that enables instances of a relation to be folded into a single instance of a "relaxed" form of the original relation. + +It is a variant of [Protostar](https://eprint.iacr.org/2023/620). Unlike Protostar, Protogalaxy enables multiple instances to be efficiently folded into the same accumulator instance. + +## Goblin Plonk + +[Goblin Plonk](https://hackmd.io/@aztec-network/BkGNaHUJn/%2FGfNR5SE5ShyXXmLxNCsg3g) is a computation delegation scheme that improves Prover performance when evaluating complex algorithms. + +In the context of an IVC scheme, Goblin Plonk enables a Prover to defer non-native group operations required by a Verifier algorithm, across multiple recursive proofs, to a single step evaluated at the conclusion of the IVC Prover algorithm. + +Goblin Plonk is composed of three subcomponents: + +#### Transcript Aggregation Subprotocol + +This subprotocol aggregates deferred computations from two independent instances, into a single instance + +#### Elliptic Curve Virtual Machine (ECCVM) Subprotocol + +The ECCVM is a Honk circuit with a custom circuit arithmetisation, designed to optimally evaluate elliptic curve arithmetic computations that have been deferred. It is defined over the Grumpkin elliptic curve + +#### Translator Subprotocol + +The Translator is a Honk circuit with a custom circuit arithmetisation, designed to validate the input commitments of an ECCVM circuit align with the delegated computations described by a Goblin Plonk transcript commitment + +## Plonk Data Bus + +The [Plonk Data Bus](https://aztecprotocol.slack.com/files/U8Q1VAX6Y/F05G2B971FY/plonk_bus.pdf) protocol enables efficient data transfer between two Honk instances within a larger IVC protocol. + +# Polynomial Commitment Schemes + +The UltraPlonk, Honk, Goblin Plonk and Plonk Data Bus protocols utilize Polynomial Interactive Oracle Proofs as a core component, neccessitating the use of polynomial commitment schemes (PCX). + +UltraPlonk and Honk utilize multilinear PCS. The Plonk Data Bus and Goblin Plonk also utilize univariate PCS. + +For multilinear polynomial commitment schemes, we use the [ZeroMorph](https://eprint.iacr.org/2023/917) protocol, which itself uses a univariate PCS as a core component. + +Depending on context we use the following two univariate schemes within our cryptography stack + +## KZG Commitments + +The [KZG](https://www.iacr.org/archive/asiacrypt2010/6477178/6477178.pdf) polynomial commitment scheme requires a universal setup and is instantiated over a pairing-friendly elliptic curve. + +Computing an opening proof of a degree-$n$ polynomial requires $n$ scalar multiplications, with a constant proof size and a constant verifier time. + +## Inner Product Argument + +The [IPA](https://eprint.iacr.org/2019/1177.pdf) PCS has worse asymptotics than KZG but can be instantiated over non-pairing friendly curves. + +Computing an opening proof of a degree-$n$ polynomial requires $2n$ scalar multiplications, with a $O(logn)$ proof size and an $O(n)$ verifier time. + +To batch-verify multiple opening proofs, we use the technique articulated in the [Halo](https://eprint.iacr.org/2019/1021) protocol. To compute a proof of a single rollup block, only one linear-time PCS opening proof is verified despite multiple IPA proofs being generated as part of constructing the rollup proof. + +# Combined IVC + Proving System Protocol + +The following block diagrams describe the components used by the client-side and server-side Provers when computing client proofs and rollup proofs respectively. + +![proof-system-components](../cryptography/images/proof-system-components.png) From 3f3fc5304dca8c908156abf9926048adada1a8d4 Mon Sep 17 00:00:00 2001 From: zac-williamson Date: Mon, 11 Dec 2023 16:06:13 +0000 Subject: [PATCH 02/14] protogalaxy tweak --- yellow-paper/docs/cryptography/protocol-overview.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/yellow-paper/docs/cryptography/protocol-overview.md b/yellow-paper/docs/cryptography/protocol-overview.md index 949c11195777..8c3e1cd19787 100644 --- a/yellow-paper/docs/cryptography/protocol-overview.md +++ b/yellow-paper/docs/cryptography/protocol-overview.md @@ -48,6 +48,16 @@ The [Protogalaxy](https://eprint.iacr.org/2023/1106) protocol defines a folding It is a variant of [Protostar](https://eprint.iacr.org/2023/620). Unlike Protostar, Protogalaxy enables multiple instances to be efficiently folded into the same accumulator instance. +The Protogalaxy protocol is split into two subprotocols, each modelled as interactive protocols between a Prover and a Verifier. + +#### Protogalaxy Fold + +The "Fold" Prover/Verifier validates that `k` instances of a defined relation (in our case the Honk relation) have been correctly folded into an accumulator instance. + +#### Protogalaxy Decider + +The "Decider" Prover/Verifier valiate whether an accumulator instance correctly satisfies the accumulator relation. + ## Goblin Plonk [Goblin Plonk](https://hackmd.io/@aztec-network/BkGNaHUJn/%2FGfNR5SE5ShyXXmLxNCsg3g) is a computation delegation scheme that improves Prover performance when evaluating complex algorithms. From f2fdfaeb8a71ca52eb8bfadd110521fb36af58e6 Mon Sep 17 00:00:00 2001 From: zac-williamson Date: Mon, 11 Dec 2023 16:24:12 +0000 Subject: [PATCH 03/14] added performance targets --- .../docs/cryptography/performance-targets.md | 121 ++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 yellow-paper/docs/cryptography/performance-targets.md diff --git a/yellow-paper/docs/cryptography/performance-targets.md b/yellow-paper/docs/cryptography/performance-targets.md new file mode 100644 index 000000000000..ef9c2ef221a1 --- /dev/null +++ b/yellow-paper/docs/cryptography/performance-targets.md @@ -0,0 +1,121 @@ +# Honk targets and win conditions + +## Introduction & context + +Aztec's cryptography tech stack and its associated implementation is an open-ended project with potential for many enhancements, optimisations and scope-creep. + +This document is designed to definitively answer the following questions: + +1. What are the metrics we care about when measuring our cryptography components? +3. What are minimum satisfiable values for these metrics? +4. What are the aspirational values for these metrics? + +# Important Metrics + +The following is a list of the relevant properties that affect the performance of the Aztec network: + +* Size of a user transaction (in kb) +* Time to generate a user transaction proof +* Memory required to generate a user transaction proof +* Time to generate an Aztec Virtual Machine proof +* Memory required to generate an Aztec Virtual Machine proof +* Time to compute a 2x2 rollup proof +* Memory required to compute a 2x2 rollup proof + + + + "MVP" = minimum standards that we can go to main-net with. + +| metric | how to measure | MVP | ideal | +| --- | --- | --- | --- | +| proof size | total size of a user tx incl. goblin plonk proofs | 32kb | 8kb | +| prover time | 8 iterations of protogalaxy with 2^17 circuits (web browser) | 1 min | 10 seconds | +| verifier time | how long does it take the verifier to check a proof (incl. grumpkin IPA MSMs) | 25ms | 1ms | +| memory consumption | fold 2^17 circuits into an accumulator an arbitrary number of times | 2gb | 512mb | +| size of the kernel circuit | number of gates | 2^17 | 2^15 | +| Aztec Virtual Machine prover time | 1 million VM step circuit | 30 seconds | 5 seconds | +| Aztec Virtual Machine memory consumption | 1 million VM step circuit | 128Gb | 16Gb | + +### Proof size + +At a tx throughput of 1,024 tx per second, each Aztec node (not sequencer/prover, just a regular node that is sending transactions) needs to download `1024*proof_size` bytes of data to keep track of the mempool. 32kb proofs = 32MB per second which is on the threshold of practical outside of a datacenter. 8MB per second is much more practical. + +At launch, the throughput won't be this high, but ideally we architect Aztec such that the network can scale effectively by throwing hardware+resources at bottlenecks (easy to do in a post-decentralisation), without protocol, architecture or tech upgrades ( harder post-decentralisation). + +### Prover time + +The critical UX factor. 1 minute per user tx is on the cusp of workable. The faster we can get this the better our network's value proposition for users and developers + +### Verifier time + +This matters because verifying a transaction is effectively free work being performed by sequencers and network nodes that propagate txns to the mempool. If verification time becomes too large it opens up potential DDOS attacks. + +At a 1,024 transactions per second and 20ms verification time, a block builder needs to run 20 machines in parallel just to verify natively all of the proofs in a block! Not ideal but probably tolerable given this problem has a "more hardware go brrrr" solution. + +### Memory consumption + +This is *critical*. Users can tolerate slow proofs, but if Honk consumes too much memory, a user cannot make a proof at all. + +safari on iPhone will purge tabs that consume more than 1gb of RAM. 2gb will work in web browsers and some phones (but not all). 512mb will allow most phones to make proofs. + +### Kernel circuit size + +Not a critical metric, but the prover time + prover memory metrics are predicated on a kernel circuit costing about 2^17 constraints! + +### AVM Prover time + +Our goal is to hit main-net with a network that can support 10 transactions per second. We need to estimate how many VM computation steps will be needed per transaction to determine the required speed of the VM Prover. The following uses very conservative estimations due to the difficulty of estimating this. + +An Ethereum block consists of approximately 1,000 transactions, with a block gas limit of roughly 10 million gas. Basic computational steps in the Ethereum Virtual Machine consume 3 gas. If the entire block gas limit is consumed with basic computation steps (not true but let's assume for a moment), this implies that 1,000 transactions consume 3.33 million computation steps. i.e. 10 transactions per second would require roughly 33,000 steps per second and 3,330 steps per transaction. + +An AVM circuit with 1 million steps can therefore accomodate approximately 300 transactions. Proof construction time must therefore be approximately 30 seconds to be able to prove all AVM programs in a block and achieve 10 tps. + +### AVM Memory consumption + +A large AWS instance can consume 128Gb of memory which puts an upper limit for AVM RAM consumption. Ideally consumer-grade hardware can be used to generate AVM proofs i.e. 16 Gb. + + + From 22707ef5ff43a08c9c83c168c5cdcc2a58cc0fd9 Mon Sep 17 00:00:00 2001 From: zac-williamson Date: Tue, 12 Dec 2023 13:24:19 +0000 Subject: [PATCH 04/14] updated performance targets --- .../docs/cryptography/performance-targets.md | 85 ++++++++++--------- 1 file changed, 47 insertions(+), 38 deletions(-) diff --git a/yellow-paper/docs/cryptography/performance-targets.md b/yellow-paper/docs/cryptography/performance-targets.md index ef9c2ef221a1..d60a65b50daf 100644 --- a/yellow-paper/docs/cryptography/performance-targets.md +++ b/yellow-paper/docs/cryptography/performance-targets.md @@ -32,15 +32,31 @@ The following is a list of the relevant properties that affect the performance o "MVP" = minimum standards that we can go to main-net with. -| metric | how to measure | MVP | ideal | +Note: gb = gigabytes (not gigabits, gigibits or gigibytes) + +| metric | how to measure | MVP (10tps) | ideal (100tps) | | --- | --- | --- | --- | | proof size | total size of a user tx incl. goblin plonk proofs | 32kb | 8kb | | prover time | 8 iterations of protogalaxy with 2^17 circuits (web browser) | 1 min | 10 seconds | -| verifier time | how long does it take the verifier to check a proof (incl. grumpkin IPA MSMs) | 25ms | 1ms | -| memory consumption | fold 2^17 circuits into an accumulator an arbitrary number of times | 2gb | 512mb | +| verifier time | how long does it take the verifier to check a proof (incl. grumpkin IPA MSMs) | 20ms | 1ms | +| client memory consumption | fold 2^19 circuits into an accumulator an arbitrary number of times | 4gb | 1gb | | size of the kernel circuit | number of gates | 2^17 | 2^15 | -| Aztec Virtual Machine prover time | 1 million VM step circuit | 30 seconds | 5 seconds | -| Aztec Virtual Machine memory consumption | 1 million VM step circuit | 128Gb | 16Gb | +| Aztec Virtual Machine prover time | 1 million VM step circuit | 60 seconds | 6 seconds | +| Aztec Virtual Machine memory consumption | 1 million VM step circuit | 128gb | 16gb | +| 2x2 rollup proving time | 1 2x2 rollup proof | 7.4 seconds | 0.74 seconds | +| 2x2 rollup memory consumption | 1 2x2 rollup proof | 128gb | 16gb | + +To come up with the above estimates, we are targetting 10 transactions per second for the MVP and 100 tps for the "ideal" case. We are assuming both block producers and rollup Provers have access to 128-core machines with 128gb of RAM. Additionally, we assume that the various process required to produce a block consume the following: + +| process | percent of block production time allocated to process | +| --- | --- | +| transaction validation | 10% | +| block building (tx simulation) | 20% | +| public VM proof construction time | 20% | +| rollup prover time | 40% | +| UltraPlonk proof compression time | 10% | + +These are very rough estimates that could use further evaluation and validation! ### Proof size @@ -56,13 +72,17 @@ The critical UX factor. 1 minute per user tx is on the cusp of workable. The fas This matters because verifying a transaction is effectively free work being performed by sequencers and network nodes that propagate txns to the mempool. If verification time becomes too large it opens up potential DDOS attacks. -At a 1,024 transactions per second and 20ms verification time, a block builder needs to run 20 machines in parallel just to verify natively all of the proofs in a block! Not ideal but probably tolerable given this problem has a "more hardware go brrrr" solution. +If we reserve 10% of the block production time for verifying user proofs, at 10 transaction per seconds this gives us 0.01s per transaction. i.e. 10ms per proof. + +If the block producer has access to more than one physical machine that they can use to parallelise verification, we can extend the maximum tolerable verification time. For an MVP that requires 20ms to verify each proof, each block producer would require at least 2 physical machines to successfully build blocks. + +100tps with one physical machine would require a verifiation time of 1ms per proof. ### Memory consumption This is *critical*. Users can tolerate slow proofs, but if Honk consumes too much memory, a user cannot make a proof at all. -safari on iPhone will purge tabs that consume more than 1gb of RAM. 2gb will work in web browsers and some phones (but not all). 512mb will allow most phones to make proofs. +safari on iPhone will purge tabs that consume more than 1gb of RAM. The WASM memory cap is 4gb which defines the upper limit for an MVP. ### Kernel circuit size @@ -74,48 +94,37 @@ Our goal is to hit main-net with a network that can support 10 transactions per An Ethereum block consists of approximately 1,000 transactions, with a block gas limit of roughly 10 million gas. Basic computational steps in the Ethereum Virtual Machine consume 3 gas. If the entire block gas limit is consumed with basic computation steps (not true but let's assume for a moment), this implies that 1,000 transactions consume 3.33 million computation steps. i.e. 10 transactions per second would require roughly 33,000 steps per second and 3,330 steps per transaction. -An AVM circuit with 1 million steps can therefore accomodate approximately 300 transactions. Proof construction time must therefore be approximately 30 seconds to be able to prove all AVM programs in a block and achieve 10 tps. +An AVM circuit with 1 million steps can therefore accomodate approximately 300 "typical" transactions. If we budget 20% of the block time to constructing AVM public funciton proofs, proof construction time must therefore be approximately 6 seconds to be able to prove all AVM programs in a block and achieve 10 tps. -### AVM Memory consumption +However, with device parallelisation these numbers can be increased substantially. Assuming the Prover network has access to 10 machines, this scales to 60 seconds. -A large AWS instance can consume 128Gb of memory which puts an upper limit for AVM RAM consumption. Ideally consumer-grade hardware can be used to generate AVM proofs i.e. 16 Gb. - - - From d2ac3457a4b7e25e960dfe74513b5019674899ad Mon Sep 17 00:00:00 2001 From: zac-williamson Date: Tue, 12 Dec 2023 13:58:20 +0000 Subject: [PATCH 05/14] updates from comments --- .../docs/cryptography/protocol-overview.md | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/yellow-paper/docs/cryptography/protocol-overview.md b/yellow-paper/docs/cryptography/protocol-overview.md index 8c3e1cd19787..05a64b7ef3d4 100644 --- a/yellow-paper/docs/cryptography/protocol-overview.md +++ b/yellow-paper/docs/cryptography/protocol-overview.md @@ -25,7 +25,7 @@ Honk uses a custom arithmetisation that extends the Ultra circuit arithmetisatio # Incrementally Verifiable Computation Subprotocols -An Incrementally Verifiable Computation (IVC) scheme describes a protocol that enables multiple successive proofs to evolve the value taken by some defined persistent state over time. +An Incrementally Verifiable Computation (IVC) scheme describes a protocol that enables multiple successive proofs to evolve persistent state over time. IVC schemes are used by Aztec in two capacities: @@ -38,16 +38,22 @@ The client-side IVC scheme is substantially more complex than the rollup-side sc Rollup-side, each "step" in the IVC scheme is a Honk proof, which are recursively verified. As a result, no protoocols other than Honk are required to execute rollup-side IVC. -We perform one layer of "proof-system compression" in the rollup. The final proof of block-correctness is constructed as a Honk proof. An UltraPlonk circuit is used to verify the correctness of the Honk proof, so that the proof that is verified on-chain is an UltraPlonk proof (verification gas costs are lower for UltraPlonk vs Honk). +We perform one layer of "proof-system compression" in the rollup. The final proof of block-correctness is constructed as a Honk proof. An UltraPlonk circuit is used to verify the correctness of the Honk proof, so that the proof that is verified on-chain is an UltraPlonk proof. +Verification gas costs are lower for UltraPlonk vs Honk due to the following factors: + +1. Fewer precomputed selector polynomials, reducing Verifier G1 scalar multiplications +2. UltraPlonk does not use multilinear polynomials, which removes 1 pairing from the Verifier, as well as O(logn) G1 scalar multiplications. The following sections list the protocol components required to implement client-side IVC. ## Protogalaxy -The [Protogalaxy](https://eprint.iacr.org/2023/1106) protocol defines a folding scheme that enables instances of a relation to be folded into a single instance of a "relaxed" form of the original relation. +The [Protogalaxy](https://eprint.iacr.org/2023/1106) protocol defines a folding scheme that enables instances of a relation to be folded into a single instance of the original relation, but in a "relaxed" form. It is a variant of [Protostar](https://eprint.iacr.org/2023/620). Unlike Protostar, Protogalaxy enables multiple instances to be efficiently folded into the same accumulator instance. +We use the Protostar/galaxy family of folding schemes, as it efficiently supports the ability to fold multiple Honk instances (describing different circuits) into the same accumulator. To constrast, the Nova/Supernova/Hypernova family of folding schemes assume that a single circuit is being repeatedly folded (each Aztec function circuit is a distinct circuit, which breaks this assumption). + The Protogalaxy protocol is split into two subprotocols, each modelled as interactive protocols between a Prover and a Verifier. #### Protogalaxy Fold @@ -56,7 +62,7 @@ The "Fold" Prover/Verifier validates that `k` instances of a defined relation (i #### Protogalaxy Decider -The "Decider" Prover/Verifier valiate whether an accumulator instance correctly satisfies the accumulator relation. +The "Decider" Prover/Verifier validate whether an accumulator instance correctly satisfies the accumulator relation. The accumulator being satisfiable inductively shows that all instances that have been folded were satisfied as well. (additional protocol checks are required to reason about *which* instances have been folded into the accumulator. See the [IVC specification](https://hackmd.io/h0yTcOHiQWeeTXnxTQhTNQ?view) for more information. (note to zac: put this in the yellow paper!) ## Goblin Plonk @@ -72,19 +78,23 @@ This subprotocol aggregates deferred computations from two independent instances #### Elliptic Curve Virtual Machine (ECCVM) Subprotocol -The ECCVM is a Honk circuit with a custom circuit arithmetisation, designed to optimally evaluate elliptic curve arithmetic computations that have been deferred. It is defined over the Grumpkin elliptic curve +The ECCVM is a Honk circuit with a custom circuit arithmetisation, designed to optimally evaluate elliptic curve arithmetic computations that have been deferred. It is defined over the Grumpkin elliptic curve. #### Translator Subprotocol -The Translator is a Honk circuit with a custom circuit arithmetisation, designed to validate the input commitments of an ECCVM circuit align with the delegated computations described by a Goblin Plonk transcript commitment +The Translator is a Honk circuit with a custom circuit arithmetisation, designed to validate that the input commitments of an ECCVM circuit align with the delegated computations described by a Goblin Plonk transcript commitment. ## Plonk Data Bus +When passing data between successive IVC steps, the canonical method is to do so via public inputs. This adds significant costs to an IVC folding verifier (or recursive verifier when not using a folding scheme). Public inputs for part of the proof and therefore must be hashed prior to generating Fiat-Shamir challenges. When this is performed in-circuit, this adds a cost linear in the number of public inputs (with unpleasant constants ~30 constraints per field element). + +The Data Bus protocol eliminiates this cost by representing cross-step data via succinct commitments instead of raw field elements. + The [Plonk Data Bus](https://aztecprotocol.slack.com/files/U8Q1VAX6Y/F05G2B971FY/plonk_bus.pdf) protocol enables efficient data transfer between two Honk instances within a larger IVC protocol. # Polynomial Commitment Schemes -The UltraPlonk, Honk, Goblin Plonk and Plonk Data Bus protocols utilize Polynomial Interactive Oracle Proofs as a core component, neccessitating the use of polynomial commitment schemes (PCX). +The UltraPlonk, Honk, Goblin Plonk and Plonk Data Bus protocols utilize Polynomial Interactive Oracle Proofs as a core component, thus requiring the use of polynomial commitment schemes (PCS). UltraPlonk and Honk utilize multilinear PCS. The Plonk Data Bus and Goblin Plonk also utilize univariate PCS. @@ -102,6 +112,8 @@ Computing an opening proof of a degree-$n$ polynomial requires $n$ scalar multip The [IPA](https://eprint.iacr.org/2019/1177.pdf) PCS has worse asymptotics than KZG but can be instantiated over non-pairing friendly curves. +We utilize the Grumpkin elliptic curve as part of the Goblin Plonk protocol, where we utilize the curve cycle formed between BN254 and Grumpkin to translate expensiven on-native BN254 group operations in a BN254 circuit, into native group operations in a Grumpkin circuit. + Computing an opening proof of a degree-$n$ polynomial requires $2n$ scalar multiplications, with a $O(logn)$ proof size and an $O(n)$ verifier time. To batch-verify multiple opening proofs, we use the technique articulated in the [Halo](https://eprint.iacr.org/2019/1021) protocol. To compute a proof of a single rollup block, only one linear-time PCS opening proof is verified despite multiple IPA proofs being generated as part of constructing the rollup proof. From fdd535364b4188cf837b8dd2ba557ce7ba7f3232 Mon Sep 17 00:00:00 2001 From: zac-williamson Date: Tue, 12 Dec 2023 14:00:42 +0000 Subject: [PATCH 06/14] comments --- yellow-paper/docs/cryptography/protocol-overview.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/yellow-paper/docs/cryptography/protocol-overview.md b/yellow-paper/docs/cryptography/protocol-overview.md index 05a64b7ef3d4..c0f48301fba7 100644 --- a/yellow-paper/docs/cryptography/protocol-overview.md +++ b/yellow-paper/docs/cryptography/protocol-overview.md @@ -44,16 +44,16 @@ Verification gas costs are lower for UltraPlonk vs Honk due to the following fac 1. Fewer precomputed selector polynomials, reducing Verifier G1 scalar multiplications 2. UltraPlonk does not use multilinear polynomials, which removes 1 pairing from the Verifier, as well as O(logn) G1 scalar multiplications. -The following sections list the protocol components required to implement client-side IVC. +The following sections list the protocol components required to implement client-side IVC. We make heavy use of folding schemes to build an IVC scheme. A folding scheme enables instances of a relation to be folded into a single instance of the original relation, but in a "relaxed" form. Depending on the scheme, restrictions may be placed on the instances that can be folded. + +The main two families of folding schemes are derived from the [Nova](https://eprint.iacr.org/2021/370) protocol and the [Protostar](https://eprint.iacr.org/2023/620) protocol respectively. ## Protogalaxy -The [Protogalaxy](https://eprint.iacr.org/2023/1106) protocol defines a folding scheme that enables instances of a relation to be folded into a single instance of the original relation, but in a "relaxed" form. +The [Protogalaxy](https://eprint.iacr.org/2023/1106) protocol efficiently supports the ability to fold multiple Honk instances (describing different circuits) into the same accumulator. To constrast, the Nova/Supernova/Hypernova family of folding schemes assume that a single circuit is being repeatedly folded (each Aztec function circuit is a distinct circuit, which breaks this assumption). It is a variant of [Protostar](https://eprint.iacr.org/2023/620). Unlike Protostar, Protogalaxy enables multiple instances to be efficiently folded into the same accumulator instance. -We use the Protostar/galaxy family of folding schemes, as it efficiently supports the ability to fold multiple Honk instances (describing different circuits) into the same accumulator. To constrast, the Nova/Supernova/Hypernova family of folding schemes assume that a single circuit is being repeatedly folded (each Aztec function circuit is a distinct circuit, which breaks this assumption). - The Protogalaxy protocol is split into two subprotocols, each modelled as interactive protocols between a Prover and a Verifier. #### Protogalaxy Fold From 1864a7e59eabf3313ea5a8b10555697bfb3c7279 Mon Sep 17 00:00:00 2001 From: zac-williamson Date: Tue, 12 Dec 2023 14:02:24 +0000 Subject: [PATCH 07/14] comments --- yellow-paper/docs/cryptography/protocol-overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yellow-paper/docs/cryptography/protocol-overview.md b/yellow-paper/docs/cryptography/protocol-overview.md index c0f48301fba7..db0908d1b184 100644 --- a/yellow-paper/docs/cryptography/protocol-overview.md +++ b/yellow-paper/docs/cryptography/protocol-overview.md @@ -25,7 +25,7 @@ Honk uses a custom arithmetisation that extends the Ultra circuit arithmetisatio # Incrementally Verifiable Computation Subprotocols -An Incrementally Verifiable Computation (IVC) scheme describes a protocol that enables multiple successive proofs to evolve persistent state over time. +An Incrementally Verifiable Computation (IVC) scheme describes a protocol that defines some concept of persistent state, and enables multiple successive proofs to evolve the state over time. IVC schemes are used by Aztec in two capacities: From c8fc369d9d05d7e463c2b38c6f4cd5d9ae661d78 Mon Sep 17 00:00:00 2001 From: zac-williamson Date: Tue, 12 Dec 2023 18:55:33 +0000 Subject: [PATCH 08/14] comments --- yellow-paper/docs/cryptography/performance-targets.md | 1 + 1 file changed, 1 insertion(+) diff --git a/yellow-paper/docs/cryptography/performance-targets.md b/yellow-paper/docs/cryptography/performance-targets.md index d60a65b50daf..c5e30c2c1fbd 100644 --- a/yellow-paper/docs/cryptography/performance-targets.md +++ b/yellow-paper/docs/cryptography/performance-targets.md @@ -67,6 +67,7 @@ At launch, the throughput won't be this high, but ideally we architect Aztec suc ### Prover time The critical UX factor. 1 minute per user tx is on the cusp of workable. The faster we can get this the better our network's value proposition for users and developers +. The benchmark is a standard "Aztec Connect" defi interaction transaction, as this is a tx with non-trivial complexity but can also be expected to be a common type of transaction. (note: we need to write such a circuit in noir so we can benchmark against it!) ### Verifier time From d3b154adc32954fce55f1ab2dd5b7ab5870ff318 Mon Sep 17 00:00:00 2001 From: zac-williamson Date: Mon, 18 Dec 2023 12:51:45 +0000 Subject: [PATCH 09/14] updated Prover time target --- .../docs/cryptography/performance-targets.md | 41 +++++++++++++++++-- 1 file changed, 38 insertions(+), 3 deletions(-) diff --git a/yellow-paper/docs/cryptography/performance-targets.md b/yellow-paper/docs/cryptography/performance-targets.md index c5e30c2c1fbd..f478f101b2a7 100644 --- a/yellow-paper/docs/cryptography/performance-targets.md +++ b/yellow-paper/docs/cryptography/performance-targets.md @@ -37,7 +37,7 @@ Note: gb = gigabytes (not gigabits, gigibits or gigibytes) | metric | how to measure | MVP (10tps) | ideal (100tps) | | --- | --- | --- | --- | | proof size | total size of a user tx incl. goblin plonk proofs | 32kb | 8kb | -| prover time | 8 iterations of protogalaxy with 2^17 circuits (web browser) | 1 min | 10 seconds | +| prover time | A baseline "medium complexity" transaction (in web browser). Full description further down | 1 min | 10 seconds | | verifier time | how long does it take the verifier to check a proof (incl. grumpkin IPA MSMs) | 20ms | 1ms | | client memory consumption | fold 2^19 circuits into an accumulator an arbitrary number of times | 4gb | 1gb | | size of the kernel circuit | number of gates | 2^17 | 2^15 | @@ -66,8 +66,43 @@ At launch, the throughput won't be this high, but ideally we architect Aztec suc ### Prover time -The critical UX factor. 1 minute per user tx is on the cusp of workable. The faster we can get this the better our network's value proposition for users and developers -. The benchmark is a standard "Aztec Connect" defi interaction transaction, as this is a tx with non-trivial complexity but can also be expected to be a common type of transaction. (note: we need to write such a circuit in noir so we can benchmark against it!) +The critical UX factor. To measure prover time for a transaction, we must first define a baseline transaction we wish to measure and the execution environment of the Prover. + +As we build+refine our MPV, we want to avoid optimising the best-case scenario (i.e. the most basic tx type, a token transfer). Instead we want to ensure that transactions of a "moderate" complexity are possible with consuer hardware. + +As a north star, we consider a private swap, and transpose it into an Aztec contract. + +To perform a private swap, the following must occur: + +1. Validate the user's account contract (1 kernel call) +2. Call a swap contract (1 kernel call) +3. The swap contract will initiate `transfer` calls on two token contracts (2 kernel calls) +4. A fee must be paid via our fee abstraction spec (1 kernel call) + +In total we have 5 kernel calls and 5 function calls. + +We can further abstract the above by making the following assumption: + +1. The kernel circuit is $2^{17}$ constraints +2. The average number of constraints per function call is $2^{17}$ constraints, but the first function called has $2^{19}$ constraints + +Defining the first function to cost $2^{19}$ constraints is a conservative assumption due to the fact that the kernel circuit can support functions that have a max of $2^{19}$ constraints. We want to ensure that our benchmarks (and possible optimisations) capture the "heavy function" case and we don't just optimise for lightweight functions. + +#### Summary of what we are measuring to capture Prover time + +1. A mock kernel circuit has a size of $2^{17}$ constraints and folds *two* Honk instances into an accumulator (the prev. kernel and the function being called) +2. The Prover must prove 4 mock function circuit proofs of size $2^{17}$ and one mock function proof of size $2^{19}$ +3. The Prover must iteratively prove 5 mock kernel circuit proofs + +#### Execution environment + +For the MVP we can assume the user has reasonable hardware. For the purpose we use a 2-year-old macbook with 16gb RAM. The proof must be generated in a web browser + +#### Performance targets + +For an MVP, we target a 1 minute proof generation time. This is a substantial amount of time to ask a user to wait and we are measuring on good hardware. + +In an ideal world, a 10 second proof generation time would be much better for UX. ### Verifier time From 71b0a8b7c0c8fcb045ff163264cb79d5d032d587 Mon Sep 17 00:00:00 2001 From: zac-williamson Date: Mon, 18 Dec 2023 12:53:53 +0000 Subject: [PATCH 10/14] wip --- yellow-paper/docs/cryptography/performance-targets.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/yellow-paper/docs/cryptography/performance-targets.md b/yellow-paper/docs/cryptography/performance-targets.md index f478f101b2a7..17925d1edd44 100644 --- a/yellow-paper/docs/cryptography/performance-targets.md +++ b/yellow-paper/docs/cryptography/performance-targets.md @@ -78,8 +78,9 @@ To perform a private swap, the following must occur: 2. Call a swap contract (1 kernel call) 3. The swap contract will initiate `transfer` calls on two token contracts (2 kernel calls) 4. A fee must be paid via our fee abstraction spec (1 kernel call) +5. A final "cleanup" proof is generated that evaluates state reads and processes the queues that have been constructed by previous kernel circuits (1 kernel call + 1 function call; the cleanup proof) -In total we have 5 kernel calls and 5 function calls. +In total we have 6 kernel calls and 6 function calls. We can further abstract the above by making the following assumption: @@ -91,8 +92,8 @@ Defining the first function to cost $2^{19}$ constraints is a conservative assum #### Summary of what we are measuring to capture Prover time 1. A mock kernel circuit has a size of $2^{17}$ constraints and folds *two* Honk instances into an accumulator (the prev. kernel and the function being called) -2. The Prover must prove 4 mock function circuit proofs of size $2^{17}$ and one mock function proof of size $2^{19}$ -3. The Prover must iteratively prove 5 mock kernel circuit proofs +2. The Prover must prove 5 mock function circuit proofs of size $2^{17}$ and one mock function proof of size $2^{19}$ +3. The Prover must iteratively prove 6 mock kernel circuit proofs #### Execution environment From c760d8ba55761ca3476c1ec220b9b6f12d57a294 Mon Sep 17 00:00:00 2001 From: zac-williamson Date: Mon, 18 Dec 2023 13:01:33 +0000 Subject: [PATCH 11/14] updated proof size --- .../docs/cryptography/performance-targets.md | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/yellow-paper/docs/cryptography/performance-targets.md b/yellow-paper/docs/cryptography/performance-targets.md index 17925d1edd44..c3576e794468 100644 --- a/yellow-paper/docs/cryptography/performance-targets.md +++ b/yellow-paper/docs/cryptography/performance-targets.md @@ -36,7 +36,7 @@ Note: gb = gigabytes (not gigabits, gigibits or gigibytes) | metric | how to measure | MVP (10tps) | ideal (100tps) | | --- | --- | --- | --- | -| proof size | total size of a user tx incl. goblin plonk proofs | 32kb | 8kb | +| proof size | total size of a user tx incl. goblin plonk proofs | 80kb | 8kb | | prover time | A baseline "medium complexity" transaction (in web browser). Full description further down | 1 min | 10 seconds | | verifier time | how long does it take the verifier to check a proof (incl. grumpkin IPA MSMs) | 20ms | 1ms | | client memory consumption | fold 2^19 circuits into an accumulator an arbitrary number of times | 4gb | 1gb | @@ -60,9 +60,23 @@ These are very rough estimates that could use further evaluation and validation! ### Proof size -At a tx throughput of 1,024 tx per second, each Aztec node (not sequencer/prover, just a regular node that is sending transactions) needs to download `1024*proof_size` bytes of data to keep track of the mempool. 32kb proofs = 32MB per second which is on the threshold of practical outside of a datacenter. 8MB per second is much more practical. +The MVP wishes to target a tx through put of 10 tx per second. -At launch, the throughput won't be this high, but ideally we architect Aztec such that the network can scale effectively by throwing hardware+resources at bottlenecks (easy to do in a post-decentralisation), without protocol, architecture or tech upgrades ( harder post-decentralisation). +Each Aztec node (not sequencer/prover, just a regular node that is sending transactions) needs to download `10*proof_size` bytes of data to keep track of the mempool. However, this is the *best case* scenario. + +More practically, the data throughput of a p2p network will be less than the bandwidth of participants due to network coordination costs. +As a rough heuristic, we assume that network bandwidth will be 10% of p2p user bandwidth. +NOTE: can we find some high-quality information about p2p network throughput relative to the data consumed by p2p node operators? + +As a result, the MPV data throughput could scale up to `100 * proof_size` bytes of data per second. + +For an MVP we wish to target a maximum bandwidth of 8MB per second (i.e. a good broadband connection). This gives us a network bandwidth of 0.8MB/s. + +This sets the proof size limit to 819.2 kb per second per 100 transactions => 82 kilobytes of data per transaction. + +As a rough estimate, we can assume the non-proof tx data will be irrelevant compared to 82kb, so we target a proof size of $80$ kilobytes for the MPV. + +To support 100 transactions per second we would rquire a proof size of $8$ kilobytes. ### Prover time From 8080c34c19f72091f885cce83813762f1a8b4925 Mon Sep 17 00:00:00 2001 From: zac-williamson Date: Mon, 18 Dec 2023 13:03:12 +0000 Subject: [PATCH 12/14] comments --- yellow-paper/docs/cryptography/protocol-overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yellow-paper/docs/cryptography/protocol-overview.md b/yellow-paper/docs/cryptography/protocol-overview.md index db0908d1b184..2d1eae749d44 100644 --- a/yellow-paper/docs/cryptography/protocol-overview.md +++ b/yellow-paper/docs/cryptography/protocol-overview.md @@ -17,7 +17,7 @@ UltraPlonk utilizes the "Ultra" circuit arithmetisation. This is a configuration ## Honk -Honk is a variant of the PLONK protocol. Plonk performs polynomial testing via evaluating a polynomial relation is zero modulo the vanishing polynomial of a multiplicative subgroup. Honk performs the polynomial testing via evaluating, using a sumcheck protocol, that a relation over multilinear polynomials vanishes when summed over a boolean hypercube. +Honk is a variant of the PLONK protocol. Plonk performs polynomial testing via checking a polynomial relation is zero modulo the vanishing polynomial of a multiplicative subgroup. Honk performs the polynomial testing via checking, using a sumcheck protocol, that a relation over multilinear polynomials vanishes when summed over a boolean hypercube. The first protocol to combine Plonk and the sumcheck protocol was [HyperPlonk](https://eprint.iacr.org/2022/1355) From 980b7feafda7d9bcf7e89bed435b851e97f7a709 Mon Sep 17 00:00:00 2001 From: zac-williamson Date: Wed, 20 Dec 2023 12:59:28 +0000 Subject: [PATCH 13/14] comments, updates --- .../docs/cryptography/performance-targets.md | 50 ++++++++++++------- .../docs/cryptography/protocol-overview.md | 12 ++--- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/yellow-paper/docs/cryptography/performance-targets.md b/yellow-paper/docs/cryptography/performance-targets.md index c3576e794468..4fd98ca7cd2d 100644 --- a/yellow-paper/docs/cryptography/performance-targets.md +++ b/yellow-paper/docs/cryptography/performance-targets.md @@ -7,8 +7,8 @@ Aztec's cryptography tech stack and its associated implementation is an open-end This document is designed to definitively answer the following questions: 1. What are the metrics we care about when measuring our cryptography components? -3. What are minimum satisfiable values for these metrics? -4. What are the aspirational values for these metrics? +1. What are minimum satisfiable values for these metrics? +1. What are the aspirational values for these metrics? # Important Metrics @@ -19,8 +19,8 @@ The following is a list of the relevant properties that affect the performance o * Memory required to generate a user transaction proof * Time to generate an Aztec Virtual Machine proof * Memory required to generate an Aztec Virtual Machine proof -* Time to compute a 2x2 rollup proof -* Memory required to compute a 2x2 rollup proof +* Time to compute a 2-to-1 rollup proof +* Memory required to compute a 2-to-1 rollup proof