Skip to content

Addresses in Beam

valdok edited this page Aug 19, 2024 · 9 revisions

image

There're (too) many different kinds of addresses in Beam:

  • Regular (a.k.a. new-style)
  • Legacy (BBS-only, a.k.a. old-style)
  • Offline
  • Max-privacy

In addition to those kinds of addresses, there's more terminology:

  • Payment Tokens, that consist of an address with the requested payment amount
  • Vouchers
  • Endpoints (alternatively called as Signature, or Identity)
  • Payment proof

Some of the above things are permanent, some expire, and some are intended for single usage. In addition to that, when the wallet is restored, the addresses are not preserved (new wallet instance generates new addresses). All this is very confusing. Here we'll explain in details how things work, why historically so many kinds of addresses were implemented, and what is relevant today.

What are Beam addresses?

First and foremost:

there are no addresses on the Beam blockchain per se.


Beam is based on UTXO model (set of coins, in simple words). There're 2 types of UTXOs:

  • MW (MimbleWimble) UTXOs.
  • Shielded TXOs. Those are created and spent using in Lelantus-MW txs.

Both kinds of UTXOs are opaque, and look like random data. No addresses that expose who owns them, and the value is concealed.

Each UTXO has its secret key, which is needed to build a valid tx that spends it. Means whoever knows that secret key - actually owns the coin.

How the wallet manages its coins

Each wallet has the Master Key (initialized from the secret seed phrase). It is used to derive all the coin keys. When the coins are generated by the wallet, they're encoded such that they can re recognized by the corresponding Owner Key (also derived from the Master Key).

This means the following:

  • All the coins belong to the wallet that generated it. They can be recognized by its Owner Key, and then spent in the future txs using its Master Key.
  • Coins do NOT belong to addresses.
  • Addresses are only used between the wallets to communicate and build txs (more about this later). After the tx is included in a block - addresses don't matter.

MW txs and old-style addresses

Beam is based on MW, where transactions are built interactively. Means users must communicate to build a transaction.

For this we developed an SBBS system, that allows wallets to exchange encrypted messages anonymously. Wallets can generate public/private key pairs, where the public key is used to encrypt messages, and private key can decrypt them.

That's how addresses were born on Beam. Address in fact meant SBBS address, a public key to encode messages, that can only be decoded by the appropriate private key.

Here're some notes regarding the SBBS encryption:

  • All encrypted messages are opaque (look like random data), the sender/receiver of the message is also opaque, and the message is protected against tampering (using HMAC scheme).
  • Using the SBBS address one can only encrypt messages, not decrypt.
  • There's no feasible way to realize that a specific SBBS message was encoded by a given SBBS address.
    • Means you can share your SBBS address to different users, they won't be able to see when you communicate with others.
  • Users can generate as many SBBS addresses as they want.
  • In order to receive the SBBS message, one tries to decrypt all the incoming SBBS traffic. Only the intended messages would be successfully decrypted and pass HMAC verification.
  • If you listen to several active SBBS addresses - the wallet will try to decrypt each message by each address private key.
    • The more active SBBS addresses - the harder the wallet works to receive the messages.

Address generation and expiration

As we said, a wallet may generate multiple SBBS addreses. It may also deactivate a specific address, which means it'd stop trying to decrypt incoming SBBS messages by its private key.

Theoretically there was no good reason to have more than 1 SBBS address. User could just live fine with only a single SBBS address, and share it freely. As we've said, all the messages are completely opaque, and the communication is anonymous.

There's only limited scenarios where a user may need more than 1 address. If the user wishes to provide several addresses that look like of different users (for example, have several accounts at an exchange, with different SBBS addresses for funds withdrawal).

However, due to user habits and some misconceptions, users insisted on changing addresses regularly. That's why we implemented automatic SBBS address generation and expiration

Payment proof

Unlike other blockchain designs, in Beam there're no addresses on the blockchain per se. As a result, if Alice sends funds to Bob, there's no way to prove it later from the blockchain data (Bob has plausible deniability).

To address this, we implemented a Payment Proof. It's a signature, signed by the recipient of the funds, that it indeed accepts the specific amount from the specific sender. It is signed by the receiver and verified by the sender during the transaction negotiation stage (all this happens off-chain).

The Payment Proof signature signed the following:

  • Identity (pubkey) of the sender
  • Identity (pubkey) of the receiver (the signature is signed by the corresponding private key).
  • Amount and asset type being-received
  • Transaction Kernel ID. If the tx was negotiated but not broadcasted and accepted in a block - the Payment Proof is considered invalid (i.e. there was an intention of the tx, but it didn't take place actually).

Identities of both sender/receiver were in fact their SBBS addresses. That is, the same key was used both for SBBS messages encryption, and to identify the owner of the funds.

Hardware Wallet, and new-style addresses (a.k.a. Regular addresses)

With the hardware wallet the things work differently. The Master Key and all the coin keys are managed entirely in the HW wallet. The software wallet gets the Owner Key that can recognize coins (but not spend them), and handles all the communication and blockchain state change logic.

The SBBS address must be managed by the software wallet, it's too complex for the HW wallet to decrypt all the SBBS traffic. On the other hand, when the Payment Proof is signed/verified - it must be done with the key that is managed by the HW wallet.

This is where we decided to split the SBBS address and the user identity. The SBBS address is the address you're communicating with, and the Identity is the public key of the final receiver/sender of the funds. For standard wallets both are managed by the wallet, but with the HW wallet they're managed in different places.

To support this, we defined a new-style address (now called a Regular address).

First, the address format was changed. The older SBBS address was just a hex-encoded pubkey. We decided to change it into an encoded collection of arbitrary number of parameters (to support possible future parameters for various address/token types).

The Regular address consists of the following fields:

  • SBBS address
  • User Identity

Endpoint

Historically we had several names for the above user identity: Identity, HW Identity, Signature, and etc. All that lead to confuses, so we decided to give a distinctive name to this: the Endpoint.

The rationale behind this name is the following. Suppose Alice sends funds to Bob, both use HW wallet. Conceptually you may treat this situation as this: Alice's HW wallet is the ultimate sender of the funds, Bob's HW wallet is the ultimate receiver. And they negotiate the transaction with each other. The software wallets of Alice and Bob are just intermediate entities, they're not part of the transaction negotiation.

In other words, the Endpoint is the final source/destination of the funds.

Lelantus-MW

To address the inherent MW linkability problem, we extended Beam with the Lelantus-MW protocol. It's our proprietary modification of the Lelantus protocol, adjusted to fit and complement the MW.

With it we added 2 new transaction elements:

  • Shielded Output - add an opaque coin into the shielded pool
  • Shielded Input - spend some coin from the shielded pool.

In MW transactions are interactive, when Bob receives funds from Alice, he creates his UTXO to accept the funds in advance (during negotiation stage) . And since Bob himself created his UTXO, he can recognize it using his Owner Key, and spend using his Master Key.

In contrast to MW txs, Lelantus-MW txs are non-interactive. Means Alice creates the Shielded Output tx element, without Bob being-involved. Yet she creates it in such a way that Bob will be able to recognize and spend it later.

This means that Bob should give Alice an additional data, to allow her to send funds to Bob using Lelantus-MW.

Technically each Shielded Output comes with a Ticket. It's an opaque data object, but encoded such that it can be recognized by the funds recipient (Bob). Moreover, Tickets must be unique, it's impossible to use the same ticket twice (this is related to double-spend prevention).

So, basically there're 2 options here:

  1. Bob gives Alice a source data, using which Alice may generate arbitrary number of Bob's tickets.
  2. Bob generates arbitrary number of tickets, and gives them to Alice.

Both methods have their pros and cons. And both are supported in terms of different address types.

Offline address

This corresponds to the 1st method. The Offline address in essence is a ticket generator. It also comes with the Bob's Endpoint, and is also signed by Endpoint's signature (if Alice needs to prove that she sent funds to Bob - she can show that the corresponding ticket was generated by the generator signed by Bob).

Once Alice has it, she can send arbitrary number of Lelantus-MW txs to Bob, which is a good thing.

There's however a drawback. Alice knows the internal parameters of the ticket (since she actually generated it). One of them later will be used by Bob, when he'll spend this shielded coin.

Means that the sender will notice when the receiver will spend the shielded coin. For the 3rd-party observers the shielded transactions are anonymous, but this specific kind is not anonymous w.r.t. the sender. Hence we call it Offline, but not truly private.

Note: despite the above drawback, the above is perfectly fine if you receive shielded funds from a trusted sender. For instance, you may have several wallets (with different seed phrases). You may use Offline address to transfer funds in a private way. As we've said, 3rd-party observers will see no link between the Shielded Output and the corresponding Shielded Input.

Max Privacy address

This corresponds to the 2nd option. The Max Privacy address consists of the following:

  • Receiver Endpoint
  • Arbitrary number of Vouchers.
    • Each Voucher is actually a ticket, signed by Bob Endpoint signature (to prove later that Bob is the receiver of the funds).
  • Optional SBBS address to ask for more vouchers.

This method doesn't have the drawback of the Offline address. Alice may send funds to Bob, Bob later may spend those funds anonymously w.r.t. Alice.

The obvious drawback is that there's a limited number of Vouchers/Tickets. Once they're all consumed - there's no way to send more txs. This is where the SBBS address can be used. Once Alice runs out of Bob's vouchers (or getting low on them) - her wallet may request for more Bob's vouchers via SBBS. If/when Bob will be online - his wallet will respond, and provide Alice with more vouchers automatically.

Tokens

As we've said, all the address types, except the "old-style", are represented as a collection of parameters. In addition to the address itself (whatever kind it is), it's possible to include more fields.

Using this we've introduced a so-called payment Tokens, which are a way to request a specific payment. They consist of the address (any kind), and the requested Amount and asset type.


Ideas for improvements

So we've described what Beam addresses are, why it's not a big deal to loose them (i.e. coins don't belong to addresses, you don't loose coins). We also explained why there're different kinds of addresses, and why they are necessary. The old-style address is actually obsolete, and even incompatible with the HW wallet (i.e. you can't even generate it with the HW wallet). But, unfortunately, we can't get rid of it completely, because some existing exchanges won't accept different addresses (they do a sort of a regular-expression check on the address). So they're still here.

However, many things can and should be improved, mostly regarding user experience and the UX.

The most important change can be expressed as this:


It's all about Endpoints


In simple words, each address consists of two things:

  • Who does it belong to, i.e. who is the supposed receiver of the funds. This is the Endpoint.
  • What kind of tx would that be, and how to negotiate and build it.

Endpoint, i.e. the identity of the sender/receiver - is the most important thing. It should be visible wherever applicable, and play a crucial role in the address book. Who am I paying, and who payed me. This is arguably more important than how is the payment done.

Address format

Currently all address types (except legacy) are displayed as a Base58-encoded strings of a <key, value> pairs, where key is an 1-byte identifier of the parameter. As a result, the user has no way to see either the embedded arguments, or even the address type. A better option would be encoding the arguments in a human-readable way.

For example, a Regular (online) address could be displayed as:

beam_Bk1azc8VtaYU1f6t7jiRGkxJDiAVui6Y5WvohjoU1yFA_bbs274b78587e1c9643e7472e221be1634b8efe06f747175d3d8c98ce1ef665b056d4a

It begins with beam (a common practice in some networks), then followed by a human-readable Endpoint, and then followed by the bbs address.

What if users tamper/modify address manually?

The good news is that Beam addresses are generally resistant to tampering. If one modifies the address (either intentionally or not) - there is no risk of loss of funds.

If one modifies the SBBS address, the communication with the receiver will fail. And if the Endpoint is modified, the negotiation with the receiver will fail.

Same applies to Max Privacy and Offline addresses. They contain pre-signed receiver signatures (that would be a part of the future payment proof). If one modifies some address fields - the address would become invalid.

And, again, this all boils down to the Endpoint of the address, i.e. who is the supposed recipient of the funds. If the sender verifies it and is confident that it's the intended one - there's no risk of funds loss, or the payment going into wrong hands.

Address book refactor

Address book consists of several tabs. (My active addresses, My expired addresses, Contacts). For the "Contacts" tab there is a list of all known addresses of other users.

A more sane address book should look like this

  • There should be a list of known Endpoints, not addresses/tokens. Those are actually different contacts. Each can be annotated by a name.

  • For each Endpoint we can show the following information:

    • Its SBBS address (if known)
    • Do we have its Offline address (yes/no)?
    • How many vouchers are left for Max Privacy txs?
      • Optionally - a button to request more vouchers manually
  • For owned (my) Endpoints the following information should be presented

    • Internal number. That is, all the keys are generated using Master Key, from the provided key number. Normally they're picked at random, and not shown to the user. But we can show them. By such users will be able to re-generate the same addresses after the wallet is restored.
    • Option to generate an address/token of any kind for this specific Endpoint.
    • HW wallets: option to verify the Endpoint on the HW wallet

Send screen - To

Currently in the "To" field the user puts an address. The wallet parses the address, recognizes its type, and acts accordingly. For some addresses the wallet gives an option to modify the transaction type (Online, Offline, Max Privacy) if that token has enough information.

Instead the wallet should recognize the Endpoint from the given address, check if it's already in the address book, and realize all the possible ways of sending from what it already knows about it. Not only from the parameters of the provided address.

Moreover, it should be possible to specify "To" the Endpoint only. Or just the name that the user annotated to it in the address book. The wallet should automatically find it in the address book, and allow tx types according to what is known about it.

Send screen - From

Currently this doesn't exist at all. When funds are sent - the sending wallet always identifies itself as a random user with an ephemeral Endpoint.

There should be an option to specify an existing Endpoint. By such the sender may make the receiver know who sent the funds.

In the "From" field there should be a choice of the currently existing Endpoints (i.e. active addresses), as well as previously used (perhaps no more active), or an "Anonymous", which means what it is today - a random Endpoint.

Transaction details

The transaction details are loaded with lots of technical parameters (SBBS address of sender/receiver, signatures, etc.). They are mostly meaningless to the user.

There should be the following parameters:

  • For funds transfer transactions:
    • Endpoint of the sender/receiver. If they exist in the address book - this should be mentioned.
    • Type of tx (Online, Offline, Max Privacy)
    • Amount transferred and asset type
    • Payment proof
  • For other txs (coinswap, contract calls)
    • Endpoints and Payment proof are irrelevant. Don't show them.
    • List of sent/received asset types and amounts
Clone this wiki locally