ZK Whiteboard Sessions – Module Eleven: ZK Swaps with Henry de Valence
4 Oct 2022 · 1:12:58
Henry de Valence explains how Penumbra, a cross-chain shielded exchange, lets people trade privately while the market state stays public. He begins with a Zcash-style privacy model, in which only note commitments are recorded on chain and nullifiers mark notes as spent, and shows why that model struggles with shared state, since a zero-knowledge proof must fix the exact state transition in advance. Penumbra's answer for swaps is to encrypt input amounts to a key shared across the validator set, decrypt only the batch total for each trading pair, execute the exchange once per block, and let users later mint their pro rata output without signing again. Trading within one pool also keeps many different assets from splitting into small, separate anonymity sets.
Speakers
Topics
Transcript
foreign [Music] welcome to another episode of the ZK whiteboard series I'm Brendan I work at polygon and I'm really happy to be joined by Henry who's the creator of penumbra and previously was at the zcash foundation um it's a amazingly talented applied cryptographer accelerator of ed25519 of uh rust crypto in general and um so today we're doing something a little bit different this is more of an
application focused whiteboard series as opposed to like a more theoretical or academic one and but I'm really excited to see how you're using ZK stuff uh kind of for real world impact so welcome Henry all right um so um uh working on penumbra that's what we were talking about today as a sort of way to get started on that we could start with the question of like you know what is it um and the answer is um penumbra is a uh cross chain shielded
decks so there's sort of three parts to that and we could go through those um you know unpack each one of those a little bit so for the first part this like cross chain all right so we have um uh sort of native uh so for the cross chain part um we are natively uh IBC compatible so IBC is a generic cross chain communication system that was originally
developed for the cosmos ecosystem but is fundamentally totally agnostic to the way that the uh you know you could in principle use it with any chain and the the thing that's really cool about IBC is that it's fundamentally not sort of oh this is a bridge or this is you know some sort of specific thing it's a it's it's more like you know TCP for blockchains it's a way to have two chains securely communicate and pass messages to each other and the really powerful thing about that design is that it means that if you wanted to for instance do bridging you can do so without any other sort of additional trust assumptions Beyond uh just sort of
trusting that I can do a transaction on chain a and I trust that I can do a transaction on chain B and if I trust in both of those things because A and B are able to read each other's state I can now use both send value between them have like a cross chain account cross-chain queries you know all this cool stuff cool so so assets are now untethered to yeah cool exactly um the second piece of this this shielded piece is uh we have a zcash style shielded pool So when you say shielded pool that means that the amount so I have some asset that exists in the shielded pool and
only I know the amount of that asset and that I own it and right I can do transfers uh anonymously right so the the thing that we've added to this design is um the ability to have um multi-asset uh capability right because zcash is just Zack right right okay and what's in this shielded pool so this what's in uh the shielded pool is um a collection of notes which you can think of as basically being like uh utxos um or more specifically uh if you're very Bitcoin e it's like a pay to public
key utxo so a note so value uh on the chain is stored in notes and a note is some typed value which is you know V that's the amount and some asset ID which is a just a random field element and then there's also an address cool so I I will say that I own so much denta
coin that it wouldn't fit in a u64 but yeah I'm probably uh in fact we're actually so this is the current design one of the things that we're probably going to be doing uh you know in the next little while is swapping this out from a u64 to u128 cool and the reason is that you know some chains most notably ethereum chose to do like a absurd level of precision and now all of us in this cross chain environment are cursed with the legacy of that choice [Music] um but basically right you can think of a note as being a typed Value Plus an address that controls that value and what does it mean for it to be shielded
it means that uh when I do a transaction um I'm going to be able to spend notes without revealing I just sort of am doing this ZK proof that I control this note I'm proving that it was previously included in the chain I prove that it hasn't been spent already and I proved that using the the address that I have the authority to control that funds but all of that is wrapped up inside the ZK proof and so all that some external Observer sees when they look at the transactions on chain it's like oh someone spent a note someone created a note you know what's the amount of that note I don't know what's the type I don't know what's the address that is
involved I don't know all of that is is hidden so so it's pretty much optimal products yes and that the anonymity set the the really great thing about the the zcash style design is that the anonymity set is every note that has ever been created um so the more you get get people to use the chain the better the Privacy set is and it always gets better over time cool so that's this sort of second part the third part oh I've just a marker um the third part is uh having a DEX and as just some kind of like Baseline
motivation you know why build a decks at all right um why why not just do sort of some kind of cross chain shielded pool and the answer to that you know actually sort of came out of some reflection that I you know I personally had um on my time working on zcash which is like you know from a cryptographic point of view from uh you know applied cryptography cryptographic engineering standpoint like this is sort of you know this is the optimal design to have privacy um this is like the best you know the the the the the crypto engineering is like you know the best in class but what
can you actually do with it well you can like send funds like I could send you a payment of like some tokens yeah right um and that I think actually you know there's this uh this idea that sort of payments of this like be-all end-all of of uh blockchains as like the way to measure uh whether it's useful but actually I think payments are kind of this like hardest possible problem to solve and the reason is that if if we just do a payment transaction um nobody's sort of doing that just because there's always some kind of counter flow in the real world uh coming back and in the opposite direction and so that means
that in order for me to be using this system to do payments I have to have some off-chain like social infrastructure already set up and so there's kind of this chicken and egg problem where it's like oh the blockchain is supposed to be the coordination tool but before I can do the coordination with the coordination tool I first have to separately coordinate with somebody to use that coordination tool I can't just make a transaction and have that be economically useful in itself Force someone to accept CK right yeah um and so thinking sort of from first principles like okay what's the like minimum viable transaction where the entire kind of economic logic of that transaction can be uh recorded on chain and that's at some kind of trade and
trading also is a really interesting use case for privacy because it's a it's an environment where um privacy thought of as sort of having control over information disclosure isn't just kind of an abstract principle but it has this very quantifiable near-term Financial value so there's all kinds of abuse that happens on transparent chains like ethereum where you know somebody's trying to make a trade other people see that they're going to make the trade they get front run they get back run they get like sandwich there's like poison sandwiches there's like salmonella there's like this whole thing of all of these
different um uh attacks that people play and it's because everybody can see what everybody is about to do and so kind of the the sort of big picture idea of penumbra is um can you like use the fact that uh trading is a case where privacy has some kind of uh Financial value to bootstrap the creation of this like big you know ever expanding privacy set that's a that's a really nice way to put it I think yeah so that that's kind of a sort of long-winded motivation but um you know getting into that sort of concrete pieces of the the decks they're sort of two actually sort of sub pieces
so I'll just go in and and modify this um so anytime you have a decks you have sort of two sides right either somebody can be submitting a trade as sort of a market taker or they can be depositing liquidity as a market maker so on the um Market taker side we have uh sealed input batch swaps so the idea is that instead of having a model where you sort of each individual person submits a trade um
we're going to have a each trade only so only revealed the trading pair in the clear and encrypt the input amounts to a decryption key that is charted among the whole validator set so so you need the entire validator set to collaborate to decrypt exactly so no individual validator can sort of see uh the the contents of a proposed trade until as their uh processing a finalized block they're going to go through each trading pair where people have submitted swaps sum up all of the encrypted inputs
to get an encryption of the batch total and decrypt only the batch total so it's like you have you know all these individual um you know encrypted transaction values those get summed up and decrypted into some kind of combined input value that gets you know sent off to the decks as a single trade and then once that's executed um the clearing price uh for that blocks batch input gets written into the chain State and
everybody can everybody who had um uh participated in the batch can later mint uh their Pro rata share of the output um and we'll get to sort of the the details of how that works a little bit later on this part actually I think is one of the most interesting pieces of penumbra because um it goes from sort of this this problem of making private transactions possible where it's like okay we have this thing how do we make it private right you can play this game like okay how you know how do we make it more how do we make more and more things private but if you
have a market you don't actually want everything to be private right you want to have public prices people want to know like what's the state of the market I'm going to be trading against and so you need to have some kind of public aggregate data that's part of the the public shared State on the other hand you don't want to have each individual person's activity be revealed so you have to have some way to manage the interplay between individual private actions and some kind of public transparent Aggregates um right because like I could generated proof that that says that I made some valid transactions swapping uh pairs in amm but if you wanted to trade
in that same pool like you kind of need to know what yeah exactly what the impact is on the pool right and and I think the the consequences of this on you know what is even the state model of the chain how do you um what does it mean to make a proof of a transaction uh how is that structured um it's it's actually interesting I think that as a sort of a side effect of trying to solve this one specific problem we've kind of got sort of a first approximation of some kind of more General model for having private interaction with public shared State yeah I think totally because here uh not to belaborate the point but here uh you
can just generate a proof I'm only touching state that I own that's literally my you know tokens um but here we have this my tokens that I own that I can generate a proof for but then the shirts are the pool that everyone needs to know to sort of get the price of that which they're trading right exactly and and when you're making that proof right like the fact that it's a proof of knowledge means you have to know what you are proving about and so you can't ever make a proof that involves anybody else's day data because you don't know what their state is and you know the way that you would do a transaction in in this model is that like it's not that I you know go and
update somebody else's account balance or something but I'm I'm literally gonna sort of consume some of my notes that are my state and then I produce a new note that will be controlled by somebody else and sort of send it off to them but at no point is there actually any kind of interaction between different users [Music] um this is the so the the batch swaps um is sort of the the front end to the the decks not in the sense of like a user interface but in the sense that it's how do you um go from you know tokens in the shielded pool to interacting with this uh uh public State the second piece of
that is um the on the market maker side um yeah how do you create liquidity positions and this part actually is not as um there's there's interesting pieces here but it's really more on the kind of like defy like Market design stuff not really so much interesting on the um on the sort of ZK system design part so we probably won't go super deeply into that um but you know it's sort of all concentrated liquidity and um you just sort of make this big
uh graph of all the available liquidity and use it all at once and you can do that because in this model sort of as a side effect of oh we have to do this to make the the sort of private State interactions work one one other interesting point is that you're only actually going to ever execute uh the the decks once per block because you're executing it on this bashed uh sort of accumulation of everybody's trading intent and so instead of having to execute that so you know potentially thousands of times per block you know you're only going to ever execute it once and so you can make it considerably more uh sophisticated from a market design point of view because you're
amortizing whatever computational cost you have over every single trade that was submitted in um in the block yeah this I think is really interesting because um like if you think about ethereum uh like I make a trade you make a trade we both get front run we both get back run and so every time the unit swap contract is being invoked but under this model we're basically like summing up uh everyone trading on on both sides of the pool the pair um and then we're only doing like the Dex logic one time which I think it's a really cool feature so our ultimate goal is to try to explain here's how you can do private interaction with shared State and
specifically how you do private inputs to a public trading system in order to sort of get to that eventual thing though it's probably good to start off with some kind of overview um of the Z cash Style State model so the reason that I say zcash style is because I think it's important to like give credit where it's due to you know the the original place where this was
designed however I don't want to misrepresent you know that this is how like our our system is actually you know in in various ways uh different um so this isn't actually a description of zcash it's a description of of penumbra um but the the sort of high level idea is uh okay we want to make a uh private transactions and when we say when you say private that's both uh keeping the amounts confidential and uh keeping the meta
shielding yeah the shielding like that I'm sending to you and and it's it's actually you know there's some designs where it's like oh well we'll hide only the amounts but leave the address is there but in practice this like really isn't very meaningful because if you know all of the metadata you can figure out what the activity is yeah yeah um you know there's this famous quote from I think one of the former MacArthur or something I'm sorry uh McMaster or something yeah I don't recall who off the off the top of my head but it was like you know well giving some testimony in the Senate being like well we kill people based on metadata so anyway it seems like worth protecting yeah um and what's kind of the overall
strategy here um so first uh we're gonna have uh a chain where we have these um uh fragmented so instead of having okay we're going to have this like one big you know Global immutable State like on ethereum we're gonna have more of a Bitcoin style design where um you're gonna have all these like little individual um fragments of state and we're just trying to do like basic you know sending value around so these will be our
um notes and that uh as I I mentioned before consists of um typed value and a controlling address so if you have the sort of you know object capabilities brain you can think of this as being like well every value has some kind of notion of what's the thing that has the cryptographic capability to spend that value so this is sort of the basic
um uh fragment of State so that this is how we represent a multi-asset shielded yeah um is you know a typed value and some kind of capability that can uh spend it so that's interesting because right now it's an address but it could eventually be like some a verification key or something like in theory or some so it sort of has to be an address in some sense um it what it really needs to be is some kind of cryptographic key material the details of exactly how that key material is shaped can vary based on the system but if the eventual goal is that we want
uh all of the knowledge of of these individual parts of the chain state to move off chain then you have to have some kind of cryptographic key material that is going to be recorded as the controller of it sure it doesn't work to have an on-chain account because if you have an on-chain account the only way that that can work is if the chain is updating it but then everybody has to know what it is yeah yeah so to have privacy you need to have some kind of key material but but I just mean that could be a public key or it could be like a verification key for some that might not work in in this case but um like you could have a multi-sig
that's just like a circuit that has uh like many addresses that can be satisfied off traded uh uh yeah I guess so yeah uh but sorry sorry anyway so yeah just um so we're going to think of this as just being that um our goal is to to record some kind of typed value and so the the minimum piece of state that you could have is some amount of value and some address that gets to control what happens with that value um these are going to be sort of our I'll just sort of draw these all out as
boxes you can imagine this is like the set of all of the notes that have ever been created um you can put that into all this one series um you can put that into this um uh Merkle tree that we'll call the note commitment tree or well getting ahead of myself and so this is right so so first we've just done this first move of okay we're going to fragment all the chain state the second um
big change that we'll do is we move the state off chain um and so in order to do that right we have let's you know maybe we can like shade in these values to represent that this is you know the sort of the full note where we know what the value is we know the the address Etc um and to do this we're going to replace the nodes with note
commitments so I'll redraw exactly this diagram but now we're going to use these Hollow boxes to represent that only some you know cryptographic commitment to the the real piece of state is uh recorded as part of the public chain state um and so now instead of having a set of notes
we have a set of note commitments so how is this actually going to work with being able to do transactions well in our in the sort of first model which you can think of you know sir being more like Bitcoin you have uh what's a transaction well in my transaction I'm going to say I'm going to consume you know some set of input notes utxos whatever and then I'm going to produce some new ones and then I'm going to put this all up
into a box and there's going to be some kind of you know this is the the spent ones these are the new notes and so when when all this is in plain text that's a validator for the chain I can just make sure that the balance is sum to zero and um yeah so you know what what this transaction is is ultimately doing is saying like I'm going to compo I'm gonna um sort of consume these fragments of State produce some new fragments of state and this already is kind of interesting if you compare it to a system you know like ethereum or something else that has accounts because instead of having like Global mutable State you have
um immutable composable sort of State fragments yeah um but uh in this model right a validator can check this by seeing like you know I'll maintain uh some way of knowing you know which ones of these have already been consumed and then I can just check that I know about all the the inputs and they're unspent and then I'll add I'll you know become aware of these new notes that I've decided are valid and check signatures on the Sprint notes so uh what's the kind of corresponding model of that in the this world where we're trying to move all the state off
chain well now we need a way to uh to prove to the chain that actually you know we all of the the value balances and everything so we're going to end up with this different um kind of transaction structure where the transaction that we submit to the chain is going to say I'm going to have I'll draw these as circles and explain why in a second um and then I'll have this like ZK proof right so here's here's my transaction
that I'm going to submit what's in this proof inside of that proof I'm going to have all of the input nodes that I'm spending and all of the new notes that I'm creating and then I'm going to prove that you know this that these output nodes correspond to the cryptographic commitments that I'm asking people to include in the chain and for the notes that I'm spending I'm going to do some proof of a zero knowledge proof of inclusion that each
of these values was previously recorded in the chain and then I'm also going to reveal these so I've drawn these as circles these are called nullifiers um to every I have a way to attach to every um uh State fragment this serial number called a nullifier and that nullifier can only be derived by The Entity that controls this address uh but it's a you know fully deterministic process and so if I reveal a nullifier um I can have I can let a full node
check you know has this nullifier ever appeared and if so I'll reject the transaction as a double spend so you're sort of pulling apart those two functions of first was this no this state fragment ever previously included in the global chain straight and then second has it already been consumed so in the proof for proving that these were created in some previous block and then we're giving the nullifiers to the validator and we're proving that we did the nullifier computation correctly right so this nullifier actually does correspond to this note you know and so on but but there's no way for someone observing the chain to
link these with these and so you know right and that's why they're so the the reason that I drew these the circles is because you know the idea is that now to this sort of shaded sort of this is the true value of this note there's a note commitment that's used when you create the note and there's this second uh nullifier that's used when you spend the note but they're uh supposed to be publicly unlinkable and only uh The Entity that controls the the cryptographic key in the note is able to to derive both the note commitment and finale fire so so even though we have a blockchain where we only validators can
only see commitments um I can spend without revealing my metadata so Michael Hayden can't kill me yes perfect that's the one um and this you know you can do the actual sort of subtleties of how you build out this design there's obviously a little bit more complexity um you know one one piece that we haven't mentioned is the and the third sort of fundamental piece is that as part of this proof I also have to prove that like not just that I know about these notes but that like I actually am authorized to spend them yeah um and to do that you use some kind of re-randomizable signature but but this
is sort of fundamentally at the level of the state model um what the move is first you have a setup where your chain state is fragmented into all these little pieces and then second you have a way to move all of the actual State off chain and on chain you only record commitments to State and these nullifiers that let you mark a state fragment as spec um so this is actually already a little bit um yeah I forgot what I was gonna say
uh [Music] there's one yeah so then the the the maybe we can like switch places uh yeah yeah well no I mean I want to add one more thing okay yeah uh well wait so we should start again and then yeah great um so at this point we've um sort of done the thing right we've built this system that lets you privately record value you can make transactions so like that's why everybody in the world is using like private chains right well no okay so let's uh swap places so question is like
uh so what can't we do with this and if you think about what's going on with this uh transaction model and you compare to um say like a more traditional um you know account um I mean I guess like uh so the question is what can't we do with this setup like why is it that actually um all of the chains that people use uh
don't have this model and part of that is like okay there's like you have to make all the proofs you have to like build all the proving technology over the last few years there's been a lot of work on that but just at this sort of fundamental State model level what is the the limitation of this and to see that if we compare to a kind of uh account based system like ethereum you have basically um you know there's this like uh chain State it's this like big Global mutable state somebody applies a transaction to get a new state and then you know they keep doing this
they get like you know State Prime um and uh all of the full nodes you know all these transactions are in the clearest they can just like execute and mutate um and there's actually two like sort of fundamental things that you need in order to be able to interact with other people and have sort of some kind of like on-chain Society um and one of those is shared state so if I'm making this um uh ZK proof right I can't make any changes to anybody else's State because
I have to know all of the detail well right so this is the the clear text transaction this is the ZK proof I have to know everything that's going on inside of this state so I can't uh interact with anybody else's private State because I don't know what their private state is I can only see my sort of little uh Shard of the the fragments that I get to view well well and even uh not to jump in but but even if you modified the system to enable like some like you know uh notes that could be spent by anyone like like the state of unit swap pool or something you could generate a proof and I could
generate a proof and then we could like race to see whose is included in the chain but like ultimately only one of us is going to be able to consume that state exactly and that's actually so you know I got you know front run there um but the second point which is really the the fundamental one is early versus late binding so when someone you know sends a transaction on ethereum where they say oh I want to do this swap um they're not signing over you know I'm signing over my inputs and like the exact state of the contract and like
exactly what outputs they are I'm gonna what what outputs they're going to get they're just signing over their inputs and they're leaving it up to the chain to actually figure out what the state transaction the state transition will be but when you do a ZK proof you have to have this sort of fully sealed State transition that says you know this is exactly what the state transition is I'm giving you a proof that I have executed it correctly but the execution actually have has to happen on the client side at the time that the user makes the transaction and that means that you can't you know defer any uh execution to after things have
been sequenced on chain so you can only execute uh data that that doesn't sort of really conflict with anybody else's State updates so it's the the problem of shared state is actually not just sort of about who has knowledge of what but even if you say well the shared state will be fully uh public exactly for that reason um in Practical terms you don't know how to sort of like sequence your state transition uh so how do you you know make that work um and that's actually the sort of the the big thing that um penumbra does yeah so so how do you do
it um you have to move from a synchronous model right if again if you think about this uh type of design you can imagine those saying like there's like this one big mutex on the all of the state of the world and every time I want to make a transaction I say stop the world it's my turn I'm going to run and here are my changes and once I'm done I will let I will release my lock and let things uh continue and like this uh you know if you've ever tried to do like computer programming in like systems programming like this is like kind of a Nutty design like there's a
reason that no high performance uh like software system has like one big Global lock on everything yeah um so the challenge is like how do you move from this like synchronous execution model to an asynchronous model where it's almost like when I want to make a uh when I want to interact privately with this public State it's almost like I'm message passing from my transaction is trying to do some action and then I have to figure out you know what was the effect of that and and process it so so we're moving from like on ethereum every transaction is taking a lock on all of the state even what
it's not interacting with and so here you don't need to take any locks because you know that you're the only person that could uh mutate like you you're probably not going to have uh transactions that are trying to spend the same nullifier and and you know even if you do like you validators can just accept one of the other um and so I are we trying to move to a design where instead of taking a global lock we're taking a lock on the specific shared state that we want to the way that I would phrase it is actually it's that we're trying to get to some kind of Lock Free design um and and exactly you know to to sort of extend that analogy right it's like
okay well we've we've gone to this model where all of a sudden there isn't this like need to lock and have you know figure out how to resolve contention but the way that that was resolved is that we just like can't do any interaction with each other yeah so the problem is how do we how do we keep this nice like ZK compatible and also like you know much more scalable model of of computation but like restore the ability to like do useful interaction with each other and so that's kind of the big uh uh challenge that um we have a one solution to cool
Okay so uh now that we've had sort of this uh problem context we're going to try and get to this question of um how do we privately how do we privately interact with public shared state um and to start off I'm going to rather than sort of giving this you know here's this big like general idea of what our
computational model is going to be um we're going to actually walk through just like the specific example of how do I submit a swap right and that's actually been the way that we developed uh penumbra rather than starting with like okay we're gonna from our abstract first principles figure out exactly what the optimal private programmability model is we're going to try and solve one one concrete problem and then see what what features we can generalize from that uh solution cool um and so there's sort of this [Music] um multiple different kind of phases and to kind of keep things clear I'm going to draw some kind of dotted line
and uh everything kind of on this side of the line will be private user specific data and then everything below the line will be a public chain state actually probably a better way to phrase that now they've written a second one is to say just private user state so we're going to start off with a user who wants to submit some swap so as I
mentioned at the beginning the trading pair is going to be public and we don't necessarily want to reveal sort of which direction somebody is going on that trading pair so we're just going to have sort of you know each swap is going to come uh combine an input on one side and then input on the other side you know any rational uh Trader right is going to always have one of those be zero because it doesn't make sense to trade in both directions simultaneously but if you um if you leave that up to the user you can not reveal sort of what the direction of the the trading is so let's
say some some user has uh you know some there's some tokens A and B and they're going to take they have so let's say they're trying to trade A to B so that'll be kind of their distribution of their input funds and what they're going to do is form two things um first they're going to well I'll get to that second actually um they're going to create an encryption of their input amounts um using a additively homomorphic verifiable encryption scheme that
supports threshold decryption so that the pieces of that are you know the things that they're encrypting are their integer amount we want it to be additively homomorphic so that the validators will be able to batch up uh all of the inputs for a specific trading pair and then we also wanted to have threshold decryption so no single validator can get some kind of view of people's transactions uh and it should have some kind of end-to-end verifiability because like you know we don't want anybody to be able to forge any money so once they've formed these uh sort of encryptions of their input amounts they
include that as part of their um uh public transaction data uh and the second thing that they're going to do is they're going to Mint I'll represent a [Music] using this uh using a diamond um uh they're going to represent they're going to Mint what we call a swap nft and so this swap nft is going to uh have uh we so we mentioned that we're going to have um
all of all of the data that we're recording in the shielded pool right is a typed quantity so it's going to have uh you know unit one it's an nft of an acid ID which is a commitment to you know the trading pair A and B to their inputs so we'll call this um Delta one uh or Delta a and Delta B these are their inputs so they'll have an encrypt commitment to their uh thanks
uh their contribution to the batch and also uh to their own address so I've just realized that you know I was using these boxes previously I was using those for no commitments So to avoid a little bit of confusion I'll just do a little red con say this is going to be like an octagon because that's a shame I haven't used yet um or or maybe a long box yeah the resolution on the Octagon might be challenging yeah so we'll call these these like encryption
and I'll just write so this is like uh some this is going to be something that's that's additively where yeah it's just a cyber text for this uh so we call this um construction flow encryption just because you know by the time that you've made like oh it's additively homomorphic encryption with threshold decryption with end-to-end verifiability like at the point you have six properties you should just like give it a new name so we call it flow encryption and the idea is that what you're trying to do is encrypt flows of value between different parties different parts of a system um and be able to decrypt only the sort of aggregate amount of flow rather than
each individual user's contribution so uh the the the user when they're preparing this swap is going to [Music] um form these encryptions of their input amounts they spend the input tokens and just like burn them and they mint to themselves this Swap nft and now using the notation that we're using before they're going to submit um to the chain as part of their transaction um and a commitment to a note that records the value of their swap nft
so this will get like bundled up into a uh swap transaction you know along with whatever else they needed to do right they're going to probably have to spend some funds to get their input amounts but we'll ignore that for the moment um once the this uh transaction gets included in a block the validators are going to you know we'll get so we'll get a whole bunch of these the validators are going to go through for every trading pair and sum up all of the uh flow ciphertexts that people had submitted in transactions in that
um so this is sort of like the relevant part of the swap transaction but it would also include like nullifiers for yeah so we could we could write that in as well you know we'll also have like you know these for for like bringing in your funds yeah because you have to actually spend basically you're you're privately burning your input funds and then the uh the outputs that you get are you know this one that's coming from your your swap nft plus you know maybe you'll have some change notes from stuff that you submitted so we can label this as being like um here you're spending
input funds and then you have your encryptions of inputs and then there you have the um swap nft and maybe you have some change but importantly right like you've burned your input funds to form this transaction yep so once you know the validators get n of these transactions in a block they're going to sort them by the uh
trading pair and for each trading pair they sum up all of the um bash all of the inputs that are supposed to be batched and then do some multi-party computation to do the decryption cool I mean that sounds fancy it's really it's just threshold decryption and then once they've once they've gone and decrypted those values you know over here right this was this person's contribution but maybe once we've aggregated everything together we've got like you know this amount of Delta a and like some smaller amount of
Delta B in the opposite direction yeah yeah um so this is this like clear text batched so here right this is include but but these I I guess not to belabor it but but these are still encrypted uh during the battery so this this individual amount that well we should probably put out you know a subscript or superscript on it to say that it's you know user eyes contribution yeah this is going to stay private forever you know as long as there's multiple people in the batch right so you do actually need people to use the system to get privacy yeah but once you've got this
um you know here's the clear text batch trade the validator set actually is going to do this you know for every trading pair you know maybe there's also going to be some so here I'll put this as like Delta a and Delta B and maybe there will also be you know Delta C Delta d Delta a Delta C you know there's there's a lot of different trading pairs that somebody could do and you can imagine that it's sort of existing on some big uh liquidity graph so here's maybe we'll have like a and b
see d e over here and the so we'll have from all of these so it's like we're actually have like sort of like two levels of batching first you batch up all of the trading time for every trading pair and then once you have all of the the trading intent kind of batch together you can consider it as like okay there's some kind of flow in this direction maybe there's some flow in this direction uh or you know over that way or something and have some kind of like you know like a global
uh an optimal routing is performed which you know crucially uh were able to do this because for each pair there's only one uh like action that's performed by this exactly and so so if we were trying to do like this optimal routing is not cheap and so if we're trying to do it like on ethereum for every single uniswaptrade that's not like really terrible the other piece that makes it tenable is that on the liquidity side which we didn't get into um we've chosen the shape of the concentrated liquidity positions that we are going to support on penumbra to make this routing as efficient as possible so
there's this kind of full system design that goes into it but the the effect of this right is that it's like okay now that you do this like big computation once what comes out of that well um the output is output um we're going to get you know Lambda a and Lambda B so these are going to be the results of the sort of this is the like trade output as if you're modeling each of these as a single mm trade uh what was the other one I put like let's see Lambda C Lambda d
um and actually for each of these um it's not just that we'll get this output but also we'll get some kind of um success bit you know someone could submit a trade for instance where maybe they submit a trade on a pair where there's no liquidity or there's not enough liquidity or something and so you have to handle the case where uh the the swap is not executed and so but you just have a kind of success bid for like did this execute or not um and now sort of these outputs get written into the public chain State and sort of this computation is done so from this perspective of this like oh we're
you know doing like message passing between the private State and the public State we've uh first had um the sort of creation of this message that says I'd like to do a swap go through this whole kind of pipeline we get to these outputs and now what now what do we do um another thing that might be helpful to to kind of demarcate is that there's some kind of um like block boundary that happens here uh in that um you know this is all somebody is going to submit their their swamp this is all going to happen as part of
executing that block and as soon as that block gets executed these outputs are written into the public chain state and now um this user who had previously submitted a swap we just Swap and has it has this cool snfe right so they're going to now do a second transaction where instead of um you know previously they spent their input funds now they're going to make a proof that um you know they have this swap nft they're going to um they're going to prove that they have
you know knowledge of okay here's my um same uh swap nft or you can also think of this as being a state nft if you're getting a little bit more General um so they prove the knowledge of you know this opening of Like A and B the Delta a Delta B wrote it right because the the only only a commitment to the swap nft is right to the chain and so and actually you can it's sort of interesting um you can think of the asset ID here as being this kind of like root of another like mer you know you're you're
recording all these note commitments in a Merkle tree but actually what is that note commitment the no commitment and this is you know just sort of a sidebar box but like the note commitment here is a hash of the uh amount the type the like asset ID and the address and if your asset ID is also a hash you know now this is like another kind of like level of uh mercolization and so if you were going to generalize this you
know you could put arbitrary nested amounts of data and have arbitrarily complicated little State machines um all you know binding everything into this this asset ID true um so what are they going to do with this this swap nft though well what they what they're going to do is they're going to Mint uh some output notes that correspond to their Pro rata share of the batch what's that share well we know that the total uh aggregated uh output is you know Lambda a and Lambda B so they're going to get one output that's like uh
Lambda a that's the total batch amount of uh type A that's that's coming out of the batch and the amount that they're supposed to get is their contribution from you know the B to a Direction divided by the total batch size now that's only correct though if this uh swap actually succeeded if there wasn't enough liquidity or something these users have all burned their input funds so we don't want them to be kind of completely out of luck so what we do is we use this success bit
to interpolate between you know the success case where you get your pro router or 1 minus F times uh Delta a I so if s is equal to one this is a one and you pick up this term if s is equal to zero this term gets killed and you just get your inputs back so you do exactly the same thing for uh the other side of the uh tray this is like a little bit squished but you know it's a repeat of the previous so
hopefully it's not too confusing um and they're gonna mint you know this is gonna turn into uh some note yeah and they're going to get another note for their other side of the output um and they're going to uh spend so they're they're going to do this like instead of this uh swap transaction they do a swap claim and this is going to be the nullifier from the Swap nft and these are going to be the
um uh commitments yes the output note commitments very cool so one thing that you might have noticed is that so far we've only used you know a b the Delta a and Delta B but we actually put other stuff in this commitment particularly we put an address and the reason for that is that in this small claim action we also have a proof statement so that the proof you can think of this as sort of being like a special case spend where it's I do this spend but I also prove that the thing that I'm spending was a swap nft that
had you know this swap data and I pre I have to prove that it happened at a particular height so that I can know I can convince the well the verifier you you need to link it to that right right because I don't want to you don't want to have a situation where somebody can like submit two identical swaps in two different blocks and then be like oh I'll mint this one Whatever the best price was yeah yeah um but the final thing that you have to prove is that the output note commitments are actually going to be control these uh commitments or commitments to notes not just that have the correct amount of value but that are that those values are controlled by this address and the
reason that that is really important is that if you have that you've already kind of set up what the destination address is when you signed this original transaction and by proving that it's going to the same address that was originally authorized in the first place you can skip having to do any signing for the second transaction so if you imagine a you know somebody's using a hardware wallet or something the idea of oh well we'll have this like async State model execution where you just kind of drive it forward a block at a time yeah that kind of sucks if you have to like go on your little Pledger
device or something then yeah and and so the point is that by um by including the by carrying forward here's the thing that should have the capability over the final um destination uh the the output of this eventual computation um you've sort of made the the state transition much more rigid and therefore it's safe just to have your wallet or something um automatically create and submit these uh swap claim transactions uh without having to have any kind of further intervention because you've already kind
of pre-authorized here's who's supposed to get like I'm not just signing this is what I want to happen but also as part of that I'm saying and this is the entity that gets to control the output you know which is me yeah so so you could you could imagine doing that in like kind of the metamask equivalent and not having to go to your Hardware wallet again to like re to actually access your yeah or like you're you're assuming that somebody's using a hardware wallet they only have to use it in the case that it's meaningful which is like you know are they going to authorize a trade yeah that's where it makes sense to actually have that uh kind of stronger custody but once they've submitted that this sort of secondary transaction
it's not that there's anything new happening it's just that this is a way for the user to kind of claim the results of their outputs okay sort of complete the loop and like get ready to spend exactly um awesome cool uh yeah and I mean the really cool thing about this is that if you think about this kind of in this end-to-end process what actually gets uh revealed well when someone submitted a swap sure they they revealed what the trading pair was but their inputs are private those inputs get batched together with other people's inputs
and then later when they're claiming their outputs they just you know the the swap claim is going to have to reveal here's what the the height was and what the trading pair was in order to use this public price data but the actual minting is happening privately so as long as there are sufficient uh Traders you know doing volume on their decks the individual users uh specific trade amount actually gets long-term privacy you know forever it's not just some kind of like oh we'll do a commit and reveal where you know we'll agree we'll like
blind some trades and then reveal them after the fact but actually people's individual swaps get some long-term privacy and if we Circle all the way back to this idea of oh we want to have a cross chain multi-asset shielded pool this is actually really important because if you don't have a way to like privately transmute assets from one type to another you don't actually have one multi-asset shielded pool you have like 10 Single asset shielded pools kind of stacked together like plywood or something yeah but there's no mixing between the the layers well you have to imagine that for some
of those tokens the anonymity set for that childhood pool is going to be like very very small whereas in this model they all benefit collectively from every transactions yeah very cool um so this is the the picture of how the swaps work but hopefully it's kind of clear that you could generalize this to um you know various kinds of uh programmability computation smart contract logic and the kind of fundamental idea is you think of your inter your your particular funds interaction with some smart contract as being a kind of like asynchronous messaging
and every time you send or receive a message from the public shared computation that translates into a different state which is represented as a an nft and you use the fact that your shielded pool can enfor like it prevents double spends to enforce that this state machine gets ratcheted forward one step at a time uh as the the computation is is performed and similarly to the way that for instance uh Futures work in in Rust right your your user agent is the thing that is pulling those Futures and
driving them out to to completion cool yeah I I mean I I really like the the approach I I think a lot of people are trying to do like privacy preserving computation or private computation on chin and uh I think that's like a really painful thing uh with most designs but I really like how you're starting with something that's like immediately useful um and yeah it really offers a lot of a lot of value so I I think the number is one of the things I'm most excited about in the in CK apps cool well we're pretty excited too well thank you Henry uh anything where should people go to like find out more about penumbra um if they
go to uh penumbra.zone that's sort of the project landing page and from there there's links to like the Discord we have a work in progress protocol spec that has like you know way more details than this um and the other thing is that we run some weekly test Nets so if you go to guide.penember.zone that has all the instructions of like you know here's how you can play with the test net so if if you want to sort of see you know the half finished like slightly broken version slightly to mostly broken version of this um that's the way to do it awesome well thank you very much cool this is great thanks everyone
[Music]