<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Santiago Palladino</title>
    <description>The latest articles on DEV Community by Santiago Palladino (@spalladino).</description>
    <link>https://dev.to/spalladino</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1436%2F39e1b060-9c17-43c1-9ca7-205d6908aa73.png</url>
      <title>DEV Community: Santiago Palladino</title>
      <link>https://dev.to/spalladino</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/spalladino"/>
    <language>en</language>
    <item>
      <title>A beginner's intro to coding zero-knowledge proofs</title>
      <dc:creator>Santiago Palladino</dc:creator>
      <pubDate>Thu, 09 Feb 2023 15:11:03 +0000</pubDate>
      <link>https://dev.to/spalladino/a-beginners-intro-to-coding-zero-knowledge-proofs-c56</link>
      <guid>https://dev.to/spalladino/a-beginners-intro-to-coding-zero-knowledge-proofs-c56</guid>
      <description>&lt;p&gt;Zero-knowledge proofs are becoming increasingly popular, but it can be a hard space to navigate and find the resources to &lt;strong&gt;get started as a developer&lt;/strong&gt;. After spending some time studying the topic, I'm compiling here what I learned in hope it helps others. Note from the title that this is a beginner's guide, as in its author (me!) being a beginner on ZKP programming, so please reach out if you find anything off in this article!&lt;/p&gt;

&lt;p&gt;This article will cover what a zero-knowledge proof is, how it is used from a developer's perspective, and go through a few languages for writing them. It will &lt;strong&gt;not&lt;/strong&gt; go through the underlying math: we'll treat ZKPs as a cryptographic black box.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a zero-knowledge proof?
&lt;/h2&gt;

&lt;p&gt;A zero-knowledge proof (ZKP for short) is a &lt;strong&gt;cryptographic proof about a fact that does not reveal any info&lt;/strong&gt; about said fact.&lt;/p&gt;

&lt;p&gt;A classic example to introduce ZKPs is that I (the &lt;strong&gt;prover&lt;/strong&gt;) can prove to you (the &lt;strong&gt;verifier&lt;/strong&gt;) that I know a &lt;a href="https://en.wikipedia.org/wiki/Graph_coloring" rel="noopener noreferrer"&gt;valid coloring for a graph&lt;/a&gt; without revealing it. To do it, we play a game where I color the graph using a random set of colors, then cover it, and you choose an edge at random. If my coloring was valid, then both nodes connected by that edge must have different colors. Then we repeat, with a different set of colors each time, until you are satisfied. Since I re-paint the graph before every round, you &lt;strong&gt;don't learn anything about the coloring&lt;/strong&gt;, but you can verify that it was valid every time.&lt;/p&gt;

&lt;p&gt;Another well-known example of what could be considered a ZKP is a &lt;strong&gt;digital signature&lt;/strong&gt;: I can produce a proof that I hold a secret string (my private key) that corresponds to a public one (my public key) by signing a message, and that signature does not reveal any bits from my private key.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a zkSNARK?
&lt;/h2&gt;

&lt;p&gt;SNARK stands for &lt;em&gt;Succinct Non-interactive ARgument of Knowledge&lt;/em&gt;. The important bits here are the first two words: &lt;strong&gt;succinct&lt;/strong&gt; and &lt;strong&gt;non-interactive&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A proof is &lt;strong&gt;succinct&lt;/strong&gt; if it's, well, &lt;em&gt;small&lt;/em&gt;. This means that, regardless of the complexity of the fact that we are proving, we can keep proofs small and quick to verify. This is what makes ZKPs attractive for &lt;a href="https://ethereum.org/en/developers/docs/scaling/zk-rollups/" rel="noopener noreferrer"&gt;building rollups&lt;/a&gt;: you can generate a succinct proof that all operations that occurred on the L2 chain were valid, succinct enough that you can verify it in a contract on L1. Protocols like &lt;a href="https://minaprotocol.com/lightweight-blockchain" rel="noopener noreferrer"&gt;Mina&lt;/a&gt; take this to the extreme with &lt;a href="https://minaprotocol.com/blog/meet-pickles-snark-enabling-smart-contracts-on-coda-protocol" rel="noopener noreferrer"&gt;recursive proofs&lt;/a&gt;, which allow them to prove the validity of the entire history of the chain with a &lt;strong&gt;constant-size proof&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;As for &lt;strong&gt;non-interactivity&lt;/strong&gt;, just think how cumbersome it would be to deal with signatures if you needed the signer to be online every single time someone needed to verify it. In the examples above, the graph coloring proof was interactive, requiring an online game between the &lt;em&gt;prover&lt;/em&gt; and the &lt;em&gt;verifier&lt;/em&gt;. Fortunately, zkSNARKs do not have this requirement.&lt;/p&gt;

&lt;h3&gt;
  
  
  ZKPs flavors
&lt;/h3&gt;

&lt;p&gt;Turns out that zkSNARKs are not the only kind of interesting ZKPs. There are also &lt;a href="https://vitalik.ca/general/2017/11/09/starks_part_1.html" rel="noopener noreferrer"&gt;&lt;strong&gt;STARKs&lt;/strong&gt;&lt;/a&gt; (pioneered by &lt;a href="https://starkware.co/" rel="noopener noreferrer"&gt;Starkware&lt;/a&gt; and used to power &lt;a href="https://starkware.co/starknet/" rel="noopener noreferrer"&gt;Starknet&lt;/a&gt;) and &lt;a href="https://crypto.stanford.edu/bulletproofs/#:~:text=Compared%20to%20SNARKs%2C%20Bulletproofs%20require,in%20Bitcoin%20and%20other%20cryptocurrencies." rel="noopener noreferrer"&gt;&lt;strong&gt;Bulletproofs&lt;/strong&gt;&lt;/a&gt; (used in &lt;a href="(https://web.getmonero.org/resources/moneropedia/bulletproofs.html)"&gt;Monero&lt;/a&gt;). These differ in the running time for generating and verifying a proof, as well as the resulting proof size, or in the need for trusted setups (more on this in the next section). &lt;a href="https://matter-labs.io/" rel="noopener noreferrer"&gt;MatterLabs&lt;/a&gt; has a great comparison between them &lt;a href="https://github.com/matter-labs/awesome-zero-knowledge-proofs#comparison-of-the-most-popular-zkp-systems" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Even within SNARKs, you'll find that there are multiple flavors. &lt;a href="https://eprint.iacr.org/2016/260.pdf" rel="noopener noreferrer"&gt;&lt;strong&gt;Groth16&lt;/strong&gt;&lt;/a&gt; is one of the most popular. The &lt;a href="https://eprint.iacr.org/2019/953.pdf" rel="noopener noreferrer"&gt;&lt;strong&gt;PLONK&lt;/strong&gt;&lt;/a&gt; family, which includes &lt;a href="https://docs.zkproof.org/pages/standards/accepted-workshop3/proposal-turbo_plonk.pdf" rel="noopener noreferrer"&gt;TurboPLONK&lt;/a&gt; and &lt;a href="https://twitter.com/aztecnetwork/status/1303315879392874496?lang=en" rel="noopener noreferrer"&gt;UltraPLONK&lt;/a&gt;, can remove the need for a circuit-specific trusted setup at the expense of proof generation and verification time, or add support for new types of operations. &lt;/p&gt;

&lt;p&gt;Furthermore, there are different &lt;strong&gt;elliptic curves&lt;/strong&gt; to pick from, or different &lt;strong&gt;polynomial commitment schemes&lt;/strong&gt; that can be used. &lt;a href="https://docs.gnark.consensys.net/" rel="noopener noreferrer"&gt;Consensys Gnark&lt;/a&gt; provides a great explainer on SNARK proving schemes and curves &lt;a href="https://docs.gnark.consensys.net/Concepts/schemes_curves" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Usually, picking a ZKP language to work with will determine which ZK backend you end up using, though there are some like Circom or Gnark that &lt;a href="https://iden3.io/circom#:~:text=Integration%20with%20Zero%2DKnowledge%20SNARK%20proving%20systems" rel="noopener noreferrer"&gt;support more than a single proving system&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Trusted setup
&lt;/h3&gt;

&lt;p&gt;Some flavors of proving systems require what's called a &lt;a href="https://vitalik.ca/general/2022/03/14/trustedsetup.html" rel="noopener noreferrer"&gt;&lt;strong&gt;trusted setup&lt;/strong&gt;&lt;/a&gt;. A trusted setup is a one-time ceremony, run by multiple participants, which produces a set of random values that power the ZK proving system. &lt;/p&gt;

&lt;p&gt;These ceremonies are critical because if all of its participants collude they can break the proving system. Here, &lt;em&gt;breaking the proving&lt;/em&gt; system means being able to generate a proof for an invalid claim that gets accepted by the verifier. Fortunately, having just one honest participant does the trick: that's why you'll find &lt;a href="https://blog.ethereum.org/2023/01/16/announcing-kzg-ceremony" rel="noopener noreferrer"&gt;calls for as many community members as possible&lt;/a&gt; to participate in such a ceremony.&lt;/p&gt;

&lt;p&gt;Certain flavors, like Groth16, require &lt;strong&gt;a trusted setup for each circuit&lt;/strong&gt;: this means that, for every program you code, you need to run a new ceremony. Others, like PLONK, need just &lt;strong&gt;one universal trusted setup&lt;/strong&gt; that can be reused on any program built with that flavor. And others, like STARKs, &lt;strong&gt;don't need any trusted setup at all&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Constraints
&lt;/h3&gt;

&lt;p&gt;The main thing you need to know about ZKPs internals is that the proof operates on a mathematical &lt;strong&gt;constraint system&lt;/strong&gt;. In other words, prover engines do not deal with code like &lt;code&gt;x := y * z&lt;/code&gt;, but with constraints of the form &lt;code&gt;x - y * z = 0&lt;/code&gt;. Depending on the language you're working with and the prover backend, these may impact how you structure your code.&lt;/p&gt;

&lt;p&gt;For instance, Circom only allows you to write &lt;a href="https://docs.circom.io/getting-started/writing-circuits/" rel="noopener noreferrer"&gt;quadratic expressions&lt;/a&gt; on your variables, whereas Halo2 lets you write &lt;a href="https://zcash.github.io/halo2/concepts/arithmetization.html" rel="noopener noreferrer"&gt;polynomial constraints of any degree&lt;/a&gt;. As we'll see later, one of the outputs of compiling a program in a ZKP language will be the set of constraints.&lt;/p&gt;

&lt;p&gt;This has the implication that certain operations are easier to represent in a ZKP than others: addition can be represented in a single constraint, whereas bit manipulation may require hundreds, as every bit may need to be represented as a separate variable. This is the reason why specific cryptographic primitives are typically chosen when working on ZKPs. As an example, &lt;a href="https://iden3-docs.readthedocs.io/en/latest/iden3_repos/research/publications/zkproof-standards-workshop-2/pedersen-hash/pedersen.html" rel="noopener noreferrer"&gt;Pedersen hashes&lt;/a&gt; are hash functions that can be represented in an arithmetic circuit much more efficiently than keccak, so they are frequently found in ZKPs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Finite fields
&lt;/h3&gt;

&lt;p&gt;Another important bit you need to know is that constraints operate in a &lt;strong&gt;finite field&lt;/strong&gt; of a size determined by the underlying elliptic curve. What this means is that all arithmetic operations are computed modulo a certain value, meaning they will wrap-around that value. Don't worry though, this value is usually large enough. For instance, in Circom it is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;21888242871839275222246405745257275088548364400416034343698204186575808495617
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This also means that, if you want to define specific thresholds for your integer variables, you'll need to add extra constraints for it. Some languages like Noir &lt;a href="https://noir-lang.org/language_concepts/data_types.html#integer-types" rel="noopener noreferrer"&gt;will do it for you&lt;/a&gt;, whereas others will require you to &lt;a href="https://github.com/starkware-libs/cairo-lang/blob/de741b92657f245a50caab99cfaef093152fd8be/src/starkware/cairo/common/uint256.cairo" rel="noopener noreferrer"&gt;do it manually&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why all the buzz?
&lt;/h2&gt;

&lt;p&gt;ZKPs have drawn a lot of attention lately. The main reason is that they can be used as a means to &lt;strong&gt;cheaply verify any computation&lt;/strong&gt;, effectively becoming a general-purpose cryptographic building block. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/gubsheep" rel="noopener noreferrer"&gt;Gubsheep&lt;/a&gt; describes ZKPs as &lt;a href="https://archive.devcon.org/archive/watch/6/zkps-and-programmable-cryptography/?tab=YouTube" rel="noopener noreferrer"&gt;&lt;strong&gt;programmable cryptography&lt;/strong&gt;&lt;/a&gt;, in the sense that you can use them to program cryptographic proofs for general problems. For instance, you could prove set membership using &lt;a href="https://en.wikipedia.org/wiki/Ring_signature" rel="noopener noreferrer"&gt;ring signatures&lt;/a&gt; which are specifically built to tackle that problem, or just &lt;a href="https://youtu.be/SJKBQ0krciw?t=253" rel="noopener noreferrer"&gt;coding a zkSNARK circuit for it&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;In the &lt;a href="https://archive.devcon.org/archive/watch/6/what-to-know-about-zero-knowledge/?tab=YouTube" rel="noopener noreferrer"&gt;Devcon6 panel on Zero Knowledge&lt;/a&gt;, there's a great point made about their power in enabling &lt;strong&gt;interoperability&lt;/strong&gt; across different systems: once you have a system that can verify a ZKP, then you can verify that any other system with any computational environment behaved as expected, as long as you can express its computation as a ZKP. This is what powers zk-rollups: if you can write the rules of your chain as a ZKP, then you can push that proof to Ethereum and verify it on the EVM - even if your rollup doesn't use the EVM as an execution environment!&lt;/p&gt;

&lt;h2&gt;
  
  
  What does a circuit look like?
&lt;/h2&gt;

&lt;p&gt;Let's now look into how all this works. The first step is to write a program in your ZK language or framework of choice, such as Circom, Halo2, or Noir. These programs are often referred to as &lt;strong&gt;circuits&lt;/strong&gt;, which express constraints among your set of variables, or &lt;strong&gt;signals&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;For example, we can build a circuit in Circom that lets us prove that we know two numbers, &lt;code&gt;a&lt;/code&gt;  and &lt;code&gt;b&lt;/code&gt;, such that &lt;code&gt;c = (a*b)^2&lt;/code&gt;, without revealing them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;template MultiplierSq() {
  signal input a;
  signal input b;
  signal ab;
  signal output c;
  ab &amp;lt;== a * b;
  c &amp;lt;== ab * ab;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are defining two private input signals, an intermediate variable, and an output value. Note that, since Circom does not allow us to write anything more complex than quadratic constraints, we cannot directly write &lt;code&gt;c &amp;lt;== (a*b)^2&lt;/code&gt;, that's why we need the intermediate &lt;code&gt;ab&lt;/code&gt; signal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating and verifying a proof
&lt;/h3&gt;

&lt;p&gt;The workflow for using a ZKP circuit is not the same as a regular program, since we have two different agents: the &lt;strong&gt;prover&lt;/strong&gt; and the &lt;strong&gt;verifier&lt;/strong&gt;. And even within the prover, there are multiple steps involved to generate the proof. Let's go through them:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We first write and &lt;strong&gt;compile the circuit&lt;/strong&gt;. This outputs several artifacts, such as the set of constraints defined by the circuit, and a script or binary to be used in the step below.&lt;/li&gt;
&lt;li&gt;Depending on the SNARK flavor being used, it may be necessary to run a &lt;strong&gt;trusted setup ceremony&lt;/strong&gt; to generate the proving and verifying keys, which are cryptographic material required for the proving and verifying process, as their names imply.&lt;/li&gt;
&lt;li&gt;When interacting with our zk-app, the user enters the private and public inputs for the circuit. The first step is to &lt;strong&gt;"execute" the circuit as if it were a program&lt;/strong&gt;, using the script or binary generated during compilation. This calculates the values for all intermediate and output variables, given the input. In the example above, given &lt;code&gt;a = 2&lt;/code&gt; and &lt;code&gt;b = 3&lt;/code&gt;, it will calculate that &lt;code&gt;ab = 6&lt;/code&gt; and &lt;code&gt;c = 36&lt;/code&gt;. This assignment of every signal to its concrete value is called a &lt;strong&gt;witness&lt;/strong&gt; or &lt;strong&gt;trace&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Given the trace from step 3 and the proving key from step 2, the prover can now generate a &lt;strong&gt;zero-knowledge proof&lt;/strong&gt; that all the constraints defined in the circuit hold, and only reveals the output value &lt;code&gt;c&lt;/code&gt;. This proof can now be sent to the verifier.&lt;/li&gt;
&lt;li&gt;The verifier, using the submitted proof and the verifying key, can now &lt;strong&gt;verify that the proof is correct&lt;/strong&gt; for its public output. In our examples, the verifier can cryptographically check that the prover knows three values (&lt;code&gt;a&lt;/code&gt;, &lt;code&gt;b&lt;/code&gt;, &lt;code&gt;ab&lt;/code&gt;) such that &lt;code&gt;a * b = ab&lt;/code&gt; and &lt;code&gt;ab * ab = c&lt;/code&gt;, where &lt;code&gt;c = 36&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Keep in mind that the verification step is cheap, so the verifier can be run as an EVM smart contract. This allows to &lt;strong&gt;trustlessly verify any off-chain computation&lt;/strong&gt; that can be expressed as a ZKP.&lt;/p&gt;

&lt;p&gt;If you want to try out the workflow above yourself, I strongly reccomend &lt;strong&gt;Circom's &lt;a href="https://docs.circom.io/getting-started/installation/" rel="noopener noreferrer"&gt;getting started guide&lt;/a&gt;&lt;/strong&gt; that will take you through the necessary steps. In Circom, compiling a circuit will output a WASM or a C++ program that computes the witness, as well as a &lt;a href="https://medium.com/@VitalikButerin/quadratic-arithmetic-programs-from-zero-to-hero-f6d558cea649#5539" rel="noopener noreferrer"&gt;R1CS representation&lt;/a&gt; that, together with the &lt;a href="https://docs.circom.io/getting-started/proving-circuits/#powers-of-tau" rel="noopener noreferrer"&gt;trusted setup ceremony&lt;/a&gt;, outputs the proving and verifying keys. Then, in order to &lt;a href="https://docs.circom.io/getting-started/proving-circuits/#generating-a-proof" rel="noopener noreferrer"&gt;generate the proof&lt;/a&gt;, you supply the calculated witness and the proving key. To verify it, just use the generated proof along with the verifying key. You can also &lt;a href="https://docs.circom.io/getting-started/proving-circuits/#verifying-from-a-smart-contract" rel="noopener noreferrer"&gt;autogenerate a Solidity contract&lt;/a&gt; for running the verification on-chain.&lt;/p&gt;

&lt;h2&gt;
  
  
  Execution vs constraints
&lt;/h2&gt;

&lt;p&gt;In the workflow above, you may have noted that the circuit is used twice by the prover: first to generate the witness, and then to derive the constraints that are covered by the proof. These two runs are completely different beasts, and understanding their difference is one of the keys to understanding how ZKPs work.&lt;/p&gt;

&lt;p&gt;Let's go back to our Circom example from before, where we had two instructions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ab &amp;lt;== a * b;
c &amp;lt;== ab * ab;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Circom, a &lt;a href="https://docs.circom.io/circom-language/signals/" rel="noopener noreferrer"&gt;fat arrow is just syntax sugar for two different instructions&lt;/a&gt;, assignment and constrain, so the above can be expanded to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ab &amp;lt;-- a*b
ab === a*b
c &amp;lt;-- ab * ab
c === ab * ab
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;a &amp;lt;-- a*b&lt;/code&gt; instructions means &lt;em&gt;during the execution phase, assign &lt;code&gt;a*b&lt;/code&gt; to &lt;code&gt;ab&lt;/code&gt;&lt;/em&gt;, and gets ignored when compiling the constraints. On the other hand, &lt;code&gt;ab === a*b&lt;/code&gt; means &lt;em&gt;add a constraint that forces &lt;code&gt;ab&lt;/code&gt; to be equal to &lt;code&gt;a*b&lt;/code&gt;&lt;/em&gt;, which gets ignored during execution. In other words, when writing a circuit &lt;strong&gt;you're writing two different programs, that belong to two different programming paradigms, in a single one&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;While you will usually write assignments and constraints that are equivalent, sometimes you need to split them up. A good example of this is the &lt;code&gt;IsZero&lt;/code&gt; circuit.&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;IsZero&lt;/code&gt; circuit
&lt;/h3&gt;

&lt;p&gt;Writing a circuit that outputs 1 if an input signal is zero and 0 otherwise is surprisingly difficult when you are constrained (pun intended) to just quadratic expressions. If you are thinking of using an expression like &lt;code&gt;x === 0&lt;/code&gt;, note that that will not return a boolean on whether &lt;code&gt;x&lt;/code&gt; is zero or not, but instead it will constrain the signal &lt;code&gt;x&lt;/code&gt; to be zero in this circuit.&lt;/p&gt;

&lt;p&gt;Fortunately, Circom has a &lt;a href="https://github.com/iden3/circomlib" rel="noopener noreferrer"&gt;library&lt;/a&gt; of useful building blocks that includes an &lt;a href="https://github.com/iden3/circomlib/blob/master/circuits/comparators.circom" rel="noopener noreferrer"&gt;&lt;code&gt;IsZero&lt;/code&gt;&lt;/a&gt; circuit that returns &lt;code&gt;0&lt;/code&gt; or &lt;code&gt;1&lt;/code&gt; depending on whether the input is zero, and looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;template IsZero() {
  signal input in;
  signal output out;
  signal inv;

  inv &amp;lt;-- in!=0 ? 1/in : 0;
  out &amp;lt;-- -in*inv +1;
  out === -in*inv +1;
  in*out === 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a good example of decoupling execution and constraints in a circuit. Let's begin analyzing the constraints. The constraint &lt;code&gt;in * out = 0&lt;/code&gt;  tells us that &lt;code&gt;in&lt;/code&gt; or &lt;code&gt;out&lt;/code&gt; is zero. If &lt;code&gt;in&lt;/code&gt; is zero, then &lt;code&gt;out = -in * inv + 1 = 1&lt;/code&gt;, so we're good. And if &lt;code&gt;out&lt;/code&gt; is zero, then it follows that &lt;code&gt;in * inv = 1&lt;/code&gt;, which means that &lt;code&gt;in&lt;/code&gt; cannot be zero. Great!&lt;/p&gt;

&lt;p&gt;But note that the actual value of &lt;code&gt;inv&lt;/code&gt; never popped up in our reasoning, since we did not need it. This is valid for writing constraints, but when it comes to populating the trace, it falls short. We need to tell Circom how to calculate the value for &lt;code&gt;inv&lt;/code&gt; in the witness generation phase: that's where the &lt;code&gt;inv &amp;lt;-- in!=0 ? 1/in : 0&lt;/code&gt; expression comes in. Cairo appropriately calls this sort of expressions &lt;a href="https://www.cairo-lang.org/docs/how_cairo_works/hints.html" rel="noopener noreferrer"&gt;&lt;em&gt;hints&lt;/em&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Note that we're using operations much more complex than a quadratic expression here: we have a conditional, a comparison, and a division. This is because the &lt;strong&gt;execution phase is unrelated to the constraints&lt;/strong&gt;, and as such, is &lt;strong&gt;not bound by the restrictions of generating a ZKP&lt;/strong&gt;. So we are back to pretty much usual programming when working in the execution phase, having access to additional operators, control flow statements, or even &lt;a href="https://docs.circom.io/circom-language/functions/" rel="noopener noreferrer"&gt;auxiliary functions&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Underconstrained computation bugs
&lt;/h3&gt;

&lt;p&gt;However, this difference between execution and constraint generation phases can open the door to a very nasty kind of bugs. Going &lt;a href="https://twitter.com/smpalladino/status/1607483400021241856" rel="noopener noreferrer"&gt;back to the &lt;code&gt;IsZero&lt;/code&gt; example&lt;/a&gt;, &lt;strong&gt;what would have happened if we forgot to write one of the constraints&lt;/strong&gt;, say the &lt;code&gt;in*out = 0&lt;/code&gt; one? &lt;/p&gt;

&lt;p&gt;Let's follow the workflow we know, assuming &lt;code&gt;in=3&lt;/code&gt; as input:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The circuit would have compiled fine, since there are no errors.&lt;/li&gt;
&lt;li&gt;Witness generation would have followed the execution instructions, and correctly calculated the values &lt;code&gt;inv=3^-1, out=0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The prover would have generated a proof based on the witness and the public output, since the constraint &lt;code&gt;out = -in*inv +1&lt;/code&gt; holds.&lt;/li&gt;
&lt;li&gt;The verifier would have accepted it as valid, trusting that the prover has a private non-zero value.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So far so good. But what happens if a &lt;strong&gt;malicious prover wants to convince us that they have a zero value&lt;/strong&gt;, when they actually have &lt;code&gt;in=3&lt;/code&gt;? Remember we don't have the &lt;code&gt;in*out = 0&lt;/code&gt; in this thought experiment.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The malicious user can manually craft a witness where &lt;code&gt;in=3, inv=0, out=1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Since the witness satisfies the constraint &lt;code&gt;out = -in*inv +1&lt;/code&gt;, the prover can generate a proof for it.&lt;/li&gt;
&lt;li&gt;The verifier happily accepts it, and &lt;strong&gt;believes that the user has a zero value when they actually don't&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This kind of issues, dubbed &lt;a href="https://consensys.net/diligence/blog/2022/01/under-constrained-computation-a-new-kind-of-bug/" rel="noopener noreferrer"&gt;under-constrained computation&lt;/a&gt;, are particularly hard to catch. Any unit test that treats the circuit as a black box would never trigger them, as they use the circuit's execution logic to build the witness, which will pass the constraints. The only way to reproduce them is to &lt;a href="https://twitter.com/BlakeMScurr/status/1607525340876001281" rel="noopener noreferrer"&gt;manually assemble a witness with custom logic&lt;/a&gt;, which requires that you exactly know the attack you are looking for.&lt;/p&gt;

&lt;p&gt;Alternatively, there are efforts for verifying the soundness of a circuit you've written with regard to the function you want to encode, such as &lt;a href="https://twitter.com/SentientRosbot/status/1607722581431570434" rel="noopener noreferrer"&gt;Ecne&lt;/a&gt;, whcih I still have to try out.&lt;/p&gt;

&lt;p&gt;The bottom line here is that you should be particularly &lt;strong&gt;careful when you write execution code separate from your constraint generation code&lt;/strong&gt;, since it opens the door to underconstrained ZK programs.&lt;/p&gt;

&lt;h2&gt;
  
  
  A real-world example
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/tornadocash/tornado-core" rel="noopener noreferrer"&gt;Tornado Cash&lt;/a&gt; is a great learning resource on how to build a real-world zk-app with Circom circuits. I strongly recommend going through the &lt;a href="https://berkeley-defi.github.io/assets/material/Tornado%20Cash%20Whitepaper.pdf" rel="noopener noreferrer"&gt;3-page-long white paper&lt;/a&gt;, as well as Gubsheep's &lt;a href="https://learn.0xparc.org/materials/circom/learning-group-1/breaking-down-tornado" rel="noopener noreferrer"&gt;breaking down Tornado Cash&lt;/a&gt; session from the 0xparc course, plus Porter's &lt;a href="https://www.youtube.com/video/jGmvJZ7m7WU/livestreaming" rel="noopener noreferrer"&gt;overview of the white paper&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The gist of Tornado, in case you are not familiar with it, is that you can deposit ETH in discrete amounts (there are &lt;em&gt;notes&lt;/em&gt; of 0.1, 1, 10, and 100 ETH) into a contract, and later anonymously withdraw each note into other addresses. This has the effect of mixing your notes with those from other people, granting anonimity as long as there is enough usage.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does it work?
&lt;/h3&gt;

&lt;p&gt;For the sake of the explanation, we'll go through a slightly simplified version of the protocol, and follow &lt;a href="https://docs.google.com/presentation/d/1lmMImuT-OO-5igzRFxi1XZsc9ryfhHTiUXuEwAkX6Uk/edit#slide=id.p" rel="noopener noreferrer"&gt;Gubsheep's version&lt;/a&gt; instead of the one actually implemented.&lt;/p&gt;

&lt;p&gt;Whenever a user wants to deposit a note, they generate a &lt;em&gt;secret&lt;/em&gt; value &lt;code&gt;s&lt;/code&gt;, and submit their 1 ETH note along with a hash of the secret &lt;code&gt;H(s)&lt;/code&gt; to the contract. The contract collects all submitted secret hashes into a merkle tree, and stores its root &lt;code&gt;R&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now, when a user wants to withdraw their note, they need to prove that they have the secret that corresponds to &lt;code&gt;H(s)&lt;/code&gt;. To do this, the user submits a ZKP that shows that they know a private value &lt;code&gt;s&lt;/code&gt; such that &lt;code&gt;H(s)&lt;/code&gt; is in the merkle tree of root &lt;code&gt;R&lt;/code&gt;. It is not revealed &lt;em&gt;which&lt;/em&gt; of all the leaves of the tree is the user' s &lt;code&gt;H(s)&lt;/code&gt;, as the ZKP only public output is &lt;code&gt;R&lt;/code&gt;, so this preserves anonimity. The merkle proof is &lt;a href="https://github.com/tornadocash/tornado-core/blob/master/circuits/merkleTree.circom" rel="noopener noreferrer"&gt;checked by a circuit&lt;/a&gt; in the ZKP.&lt;/p&gt;

&lt;p&gt;We also need a way to ensure that a user cannot withdraw the same note twice. Here is where the concept of &lt;em&gt;nullifier&lt;/em&gt; comes in. A nullifier is a value, deterministically generated from the original secret, that is tracked to prevent double-spends. &lt;/p&gt;

&lt;p&gt;So, in addition to proving membership to the merkle tree of root &lt;code&gt;R&lt;/code&gt;, the ZKP also outputs a value &lt;code&gt;G(s)&lt;/code&gt; to be used as a nullifier, where &lt;code&gt;G&lt;/code&gt; is another hash function different to &lt;code&gt;H&lt;/code&gt;. Then, whenever a note is withdrawn, its nullifier is added to a nullifier set in the smart contract, and the withdrawal is rejeted if it already exists. Note that &lt;code&gt;G&lt;/code&gt; needs to be different to &lt;code&gt;H&lt;/code&gt;, otherwise the ZKP would reveal &lt;code&gt;H(s)&lt;/code&gt;, which can be traced back to the original deposit and break anonimity.&lt;/p&gt;

&lt;p&gt;In other words, whenever a user wants to withdraw, they submit a ZKP that states that &lt;strong&gt;they know a secret value that's in a merkle tree of root &lt;code&gt;R&lt;/code&gt;, and exposes the nullifier of that secret value&lt;/strong&gt;. Then the contract can check that the merkle root matches and the nullifier hasn't been used it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you went through Tornado's white paper, you'll note that the nullifier concept is where their implementation diverges from what we described here. Tornado actually uses two different secret values, called randomness &lt;code&gt;r&lt;/code&gt; and nullifier &lt;code&gt;k&lt;/code&gt;, and the public value they store is called the &lt;em&gt;nullifier hash&lt;/em&gt;. Tornado also uses a single hash function (Pedersen hashes) instead of two different ones, and they compute the merkle tree leaf as &lt;code&gt;H(r || k)&lt;/code&gt; and the nullifier hash as &lt;code&gt;H(k)&lt;/code&gt;. The important thing is that the nullifier cannot be linked back to the merkle tree leaf, and that it is deterministically generated from the secret. You can check out Tornado's full circuits in Circom &lt;a href="https://github.com/tornadocash/tornado-core/blob/master/circuits/withdraw.circom" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Languages for ZKPs
&lt;/h2&gt;

&lt;p&gt;There are multiple languages and frameworks that you can choose from for writing ZK circuits, either general purpose (like Circom) or specific to a certain platform (like Cairo). I have tried out three different languages, &lt;strong&gt;Circom, Halo2, and Noir&lt;/strong&gt;, and &lt;a href="https://github.com/spalladino/zkp-tests" rel="noopener noreferrer"&gt;implemented the same circuit&lt;/a&gt; to &lt;a href="https://twitter.com/smpalladino/status/1606056973270556672" rel="noopener noreferrer"&gt;compare them&lt;/a&gt;. The circuit proves that the user knows the results of a private set of rock-paper-scissors matches, such that the total score matches a public output. The score is calculated as specified in the definition of &lt;a href="https://adventofcode.com/2022/day/2" rel="noopener noreferrer"&gt;advent of code 2022 day 2&lt;/a&gt;, which I used for inspiration for the problem.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Your total score is the sum of your scores for each round. The score for a single round is the score for the shape you selected (1 for Rock, 2 for Paper, and 3 for Scissors) plus the score for the outcome of the round (0 if you lost, 3 if the round was a draw, and 6 if you won).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;What follows is an overview of each language, my personal impression of it, and how the rock-paper-scissors circuit looks like in it. Keep in mind I'm a beginner in all of them, so there may be errors. Please reach out if you find any so I can fix this article.&lt;/p&gt;

&lt;p&gt;Other languages and frameworks I still have to try out are &lt;a href="https://github.com/Zokrates/ZoKrates" rel="noopener noreferrer"&gt;Zokrates&lt;/a&gt;, &lt;a href="https://www.cairo-lang.org/" rel="noopener noreferrer"&gt;Cairo&lt;/a&gt;, &lt;a href="https://docs.minaprotocol.com/zkapps/snarkyjs-reference" rel="noopener noreferrer"&gt;SnarkyJS&lt;/a&gt;, &lt;a href="https://docs.gnark.consensys.net/" rel="noopener noreferrer"&gt;Gnark&lt;/a&gt;, and &lt;a href="https://www.aleo.org/post/leo-programming-language" rel="noopener noreferrer"&gt;Leo&lt;/a&gt;. I hope to update this post as I go through them!&lt;/p&gt;

&lt;h3&gt;
  
  
  Circom
&lt;/h3&gt;

&lt;p&gt;I found &lt;a href="https://docs.circom.io/" rel="noopener noreferrer"&gt;Circom&lt;/a&gt; to be the best language to start learning ZKPs, as suggested by &lt;a href="https://twitter.com/cyber_porter/status/1598428022465449984" rel="noopener noreferrer"&gt;CyberPorter&lt;/a&gt;. To me, &lt;strong&gt;Circom has the ideal level of abstraction for learning&lt;/strong&gt;: not too high level that it abstracts away some of the quirks of ZKP, and not too low level that you get bogged down in annoying details. It also has been around for quite some time (modulo how new everything ZK is!), so you can find more documentation and samples, as well as the &lt;a href="https://learn.0xparc.org/circom/" rel="noopener noreferrer"&gt;awesome Circom workshops&lt;/a&gt; from &lt;a href="https://0xparc.org/" rel="noopener noreferrer"&gt;0xparc&lt;/a&gt;. Last but not least, there is &lt;a href="https://github.com/iden3/circomlib" rel="noopener noreferrer"&gt;circomlib&lt;/a&gt;, a library of common building blocks for Circom.&lt;/p&gt;

&lt;p&gt;Circom ships with a &lt;a href="https://docs.circom.io/getting-started/installation/#installing-circom" rel="noopener noreferrer"&gt;rust-based compiler CLI&lt;/a&gt;, plus an &lt;a href="https://www.npmjs.com/package/snarkjs" rel="noopener noreferrer"&gt;npm package&lt;/a&gt; for trusted setups and proof generation and verification. The benefit of having an npm package is that you can &lt;strong&gt;generate proofs in the browser&lt;/strong&gt;, opening the door to building zk-apps. You can also autogenerate Solidity contracts for verifying proofs on-chain. Circom also lets you to choose your proving engine between Groth16 and PLONK.&lt;/p&gt;

&lt;p&gt;As mentioned before, in Circom you work assembling &lt;strong&gt;circuits&lt;/strong&gt;, where each circuit has a set of input, internal, and output &lt;a href="https://docs.circom.io/circom-language/signals/" rel="noopener noreferrer"&gt;signals&lt;/a&gt;. Circuits are defined as &lt;a href="https://docs.circom.io/circom-language/templates-and-components/" rel="noopener noreferrer"&gt;templates&lt;/a&gt;, which can be parameterized with values known at compile-time, which are similar to C++ &lt;a href="https://en.cppreference.com/w/cpp/language/function_template" rel="noopener noreferrer"&gt;function templates&lt;/a&gt;. Circom also has the concept of &lt;a href="https://docs.circom.io/circom-language/functions/" rel="noopener noreferrer"&gt;functions&lt;/a&gt; as a reusable building block in the execution phase.&lt;/p&gt;

&lt;p&gt;The main challenges are Circom is &lt;strong&gt;understanding when you are writing constraint-generation code, and when you are writing witness-generation code&lt;/strong&gt;, and tracking &lt;strong&gt;what values are &lt;a href="https://docs.circom.io/circom-language/circom-insight/unknowns/" rel="noopener noreferrer"&gt;known at compile-time&lt;/a&gt;&lt;/strong&gt; versus only known at runtime. Many language constructs are only available for witness generation, like &lt;a href="https://docs.circom.io/circom-language/basic-operators/" rel="noopener noreferrer"&gt;boolean or comparison operators&lt;/a&gt;, or can only depend on values known at compile-time, such as &lt;a href="https://docs.circom.io/circom-language/control-flow/" rel="noopener noreferrer"&gt;control flow statements&lt;/a&gt;. Also, keeping in mind the difference between constraint and witness generation times can guard you against underconstrained computation bugs.&lt;/p&gt;

&lt;h4&gt;
  
  
  Rock-paper-scissors in Circom
&lt;/h4&gt;

&lt;p&gt;The &lt;a href="https://github.com/spalladino/zkp-tests/blob/master/circom/circuits/advent2.circom" rel="noopener noreferrer"&gt;circuits for the rock-paper-scissors problem&lt;/a&gt; were fun to write in Circom. Since it's not possible to write conditional expressions in constraints, you need to resort to math-based tricks. As a simple example, the first circuit, which validates the input of a play by checking that it is 0, 1, or 2, looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;template AssertIsRPS() {
  signal input x;
  signal isRP &amp;lt;== (x-0) * (x-1);
  isRP * (x-2) === 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code for &lt;a href="https://github.com/spalladino/zkp-tests/blob/c36b23f83240140e0dfd7730194ab188b442abb8/circom/circuits/advent2.circom#L30-L61" rel="noopener noreferrer"&gt;calculating the score of a single round&lt;/a&gt; uses similar constructs, along with the &lt;a href="https://github.com/iden3/circomlib/blob/cff5ab6288b55ef23602221694a6a38a0239dcc0/circuits/comparators.circom#L37-L46" rel="noopener noreferrer"&gt;&lt;code&gt;IsEqual&lt;/code&gt; circuit from CircomLib&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Returns the score for a single round, given the plays by x and y
template Round() {
  signal input x, y;
  signal output out;

  // ensure that each input is within 0,1,2
  AssertIsRPS()(x);
  AssertIsRPS()(y);

  // check if match was a draw
  signal isDraw &amp;lt;== IsEqual()([x, y]);

  signal diffYX &amp;lt;== (y+3)-x;

  // y wins if y-x = 1 mod 3
  signal yWins1 &amp;lt;== (diffYX-1) * (diffYX-4);
  signal yWins &amp;lt;== IsZero()(yWins1);

  // x wins if y-x = 2 mod 3
  signal xWins1 &amp;lt;== (diffYX-2) * (diffYX-5);
  signal xWins &amp;lt;== IsZero()(xWins1);

  // check that exactly one of xWins, yWins, isDraw is true
  // we probably can do without these constraints
  signal xOrYWins &amp;lt;== (xWins - 1) * (yWins - 1);
  xOrYWins * (isDraw - 1) === 0;
  xWins + yWins + isDraw === 1;

  // score is 6 if y wins, 3 if draw, 0 if x wins
  // plus 1, 2, 3 depending on the choice of RPS
  out &amp;lt;== yWins * 6 + isDraw * 3 + y + 1;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, the &lt;a href="https://github.com/spalladino/zkp-tests/blob/c36b23f83240140e0dfd7730194ab188b442abb8/circom/circuits/advent2.circom#L65-L78" rel="noopener noreferrer"&gt;outermost circuit&lt;/a&gt; loops through a parameterizable number of rounds &lt;code&gt;n&lt;/code&gt;, and aggregates all scores. Note that a loop can be used here since it depends on &lt;code&gt;n&lt;/code&gt;, which is a template parameter known at compile-time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;template Game(n) {
  signal input xs[n];
  signal input ys[n];
  signal scores[n];
  signal output out;

  var score = 0;
  for (var i = 0; i &amp;lt; n; i++) {
    scores[i] &amp;lt;== Round()(xs[i], ys[i]);
    score += scores[i];
  }

  out &amp;lt;== score;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Halo2
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://zcash.github.io/halo2/" rel="noopener noreferrer"&gt;Halo2&lt;/a&gt; is not a language but a Rust-based framework, maintained by the ZCash team. Halo2 is specific to &lt;a href="https://www.youtube.com/watch?v=lDL-sirFB-Y" rel="noopener noreferrer"&gt;PLONKish&lt;/a&gt;, giving you very direct control of how &lt;a href="https://zcash.github.io/halo2/concepts/arithmetization.html" rel="noopener noreferrer"&gt;circuits are represented in the arithmetization&lt;/a&gt;. This makes Halo2 very low-level, but ideal for writing highly optimized circuits.&lt;/p&gt;

&lt;p&gt;To me, Halo2 had the steepest learning curve by far. Not just because of having to understand how PLONKish arithmetization works to build the circuits, but mostly because I found Halo2's API quite complex and its documentation hard to find. There are also few resources for learning Halo2: the best I found were the &lt;a href="https://learn.0xparc.org/halo2/" rel="noopener noreferrer"&gt;0xparc course&lt;/a&gt; which provides a few &lt;a href="https://github.com/icemelon/halo2-examples" rel="noopener noreferrer"&gt;really valuable code samples&lt;/a&gt;, as well as &lt;a href="https://github.com/zcash/halo2/tree/main/halo2_proofs/examples" rel="noopener noreferrer"&gt;the examples in the main repo&lt;/a&gt;. You may also want to check out &lt;a href="https://github.com/adria0/awesome-halo2" rel="noopener noreferrer"&gt;awesome-halo2&lt;/a&gt; for updated resources.&lt;/p&gt;

&lt;p&gt;When starting with Halo2, keep in mind that there are &lt;strong&gt;two flavors of the framework&lt;/strong&gt; out there: the &lt;a href="https://github.com/zcash/halo2" rel="noopener noreferrer"&gt;vanilla one&lt;/a&gt; maintained by ZCash, and the &lt;a href="https://github.com/privacy-scaling-explorations/halo2" rel="noopener noreferrer"&gt;fork&lt;/a&gt; by &lt;a href="https://appliedzkp.org/" rel="noopener noreferrer"&gt;Ethereum's Privacy and Scaling Explorations team&lt;/a&gt; which uses a different polynomial commitment (&lt;a href="https://dankradfeist.de/ethereum/2020/06/16/kate-polynomial-commitments.html" rel="noopener noreferrer"&gt;KZG&lt;/a&gt; instead of &lt;a href="https://dankradfeist.de/ethereum/2021/07/27/inner-product-arguments.html" rel="noopener noreferrer"&gt;IPA&lt;/a&gt;) that's more friendly for Ethereum.&lt;/p&gt;

&lt;h4&gt;
  
  
  PLONKish arithmetization
&lt;/h4&gt;

&lt;p&gt;The key to building circuits in Halo2 is to begin by designing how the &lt;a href="https://zcash.github.io/halo2/concepts/arithmetization.html" rel="noopener noreferrer"&gt;&lt;strong&gt;underlying PLONKish matrix&lt;/strong&gt;&lt;/a&gt; will look like. In PLONKish, circuits are defined over a matrix that you directly define. This matrix is composed by multiple columns, where a column may represent a public output (called &lt;strong&gt;instance&lt;/strong&gt;), a private witness value (called &lt;strong&gt;advice&lt;/strong&gt;), a constant value (called &lt;strong&gt;fixed&lt;/strong&gt;), a flag on whether a constraint is enabled (called &lt;strong&gt;selector&lt;/strong&gt;, more on this below), or a &lt;a href="https://learn.0xparc.org/materials/halo2/learning-group-1/exercise-3/" rel="noopener noreferrer"&gt;&lt;strong&gt;lookup&lt;/strong&gt; value&lt;/a&gt; (used for &lt;a href="https://zcash.github.io/halo2/user/lookup-tables.html" rel="noopener noreferrer"&gt;lookup tables&lt;/a&gt;, an advanced feature).&lt;/p&gt;

&lt;p&gt;Once you have the matrix set up, it's time to define the polynomial constraints using &lt;strong&gt;gates&lt;/strong&gt;. A gate in Halo2 defines one or more constraints to be applied over a set of cells in the matrix. Each gate is controlled via a &lt;strong&gt;selector&lt;/strong&gt; column: if the selector is enabled at a row, then the constraints imposed by the gate relative to that row will be enforced. &lt;/p&gt;

&lt;p&gt;A gate can define constraints across multiple rows. For example, here's an example of an L-shaped multiplication gate &lt;a href="https://zcash.github.io/halo2/user/simple-example.html#configure-the-chip" rel="noopener noreferrer"&gt;straight out of the Halo2 book&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;meta.create_gate("mul", |meta| {
    // To implement multiplication, we need three advice cells and a selector
    // cell. We arrange them like so:
    //
    // | a0  | a1  | s_mul |
    // |-----|-----|-------|
    // | lhs | rhs | s_mul |
    // | out |     |       |
    //
    // Gates may refer to any relative offsets we want, but each distinct
    // offset adds a cost to the proof. The most common offsets are 0 (the
    // current row), 1 (the next row), and -1 (the previous row), for which
    // `Rotation` has specific constructors.
    let lhs = meta.query_advice(advice[0], Rotation::cur());
    let rhs = meta.query_advice(advice[1], Rotation::cur());
    let out = meta.query_advice(advice[0], Rotation::next());
    let s_mul = meta.query_selector(s_mul);

    // Finally, we return the polynomial expressions that constrain this gate.
    // For our multiplication gate, we only need a single polynomial constraint.
    //
    // The polynomial expressions returned from `create_gate` will be
    // constrained by the proving system to equal zero. Our expression
    // has the following properties:
    // - When s_mul = 0, any value is allowed in lhs, rhs, and out.
    // - When s_mul != 0, this constrains lhs * rhs = out.
    vec![s_mul * (lhs * rhs - out)]
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code sample above, &lt;code&gt;a0&lt;/code&gt; and &lt;code&gt;a1&lt;/code&gt; are advice columns, and &lt;code&gt;s_mul&lt;/code&gt; is the selector that defines whether the &lt;code&gt;mul&lt;/code&gt; multiplication gate will be enforced. If it is, then the value for &lt;code&gt;a0&lt;/code&gt; &lt;em&gt;in the next row&lt;/em&gt; will be constrained to be equal to the product of &lt;code&gt;a0&lt;/code&gt; and &lt;code&gt;a1&lt;/code&gt; on the current row.&lt;/p&gt;

&lt;p&gt;In addition, Halo2 allows you to define &lt;a href="https://docs.rs/halo2_proofs/0.2.0/halo2_proofs/circuit/struct.AssignedCell.html#method.copy_advice" rel="noopener noreferrer"&gt;&lt;strong&gt;equality constraints&lt;/strong&gt;&lt;/a&gt;, where you require that a specific cell in your matrix must be equal to another. This is useful for "copying" values across your matrix, or for constraining a public &lt;em&gt;instance&lt;/em&gt; cell to equal a specific private &lt;em&gt;advice&lt;/em&gt; cell in order to expose a value.&lt;/p&gt;

&lt;p&gt;As another example, you could define a circuit for &lt;a href="https://github.com/icemelon/halo2-tutorial/blob/master/src/example1.rs" rel="noopener noreferrer"&gt;proving the N-th Fibonacci number&lt;/a&gt;, where row &lt;code&gt;i&lt;/code&gt; of the matrix has the values &lt;code&gt;x[i-2], x[i-1], x[i]&lt;/code&gt;. This means you'd need three &lt;em&gt;advice&lt;/em&gt; columns to begin with, let's call them &lt;a href="https://github.com/icemelon/halo2-tutorial/blob/c9ceff8733a9a5033532502f92c7f68ee8a43f7a/src/example1.rs#L41-L43" rel="noopener noreferrer"&gt;&lt;code&gt;a, b, c&lt;/code&gt;&lt;/a&gt;. Then, you'd &lt;a href="https://github.com/icemelon/halo2-tutorial/blob/c9ceff8733a9a5033532502f92c7f68ee8a43f7a/src/example1.rs#L53-L60" rel="noopener noreferrer"&gt;constrain &lt;code&gt;c&lt;/code&gt; to be equal to &lt;code&gt;a + b&lt;/code&gt;&lt;/a&gt; in the same row using a &lt;em&gt;gate&lt;/em&gt;, which requires adding a &lt;a href="https://github.com/icemelon/halo2-tutorial/blob/c9ceff8733a9a5033532502f92c7f68ee8a43f7a/src/example1.rs#L45" rel="noopener noreferrer"&gt;&lt;em&gt;selector&lt;/em&gt; column&lt;/a&gt; for &lt;a href="https://github.com/icemelon/halo2-tutorial/blob/c9ceff8733a9a5033532502f92c7f68ee8a43f7a/src/example1.rs#L77-L78" rel="noopener noreferrer"&gt;controlling it&lt;/a&gt;. And you'd have to &lt;a href="https://github.com/icemelon/halo2-tutorial/blob/c9ceff8733a9a5033532502f92c7f68ee8a43f7a/src/example1.rs#L119-L120" rel="noopener noreferrer"&gt;set up &lt;em&gt;equality constraints&lt;/em&gt;&lt;/a&gt; so that &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; are equal to &lt;code&gt;b&lt;/code&gt; and &lt;code&gt;c&lt;/code&gt; from the previous row. Last, in order to &lt;a href="https://github.com/icemelon/halo2-tutorial/blob/c9ceff8733a9a5033532502f92c7f68ee8a43f7a/src/example1.rs#L182" rel="noopener noreferrer"&gt;expose the N-th number as a public value&lt;/a&gt;, you'd need an &lt;a href="https://github.com/icemelon/halo2-tutorial/blob/c9ceff8733a9a5033532502f92c7f68ee8a43f7a/src/example1.rs#L44" rel="noopener noreferrer"&gt;&lt;em&gt;instance&lt;/em&gt; column&lt;/a&gt;, constrained to &lt;a href="https://github.com/icemelon/halo2-tutorial/blob/c9ceff8733a9a5033532502f92c7f68ee8a43f7a/src/example1.rs#L139" rel="noopener noreferrer"&gt;equal the value of &lt;code&gt;c&lt;/code&gt; at the last row&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Chips, gadgets, and regions
&lt;/h4&gt;

&lt;p&gt;The main building blocks for circuits in Halo2 are &lt;a href="https://docs.rs/halo2_gadgets/0.2.0/halo2_gadgets/" rel="noopener noreferrer"&gt;gadgets and chips&lt;/a&gt;. &lt;a href="https://zcash.github.io/halo2/concepts/chips.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Chips&lt;/strong&gt;&lt;/a&gt; are the lowest level unit. A chip will typically expose a method for configuring its gates, as well as multiple methods for assigning values to its cells during synthesis (more on this phase below). You can also build chips composed out of other chips. &lt;a href="https://zcash.github.io/halo2/concepts/gadgets.html" rel="noopener noreferrer"&gt;&lt;strong&gt;Gadgets&lt;/strong&gt;&lt;/a&gt;, on the other hand, operate at a higher level of abstraction, hiding the underlying chips' implementation details, though you can build your circuits directly out of chips and &lt;a href="https://zcash.github.io/halo2/user/gadgets.html" rel="noopener noreferrer"&gt;skip gadgets altogether&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To promote reusability, you'll notice that chips always operate over &lt;em&gt;relative offsets&lt;/em&gt;. This allows multiple chips to be grouped into &lt;a href="https://docs.rs/halo2_proofs/0.2.0/halo2_proofs/circuit/trait.Layouter.html#tymethod.assign_region" rel="noopener noreferrer"&gt;&lt;strong&gt;regions&lt;/strong&gt;&lt;/a&gt; in a circuit. Once all regions and their shapes have been defined, it is the responsibility of a &lt;a href="https://docs.rs/halo2_proofs/0.2.0/halo2_proofs/plonk/trait.FloorPlanner.html" rel="noopener noreferrer"&gt;&lt;strong&gt;floor planner&lt;/strong&gt;&lt;/a&gt; to arrange these regions on the matrix, so you don't need to directly define where each chip is actually placed. However, depending on how you structure your circuits, it is perfectly possible to pack everything into a single region and not delegate placement to the planner.&lt;/p&gt;

&lt;h4&gt;
  
  
  Halo2 Rust API
&lt;/h4&gt;

&lt;p&gt;In Halo2, similar to Circom, the main thing to keep in mind is that &lt;strong&gt;your code will be invoked multiple times in different circumstances&lt;/strong&gt;: whether it is to configure the matrix, generate the constraints, create a proof, or calculate a witness.&lt;/p&gt;

&lt;p&gt;Your circuits need to implement a &lt;a href="https://docs.rs/halo2_proofs/0.2.0/halo2_proofs/plonk/trait.Circuit.html" rel="noopener noreferrer"&gt;specific &lt;code&gt;Circuit&lt;/code&gt; trait&lt;/a&gt; that defines methods that will be called throughout this lifecycle, either with concrete or unknown &lt;a href="https://docs.rs/halo2_proofs/0.2.0/halo2_proofs/circuit/struct.Value.html" rel="noopener noreferrer"&gt;&lt;code&gt;Value&lt;/code&gt;s&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;pub&lt;/span&gt; &lt;span class="k"&gt;trait&lt;/span&gt; &lt;span class="n"&gt;Circuit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Clone&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;FloorPlanner&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FloorPlanner&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;without_witnesses&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;ConstraintSystem&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;synthesize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;Self&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;layouter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;Layouter&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;F&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important bits here are &lt;code&gt;configure&lt;/code&gt; and &lt;code&gt;synthesize&lt;/code&gt;. The TLDR is that &lt;code&gt;configure&lt;/code&gt; will set up the matrix shape and its gates, and &lt;code&gt;synthesize&lt;/code&gt; will calculte the witness and populate the matrix with the corresponding values. However, &lt;code&gt;synthesize&lt;/code&gt; may also be invoked with unknown values during other stages, so you need to always work with wrapped &lt;a href="https://docs.rs/halo2_proofs/0.2.0/halo2_proofs/circuit/struct.Value.html" rel="noopener noreferrer"&gt;&lt;code&gt;Value&lt;/code&gt;s&lt;/a&gt;. For instance, and while it may seem anti-intuitive, polynomial constraints in gates are defined during &lt;em&gt;configuration&lt;/em&gt;, but equality constraints are set up at &lt;em&gt;synthesis&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://zcash.github.io/halo2/user/simple-example.html" rel="noopener noreferrer"&gt;example&lt;/a&gt; in the Halo2 book has a good step by step on how to implement a simple circuit with a single chip in case you need a scaffold to follow.&lt;/p&gt;

&lt;h4&gt;
  
  
  Rock-paper-scissors in Halo2
&lt;/h4&gt;

&lt;p&gt;The &lt;a href="https://github.com/spalladino/zkp-tests/blob/c36b23f83240140e0dfd7730194ab188b442abb8/halo2/src/advent2.rs" rel="noopener noreferrer"&gt;RPS implementation in Halo2&lt;/a&gt; is much more verbose than in Circom, so we'll only reproduce some parts here. To begin with, the matrix is set up with the following columns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An advice column for each of the two players, &lt;code&gt;xs&lt;/code&gt; and &lt;code&gt;ys&lt;/code&gt;, where the value in row &lt;code&gt;i&lt;/code&gt; represents what move the player chose in round &lt;code&gt;i&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A third advice column &lt;code&gt;accum&lt;/code&gt; that tracks the accumulated total score, so row &lt;code&gt;i&lt;/code&gt; contains the sum of the scores of all rounds up to &lt;code&gt;i&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;A public instance column, where the last cell is constrained to be equal to the value of &lt;code&gt;accum&lt;/code&gt;, so only the total score is revealed and not the intermediate ones.&lt;/li&gt;
&lt;li&gt;A selector for enabling the single gate that validates inputs and calculates the score of each round.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;a href="https://github.com/spalladino/zkp-tests/blob/c36b23f83240140e0dfd7730194ab188b442abb8/halo2/src/advent2.rs#L31-L91" rel="noopener noreferrer"&gt;main chip&lt;/a&gt; defines a custom gate that packs all constraints for each round: validating that inputs are in range, and calculating the score for the round and adding it to the accumulated total score. This chip uses the values of &lt;code&gt;xs&lt;/code&gt;, &lt;code&gt;ys&lt;/code&gt;, and &lt;code&gt;accum&lt;/code&gt; in a row as "inputs", and "outputs" the new score in the &lt;code&gt;accum&lt;/code&gt; column at the next row.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="nf"&gt;.create_gate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"round"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="nf"&gt;.query_selector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="nf"&gt;.query_advice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;col_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Rotation&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="nf"&gt;.query_advice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;col_y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Rotation&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;accum&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="nf"&gt;.query_advice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;col_accum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Rotation&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="c1"&gt;// We store the output in the accum column in the next row&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="nf"&gt;.query_advice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;col_accum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Rotation&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

    &lt;span class="c1"&gt;// Constraints for each round&lt;/span&gt;
    &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="c1"&gt;// out = y_wins * 6 + is_draw * 3 + y + 1 + accum&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y_wins&lt;/span&gt;&lt;span class="nf"&gt;.expr&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nn"&gt;F&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;is_draw&lt;/span&gt;&lt;span class="nf"&gt;.expr&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nn"&gt;F&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;const_val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;accum&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="c1"&gt;// x in (0,1,2)&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;const_val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;const_val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="c1"&gt;// y in (0,1,2)&lt;/span&gt;
        &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;const_val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;const_val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;y_wins&lt;/code&gt; and &lt;code&gt;is_draw&lt;/code&gt; above are &lt;code&gt;IsZero&lt;/code&gt; chips defined like the following. Note that we can reuse the same selector column for all constraints, since there is no row in which we would want to enable some but disable others.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// yWins &amp;lt;==&amp;gt; (y+2-x) * (y-1-x) == 0;&lt;/span&gt;
&lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;y_wins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;IsZeroChip&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;configure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="nf"&gt;.query_selector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; 
    &lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="nf"&gt;.query_advice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;col_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Rotation&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="nf"&gt;.query_advice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;col_y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Rotation&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;cur&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;const_val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nf"&gt;const_val&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When synthesizing the circuit, we loop over the inputs for each round, calculate the accumulated score, and assign the calculated values to our matrix. Note that, for the "execution" mode, we can directly use conditional expressions to calculate the score.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Assign one row per round&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;ys&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;]];&lt;/span&gt; 

  &lt;span class="c1"&gt;// Enable the selector for the round gate&lt;/span&gt;
  &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.config.selector&lt;/span&gt;&lt;span class="nf"&gt;.enable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// This is requiring us to add a constant column to the chip config just with zeros&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="nf"&gt;.assign_advice_from_constant&lt;/span&gt;&lt;span class="p"&gt;(||&lt;/span&gt; &lt;span class="s"&gt;"zero"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;col_accum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;F&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ZERO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Set x and y advice columns to the input values&lt;/span&gt;
  &lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="nf"&gt;.assign_advice&lt;/span&gt;&lt;span class="p"&gt;(||&lt;/span&gt; &lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"x[{}]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="n"&gt;col_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;,||&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="nf"&gt;.assign_advice&lt;/span&gt;&lt;span class="p"&gt;(||&lt;/span&gt; &lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"y[{}]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;&lt;span class="n"&gt;col_y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;,||&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Assign the is_zero chips to the same expressions defined in the gates&lt;/span&gt;
  &lt;span class="c1"&gt;// yWins &amp;lt;==&amp;gt; (y+2-x) * (y-1-x) == 0;&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;y_wins_chip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;IsZeroChip&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y_wins&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;y_wins_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nn"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;known&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;F&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nn"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;known&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;F&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ONE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;y_wins&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y_wins_chip&lt;/span&gt;&lt;span class="nf"&gt;.assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_wins_value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// isDraw &amp;lt;==&amp;gt; y-x == 0;&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;is_draw_chip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;IsZeroChip&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_draw&lt;/span&gt;&lt;span class="nf"&gt;.clone&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;is_draw_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;is_draw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;is_draw_chip&lt;/span&gt;&lt;span class="nf"&gt;.assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;is_draw_value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Calculate the score of this round&lt;/span&gt;
  &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;round_score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y_wins&lt;/span&gt;&lt;span class="nf"&gt;.zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;is_draw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.and_then&lt;/span&gt;&lt;span class="p"&gt;(|(&lt;/span&gt;&lt;span class="n"&gt;y_wins&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;is_draw&lt;/span&gt;&lt;span class="p"&gt;)|&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;partial_score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;y_wins&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;is_draw&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="nn"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;known&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;F&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;partial_score&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nn"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;known&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;F&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ONE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Assign the col_accum *in the next row* to the new score&lt;/span&gt;
  &lt;span class="n"&gt;accum_value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;accum_value&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;round_score&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="n"&gt;out_cell&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;region&lt;/span&gt;&lt;span class="nf"&gt;.assign_advice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="nd"&gt;format!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"out[{}]"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="n"&gt;col_accum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="n"&gt;accum_value&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last bit is exposing the total score as a public output of the circuit, by &lt;a href="https://docs.rs/halo2_proofs/0.2.0/halo2_proofs/circuit/trait.Layouter.html#tymethod.constrain_instance" rel="noopener noreferrer"&gt;constraining the instance column&lt;/a&gt; to match the &lt;code&gt;accum&lt;/code&gt; one in the last row of the matrix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="n"&gt;layouter&lt;/span&gt;&lt;span class="nf"&gt;.constrain_instance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;out_cell&lt;/span&gt;&lt;span class="nf"&gt;.cell&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.config.instance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Noir
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://aztec.network/noir/" rel="noopener noreferrer"&gt;Noir&lt;/a&gt;, built by &lt;a href="https://aztec.network/" rel="noopener noreferrer"&gt;Aztec&lt;/a&gt;, is the newest language of the pack and is under active development. It is distributed as &lt;code&gt;nargo&lt;/code&gt;, a &lt;a href="https://noir-lang.org/getting_started/nargo/installation.html" rel="noopener noreferrer"&gt;rust-based CLI&lt;/a&gt;, and as a set of &lt;a href="https://noir-lang.org/getting_started/typescript.html" rel="noopener noreferrer"&gt;npm packages&lt;/a&gt;. The npm packages releases seem to lag slightly behind the crate, which has the bleeding edge features and only got &lt;a href="https://github.com/noir-lang/noir/releases/tag/v0.1.0" rel="noopener noreferrer"&gt;its first stable release&lt;/a&gt; a few days ago (early February). Both the rust crate and the npm package can be used to compile Noir programs, generate and verify proofs, and create a verifier Solidity contract.&lt;/p&gt;

&lt;p&gt;Noir is heavily inspired in Rust, as in it shares almost the same syntax. It supports integer, booleans, tuples, structs, and arrays, as well as a basic &lt;a href="https://noir-lang.org/language_concepts/data_types.html#the-field-type" rel="noopener noreferrer"&gt;&lt;code&gt;field&lt;/code&gt; type&lt;/a&gt; which represents an element in the native field of the proving backend (think an unsigned int capped to a big prime of about 254 bits), and is more performant than regular integers.&lt;/p&gt;

&lt;p&gt;Unlike Circom, &lt;strong&gt;Noir does not allow you to define code used only for witness generation&lt;/strong&gt; (aka hints). Noir supports control flow statements and operators out of the box, and converts them to equivalent constraints as needed. This helps prevent any unconstrained computation bugs, at the expense of performance. That said, you &lt;em&gt;can&lt;/em&gt; define constraints unrelated to witness generation, using the special &lt;a href="https://noir-lang.org/language_concepts/constrain.html" rel="noopener noreferrer"&gt;&lt;code&gt;constrain&lt;/code&gt; keyword&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Rock-paper-scissors in Noir
&lt;/h4&gt;

&lt;p&gt;Noir feels a bit like cheating compared to the other languages, since it abstracts away most complexities related to ZKPs, and feels like writing regular Rust code. The entirety of the program fits in 30 lines, and reads like a regular program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;global N: Field = 3;

#[builtin(arraylen)]
fn len&amp;lt;T&amp;gt;(_input : [T]) -&amp;gt; comptime Field {}

fn round(x: Field, y: Field) -&amp;gt; Field {
    constrain (x as u8) &amp;lt;= 2;
    constrain (y as u8) &amp;lt;= 2;

    let mut score = 0;
    let diffYX = (y + 3 - x);

    if x == y {
        score = 3;
    }    
    if (diffYX == 4) | (diffYX == 1) {
        score = 6;
    }

    score + y + 1
}

fn main(xs: [Field; N], ys: [Field; N]) -&amp;gt; pub Field {
    let mut result = 0;

    for i in 0..len(xs) {
        result = result + round(xs[i], ys[i]);
    }
    result
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's worth mentioning that I didn't run any analysis regarding the number of constraints generated by each language, but it is expected that Noir, given its higher abstraction level, produces a higher number of constraints, which impact proving time. Nevertheless, as the compiler matures, more optimizations should be added that get automatically incorporated to Noir-written programs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;If you got to this point and want to keep learning, here are some of the resources I used for getting up to speed with ZKPs. I encourage you to go through them if you want to learn directly from the masters!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://twitter.com/cyber_porter" rel="noopener noreferrer"&gt;CyberPorter&lt;/a&gt; produced &lt;a href="https://twitter.com/smpalladino/status/1599836549000024064" rel="noopener noreferrer"&gt;a set of 6 classes&lt;/a&gt; that provide a great overview of ZKPs, including the motivation, a mapping of the space and who's working on it, a deep dive on TornadoCash, an overview of Circom, Cairo, SnarkyJS, and Noir, and a walkthrough of the math behind Groth16.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://learn.0xparc.org/" rel="noopener noreferrer"&gt;0xPARC&lt;/a&gt; has two full courses online, one on Circom and another on Halo2. I strongly recommend starting with the Circom one, led mostly by the great &lt;a href="https://twitter.com/gubsheep" rel="noopener noreferrer"&gt;Gubsheep&lt;/a&gt;, the guy behind the &lt;a href="https://zkga.me/" rel="noopener noreferrer"&gt;Dark Forest game&lt;/a&gt;. These courses include hands-on workshops that take you step by step on how to build several circuits. If you want to take a stab at Halo2, I'd say they are a must-see, since there are not many other resoruces on it.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://vitalik.ca/" rel="noopener noreferrer"&gt;Vitalik&lt;/a&gt; has multiple blog posts on pretty much every cryptographic concept you need for understanding SNARKs and STARKs, as well as interesting &lt;a href="https://vitalik.ca/general/2022/06/15/using_snarks.html" rel="noopener noreferrer"&gt;uses&lt;/a&gt; for the tech. If you want to go deeper into the workings of ZKPs, search on his blog first.&lt;/li&gt;
&lt;li&gt;The &lt;a href="https://scroll.io/" rel="noopener noreferrer"&gt;Scroll team&lt;/a&gt;, who are building a ZK-EVM, run an excellent educational blog when it comes to ZKPs. In particular, the article on &lt;a href="https://scroll.io/blog/proofGeneration" rel="noopener noreferrer"&gt;proof generation&lt;/a&gt; provides a great step-by-step on the whole workflow involved when creating a ZKP.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/sindresorhus/awesome" rel="noopener noreferrer"&gt;Awesome lists&lt;/a&gt; are awesome, and &lt;a href="https://matter-labs.io/" rel="noopener noreferrer"&gt;Matter Labs&lt;/a&gt;, the team behind zkSync, keeps an &lt;a href="https://github.com/matter-labs/awesome-zero-knowledge-proofs" rel="noopener noreferrer"&gt;awesome-zero-knowledge-proofs&lt;/a&gt; with links to all kind of resources.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>zeroknowledge</category>
      <category>circom</category>
      <category>halo2</category>
      <category>noir</category>
    </item>
    <item>
      <title>A look into formal verification of smart contracts using Certora</title>
      <dc:creator>Santiago Palladino</dc:creator>
      <pubDate>Fri, 02 Dec 2022 18:27:40 +0000</pubDate>
      <link>https://dev.to/spalladino/a-look-into-formal-verification-of-smart-contracts-using-certora-3o8g</link>
      <guid>https://dev.to/spalladino/a-look-into-formal-verification-of-smart-contracts-using-certora-3o8g</guid>
      <description>&lt;p&gt;&lt;em&gt;This is an overview of how smart contract formal verification works using Certora. It is definitely not an in-depth review of either Certora or formal verification techniques, of which I'm not an expert. Special thanks to Shelly Grossman and Nurit Dor from Certora for reviewing this article.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In software, we rely on automated tests for checking if our code matches our expectations. Testing helps guide development and uncover bugs, but a green test run only means that our tests haven't stumbled upon any issues for the scenario we chose. It certainly does not mean that our code is correct.&lt;/p&gt;

&lt;p&gt;Formal verification is a more powerful method that can mathematically prove that our code adheres to a specification. As described in &lt;a href="https://ethereum.org/en/developers/docs/smart-contracts/formal-verification/" rel="noopener noreferrer"&gt;"Formal verification of smart contracts"&lt;/a&gt; on ethereum.org:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Formal verification refers to the process of evaluating the correctness of a system with respect to a formal specification. In simpler terms, formal verification allows us to check if the behavior of a system satisfies some requirements (i.e., it does what we want).&lt;/p&gt;

&lt;p&gt;When implemented in smart contracts, formal verification can prove that a contract's business logic meets a predefined specification. Compared to other methods for assessing the correctness of contract code, such as testing, formal verification gives stronger guarantees that a smart contract is functionally correct.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Given how critical blockchain applications can be, smart contracts are fertile ground for formal verification. The deterministic and bounded execution in the EVM also make formal methods easier to apply. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://certora.com/" rel="noopener noreferrer"&gt;&lt;strong&gt;Certora&lt;/strong&gt;&lt;/a&gt; is one of the players in this field, offering a platform for formal verification using a proprietary spec language, &lt;a href="https://docs.certora.com" rel="noopener noreferrer"&gt;Certora Verification Language&lt;/a&gt; or CVL. These specifications are uploaded, along with the smart contract code, to a proprietary cloud-based platform for verification. Given how resource-intensive formal proofs can be, these are not suited for running locally.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FWCPh7AM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FWCPh7AM.png" alt="Example spec run for an ERC20Permit contract"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Under the hood, Certora generates a set of constraints out of decompiled EVM bytecode and the CVL specs, which are then passed through an SMT solver. But this is out of scope for this article: refer to their &lt;a href="https://medium.com/certora/certora-technology-white-paper-cae5ab0bdf1" rel="noopener noreferrer"&gt;whitepaper&lt;/a&gt; for an in-depth explanation of how it works. So let's jump directly onto the formal specs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does a spec look like in CVL?
&lt;/h2&gt;

&lt;p&gt;The main building block of CVL is a &lt;a href="https://docs.certora.com/en/latest/docs/user-guide/bank/index.html#rules-in-the-certora-verification-language" rel="noopener noreferrer"&gt;&lt;strong&gt;rule&lt;/strong&gt;&lt;/a&gt;. Rules are structured as &lt;a href="https://en.wikipedia.org/wiki/Hoare_logic" rel="noopener noreferrer"&gt;Hoare triples&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;precondition&lt;/strong&gt; defines the current state of the contract&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;operation&lt;/strong&gt; is executed on the contract&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;postcondition&lt;/strong&gt; asserts properties on the resulting state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As an example, taken from &lt;a href="https://github.com/Certora/Tutorials/tree/master/01.Lesson_GettingStarted/BankLesson1" rel="noopener noreferrer"&gt;Certora's tutorials&lt;/a&gt; (most examples in this article will be copied or adapted from it), let's say we have a Bank contract that receives and stores deposits from users. We want to verify that, after every deposit, the total funds deposited are greater than every individual user balance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rule totalFundsAfterDeposit(env e, uint256 amount) {
  uint256 userFundsBefore = getFunds(e, e.msg.sender);
  uint256 totalBefore = getTotalFunds(e);

  require totalBefore &amp;gt;= userFundsBefore;

  deposit(e, amount);

  assert getTotalFunds(e) &amp;gt;= getFunds(e, e.msg.sender);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the &lt;code&gt;require&lt;/code&gt; precondition before the action. Preconditions are not just used to set the stage: they are needed to restrict the space of valid states for a contract. Otherwise, the prover assumes that any state is possible when trying to prove the rule, &lt;strong&gt;even unreacheable ones&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The power of this spec is that no matter the initial set of balances, the amount deposited, or the user who sends the deposit, we know that this condition will hold. In a unit test, we'd only be testing this for a specific initial state, with a specific deposit from a specific user. A formal spec proves &lt;strong&gt;this property holds for every single input&lt;/strong&gt; on &lt;strong&gt;every initial state&lt;/strong&gt; covered by the precondition.&lt;/p&gt;

&lt;p&gt;CVL also lets us prove that properties hold no matter what function is called. Much like we are proving our property holds for any deposit amount, we can also &lt;strong&gt;prove it over any function call on the contract&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rule totalFundsAfterAnyAction(env e, method f) {
  uint256 userFundsBefore = getFunds(e, e.msg.sender);
  uint256 totalBefore = getTotalFunds(e);

  require totalBefore &amp;gt;= userFundsBefore;

  calldataargs args;
  f(e, args);

  assert getTotalFunds(e) &amp;gt;= getFunds(e, e.msg.sender);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that we are checking that, given any valid initial state and any action executed, the resulting state is still valid. What we are actually doing here is checking that an &lt;a href="https://en.wikipedia.org/wiki/Invariant_(mathematics)#Invariants_in_computer_science" rel="noopener noreferrer"&gt;&lt;strong&gt;invariant&lt;/strong&gt;&lt;/a&gt; is preserved: a property that should always be true for a given contract. Invariants are a powerful tool when describing a system, and CVL has &lt;a href="https://docs.certora.com/en/latest/docs/user-guide/bank/index.html#invariants" rel="noopener noreferrer"&gt;a native building block&lt;/a&gt; for expressing them:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;invariant totalFundsGreaterThanAnyUser()
    forall address user. getTotalFunds() &amp;gt;= getFunds(user)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When presented with an invariant, the prover will use induction to check it, by verifying that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The property holds once the contract is constructed&lt;/li&gt;
&lt;li&gt;Assuming that the property holds (precondition), invoking any function (operation), the property still holds (postcondition)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pushing the limits
&lt;/h2&gt;

&lt;p&gt;Predicating over all possible values is a powerful primitive, but it has its limitations. For instance, we cannot perform aggregations. Following the previous example, the invariant that &lt;em&gt;total funds are the sum of each individual user funds&lt;/em&gt; cannot be expressed in CVL.&lt;/p&gt;

&lt;p&gt;Fortunately, CVL introduces another concept that allows us to handle these more complex expressions: &lt;a href="https://docs.certora.com/en/latest/docs/cvl/ghosts.html" rel="noopener noreferrer"&gt;&lt;strong&gt;ghosts&lt;/strong&gt;&lt;/a&gt;. Broadly speaking, a &lt;strong&gt;ghost is a variable or function&lt;/strong&gt; defined on CVL that &lt;strong&gt;allows collecting or injecting information into contract "executions"&lt;/strong&gt; during verifications.&lt;/p&gt;

&lt;p&gt;This is easier to understand &lt;a href="https://github.com/Certora/Tutorials/blob/2d12eecd3627d220b5f2839aa4d1035345a7ac61/07.Lesson_InductiveReasoning/Invariants/Bank/invariant.spec#L25-L48" rel="noopener noreferrer"&gt;with an example&lt;/a&gt;. To capture the invariant that &lt;em&gt;total funds are the sum of each individual user funds&lt;/em&gt;, we can declare a ghost that "accumulates" each user deposit &lt;strong&gt;whenever the funds mapping variable is updated&lt;/strong&gt; on the contract, and then compares that to the reported value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ghost sumOfAllFunds() returns uint256{
  init_state axiom sumOfAllFunds() == 0;
}

hook Sstore funds[KEY address user] uint256 newBalance (uint256 oldBalance) STORAGE {
  havoc sumOfAllFunds assuming sumOfAllFunds@new() == sumOfAllFunds@old() + newBalance - oldBalance;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The snippet above is declaring a function &lt;code&gt;sumOfAllFunds&lt;/code&gt; that returns a number, with an initial state of zero, and &lt;strong&gt;gets updated whenever there's a write to storage&lt;/strong&gt; at the &lt;code&gt;funds&lt;/code&gt; mapping, using both the old and new values of the sum and the entry in the mapping. We can now write an invariant that uses this ghost function and matches it to the returned value from the contract:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;invariant totalFunds_GE_to_sum_of_all_funds()
  getTotalFunds() &amp;gt;= sumOfAllFunds()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the snippet above, &lt;code&gt;getTotalFunds&lt;/code&gt; is a call to the contract, which is compared to the ghost &lt;code&gt;sumOfAllFunds&lt;/code&gt; value that we hold in our spec.&lt;/p&gt;

&lt;p&gt;Hooks can also be defined on reads, not just writes. This lets us &lt;strong&gt;inject preconditions upon every value that is read out of storage&lt;/strong&gt;, which can be used to further narrow down the state of the contract that we are verifying.&lt;/p&gt;

&lt;p&gt;Hooks are an interesting tool for enhancing the expresiveness of proofs, but they come at a disadvantage. While rules and invariants are predicated on the external interface of the contract, hooks &lt;strong&gt;bind a spec to implementation details&lt;/strong&gt;. This means a spec that is valid for an implementation may not work on a different one even if they have the same interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Loops and unrolls
&lt;/h2&gt;

&lt;p&gt;Loops are particularly tricky when we have to prove the correctness of an algorithm. The Hoare approach is to devise a &lt;a href="https://en.wikipedia.org/wiki/Loop_invariant" rel="noopener noreferrer"&gt;&lt;em&gt;loop invariant&lt;/em&gt;&lt;/a&gt;, a property that holds across each execution of the loop, and that can be used to prove that the loop finishes and that yields a particular end state.&lt;/p&gt;

&lt;p&gt;However, coming up with a loop invariant &lt;a href="https://www.cs.scranton.edu/~mccloske/courses/cmps144/invariants_lec.html" rel="noopener noreferrer"&gt;is not easy&lt;/a&gt;, and it's much harder to do in an automated way. Therefore, the Certora prover works by &lt;strong&gt;&lt;a href="https://docs.certora.com/en/latest/docs/prover/approx/loops.html" rel="noopener noreferrer"&gt;unrolling loops&lt;/a&gt; a configurable number of times&lt;/strong&gt;. This means that loops get converted into N copies of the body of the loop, and treated as regular non-iterative code.&lt;/p&gt;

&lt;p&gt;Since unrolling a loop a fixed number of times can hide bugs, by default the prover will alert if the loop would have run more times than it was unrolled. But since this is usually the case, the prover is typically run in &lt;a href="https://docs.certora.com/en/latest/docs/prover/cli/options.html#options-regarding-source-code-loops" rel="noopener noreferrer"&gt;optimistic-loop&lt;/a&gt; mode, which removes these alerts - at the cost of potentially hiding bugs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dealing with multiple contracts
&lt;/h2&gt;

&lt;p&gt;A protocol is rarely composed of a single contract. Even though CVL seems to be geared towards testing individual contract properties, it also has tools for managing multiple contracts.&lt;/p&gt;

&lt;p&gt;The simplest option is &lt;strong&gt;&lt;a href="https://docs.certora.com/en/latest/docs/user-guide/multicontract/index.html#working-with-known-contracts" rel="noopener noreferrer"&gt;linking&lt;/a&gt; one contract to another&lt;/strong&gt;. When running the prover, we can tell it that a field in a contract refers to an instance of another known contract. And CVL lets us refer to all registered contracts when writing our rules.&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://docs.certora.com/en/latest/docs/user-guide/multicontract/index.html#working-with-known-contracts" rel="noopener noreferrer"&gt;this example&lt;/a&gt; from Certora's documentation, we are indicating that the &lt;code&gt;asset&lt;/code&gt; field in the &lt;code&gt;Pool&lt;/code&gt; contract refers to an instance of the &lt;code&gt;ERC20&lt;/code&gt; contract:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import "../ERC20.sol";

contract Pool {
  ERC20 asset;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;certoraRun contracts/Pool.sol contracts/ERC20.sol &lt;span class="nt"&gt;--link&lt;/span&gt; Pool:asset&lt;span class="o"&gt;=&lt;/span&gt;ERC20 ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In case we have &lt;strong&gt;multiple implementations&lt;/strong&gt; for a given contract, we can register them all and have the prover try every known implementation that satisfies the required interface. In &lt;a href="https://docs.certora.com/en/latest/docs/user-guide/multicontract/index.html#erc20-dispatcher" rel="noopener noreferrer"&gt;this example&lt;/a&gt;, registering the ERC20 interface methods with the &lt;code&gt;DISPATCHER&lt;/code&gt; keyword instructs the prover to try every ERC20 implementation we have in stock.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;methods {
  totalSupply()                         returns (uint256) =&amp;gt; DISPATCHER(true)
  balanceOf(address)                    returns (uint256) =&amp;gt; DISPATCHER(true)
  allowance(address,address)            returns (uint)    =&amp;gt; DISPATCHER(true)
  approve(address,uint256)              returns (bool)    =&amp;gt; DISPATCHER(true)
  transfer(address,uint256)             returns (bool)    =&amp;gt; DISPATCHER(true)
  transferFrom(address,address,uint256) returns (bool)    =&amp;gt; DISPATCHER(true)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, whenever our &lt;code&gt;Pool&lt;/code&gt; contract being verified makes a call to an ERC20 method, the prover will look for every ERC20 implementation we have and try it.&lt;/p&gt;

&lt;p&gt;But things get messier when &lt;a href="https://docs.certora.com/en/latest/docs/user-guide/multicontract/index.html#working-with-unknown-contracts" rel="noopener noreferrer"&gt;&lt;strong&gt;working with unknown contracts&lt;/strong&gt;&lt;/a&gt;. What happens if we do not know what will be the instance that our contract will be working with? Following the previous example, what if we want to verify our system will work properly with any ERC20 implementation, even one we did not anticipate or a maliciously crafted one?&lt;/p&gt;

&lt;p&gt;As we saw in the example above, the prover works on a method-by-method basis when dealing with external calls. For each method called by the contract being verified, we can &lt;strong&gt;define how we expect that call to behave&lt;/strong&gt;. This is referred to as &lt;a href="https://docs.certora.com/en/latest/docs/cvl/methods.html#summary-types" rel="noopener noreferrer"&gt;summaries&lt;/a&gt; in CVL.&lt;/p&gt;

&lt;p&gt;For example, &lt;a href="https://docs.certora.com/en/latest/docs/cvl/methods.html#view-summaries-always-constant-per-callee-constant-and-nondet" rel="noopener noreferrer"&gt;view functions&lt;/a&gt; can be annotated as returning anything from a constant to a completely non-deterministic value. Here's an example &lt;a href="https://github.com/OpenZeppelin/openzeppelin-contracts/blob/2c5194f3f13d3f9ce301d8100b9f5fe0cec6d7d8/certora/specs/GovernorPreventLateQuorum.spec#L43-L76" rel="noopener noreferrer"&gt;taken from OpenZeppelin contracts&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;methods {
  hashProposal(...) returns (uint256) =&amp;gt; NONDET
  hashOperationBatch(...) =&amp;gt; DISPATCHER(true)
  executeBatch(...) =&amp;gt; CONSTANT
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The main challenge is &lt;a href="https://docs.certora.com/en/latest/docs/cvl/methods.html#havoc-summaries-havoc-all-and-havoc-ecf" rel="noopener noreferrer"&gt;dealing with non-view functions&lt;/a&gt;. The default behavior of the prover is to assume that &lt;strong&gt;an external call can alter all state on every contract &lt;em&gt;but&lt;/em&gt; the caller&lt;/strong&gt;, noted as &lt;code&gt;HAVOC_ECF&lt;/code&gt;. This can lead to state changes in external contracts that are unreachable, making verification more difficult. Furthermore, it assumes that the call is non-reentrant, which in reality is &lt;a href="https://github.com/pcaversaccio/reentrancy-attacks" rel="noopener noreferrer"&gt;a frequent source of attacks&lt;/a&gt;. This last issue can be avoided by indicating that calls &lt;em&gt;can&lt;/em&gt; re-enter, noted as &lt;code&gt;HAVOC_ALL&lt;/code&gt;, but this means that &lt;strong&gt;an external call can mutate any state in any contract, caller included&lt;/strong&gt;. This leaves the contract being verified in a state where we don't know anything about it after an external call is made. This severely limits what we can prove.&lt;/p&gt;

&lt;p&gt;A more reasonable approach is to assume that the callee &lt;em&gt;can&lt;/em&gt; call back into any contract, but restrict it to actual method calls, instead of arbitrary state changes. However, this needs to be handled manually, by &lt;strong&gt;&lt;a href="https://docs.certora.com/en/latest/docs/user-guide/multicontract/index.html#designing-flexible-dispatchees" rel="noopener noreferrer"&gt;writing a contract that calls into each method&lt;/a&gt;&lt;/strong&gt; based on an arbitrary parameter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;contract Receiver is ArbitraryValues {
  ERC20 asset;
  function exec() external {
    uint callback = arbitraryUint();
    if (callback == 0) 
      asset.approve(arbitraryAddress(), arbitraryUint());
    else if (callback == 1) 
      asset.transfer(arbitraryAddress(), arbitraryUint());
    else if (callback == 2) 
      asset.transferFrom(arbitraryAddress(), arbitraryAddress(), arbitraryUint());
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;ArbitraryValues&lt;/code&gt; base contract provides a set of &lt;code&gt;arbitraryValue()&lt;/code&gt; methods that return a non-determistic value whenever we need it. These are used to pick both the method to be called and its arguments.&lt;/p&gt;

&lt;p&gt;Note that this approach &lt;strong&gt;does not cover all possible interactions&lt;/strong&gt;, since we are executing just a single callback, whereas there could be multiple reentrant calls.&lt;/p&gt;

&lt;p&gt;One last approach to working with unknown contract implementations is to &lt;strong&gt;map a method to a function in CVL&lt;/strong&gt;. Whenever that method is called from the contract being verified, the function will be called instead. This allows us to prove that our contract works as expected &lt;em&gt;assuming&lt;/em&gt; that the callee adheres to the spec that has been defined. Note that the callee is not verified here, since there is no implementation to verify it against!&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the best use cases for CVL?
&lt;/h2&gt;

&lt;p&gt;After going through scenarios where we push the limits of CVL, let's close with the scenarios where it really shines. The &lt;a href="https://github.com/Certora/Tutorials/blob/2d12eecd3627d220b5f2839aa4d1035345a7ac61/06.Lesson_ThinkingProperties/Categorizing_Properties.pdf" rel="noopener noreferrer"&gt;presentation on categorizing properties&lt;/a&gt; from Certora's tutorial gives a good overview of these.&lt;/p&gt;

&lt;p&gt;Understanding a smart contract as &lt;strong&gt;a finite-state machine&lt;/strong&gt; (obligatory mention to &lt;a href="https://github.com/pirapira/bamboo/blob/master/doc/manifest.md" rel="noopener noreferrer"&gt;Yoichi's bamboo&lt;/a&gt;, my favorite smart contract programming language that never happened) allows us to define clear rules on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what are the &lt;strong&gt;valid states&lt;/strong&gt; for the contract, and&lt;/li&gt;
&lt;li&gt;what are the &lt;strong&gt;valid transitions&lt;/strong&gt; between those states.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's grab some examples from &lt;a href="https://github.com/OpenZeppelin/openzeppelin-contracts/blob/2c5194f3f13d3f9ce301d8100b9f5fe0cec6d7d8/certora/specs/TimelockController.spec" rel="noopener noreferrer"&gt;OpenZeppelin's TimelockController spec&lt;/a&gt;. In a Timelock, operations can have different states. We can write a rule that checks, for instance, that calling &lt;code&gt;execute&lt;/code&gt; is the only way for moving an operation from &lt;code&gt;ready&lt;/code&gt; to &lt;code&gt;done&lt;/code&gt; state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rule readyDoneTransition(method f, env e){
  bytes32 id;
  require isOperationReady(e, id);

  calldataarg args;
  f(e, args);

  assert isOperationDone(id) =&amp;gt; f.selector == execute(...).selector;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or that &lt;code&gt;done&lt;/code&gt; is a final state: no matter what we call on the contract, a &lt;code&gt;done&lt;/code&gt; proposal will always stay that way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rule doneToNothingTransition(method f, env e){
  bytes32 id;
  require isOperationDone(id);

  calldataarg args;
  f(e, args);

  assert isOperationDone(id);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we can rely on invariants to assert the validity of each of these states (see &lt;a href="https://www.cs.cornell.edu/courses/cs3110/2014sp/lectures/10/representation-invariants.html" rel="noopener noreferrer"&gt;representation invariants&lt;/a&gt;). For instance, an operation is &lt;code&gt;ready&lt;/code&gt; to be executed if and only if its associated timestamp is non-zero and in the past:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;invariant readyCheck(env e, bytes32 id)
  (e.block.timestamp &amp;gt;= getTimestamp(id) &amp;amp;&amp;amp; getTimestamp(id) &amp;gt; 1) 
  &amp;lt;=&amp;gt; isOperationReady(e, id)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another use case is for writing unit-test-like specs. For instance, in an ERC20, we would write a test that the &lt;code&gt;transfer&lt;/code&gt; works: it decreases the balance of the sender and increases the balance of the receiver by the sent amount. We would test it with specific addresses with specific balances and a specific amount. But here we can just write that property, and have the prover &lt;strong&gt;verify it for every possible initial state and input&lt;/strong&gt;, not just the ones we used in the unit test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rule transfer(env e, address recipient, uint256 amount) {
  address holder = e.msg.sender;
  uint256 holderBalanceBefore = balanceOf(holder);
  uint256 recipientBalanceBefore = balanceOf(recipient);

  transfer(e, recipient, amount);

  assert balanceOf(holder)    == holderBalanceBefore    - (holder == recipient ? 0 : amount);
  assert balanceOf(recipient) == recipientBalanceBefore + (holder == recipient ? 0 : amount);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But we can also test more general properties. Following the previous example, we can just check that a &lt;code&gt;transfer&lt;/code&gt; always increases the balance of the recipient and decreases that of the sender.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rule transfer(env e, address recipient, uint256 amount) {
  address holder = e.msg.sender;
  uint256 holderBalanceBefore = balanceOf(holder);
  uint256 recipientBalanceBefore = balanceOf(recipient);

  transfer(e, recipient, amount);

  assert balanceOf(holder) &amp;lt;= holderBalanceBefore;
  assert balanceOf(recipient) &amp;gt;= recipientBalanceBefore;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or that &lt;code&gt;transfer&lt;/code&gt; cannot create new tokens for the sender or recipient, meaning that the sum of their balances must remain constant.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rule transfer(env e, address recipient, uint256 amount) {
  uint256 balanceSenderBefore = balanceOf(e, e.msg.sender);
  uint256 balanceRecipientBefore = balanceOf(e, recipient);
  transfer(e, recipient, amount);

  assert balanceRecipientBefore + balanceSenderBefore == balanceOf(e, e.msg.sender) + balanceOf(e, recipient);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are examples of &lt;strong&gt;high-level properties&lt;/strong&gt; that hold over every execution of a certain operation, like &lt;code&gt;transfer&lt;/code&gt;, or that hold over the entire contract throughout its lifecycle. The latter are best expressed in the form of invariants, as we saw early on with the Bank example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;invariant totalFundsGreaterThanAnyUser()
  forall address user. getTotalFunds() &amp;gt;= getFunds(user)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Learn more
&lt;/h2&gt;

&lt;p&gt;To start playing with CVL, the &lt;a href="https://demo.certora.com/" rel="noopener noreferrer"&gt;demo site&lt;/a&gt; has a great interactive online editor, where you can write your contract and spec side-by-side and run the prover on it, or try out a bunch of examples.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FWxfGdWF.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi.imgur.com%2FWxfGdWF.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Certora's &lt;a href="https://github.com/Certora/Tutorials" rel="noopener noreferrer"&gt;tutorial on github&lt;/a&gt; is also a great starting point for the basic concepts, though the lessons for more advanced ones are still under development. The &lt;a href="https://docs.certora.com/en/latest/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; provides a good overview and reference for many concepts, though it's also a work in progress, and redirects to an older set of docs for the more advanced ones. A &lt;a href="https://github.com/Certora/LiquidityPoolExample" rel="noopener noreferrer"&gt;multi-contract example&lt;/a&gt; repo is a good complement to see the documented concepts in action.&lt;/p&gt;

&lt;p&gt;But when you are ready to move on from the tutorial and docs, the best source for learning are the &lt;strong&gt;actual specs for real-life projects&lt;/strong&gt;, &lt;a href="https://github.com/OpenZeppelin/openzeppelin-contracts/blob/formal-verification/certora/specs" rel="noopener noreferrer"&gt;OpenZeppelin Contracts&lt;/a&gt; and &lt;a href="https://www.certora.com/dashboards/aave-dashboard/" rel="noopener noreferrer"&gt;AAVE&lt;/a&gt; being good examples.&lt;/p&gt;

</description>
      <category>ethereum</category>
      <category>formalverification</category>
      <category>smartcontracts</category>
    </item>
    <item>
      <title>Type-checking Lambda permissions with Typescript</title>
      <dc:creator>Santiago Palladino</dc:creator>
      <pubDate>Fri, 04 Nov 2022 14:00:00 +0000</pubDate>
      <link>https://dev.to/spalladino/type-checking-lambda-permissions-with-typescript-2de7</link>
      <guid>https://dev.to/spalladino/type-checking-lambda-permissions-with-typescript-2de7</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;With Typescript, we can define the permissions granted to our lambda functions in our serverless apps using types. This lets us &lt;strong&gt;type-check access to resources&lt;/strong&gt;, raising at compile-time any errors caused by missing permissions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// We define our app permissions as objects&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ProductsAccess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;Products&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MailerAccess&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;Mailer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// And we restrict access to any resource by requiring those permissions&lt;/span&gt;
&lt;span class="nx"&gt;getProductStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_policy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;ProductsAccess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;DynamoProductStore&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;getMailService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_policy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;MailerAccess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;SESMailer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Then we define the type of policies required by our lambda as an argument&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;lambdaHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;policies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;ProductsAccess&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// And use those policies when requesting access to a resource&lt;/span&gt;
  &lt;span class="c1"&gt;// so the compiler catches if we try to access a resource for which we don't have the required policy&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getProductStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;policies&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Next line fails to compile since our policies do not include acess to the mail service!&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mailer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getMailService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;policies&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And since we have defined our policies in code as part of each lambda handler, we can declare all parameters for each lambda in its handler file and &lt;strong&gt;use CDK to go through them and create the associated resources&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/api/get-product.ts&lt;/span&gt;
&lt;span class="c1"&gt;// We attach the lambda parameters to the handler function&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;makeHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lambdaHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;policies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReadOnlyProducts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;httpMethod&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;logicalName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GetProductFunction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;resourcePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;products/{id}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;__filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// bin/stack.ts&lt;/span&gt;
&lt;span class="c1"&gt;// And we iterate through all handlers and create the associated lambda&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MyStack&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../lib/my-stack&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;handlers&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../src/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;MyStack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MyStack&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;makeFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib/stack.ts&lt;/span&gt;
&lt;span class="c1"&gt;// We build into the stack the logic to add each new lambda&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;MyStack&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Stack&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;makeFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HandlerParams&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;NodejsFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logicalName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;..&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getFunctionSettings&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;grantRights&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;policies&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resourceForPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resourcePath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;httpMethod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;LambdaIntegration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lets us define each Lambda in our application, along with its required permissions, in the same file where we declare the handler function, and &lt;strong&gt;leverage the type checker to catch any missing permissions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So if you find this interesting, read on for the longer version, or check out &lt;a href="https://github.com/spalladino/serverless-typescript-demo/"&gt;this fork&lt;/a&gt; of the AWS &lt;code&gt;serverless-typescript-demo&lt;/code&gt; for a full code sample.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem with permissions errors
&lt;/h2&gt;

&lt;p&gt;A common error when building serverless applications is missing a permission for accessing a resource in a lambda function. These errors are particularly annoying because they show up late in the development lifecycle, since unit or local tests do not uncover permissions errors: you depend on integration tests to check that your lambdas have all the rights needed to run properly. An error here requires a full redeploy of the stack and a retest, which takes valuable developer time.&lt;/p&gt;

&lt;p&gt;Moving these errors to earlier in the development cycle yields a faster feedback loop. In this article, we'll explore how to catch these errors at compile time leveraging the Typescript type checker, and take it one step further by integrating our new typed permissions directly into our CDK stack definition.&lt;/p&gt;

&lt;h2&gt;
  
  
  Typing permissions
&lt;/h2&gt;

&lt;p&gt;Let's start by defining our application permissions as Typescript types. For the sake of the example, let's say we have a &lt;code&gt;Products&lt;/code&gt; DynamoDB table in our application. We'll define two permissions, &lt;code&gt;ReadProducts&lt;/code&gt; and &lt;code&gt;WriteProducts&lt;/code&gt;, and use them to define a read-only and a full-access policy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ReadOnlyProducts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;ReadProducts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ReadWriteProducts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;ReadOnlyProducts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;WriteProducts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note the &lt;code&gt;as const&lt;/code&gt; in the declarations. This ensures that the type of each policy requires a &lt;code&gt;true&lt;/code&gt; value for each property, and not any boolean.&lt;/p&gt;

&lt;p&gt;We could have defined our policies as just an enumeration of permissions instead of using an object as we did above. But using objects like this plays nicely with the type system: a policy that extends another with additional permissions will also extend it in the eyes of the compiler.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;listProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;policy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;ReadOnlyProducts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nx"&gt;requiresReadProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ReadOnlyProducts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Works&lt;/span&gt;
&lt;span class="nx"&gt;requiresReadProducts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ReadWriteProducts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Works, since RW extends RO!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can define whatever arbitrary permissions you need for your application. These can go about sending emails, managing users, or pushing notifications. And you can combine them freely into policies. We'll worry about converting them into actual IAM policies later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example of a policy needed for running a UserManager&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserManagerPolicy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;ReadUsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;WriteUsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;SendEmails&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;PushNotifications&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Checking permissions when accessing resources
&lt;/h2&gt;

&lt;p&gt;Once we have our sets of application permissions defined, we can now enforce them to request access to resources in our code.&lt;/p&gt;

&lt;p&gt;Going back to the example from the previous section, we can abstract access to the &lt;code&gt;Products&lt;/code&gt; table behind a &lt;code&gt;ProductStore&lt;/code&gt;, with a DynamoDB-based default implementation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ProductStore&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;getProduct&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;getProducts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;putProduct&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;deleteProduct&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can also restrict the interface above to getter methods, which we will use if the client has read-only permissions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ReadOnlyProductStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Pick&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ProductStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getProduct&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getProducts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now is where things get interesting: we can define a function that returns a read-only or full &lt;code&gt;ProductStore&lt;/code&gt; depending on the &lt;strong&gt;type&lt;/strong&gt; of the policies supplied by the caller:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;getProductStore&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Policy&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;ReadOnlyProducts&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_policy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Policy&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; 
  &lt;span class="nx"&gt;Policy&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;ReadWriteProducts&lt;/span&gt; 
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;ProductStore&lt;/span&gt; 
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ReadOnlyProductStore&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;DynamoProductStore&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that we don't even use the policy parameter in the body of the function, since actual permissions will be checked by the AWS policies we define. What we are doing here is asking the type system to check if the user has read-only or read-write permissions on the &lt;code&gt;Products&lt;/code&gt; table, and return the corresponding interface. On runtime, we just return the same implementation.&lt;/p&gt;

&lt;p&gt;This achieves our goal of restricting access to resources based on the &lt;strong&gt;type&lt;/strong&gt; of the policies we're working with, which raises any permission errors during compile-time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Works&lt;/span&gt;
&lt;span class="nx"&gt;getProductStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ReadWriteProducts&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;putProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Property 'putProduct' does not exist on type 'ReadOnlyProductStore'&lt;/span&gt;
&lt;span class="nx"&gt;getProductStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ReadOnlyProducts&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;putProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Argument of type '{ readonly ReadUsers: true; }' is not assignable to parameter of type '{ readonly ReadProducts: true; }'&lt;/span&gt;
&lt;span class="nx"&gt;getProductStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ReadWriteUsers&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;putProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Declaring permissions for each lambda
&lt;/h2&gt;

&lt;p&gt;The most straightforward way to use this pattern is to declare, for each lambda, which set of permissions we will be granting it. This serves as a documentation attached to each function, which we can use to easily determine which policies we need to define in our infra-as-code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;lambdaHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;APIGatewayProxyEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// We declare the policies for this lambda once&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;policies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;ReadOnlyProducts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;UserManagerPolicy&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// And use them whenever we need to instantiate a resource&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;getService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;policies&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But since we are already defining these policies in code, we can take this an extra step and use them to actually generate the policies in our infra-as-code template. As a matter of fact, we can extend this to generate the entire function template from a single source of truth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrating with CDK
&lt;/h2&gt;

&lt;p&gt;Our goal will be to write the policies for each lambda in a single place, and 1) have the type checker verify that we have the required policies for accessing all resources we need and 2) generate these policies in our infra-as-code template. Since we're already working with Typescript, we'll use CDK as our infra-as-code tool.&lt;/p&gt;

&lt;p&gt;To do this, we'll attach the policies to the exported handler function, so we can query them when building our stack from CDK.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/api/get-product.ts&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;policies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;ReadOnlyProducts&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;APIGatewayProxyEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;lambdaHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;policies&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;policies&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So when we define our stack using CDK constructs, we can import each handler and define its IAM permissions from the ones we exported.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib/stack.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;getProduct&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../src/api/get-product&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// We define our resources in the stack constructor&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;productsTable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Table&lt;/span&gt;&lt;span class="p"&gt;(...);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;RestApi&lt;/span&gt;&lt;span class="p"&gt;(...);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getProductFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;NodejsFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;GetProductsFunction&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./src/api/get-products.ts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;settings&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resourceForPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;products/{id}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;LambdaIntegration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getProductFunction&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// A helper function translates from our custom policies&lt;/span&gt;
&lt;span class="c1"&gt;// to the actual IAM permissions to be created&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;grantRights&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;policies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;policies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReadProducts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;productsTable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;grantReadData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;policies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;WriteProducts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;productsTable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;grantWriteData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="c1"&gt;// And we repeat for each lambda in the app&lt;/span&gt;
&lt;span class="nx"&gt;grantRights&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;getProductFunction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getProduct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;policies&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But now we have split the definition for our lambda in two different places: policies are in the handler source file, and the rest of the settings are in the stack file. &lt;/p&gt;

&lt;p&gt;What if consolidated them into a single source of truth in the handler?&lt;/p&gt;

&lt;h2&gt;
  
  
  Taking CDK integration one step further
&lt;/h2&gt;

&lt;p&gt;Let's take the approach from the previous section one step further and inject all information relevant to the lambda when declaring its handler function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/api/get-product.ts&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;policies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;ReadOnlyProducts&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;APIGatewayProxyEvent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;lambdaHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;policies&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="nx"&gt;policies&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;httpMethod&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;logicalName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GetProductFunction&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;resourcePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;products/{id}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;__filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can add a function to our stack that accepts this set of parameters and creates a new lambda, connects it to the API gateway, and grants it the set of permissions defined in the policies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// lib/stack.ts&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;MyStack&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Stack&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;makeFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HandlerParams&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;NodejsFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;logicalName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;relative&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;..&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getFunctionSettings&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;grantRights&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;policies&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resourceForPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resourcePath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addMethod&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;httpMethod&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;LambdaIntegration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we just invoke it for each handler in our application when constructing the stack:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// bin/stack.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;handlers&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../src/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;cdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;MyStack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MyStack&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;makeFunction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, we have the definitions of the main resources of the application in our &lt;code&gt;lib/stack.ts&lt;/code&gt; file, while each function is declared in its own individual file, along with its associated permissions - which get type checked when requesting access to any resource!&lt;/p&gt;

&lt;h2&gt;
  
  
  Full example
&lt;/h2&gt;

&lt;p&gt;You can check a full code sample of the pattern above in &lt;a href="https://github.com/spalladino/serverless-typescript-demo/"&gt;&lt;code&gt;spalladino/serverless-typescript-demo&lt;/code&gt;&lt;/a&gt;, which is a fork of the &lt;a href="https://github.com/aws-samples/serverless-typescript-demo"&gt;&lt;code&gt;aws-samples/serverless-typescript-demo&lt;/code&gt;&lt;/a&gt; that showcases a products CRUD built using Typescript and CDK.&lt;/p&gt;

</description>
      <category>serverless</category>
      <category>cdk</category>
      <category>typescript</category>
    </item>
    <item>
      <title>A case for secure web3 operations</title>
      <dc:creator>Santiago Palladino</dc:creator>
      <pubDate>Tue, 04 Oct 2022 21:25:01 +0000</pubDate>
      <link>https://dev.to/spalladino/a-case-for-secure-web3-operations-1dpb</link>
      <guid>https://dev.to/spalladino/a-case-for-secure-web3-operations-1dpb</guid>
      <description>&lt;p&gt;Security in web3 development has improved remarkably over the past years. Even though we still see frequent hacks due to coding errors, development security practices have evolved significantly across web3 teams. Full test coverage, static analysis tools, fuzzing, and mandatory peer reviews are a requirement across most teams, while audits and bug bounties add an extra layer of security.&lt;/p&gt;

&lt;p&gt;However, the security in web3 operations is far from this level of maturity. Hardly any projects have any dedicated ops teams, and there is a general lack of awareness on best practices for operations in the web3 space. Security does not end when the code is frozen and audited: deployments, upgrades, integration testing, administration, automation, and monitoring also need to be bulletproof to avoid any hacks.&lt;/p&gt;

&lt;p&gt;Going through the &lt;a href="https://rekt.news/leaderboard/"&gt;Rekt leaderboard&lt;/a&gt; is evidence enough: many of the top incidents were not caused by development mishaps but by operational oversights, and several of them could have been mitigated by proper monitoring and incident response practices. Examples include &lt;a href="https://rekt.news/badger-rekt/"&gt;compromised frontends&lt;/a&gt;, hacks that &lt;a href="https://rekt.news/ronin-rekt/"&gt;go unnoticed for days&lt;/a&gt;, &lt;a href="https://rekt.news/nomad-rekt/"&gt;incorrect initializations&lt;/a&gt;, &lt;a href="https://rekt.news/vulcan-forged-rekt/"&gt;compromised keys&lt;/a&gt;, and more. In more recent news, a &lt;a href="https://decrypt.co/110238/hacker-abritrum-ethereum-draining-bug-nitro"&gt;missing initialization in Arbitrum Nova&lt;/a&gt; led to a 400 ETH bounty payout, while &lt;a href="https://rekt.news/wintermute-rekt-2/"&gt;Wintermute was hacked for $160M&lt;/a&gt; due to a compromised private key.&lt;/p&gt;

&lt;p&gt;While working at OpenZeppelin, we set out to interview multiple projects in the space to better understand their security needs. While training their Solidity developers in security was top of mind for most teams, we noted that operational concerns were often relegated:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;“We write a one-off script whenever we need to upgrade”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;“Transactions are sent from a private key stored in a file on a shared server”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;“We’d want to use a multisig or timelock eventually but tooling is lacking”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;“I don’t know what to monitor”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;“The lead developer just deploys the contracts from his working copy”&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;“I open etherscan every morning to see if everything looks fine”&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This research led to the development of &lt;a href="https://zpl.in/defender"&gt;OpenZeppelin Defender&lt;/a&gt;, today in widespread use across the space for securing web3 operations. Here we'll share the learnings collected along the way and the pain points we found in the space. We’ll focus on five different operational areas: Integration, Deployment, Administration, Transaction Automation, and Monitoring.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integration Testing &amp;amp; Staging Environments
&lt;/h2&gt;

&lt;p&gt;The DeFi cambrian explosion from a few years back was made possible by a highly interconnected ecosystem, with a synergy only attainable by building protocols on top of others, and leveraging the primitives available to build more powerful instruments.&lt;/p&gt;

&lt;p&gt;However, testing in such an interconnected environment is challenging: how do you test your protocol when it depends on so many live systems and moving pieces? As an example, Compound’s &lt;a href="https://www.comp.xyz/t/ceth-price-feed-incident-post-mortem/3578"&gt;recent cETH price feed incident&lt;/a&gt; was triggered by perfectly valid code, audited by three different companies, but which interacted with a token implementation that had not been considered.&lt;/p&gt;

&lt;p&gt;Testnet deployments are far from representative of an actual production setup. Few protocols deploy their systems to both testnet and mainnet, and even fewer bother to deploy exactly the same versions. Testnets fragmentation doesn’t help either, though the upcoming deprecation of Rinkeby, Kovan, and Ropsten will help. Furthermore, even if the code is the same in mainnet and testnet, the state of the system differs widely due to real production usage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://hardhat.org/hardhat-network/docs/guides/forking-other-networks"&gt;Mainnet forks&lt;/a&gt; help a lot here, but it is still difficult to test what would happen in other possible scenarios. Even if it’s an extreme case, hardly any team has ever tested how their protocol would behave &lt;a href="https://makerdao.world/en/learn/governance/emergency-shutdown/"&gt;should MakerDAO hit the emergency button on DAI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Another issue is that automated integration tests on mainnet forks typically only focus on contracts. Nowadays, a web3 system is rarely composed of just smart contracts: it integrates multiple off-chain components as well, such as oracles, bots, and indexing engines, not to mention the frontends that users depend on.&lt;/p&gt;

&lt;p&gt;These issues call for new solutions in integration testing. First and foremost, live staging environments, with a setup as representative as possible (both on and off chain) of the actual mainnet environment, is a must for manual testing and assuring that all components work as expected. &lt;a href="https://docs.tenderly.co/simulations-and-forks/how-to-create-a-fork/how-to-get-a-fork-json-rpc-url-and-id"&gt;Long-lived mainnet forks&lt;/a&gt; are a good way to start here.&lt;/p&gt;

&lt;p&gt;Reliable deployment packages for popular protocols can provide the means for setting up environments with hypothetical scenarios. Imagine being able to spin up a version of Maker &lt;a href="https://blog.makerdao.com/the-market-collapse-of-march-12-2020-how-it-impacted-makerdao/"&gt;going through a black thursday scenario&lt;/a&gt; in any network with a few commands, so you can test your system reacting to it. While this requires a massive community effort to populate the many protocols and the many scenarios that are possible, it is worth the investment. This endeavor also requires a &lt;a href="https://medium.com/nomic-foundation-blog/hardhat-ignition-5a34a4e3d2de"&gt;declarative deployment standard&lt;/a&gt; to build on top of.&lt;/p&gt;

&lt;p&gt;Last, blockchain determinism and public record gives us a unique opportunity to test new implementations without even having to put them in production - the opposite of the test in prod meme. As an example, in the traditional development space, Github &lt;a href="https://github.blog/2016-02-03-scientist/"&gt;tests new code strategies by executing them against live production requests and comparing them with the legacy code&lt;/a&gt; until they are satisfied with the results. Today, we have all the building blocks needed for replaying live transactions against a new version of a system before making the upgrade, without even having to deploy the system to mainnet for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reproducible &amp;amp; Auditable Deployments
&lt;/h2&gt;

&lt;p&gt;While most web2 systems are deployed from CI/CD pipelines, contract deployment is still very much a manual process. It usually falls on a developer to checkout the code, compile it, write a hardhat deployment script, deploy from their workstation, and then verify the source code on Etherscan or Sourcify.&lt;/p&gt;

&lt;p&gt;This has several downsides, besides the hassle for the developer, who also needs to keep a funded private key handy to pay for the deployment gas costs. The main problem is a lack of traceability, as the process for going from the vetted source code to a live instance is opaque. This can lead to issues where the &lt;a href="https://medium.com/opyn/opyn-eth-put-exploit-post-mortem-1a009e3347a8#4089"&gt;deployed code does not match the audited version&lt;/a&gt;, inadvertently introducing a vulnerability. And, in the interest of transparency, having an audit report that refers to a git commit does not offer much information to a user who is interacting with an address on Metamask.&lt;/p&gt;

&lt;p&gt;Lack of reproducibility is also a problem as more protocols go multi-chain. Ideally you want to keep the same version of the code running on all the chains where you operate, but to do this, you need to be able to reliably re-deploy exactly the same version. This means starting from the same version of the source code, building with the same settings and compiler version, and deploying with the same configuration.&lt;/p&gt;

&lt;p&gt;The low-hanging fruit here is to move deployments to a transparent CI/CD pipeline, where anyone can follow the automated process from the source code to compiled bytecode, and from there to the deployed instance. Online tools can also facilitate auditability by &lt;a href="https://forum.openzeppelin.com/t/defender-release-verifying-deployment-bytecode/31531"&gt;verifying that the code at an address matches a specific artifact&lt;/a&gt;. The end goal is to have a reproducible process and auditable trail from a git commit to a deployed instance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Administration &amp;amp; Governance
&lt;/h2&gt;

&lt;p&gt;With very few exceptions, most smart contract systems keep a set of administrative functions that allow a governing body to tweak how the protocol operates. These can go from adjusting a parameter to a full-blown code upgrade. Treasury management can also be considered part of the administration of a protocol. Given how critical these functions are, it is imperative they are controlled by secure and trusted entities.&lt;/p&gt;

&lt;p&gt;The state of the art when it comes to governance has improved remarkably over the last few years. It was not uncommon to see protocols with millions of dollars managed by a single private key sitting in the Metamask wallet of the project lead developer.&lt;/p&gt;

&lt;p&gt;Fortunately, it has now become commonplace the use of multi-signature wallets, with &lt;a href="https://gnosis-safe.io/"&gt;Gnosis Safe&lt;/a&gt; being the most popular option. However, multisig contract implementations are only one part of the picture: good tooling for creating and reviewing transactions is needed to guarantee secure operations run through these contracts.&lt;/p&gt;

&lt;p&gt;Tools for creating transactions need to account for not just the multisig, but also other governance and security mechanisms set up, such as timelocks or vote-based governance contracts. Governance contracts decentralize the decisions in a community, though many projects still restrict who can create new proposals, retaining that power behind a multisig. And timelocks provide two simultaneous benefits: they give the project’s team time to react if their setup was compromised, and they protect the community against rugpulls by giving users the time to exit the protocol if a malicious proposal is put forward. While a multisig transaction builder is good enough for creating transactions sent directly to the application, more complex tools are needed as these building blocks are combined.&lt;/p&gt;

&lt;p&gt;Reviewing administrative proposals is particularly challenging from a UX perspective. Many project stakeholders are not developers, meaning they cannot manually run scripts to decode or analyze a transaction before approving it. All too often, an N/M multisig becomes 1/M, where the 1 is the lead developer who pushes a proposal and asks the remaining M-1 to sign, who blindly hit the approve button.&lt;/p&gt;

&lt;p&gt;Simulation is the best resource we have for analyzing the outcome of a transaction, but the simulation tools that we use as developers may not cut it when it comes to less tech-savvy users. There is a need for &lt;a href="https://forum.openzeppelin.com/t/defender-release-admin-simulations-safe-finalized-sentinel-tags-more-speed-for-polygon-txs-and-more/31426#transaction-simulation-and-execution-review-on-admin-proposals-1"&gt;simulation capabilities that are accessible and easy to understand&lt;/a&gt; for everyone, so they can verify by themselves, and not trust.&lt;/p&gt;

&lt;p&gt;Contract upgrades deserve a separate paragraph. Approving an upgrade as a multisig signer means agreeing to a potentially massive change, while having only the 40 hex characters of the new implementation contract as context. And while having the source code verified on Etherscan is a requirement, the process of linking that code back to a verified or audited git commit is cumbersome (if not impossible) for most users. Easy-to-audit deployments, as detailed in the previous section, are a requirement for secure upgrade operations. It also helps to have a strong suite of integration tests for the new implementation that signers can review before approving.&lt;/p&gt;

&lt;h2&gt;
  
  
  Transaction Automation
&lt;/h2&gt;

&lt;p&gt;An automated script that submits transactions to the network needs access to a funded hot wallet. Gasless transactions is one of the most popular use cases here, and compromising the key of a meta-transaction relayer would mean draining all the funds allocated to paying gas fees. However, there are scenarios where these off-chain scripts need to manage keys with sensitive privileges, such as updating an oracle or managing a bridge. A compromised private key in this scenario can have dire consequences, as was the case with &lt;a href="https://rekt.news/harmony-rekt/"&gt;Harmony’s bridge hack&lt;/a&gt; for over $100M.&lt;/p&gt;

&lt;p&gt;This makes private keys more sensitive than your average application secret, so storing them in plaintext in a dot-env file in a server where half the dev team has ssh access is not a good idea. It is key (pun intended) to leverage key management solutions that can keep the key safely stored. There are managed cloud-based options, such as &lt;a href="https://cloud.google.com/security-key-management"&gt;GCP KMS&lt;/a&gt; or &lt;a href="https://aws.amazon.com/kms/"&gt;AWS KMS&lt;/a&gt;, self-managed like &lt;a href="https://www.vaultproject.io/"&gt;Hashi Vault&lt;/a&gt;, and even &lt;a href="https://en.wikipedia.org/wiki/Hardware_security_module"&gt;hardware security modules&lt;/a&gt; for hosting your keys.&lt;/p&gt;

&lt;p&gt;Most of these solutions also expose cryptographic functions in their API, so you can send your payloads to be signed by the KMS and the &lt;a href="https://docs.openzeppelin.com/defender/relay#security-considerations"&gt;private key never leaves&lt;/a&gt; the secure vault. Keeping the keys in a secure vault also lets you maintain an audit trail of all requests for using it, so you can easily detect or trace back any unauthorized usage.&lt;/p&gt;

&lt;p&gt;Reliability is also a concern when it comes to transaction automation. In blockchain, It is not enough to send a transaction, since you have no guarantees that it will get mined. Any automation infrastructure needs to monitor any in-flight transactions to reprice and resubmit them if network congestion increases, and ensure that a low-priced transaction will not clog the sender for any subsequent ones. There are &lt;a href="https://docs.openzeppelin.com/defender/relay#under-the-hood"&gt;multiple&lt;/a&gt; &lt;a href="https://docs.biconomy.io/introduction/why-biconomy"&gt;managed&lt;/a&gt; &lt;a href="https://docs.infura.io/infura/features/itx-transactions"&gt;solutions&lt;/a&gt; for tackling this problem, though you can also write your own.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security Monitoring
&lt;/h2&gt;

&lt;p&gt;Monitoring and alerting is commonplace on any web2 application, but its adoption in the web3 space started only recently with platforms like &lt;a href="https://docs.openzeppelin.com/defender/sentinel"&gt;Defender&lt;/a&gt;, &lt;a href="https://forta.org/"&gt;Forta&lt;/a&gt;, or &lt;a href="https://tenderly.co/monitoring/"&gt;Tenderly&lt;/a&gt;. For an embarrassingly long time, the most widely adopted approach to security alerts was &lt;a href="https://twitter.com/samczsun"&gt;samczsun&lt;/a&gt;’s trademarked “u up?”. Such was the state of monitoring that the largest crypto hack ever ($624M) &lt;a href="https://rekt.news/ronin-rekt/"&gt;went unnoticed for almost a week&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Reacting timely to a security event is important not just for being on top of the incident and keeping your community reassured, but also because &lt;a href="https://forta.org/blog/web3-kill-chain/"&gt;many hacks don’t involve a single action&lt;/a&gt;. Attacks usually require multiple transactions in preparation and execution, spread over time. As an example, &lt;a href="https://forta.org/blog/how-to-derail-a-120-million-dollar-hack/"&gt;BadgerDAO’s hack lasted 10 hours&lt;/a&gt; until all user wallets were drained.&lt;/p&gt;

&lt;p&gt;Receiving an early notice of an attack can give you the time to pause the protocol and stop the bleeding. &lt;a href="https://blog.openzeppelin.com/workshop-recap-service-monitoring-and-emergency-response/"&gt;Circuit breakers&lt;/a&gt; are a particularly interesting building block here: scripts triggered by security monitoring alerts that rely on transaction automation for pausing the system when a threat is detected.&lt;/p&gt;

&lt;p&gt;Last, custom monitoring scripts are also becoming a common practice, but it’s important to &lt;a href="https://watchmen.fandom.com/wiki/Who_Watches_the_Watchmen%3F"&gt;monitor the monitoring&lt;/a&gt;. A failure on an alerting script can go undetected, since it is expected to be silent, and can lead to a missed opportunity to deter a hack.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As recent hacks prove, security in operations is as critical as in development. Security does not end with Solidity: the most secure smart contract is worth nothing if its onlyOwner wallet gets compromised. There is a need for a &lt;a href="https://www.redhat.com/en/topics/devops/what-is-devsecops"&gt;DevSecOps&lt;/a&gt; approach for the web3 ecosystem, powered by platforms and tools that provide the means to implement its processes and &lt;a href="https://docs.openzeppelin.com/defender/advisor"&gt;best practices&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>ethereum</category>
      <category>web3</category>
      <category>operations</category>
    </item>
    <item>
      <title>Speed up your AWS SAM development by deploying individual functions</title>
      <dc:creator>Santiago Palladino</dc:creator>
      <pubDate>Sun, 27 Sep 2020 20:03:37 +0000</pubDate>
      <link>https://dev.to/spalladino/speed-up-your-aws-sam-development-by-deploying-individual-functions-d74</link>
      <guid>https://dev.to/spalladino/speed-up-your-aws-sam-development-by-deploying-individual-functions-d74</guid>
      <description>&lt;p&gt;&lt;em&gt;Cover image from &lt;a href="https://aws.amazon.com/lambda/getting-started/"&gt;https://aws.amazon.com/lambda/getting-started/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The Amazon Web Services &lt;a href="https://aws.amazon.com/serverless/sam/"&gt;Serverless Application Model&lt;/a&gt; (or AWS SAM, for short) is a framework for simplified development of serverless applications on top of AWS. SAM ships with a CLI that provides common operations, such as packaging and deploying your application, or spinning up a dev server for local testing.&lt;/p&gt;

&lt;p&gt;Behind the scenes, SAM relies on &lt;a href="https://aws.amazon.com/cloudformation/"&gt;CloudFormation&lt;/a&gt;, a mature template-based language for describing and deploying entire AWS stacks. Whenever you deploy your application, SAM will compile your code, upload it to S3, and use CloudFormation to update your stack.&lt;/p&gt;

&lt;h1&gt;
  
  
  The problem
&lt;/h1&gt;

&lt;p&gt;While this process is (usually) reliable and leads to reproducible deployments, it can also &lt;strong&gt;become painfully slow as your stack grows&lt;/strong&gt;. Given a stack with about 200 resources, a deployment where nothing has changed takes about 10 minutes from start to end. Compiling the entire codebase takes time, as well as uploading it and letting CloudFormation run its course.&lt;/p&gt;

&lt;p&gt;Though 10 minutes is acceptable for a full deployment, it is not for trying out your changes while developing. You need a much faster feedback loop if you want to stay in flow. To address this, other frameworks such as &lt;a href="https://www.serverless.com/"&gt;serverless.com&lt;/a&gt; provide &lt;a href="https://www.serverless.com/framework/docs/providers/aws/cli-reference/deploy-function/"&gt;a command&lt;/a&gt; &lt;code&gt;deploy function&lt;/code&gt; that bypasses CloudFormation entirely, and simply uses the AWS Lambda API to &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/API_UpdateFunctionCode.html"&gt;update the function code&lt;/a&gt; directly. Unfortunately, &lt;a href="https://github.com/aws/serverless-application-model/issues/125#issuecomment-356729066"&gt;this is not available&lt;/a&gt; as part as the AWS SAM CLI. While researching this, I found a CLI called &lt;a href="https://www.npmjs.com/package/sampic"&gt;&lt;code&gt;sampic&lt;/code&gt;&lt;/a&gt; built by a community member on top of SAM, but it seemed too heavyweight for what I was looking for.&lt;/p&gt;

&lt;h1&gt;
  
  
  Hacking a solution
&lt;/h1&gt;

&lt;p&gt;Given that switching from SAM to serverless.com can be too disruptive in an already established project, I set out to &lt;strong&gt;reproduce the &lt;code&gt;deploy function&lt;/code&gt; behavior manually for our webpack-powered typescript AWS SAM project&lt;/strong&gt;. The end result is a 120-lines script, most of which is just logging, that picks a subset of functions from a SAM template, compiles them, and uploads them via the AWS Lambda API.&lt;/p&gt;

&lt;p&gt;Note that this solution only works if the function has already been created by &lt;code&gt;sam deploy&lt;/code&gt;. The script will not create the function if it doesn't exist, it only knows how to update its code.&lt;/p&gt;

&lt;p&gt;In this post, I'll walk through the necessary steps to build this solution - but you can also just jump directly to the entire code snippet at the end of the post!&lt;/p&gt;

&lt;h1&gt;
  
  
  Getting started
&lt;/h1&gt;

&lt;p&gt;The first step is to choose which functions to deploy. To do this, we'll compare all function names in the template to an &lt;code&gt;fname&lt;/code&gt; substring provided by the user, and filter only those that match. &lt;/p&gt;

&lt;p&gt;We'll use the &lt;a href="https://www.npmjs.com/package/yaml-cfn"&gt;&lt;code&gt;yaml-cfn&lt;/code&gt;&lt;/a&gt; package for parsing the template, since CloudFormation accepts a set of non-standard YAML tags for &lt;a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/intrinsic-function-reference.html"&gt;intrinsic functions&lt;/a&gt; which can break a vanilla yaml parser. And we'll use &lt;a href="https://lodash.com/"&gt;lodash&lt;/a&gt;, because I can't code in js without it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;readFileSync&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;yamlParse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;yaml-cfn&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pickBy&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lodash&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;TEMPLATE_FILENAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;template.yaml&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;yamlParse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;TEMPLATE_FILENAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filtered&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pickBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Resources&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fname&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; 
  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AWS::Serverless::Function&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;functions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filtered&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Properties&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This will return an array of objects like the one below, with the metadata of the functions to be deployed.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Name: 'UserInviteFunction',
FunctionName: { 'Fn::Sub': '${AWS::StackName}-${Stage}-user-invite-fn' },
CodeUri: './build/users',
Handler: 'index.inviteUser',
Events: { InviteUser: [Object] }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Compiling only what's needed
&lt;/h1&gt;

&lt;p&gt;Now that we know which functions we want to deploy, it's time to compile them. I'm currently using webpack, with one &lt;a href="https://webpack.js.org/concepts/entry-points/"&gt;entry point&lt;/a&gt; for each set of related endpoints; but if you're using a different bundler, you may need to adapt the following steps to it.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// webpack.config.js&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;authorizer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/authorizer/index.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;projects&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/endpoints/projects.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;organizations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/endpoints/organizations.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/endpoints/actions.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./src/endpoints/users.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[name]/index.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;libraryTarget&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;commonjs2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;build&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;sourceMapFilename&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[name]/index.js.map&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;To speed up compilation, we will &lt;strong&gt;filter the set of entry points&lt;/strong&gt; defined in our webpack config so we &lt;strong&gt;only compile those necessary&lt;/strong&gt; for the functions to be deployed. If you have over 25 different entrypoints like I do, this can be a major time saver!&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;uniq&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pick&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lodash&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;WEBPACK_CONFIG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./webpack.config.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;WEBPACK_CONFIG&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="c1"&gt;// We map from CodeUris like './build/users' to entries like 'users'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;entryPoints&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;uniq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;basename&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CodeUri&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;
&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;entryPoints&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Before we trigger the compilation, we'll add an extra step. When using &lt;code&gt;sam deploy&lt;/code&gt;, the SAM CLI takes care of zipping and uploading the code for us, but since we are uploading the code manually, we'll need to zip it ourselves.&lt;/p&gt;

&lt;p&gt;Unfortunately, webpack's &lt;code&gt;compression-webpack-plugin&lt;/code&gt; does not support &lt;code&gt;zip&lt;/code&gt; files, and the &lt;code&gt;zip-webpack-plugin&lt;/code&gt; &lt;a href="https://github.com/erikdesjardins/zip-webpack-plugin/issues/19"&gt;does not support multiple entry points&lt;/a&gt;. So, we will just tap into the &lt;a href="https://webpack.js.org/api/compiler-hooks/#assetemitted"&gt;&lt;code&gt;assetEmitted&lt;/code&gt; webpack hook&lt;/a&gt; and zip from there. We'll just use the &lt;code&gt;zip&lt;/code&gt; OS command to do this, but we could also use a package like &lt;a href="https://github.com/thejoshwolfe/yazl"&gt;&lt;code&gt;yazl&lt;/code&gt;&lt;/a&gt; or &lt;a href="https://stuk.github.io/jszip/"&gt;&lt;code&gt;jszip&lt;/code&gt;&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;extname&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;promisify&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;util&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;exec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;promisify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;child_process&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;webpack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;webpack&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;compiler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;webpack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;compiler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;assetEmitted&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;tapPromise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;zip&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;extname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.map&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cwd&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`zip index.zip index.js`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;cwd&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;With all of this set up, we can finally set out to compile our functions.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;promisify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;compiler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;compiler&lt;/span&gt;&lt;span class="p"&gt;))();&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasErrors&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toJson&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Resolving function names
&lt;/h1&gt;

&lt;p&gt;We now know what functions to deploy and have compiled them. But before uploading the code, we need to know the physical resource names of the lambdas we are targeting.&lt;/p&gt;

&lt;p&gt;In a CloudFormation stack, the name you assign to each resource is called the &lt;a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/resources-section-structure.html#resources-section-structure-logicalid"&gt;&lt;em&gt;logical name&lt;/em&gt;&lt;/a&gt;. However, this is not the name used when creating the resources. Given that your resources must have unique names within an account and region, CloudFormation will use a combination of your stack name, the logical name, and a unique identifier for the actual &lt;em&gt;physical name&lt;/em&gt;. You can also control the name for each resource by setting a &lt;a href="https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html#sam-function-functionname"&gt;&lt;code&gt;Name&lt;/code&gt; property&lt;/a&gt; in your template.&lt;/p&gt;

&lt;p&gt;Fortunately, the CloudFormation API allows us to retrieve the physical name for a resource given its logical name and stack via a &lt;a href="https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_DescribeStackResource.html"&gt;&lt;code&gt;DescribeStackResource&lt;/code&gt; method&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;CloudFormation&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;STACKNAME&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;MY-STACK&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cfn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;CloudFormation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resolvedFunctions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;functions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;cfn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;describeStackResource&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;LogicalResourceId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;StackName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;STACKNAME&lt;/span&gt; 
  &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resourceId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;StackResourceDetail&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PhysicalResourceId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;ResourceId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;resourceId&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Armed with the actual lambda function names, we can now finally use the &lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/API_UpdateFunctionCode.html"&gt;&lt;code&gt;UpdateFunctionCode&lt;/code&gt; API method&lt;/a&gt; to upload our code directly to our Lambda functions.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Lambda&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lambda&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Lambda&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolvedFunctions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;zipFilePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;CodeUri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index.zip&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updateFunctionCode&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;FunctionName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ResourceId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;ZipFile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;readFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;zipFilePath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
  &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Measuring it
&lt;/h1&gt;

&lt;p&gt;When compiling and deploying a single function, the script above takes roughly 20-30 seconds, most of which is spent in compilation. To compare, deploying the stack via &lt;code&gt;sam deploy&lt;/code&gt; takes about 10 minutes, which means we're in for &lt;strong&gt;a 20x speed increase&lt;/strong&gt; during development. A faster feedback loop means more development productivity, so achieving this kind of gains can be a major improvement to your project.&lt;/p&gt;
&lt;h1&gt;
  
  
  Putting it all together
&lt;/h1&gt;

&lt;p&gt;Here is the entire script we are using today for development, which puts together all the steps described above, along with some logging and validations. Keep in mind that &lt;strong&gt;some bits may be different on your own setup&lt;/strong&gt;, such as the paths where the artifacts are generated, or how your template is organized. Nevertheless, I expect it to work in most setups with just minor tweaks. &lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;



</description>
      <category>aws</category>
      <category>sam</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Announcing Crystal CodeCamp SF2017</title>
      <dc:creator>Santiago Palladino</dc:creator>
      <pubDate>Thu, 23 Mar 2017 21:25:14 +0000</pubDate>
      <link>https://dev.to/crystal-lang/announcing-crystal-codecamp-sf2017</link>
      <guid>https://dev.to/crystal-lang/announcing-crystal-codecamp-sf2017</guid>
      <description>

&lt;p&gt;&lt;em&gt;This blogpost was originally posted by &lt;a href="https://manas.tech/staff/mdavid/"&gt;MarÃ­a Inti David&lt;/a&gt; on &lt;a href="https://crystal-lang.org/2017/03/23/announcing-crystal-codecamp-sf2017.html"&gt;the official Crystal Blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We're happy to announce that the Crystal team is coming to San Francisco!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/CrystalLanguage/status/841763640629964800"&gt;Maybe you've heard&lt;/a&gt; we're organizing the first #CrystalLang &lt;a href="https://codecamp.crystal-lang.org/"&gt;CodeCamp&lt;/a&gt;. The event will consist of a 2 day hands-on training dictated by &lt;a href="https://manas.tech/staff/spalladino/"&gt;Santiago Palladino&lt;/a&gt; &amp;amp; &lt;a href="https://manas.tech/staff/ggiraldez/"&gt;Gustavo GirÃ¡ldez&lt;/a&gt;, members of the Crystal core team. &lt;a href="https://twitter.com/sdogruyol"&gt;Serdar DoÄŸruyol&lt;/a&gt; (creator of &lt;a href="http://kemalcr.com/"&gt;Kemal&lt;/a&gt;) will also be joining us as a guest speaker.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codecamp.crystal-lang.org/#Programme"&gt;The programme&lt;/a&gt; includes hands on labs, Q&amp;amp;A sessions with the team, networking sessions and more than 10 hours of training. We will provide official Crystal certificates for attendees, along with the obligatory Crystal swag.&lt;/p&gt;

&lt;p&gt;Right now this event is possible thanks to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.academyx.com/"&gt;AcademyX&lt;/a&gt;, who is sponsoring us and providing the space to host the event at their &lt;a href="https://www.academyx.com/schedule/san_francisco/"&gt;San Francisco offices&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://www.twentify.com/"&gt;Twentify&lt;/a&gt;, who is sponsoring the event and also making it possible for Serdar to travel and be a guest speaker.&lt;/li&gt;
&lt;li&gt;
&lt;a href="http://manas.tech/"&gt;Manas.Tech&lt;/a&gt;, the company behind Crystal since 2011.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We're looking for sponsors who want to support the event, so if you're interested (or know someone who might be) make sure to read our &lt;a href="https://codecamp.crystal-lang.org/assets/Crystal-Sponsors-Prospectus-583b3c87b27dce9dc8c1c3554c2bd5ae0fb448f23d78a8f61cb3ae57122a0c77.pdf"&gt;sponsorship prospectus&lt;/a&gt;. As with every other official Crystal event, all profits from sponsorships and ticket sales will be destined exclusively to Crystal Development. This will help us invest more hours in the language and &lt;a href="https://crystal-lang.org/2017/02/24/state-of-crystal-at-0.21.html"&gt;accomplish&lt;/a&gt; our &lt;a href="https://crystal-lang.org/2016/12/29/crystal-new-year-resolutions-for-2017-1-0.html"&gt;2017 resolutions&lt;/a&gt; (yes, I'm talking about Crystal 1.0).&lt;/p&gt;

&lt;p&gt;We hope this is the first of many Crystal CodeCamps around the world, so we're open for suggestions about where we should go next.&lt;/p&gt;

&lt;p&gt;PS: This blogpost will be updated as new sponsors join us, we want to thank the companies supporting Crystal in this new event series.&lt;/p&gt;


</description>
      <category>crystallang</category>
    </item>
    <item>
      <title>State of Crystal at 0.21</title>
      <dc:creator>Santiago Palladino</dc:creator>
      <pubDate>Fri, 24 Feb 2017 12:52:17 +0000</pubDate>
      <link>https://dev.to/crystal-lang/state-of-crystal-at-021</link>
      <guid>https://dev.to/crystal-lang/state-of-crystal-at-021</guid>
      <description>

&lt;p&gt;&lt;em&gt;This blogpost was originally posted on &lt;a href="https://crystal-lang.org/2017/02/24/state-of-crystal-at-0.21.html"&gt;the official Crystal Blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With the release of &lt;a href="https://groups.google.com/d/msg/crystal-lang/sGxeIxlLKX4/VFIM-iTECwAJ"&gt;version 0.21&lt;/a&gt;, we wanted to share with you the state of Crystal development so far this year, aiming towards a &lt;a href="https://crystal-lang.org/2016/12/29/crystal-new-year-resolutions-for-2017-1-0.html"&gt;1.0 version&lt;/a&gt; by the end of the year.&lt;/p&gt;

&lt;p&gt;First and foremost, we have updated our &lt;a href="https://github.com/crystal-lang/crystal/wiki/Roadmap"&gt;roadmap&lt;/a&gt; with the goals we have in mind, not just for Crystal during this year, but also tools we would like to see built using the language in the future, such as a full DSL for easily writing Ruby extensions, or a desktop UI library. We have also changed our &lt;a href="https://github.com/crystal-lang/crystal/labels"&gt;labelling scheme&lt;/a&gt; for Github issues, and updated the &lt;a href="https://github.com/crystal-lang/crystal/blob/master/CONTRIBUTING.md"&gt;contributing guidelines&lt;/a&gt; accordingly, to make it easier for anyone in the community to find out how to help with Crystal.&lt;/p&gt;

&lt;p&gt;Regarding the key features we had identified for 1.0, we are making steady progress on &lt;a href="https://github.com/crystal-lang/crystal/pull/3582"&gt;Windows support&lt;/a&gt;, with work from community member &lt;a href="https://github.com/lbguilherme"&gt;lbguilherme&lt;/a&gt; and core team member &lt;a href="https://github.com/bcardiff"&gt;bcardiff&lt;/a&gt;. Today Crystal is able to compile some programs in Windows, and the last milestone has been support for exceptions in that platform. We still have a long way to go on the standard library front, as every module was implemented with just UNIX support in mind, so contributions are most welcome from anyone interested in the Windows platform.&lt;/p&gt;

&lt;p&gt;The next big thing is &lt;a href="https://github.com/crystal-lang/crystal/tree/thread-support"&gt;parallelism&lt;/a&gt;, with core team members &lt;a href="https://github.com/ggiraldez"&gt;ggiraldez&lt;/a&gt; and &lt;a href="https://github.com/juanedi"&gt;juanedi&lt;/a&gt; working heavily on it, based on the work started by &lt;a href="https://github.com/waj"&gt;waj&lt;/a&gt;. We are happy to have a working version of the compiler built with multi-thread support, with a similar model to Go: a fixed thread pool that executes tasks from fibers, including goodies such as work-stealing. Work on this is still experimental, and there are quite a few breaking changes to define, such as explicit Thread handling; but most of the compiler and standard library specs are currently green. Kemal's author &lt;a href="https://github.com/sdogruyol/"&gt;sdogruyol&lt;/a&gt; even managed to &lt;a href="https://twitter.com/sdogruyol/status/833369972919382019"&gt;run the web framework&lt;/a&gt; in multiple threads already. However, there is still much work to do on testing and performance, to ensure the contention produced by distributing the workload on multiple threads does not offset the speed gain.&lt;/p&gt;

&lt;p&gt;We have also started discussions on the type system to ensure the feasibility of incremental compilation. We have identified some potential bottlenecks on generics and on modules-as-interfaces that will have to be addressed, and we'll do our best to identify the breaking changes required as soon as possible, as well as minimise their impact.&lt;/p&gt;

&lt;p&gt;On the communications front, we are also now cross-posting from our official blog to the awesome platform &lt;a href="https://dev.to/"&gt;dev.to&lt;/a&gt;, where you might be reading this post now. The folks at &lt;a href="https://twitter.com/thepracticaldev"&gt;ThePracticalDev&lt;/a&gt; were super friendly and set up a &lt;a href="https://dev.to/crystal-lang/"&gt;crystal-lang account&lt;/a&gt; for us in no time on the site. Many of us in the Crystal core team have been following the site and twitter feed for quite some time, and are now really excited to see Crystal have a room in the platform.&lt;/p&gt;

&lt;p&gt;Also, and not to spoil the surprise, but we have almost finished a brand new version of our website, with a much cleaner design. Expect to see it online quite soon.&lt;/p&gt;

&lt;p&gt;Last but not least, we are happy to have given talks at &lt;a href="https://www.youtube.com/watch?v=8FvrBLWUwxc"&gt;Google NYC&lt;/a&gt; and Recurse Center earlier this month, as well as organised another meetup. We are also organising the first Crystal Code Camp for April in San Francisco: &lt;a href="https://docs.google.com/a/manas.com.ar/forms/d/e/1FAIpQLSdN4a-ELm54lZFr_qcD97YLe-OTYnP7vAzMfpQdreCoG4o8_Q/viewform"&gt;let us know&lt;/a&gt; if you are interested in joining, or &lt;a href="mailto:crystal@manas.tech"&gt;contact us&lt;/a&gt; if you want to sponsor the event!&lt;/p&gt;

&lt;p&gt;We'll share news from the state of Crystal in a regular basis, so make sure to stay tuned to the blog and other &lt;a href="https://crystal-lang.org/community/"&gt;communication channels&lt;/a&gt;. Happy Crystalling!&lt;/p&gt;


</description>
      <category>crystallang</category>
    </item>
  </channel>
</rss>
