Bringing Shielded Transactions to the Web

This week, we deployed Testnet 63, which brings an important and long-awaitedfeature: a web wallet and frontend site that brings shieldedtransactions to the browser, without compromising on privacy ordecentralization. This project has been long in the making, and it's helped usdiscover subtle requirements that we've been able to feed back into the designof the core cryptographic protocol. We're so excited to finally be able torelease it, and to share our first-principles rethinking of web frontends in theshielded context.

Why rethinking? Because solving on-chain privacy has the side effect ofupending fundamental design assumptions about how frontends are built. Forinstance, on a shielded chain, there's no RPC to query for your account balance,since only you can see it. Shielded chains achieve privacy by moving end-userdata off the chain and onto end-user devices, and that means those end-userdevices must be responsible for scanning and processing that data. While thisposes challenges, it also creates opportunities. As we'll explain in this post,the resulting architecture has significant advantages for decentralization,scalability, and security.

Challenges

Privacy is about control over information disclosure. Privacy-preserving systemsare not about hiding everything at all times from everyone -- they are aboutgiving users the ability to choose what information is disclosed to whom at whattime, rather than requiring that all information is disclosed to everyone at alltimes.

This allows building on-chain systems that match the expectations of real-worldusers. For instance, in traditional finance, being able to log in to someoneelse's brokerage account and see all of their positions and trading historywould be an unacceptable data breach. Yet on on-chain, this is considered normalor even desirable. It is not. On-chain activity is the future of coordinationtechnology, but that future requires control over information disclosure.

Building that future requires rethinking both data modeling as well as datamanagement.

We need to rethink data modeling because introducing privacy requires beingable to model what information is visible to whom. The same transaction maylook different to different users, who may have different levels of visibilityinto their contents. Software needs to be able to show users what they see andwhat others see. And the way that users interact with chain data changes. Forinstance, conventional authorization flows first build a transaction, thenpresent it to the user for approval. But since shielded transactions areopaque, this flow has to be changed to allow a user to inspect the transactionbefore it is constructed. To address this challenge, we've introducedfirst-class modeling of data visibility through the entire transactionlifecycle, which you can read about here andhere.

We need to rethink data management because introducing privacy means there'sno centralized server with access to all of a user's account information.Privacy is achieved by moving end-user data onto end-user devices, which meansthose end-user devices must be responsible for scanning and processing thatdata. Execution happens on the end-user device, not on-chain, so the user'sdevice must maintain and synchronize their state. This requires thinkingholistically about how the protocol reaches all the way out to end-user devices,and how to make end-user processing scalable as the system grows.This is a significant challenge, but it is also an opportunity. Privacy forcesus to build a truly decentralized system, rather than relying on centralized RPCproviders who become chokepoints on users' access to the network.

Design Goals

In thinking about how web interfaces to Penumbra should work, we identifiedthree high-level goals:

We want to be able to support a wide variety of interfaces to Penumbra.

While it's important that there be at least one first-class wallet experience atlaunch, Penumbra's capabilities are multifaceted, and users will probably bebest served by specialized interfaces: e.g., one for basic transfers or swaps,one for governance, one for power users to manage liquidity or examine theliquidity graph, etc.

Supporting a wide variety of interfaces is also important for decentralization:no one entity should "own" the Penumbra userbase via control of a singlefrontend, or be at risk of becoming a chokepoint for control of those users.This also means that it should be possible to build frontend interfaces toPenumbra that do not require custom backend infrastructure beyond an ordinarypd full node. And the demands on that infrastructure should be as minimal aspossible, so that it's easy for anyone to run.

We want those interfaces to be as easy to build as interfaces to transparent chains.

Historically, interfaces to shielded chains have been more difficult to buildthan interfaces to transparent chains, because they require the applicationdeveloper to manage synchronization of users' private state, unlike atransparent chain, where user state is accessible via RPC. Penumbra is aboutprivacy without compromise, so we want to make it as easy to build thoseinterfaces for Penumbra as it is for a shielded chain.

We want our users to have security when interacting with those interfaces.

In order for users to benefit from the availability of a wide variety ofthird-party interfaces, users need to be confident they can use them withoutrisk of losing funds or being hacked. We need to ensure that only the user canauthorize a transaction, and be able to understand exactly what actions they'reauthorizing when they do so.

Penumbra's Web Architecture

Our high-level approach to realizing these goals is to provide a "local RPC"that restores the conventional programming model for frontends for transparentchains -- but without the dependence on centralized RPC providers who see alluser data.

We define two GRPC service interfaces, corresponding to "read" and "write" access:

  • The View service can be thought of as a personal indexer, providing read access to all private data visible by a given wallet. The view server is responsible for scanning for transactions relevant to the user, downloading them, and decrypting and indexing them locally.
  • The Custody service handles authorization requests, receiving a TransactionPlan describing a proposed transaction, allowing the user to review and authorize it, and returning a bundle of AuthorizationData with signatures needed to build the transaction. The service interface is agnostic to the custody backend, allowing software wallets, hardware wallets, or threshold custody.

These services are not just limited to the web context. By defining them asfirst-class interfaces, we can use them across the entire Penumbra toolingecosystem. For instance, the command-line wallet pcli runs them internally anddoes in-memory GRPC, and the client daemon pclientd exposes them as a networkservice.

In the web context, we provide these services through a browser extension thatruns them on the end-user device. We use the Buf.build Typescriptpackages generated from our Protobuf definitions to model all Penumbra data, andimplement a custom transport object that allows frontend code to make GRPCrequests to the browser extension exactly the same way it would make them to aremote server.

This restores the conventional programming model, where frontend code is mostlystateless and relies on RPC requests to read and write data. The onlydifference is that requests relating to private user data are processed locally,while requests relating to public chain state are sent over the network.

To handle the complexity of modeling data visibility, the view service returnstransaction views, pre-decrypted and pre-interpreted views of transaction datathat highlight exactly what data is visible to the user's wallet. For instance,while a transaction has a Spend action, a transaction view has a SpendViewthat can be either visible or opaque, with the decrypted data bundled intothe visible variant. This allows frontend developers to focus on thesemantics, without having to worry about the mechanics of Penumbra's shieldedcrypto.

All long-term key material is kept inside of the browser extension, so webcontent only has access to per-transaction data, and all transactions must beapproved through the browser extension, which provides a secure display pathfor the user to review a proposed transaction. This allows a user toselectively grant viewing or spending permissions to web interfaces torelatively untrusted web interfaces, and to revoke those permissions later.

This architecture helps realize our high-level goals for security and decentralization:

  • Because the extension exposes common service interfaces to web frontends, we know that a "first-party" frontend is not privileged over a "third-party" frontend. Our test frontend shows that it's possible to build complete functionality using public API surface, so that no entity is in control of what frontends can be written.
  • Because the extension performs local indexing, most RPC requests are processed locally, and the demands on the RPC provider are relatively lightweight. Our goal is that any pd node should be able to serve a frontend out of the box, which is why, for instance, pd has zero-configuration support for auto-HTTPS via Let's Encrypt and multiplexed grpc/grpc-web support out of the box.
  • Because authorization requires a TransactionPlan that completely describes the effects of a transaction, the extension can show a user exactly what they're authorizing.
  • Because the extension performs fine-grained, selective disclosure of transaction contents through transaction views, a compromised frontend cannot compromise any long-term key material. At worst, it can disclose historical information, and users can limit damage by revoking access or prevent it by only approving read access from frontends they trust (or run locally).

While we're not intent on the Penumbra extension being the only custody andview provider for Penumbra, building an end-to-end system has allowed us toflesh out the design. As we mature the code, we're interested in working withexisting wallets to integrate Penumbra support -- but we want to know that thecomponents they'd integrate work end-to-end first. Going forward, we'reinterested in supporting the Penumbra wallet extension as a first-class tool onits own and as a collection of libraries reusable by other wallets.

Getting Started

Penumbra's web extension is now published to the Chrome Web Store. Thefrontend site is available at https://app.testnet.penumbra.zone. Bothare still a work-in-progress, but we appreciate hearing about any and allfeedback in the Discord!

Stay tuned for more updates on our pathway to mainnet. Slowly, and then all at once.