Testnet 29: Shielded Swaps Have Arrived
We’ve been continuing to iterate on Penumbra with our weekly testnet releases. Today, we’ve released our twenty-ninth testnet, codenamed “Eukelade”, after the retrograde irregular moon of Jupiter.
This testnet is an exciting milestone: it has the first release of our shielded batch swap mechanism, which enables Penumbra users to privately swap tokens without leaving the shielded pool!
If you want to try it out, jump over to
follow the instructions on how to start interacting with the testnet. Otherwise,
keep reading to find out more about what’s new, how shielded swaps work on
Penumbra, and where we’re going next.
- The first implementation of shielded swaps, exposed through
pcli tx swap.
- A hardcoded, stub constant-product AMM backend for testing in advance of the full DEX implementation.
- Integrated support for
grpc-webby default, enabling direct RPC access from web clients to any full node.
- Support for dummy spends and outputs, allowing clients to hide the arity of their transactions.
- The memo field is now a transaction-level field, rather than attached to each output, simplifying conceptually and saving space in transactions.
pcli view list-transactionscommand that displays all transactions indexed during scanning.
- The publication of an NCC Group audit of our core cryptographic primitives: the
decaf377group and our Poseidon parameter selection.
The challenge of building shielded swaps is the challenge of providing private interaction with public shared state: we want individual users' trades and account balances to stay private, while retaining a public view of the aggregate market state, like clearing prices, available liquidity, and trading volume.
Our shielded swap implementation mediates between our shielded pool, containing private user data, and our decentralized exchange (DEX), which executes publicly. As we mentioned in our summer update blog post, Penumbra batches the swaps in each block by trading pair, revealing only the batch totals. We accomplish this by using additively homomorphic encryption of the swap amounts to a threshold key jointly controlled by the validators. Each swap transaction privately burns its input funds, mints to itself a "swap NFT" receipt recording the input amounts, and verifiably encrypts them to the validators' threshold key.
After processing all transactions in a block and obtaining the batch inputs for each trading pair, the DEX executes each batched swap against the available liquidity, recording either that the swap succeeded with some batch output, or that it failed (e.g., because there was not enough liquidity). This batch swap output data is recorded in the public chain state.
As a client detects that their swap was included in a block, they can view the batch swap output data, and send a claim transaction that spends their swap NFT and mints the appropriate output tokens: a pro rata share of the batch output, if successful, or their original inputs, if unsuccessful. Through careful design of the proof statements and state transitions, we can even allow the claim transactions to be made automatically, without requiring a second signing phase, by proving that the output funds are sent to the correct address and prepaying fees for the claim transaction.
Penumbra’s DEX is designed around concentrated liquidity, because as the first DEX to allow private trading strategies, we want to prioritize marketmakers with information to conceal. We can also take advantage of the fact that we only execute once per block to perform much more sophisticated execution, optimally routing trades across the entire liquidity graph, and performing in-protocol arbitrage to ensure that, at each block transition, the chain steps from one set of consistent prices to the next.
However, since we haven't implemented the full backend yet (there’s currently no
way to create liquidity positions), we implemented a stub
Uniswap-V2-style constant-product market
maker with some hardcoded liquidity for a few trading pairs:
penumbra:gn. This allows testing the shielded pool
integration, and will cause a floating exchange rate based on the volume of
swaps occurring in each pair. (There's even a possibility to do cycle arbitrage,
if you're really keen on it, though that arbitrage will disappear once we do
in-protocol arb with the full DEX implementation!).
Now that we've implemented the "frontend" of the AMM, the obvious next step is to work on the "backend", the DEX implementation itself. However, before we do that, we'll be pausing to regroup and refactor the way we model chain state internally, so that in addition to efficiently recording large amounts of data, we can also index and efficiently query it. This way, when we implement the DEX backend, we'll be able to efficiently query large numbers of concentrated liquidity positions, and it's also an opportunity to iterate on the design of our internal application framework based on some of the lessons we've learned so far.
We're also working on a few other parallel tracks, notably:
- Reworking the data model of our shielded pool to change from 64-bit to 128-bit amounts, for better compatibility with bridged ETH assets that inherit an excessive level of precision, and propagating those changes through our client implementation.
- Implementing support for inbound ICS20 token transfers from counterparty IBC chains.
- Work to model a plaintext view of a transaction as a standalone object, making the contents of shielded transactions more legible to third-party applications.
- Improved deployment infrastructure for validator nodes or testnets, especially with an eye towards testing IBC integrations.
- Initial work on a browser extension that provides custody (key management and transaction signing) and view (private state scanning and synchronization) services to web apps, allowing a wide variety of decentralized frontend interfaces.