How Voltage Works
As we’ve started onboarding customers to the Voltage platform, we’ve gotten a lot of questions about how Voltage works. What can we see, what can we do, what trust is required, etc. In this blog post we’ll lay out answers to these questions. We want to be as transparent as possible so people know what they’re signing up for. Our user’s privacy and control is nonnegotiable and we’ve worked hard to preserve that. We’ll start at a high-level and get more technical as we go. There’s a lot to cover so let’s jump in.
Access, Trust, and Visibility
We have no access to your seed phrase, passwords, or macaroons. Therefore, we are never able to see your transactions, spend your funds, or execute any commands against your node. However, just because we can’t control or see your money does not mean this is a trust-less system. By using Voltage you are trusting us with your node’s uptime, data, networking, and more. We don’t take this trust lightly and we want to be open about what happens in our systems. First, let me explain what we can and can’t see about your node.
What we can’t see
We can’t see any data about the Lightning Network from your node. We can’t see your node’s public key, peers, channels, balance, or transactions. We don’t have the credentials to your node, so there’s no way for us to get this information. All peer-to-peer traffic is routed through Tor. This means we can only see your node connecting to Tor entry nodes, not your actual peers. This also means your node is indistinguishable from other nodes on the network. No one can see you’re using Voltage via the network.
We have some features and products in the works that could require us to know information about your node (like your public key for example). Any of our services that require information about your node will be strictly opt-in. You will always have the ability to choose what data you share with us.
What we can see
What we can see is infrastructure level information like your node’s settings, node version, and connecting IP address. We need this information so that we can apply the right policies to our edge router. When a request is made we evaluate the requesting IP to ensure it’s allowed to talk to your node. We do not track IP addresses for any reasons other than IP whitelisting and rate limiting. Since your Lightning nodes are hooked up to our Bitcoin full nodes, it’s possible we could see some of your on-chain activity. To be very clear, we do not track this information and never will.
To summarize, your node is a locked box to us. However, our service still requires trust. We take this very seriously and privacy for our users is top of mind. We’re in the business of making Lightning better, not surveilling our users.
Now to shift a little more technical. How do we accomplish this? To start, let’s cover our infrastructure. We run all servers inside a private network with only an edge router exposed to the outside world. No Lightning node APIs are directly exposed to the internet. All servers that run the Lightning nodes don’t allow human logins. We have uninstalled SSH and any other remote access into the servers. All backups are encrypted and replicated for redundancy. To accomplish our goal of never seeing sensitive information we’ve had to make some changes to the LND codebase. Let’s go over them.
The first change is to run the stateless-init feature. This is a change not yet merged into LND. With stateless-init, macaroons are never written to disk. The admin.macaroon file is returned in the API response when you initialize your node. This means we never see your macaroon on our systems.
When initializing your node from our dashboard, an API call is made directly to your node with stateless-init set to True. The response from this API call contains the admin macaroon. When the dashboard receives the macaroon, it encrypts the data using the password you set for your node. Then it sends the encrypted data to our API for backup. Because we never see or store your node’s password, we can’t read the macaroon data. This not only enables safe backups of your macaroon, but it also makes connecting to your node very easy. When you want to connect from our dashboard, we pass the encrypted data from our API to you and prompt for the password to decrypt the macaroon in your browser. Once decrypted, the dashboard can generate things like lndconnect codes. Our dashboard is open source so you can verify for yourself what’s going on.
Next, we had to add support for TLS certificates that are signed by a trusted Certificate Authority. This not only makes for a better user experience, it also allows us to make API calls directly to the node from our dashboard. Modern browsers require an API to have CORS enabled and a trusted TLS certificate to communicate. Since we have both, we are able to make calls directly from the user’s browser to the node’s API. As previously mentioned, our dashboard is open source so you can verify this for yourself. Again, no node APIs are exposed to the internet. Therefore, we can direct traffic accurately through our edge router by using the SNI of the request. This means the packets stay encrypted from your browser to your node’s process.
Finally, we handle the Transport Layer Security. Today, LND writes out the TLS private key to disk in plaintext. This was no good for us because that meant it’s possible for us to decrypt traffic. We created a pull request to add encryption to the TLS private key so it’s never exposed. Now the TLS private key is encrypted to the node’s seed. However, this creates a strange case when the node is locked. How can we decrypt the unlock or initialize API calls if the private key is encrypted? For these we generate an ephemeral TLS key pair with the private key only held in memory for the single API call.
How this works is LND generates a TLS private key at startup but never saves it to disk. It then uses this key to generate a Certificate Signing Request and request a certificate from our certificate provider. The certificate provider then returns an HTTP challenge to prove domain ownership. LND starts up a new webserver and serves the content necessary for validation. It then makes a request to the certificate provider to validate the challenge and polls the provider’s API until it sees the certificate is issued. Once the certificate is issued, we shutdown the validation webserver and download the certificate. Then we start the wallet unlocker webserver with this ephemeral key pair. Once the node is unlocked the ephemeral key pair is deleted and the node is able to use the persistent key pair. While the workflow for TLS private key encryption is contributed back to LND, our process for requesting certificates from our provider is kept in our fork. This is because these changes are specific to Voltage and ties to a paid certificate provider shouldn't be in the upstream project.
A similar process is used for the Tor private key. LND generates a hidden service for itself to use with peer to peer traffic. We can’t have the Tor private key in plaintext for the same reasons. So we added encryption for the Tor private key as well.
That was a lot of information, but we feel it’s important that we’re transparent about our systems. There is absolutely a level of trust required on our platform, but we’ve worked hard to keep it as minimal as realistically possible. We’re trying to improve the Lightning Network by making it easier to use. We want to accomplish this without compromising on user privacy or control. If you have additional questions or comments please email [email protected] or join our Telegram group. We’ll be happy to help. Everyone should gear up now. Adoption is coming.
One thing this blog post left out was disk encryption. All of the hard drives have encryption enabled and always have. Additionally, since the release of this post we've added always-on 256-bit DRAM (memory for short) encryption to every server. Encryption is literally everywhere!