This document describes a new addressing scheme for Monero.
Chapters 1-2 are intended for general audience.
Chapters 3-7 contain technical specifications.
Table of Contents
- 1. Introduction
- 2. Features
- 3. Notation
- 4. Wallets
- 4.1 Wallet parameters
- 4.2 New wallets
- 4.3 Migration of legacy wallets
- 4.4 Additional keys
- 4.5 Key hierarchy
- 4.6 Wallet access tiers
- 4.7 Wallet public keys
- 5. Addresses
- 6. Address encoding
- 7. Test vectors
- Appendix A: Checksum
1.1 Why a new address format?
Sometime in 2024, Monero plans to adopt a new transaction protocol called Seraphis , which enables much larger ring sizes than the current RingCT protocol. However, due to a different key image construction, Seraphis is not compatible with CryptoNote addresses. This means that each user will need to generate a new set of addresses from their existing private keys. This provides a unique opportunity to vastly improve the addressing scheme used by Monero.
1.2 Current Monero addresses
The CryptoNote-based addressing scheme  currently used by Monero has several issues:
- Addresses are not suitable as human-readable identifiers because they are long and case-sensitive.
- Too much information about the wallet is leaked when scanning is delegated to a third party.
- Generating subaddresses requires view access to the wallet. This is why many merchants prefer integrated addresses .
- View-only wallets need key images to be imported to detect spent outputs .
- Subaddresses that belong to the same wallet can be linked via the Janus attack .
- The detection of outputs received to subaddresses is based on a lookup table, which can sometimes cause the wallet to miss outputs .
Jamtis is a new addressing scheme that was developed specifically for Seraphis and tackles all of the shortcomings of CryptoNote addresses that were mentioned above. Additionally, Jamtis incorporates two other changes related to addresses to take advantage of this large upgrade opportunity:
- A new 16-word mnemonic scheme called Polyseed  that will replace the legacy 25-word seed for new wallets.
- The removal of integrated addresses and payment IDs .
2.1 Address format
Jamtis addresses, when encoded as a string, start with the prefix
xmra and consist of 196 characters. Example of an address:
There is no "main address" anymore - all Jamtis addresses are equivalent to a subaddress.
2.1.1 Recipient IDs
Jamtis introduces a short recipient identifier (RID) that can be calculated for every address. RID consists of 25 alphanumeric characters that are separated by underscores for better readability. The RID for the above address is
regne_hwbna_u21gh_b54n0_8x36q. Instead of comparing long addresses, users can compare the much shorter RID. RIDs are also suitable to be communicated via phone calls, text messages or handwriting to confirm a recipient's address. This allows the address itself to be transferred via an insecure channel.
2.2 Light wallet scanning
Jamtis introduces new wallet tiers below view-only wallet. One of the new wallet tiers called "FindReceived" is intended for wallet-scanning and only has the ability to calculate view tags . It cannot generate wallet addresses or decode output amounts.
View tags can be used to eliminate 99.6% of outputs that don't belong to the wallet. If provided with a list of wallet addresses, this tier can also link outputs to those addresses. Possible use cases are:
2.2.1 Wallet component
A wallet can have a "FindReceived" component that stays connected to the network at all times and filters out outputs in the blockchain. The full wallet can thus be synchronized at least 256x faster when it comes online (it only needs to check outputs with a matching view tag).
2.2.2 Third party services
If the "FindReceived" private key is provided to a 3rd party, it can preprocess the blockchain and provide a list of potential outputs. This reduces the amount of data that a light wallet has to download by a factor of at least 256. The third party will not learn which outputs actually belong to the wallet and will not see output amounts.
2.3 Wallet tiers for merchants
Jamtis introduces new wallet tiers that are useful for merchants.
2.3.1 Address generator
This tier is intended for merchant point-of-sale terminals. It can generate addresses on demand, but otherwise has no access to the wallet (i.e. it cannot recognize any payments in the blockchain).
2.3.2 Payment validator
This wallet tier combines the Address generator tier with the ability to also view received payments (including amounts). It is intended for validating paid orders. It cannot see outgoing payments and received change.
2.4 Full view-only wallets
Jamtis supports full view-only wallets that can identify spent outputs (unlike legacy view-only wallets), so they can display the correct wallet balance and list all incoming and outgoing transactions.
2.5 Janus attack mitigation
Janus attack is a targeted attack that aims to determine if two addresses A, B belong to the same wallet. Janus outputs are crafted in such a way that they appear to the recipient as being received to the wallet address B, while secretly using a key from address A. If the recipient confirms the receipt of the payment, the sender learns that they own both addresses A and B.
Jamtis prevents this attack by allowing the recipient to recognize a Janus output.
2.6 Robust output detection
Jamtis addresses and outputs contain an encrypted address tag which enables a more robust output detection mechanism that does not need a lookup table and can reliably detect outputs sent to arbitrary wallet addresses.
3.1 Serialization functions
- The function
BytesToInt256(x)deserializes a 256-bit little-endian integer from a 32-byte input.
- The function
Int256ToBytes(x)serialized a 256-bit integer to a 32-byte little-endian output.
3.2 Hash function
Hb(k, x) with parameters
b, k, refers to the Blake2b hash function  initialized as follows:
- The output length is set to
- Hashing is done in sequential mode.
- The Personalization string is set to the ASCII value "Monero", padded with zero bytes.
- If the key
null, the hash function is initialized using the key
k(maximum 64 bytes).
- The input
SecretDerive is defined as:
SecretDerive(k, x) = H32(k, x)
3.3 Elliptic curves
Two elliptic curves are used in this specification:
- Curve25519 - a Montgomery curve. Points on this curve include a cyclic subgroup
- Ed25519 - a twisted Edwards curve. Points on this curve include a cyclic subgroup
Both curves are birationally equivalent, so the subgroups
𝔾2 have the same prime order
ℓ = 2252 + 27742317777372353535851937790883648493. The total number of points on each curve is
Curve25519 is used exclusively for the Diffie-Hellman key exchange .
Only a single generator point
B is used:
Private keys for Curve25519 are 32-byte integers denoted by a lowercase letter
d. They are generated using the following
KeyDerive1(k, x) function:
d = H32(k, x)
d &= 0x7f(clear the most significant bit)
d &= 0xf8(clear the least significant 3 bits)
All Curve25519 private keys are therefore multiples of the cofactor 8, which ensures that all public keys are in the prime-order subgroup. The multiplicative inverse modulo
ℓ is calculated as
d-1 = 8*(8*d)-1 to preserve the aforementioned property.
Public keys (elements of
𝔾1) are denoted by the capital letter
D and are serialized as the x-coordinate of the corresponding Curve25519 point. Scalar multiplication is denoted by a space, e.g.
D = d B.
The Edwards curve is used for signatures and more complex cryptographic protocols . The following three generators are used:
Hp refers to an unspecified hash-to-point function.
Private keys for Ed25519 are 32-byte integers denoted by a lowercase letter
k. They are generated using the following function:
KeyDerive2(k, x) = H64(k, x) mod ℓ
Public keys (elements of
𝔾2) are denoted by the capital letter
K and are serialized as 256-bit integers, with the lower 255 bits being the y-coordinate of the corresponding Ed25519 point and the most significant bit being the parity of the x-coordinate. Scalar multiplication is denoted by a space, e.g.
K = k G.
3.4 Block cipher
BlockEnc(s, x) refers to the application of the Twofish  permutation using the secret key
s on the 16-byte input
x. The function
BlockDec(s, x) refers to the application of the inverse permutation using the key
3.5 Base32 encoding
"Base32" in this specification referes to a binary-to-text encoding using the alphabet
xmrbase32cdfghijknpqtuwy01456789. This alphabet was selected for the following reasons:
- The order of the characters has a unique prefix that distinguishes the encoding from other variants of "base32".
- The alphabet contains all digits
0-9, which allows numeric values to be encoded in a human readable form.
- Excludes the letters
zfor the same reasons as the z-base-32 encoding .
4.1 Wallet parameters
Each wallet consists of two main private keys and a timestamp:
||private key||wallet master key|
||private key||view-balance key|
||timestamp||date when the wallet was created|
The master key
km is required to spend money in the wallet and the view-balance key
kvb provides full view-only access.
birthday timestamp is important when restoring a wallet and determines the blockchain height where scanning for owned outputs should begin.
4.2 New wallets
4.2.1 Standard wallets
Standard Jamtis wallets are generated as a 16-word Polyseed mnemonic , which contains a secret seed value used to derive the wallet master key and also encodes the date when the wallet was created. The key
kvb is derived from the master key.
4.2.2 Multisignature wallets
Multisignature wallets are generated in a setup ceremony, where all the signers collectively generate the wallet master key
km and the view-balance key
4.3 Migration of legacy wallets
Legacy pre-Seraphis wallets define two private keys:
- private spend key
- private view-key
4.3.1 Standard wallets
Legacy standard wallets can be migrated to the new scheme based on the following table:
Legacy wallets cannot be migrated to Polyseed and will keep using the legacy 25-word seed.
4.3.2 Multisignature wallets
Legacy multisignature wallets can be migrated to the new scheme based on the following table:
4.4 Additional keys
There are additional keys derived from
||scan for received outputs|
||decrypt output amounts|
||encrypt address tags|
dfr provides the ability to calculate the sender-receiver shared secret when scanning for received outputs. The key
dua can be used to create a secondary shared secret and is used to decrypt output amounts.
sga is used to generate public addresses. It has an additional child key
sct, which is used to encrypt the address tag.
4.5 Key hierarchy
The following figure shows the overall hierarchy of wallet keys. Note that the relationship between
kvb only applies to standard (non-multisignature) wallets.
4.6 Wallet access tiers
|Tier||Knowledge||Off-chain capabilities||On-chain capabilities|
||generate public addresses||none|
||recognize all public wallet addresses||eliminate 99.6% of non-owned outputs (up to § 5.3.5), link output to an address (except of change and self-spends)|
||all||view all received except of change and self-spends (up to § 5.3.14)|
4.6.1 Address generator (AddrGen)
This wallet tier can generate public addresses for the wallet. It doesn't provide any blockchain access.
4.6.2 Output scanning wallet (FindReceived)
Thanks to view tags, this tier can eliminate 99.6% of outputs that don't belong to the wallet. If provided with a list of wallet addresses, it can also link outputs to those addresses (but it cannot generate addresses on its own). This tier should provide a noticeable UX improvement with a limited impact on privacy. Possible use cases are:
- An always-online wallet component that filters out outputs in the blockchain. A higher-tier wallet can thus be synchronized 256x faster when it comes online.
- Third party scanning services. The service can preprocess the blockchain and provide a list of potential outputs with pre-calculated spend keys (up to § 5.2.4). This reduces the amount of data that a light wallet has to download by a factor of at least 256.
4.6.3 Payment validator (ViewReceived)
This level combines the tiers AddrGen and FindReceived and provides the wallet with the ability to see all incoming payments to the wallet, but cannot see any outgoing payments and change outputs. It can be used for payment processing or auditing purposes.
4.6.4 View-balance wallet (ViewAll)
This is a full view-only wallet than can see all incoming and outgoing payments (and thus can calculate the correct wallet balance).
4.6.5 Master wallet (Master)
This tier has full control of the wallet.
4.7 Wallet public keys
There are 3 global wallet public keys. These keys are not usually published, but are needed by lower wallet tiers.
||wallet spend key||
5.1 Address generation
Jamtis wallets can generate up to 2128 different addresses. Each address is constructed from a 128-bit index
j. The size of the index space allows stateless generation of new addresses without collisions, for example by constructing
j as a UUID .
Each Jamtis address encodes the tuple
(K1j, D2j, D3j, tj). The first three values are public keys, while
tj is the "address tag" that contains the encrypted value of
5.1.1 Address keys
The three public keys are constructed as:
K1j = Ks + kuj U + kxj X + kgj G
D2j = daj Dfr
D3j = daj Dua
The private keys
daj are derived as follows:
||spend key extensions||
||spend key extensions||
||spend key extensions||
5.1.2 Address tag
Each address additionally includes an 18-byte tag
tj = (j', hj'), which consists of the encrypted value of
j' = BlockEnc(sct, j)
and a 2-byte "tag hint", which can be used to quickly recognize owned addresses:
hj' = H2(sct, "jamtis_address_tag_hint" || j')
5.2 Sending to an address
5.3 Receiving an output
5.4 Change and self-spends
5.5 Transaction size
Jamtis has a small impact on transaction size.
5.5.1 Transactions with 2 outputs
The size of 2-output transactions is increased by 28 bytes. The encrypted payment ID is removed, but the transaction needs two encrypted address tags
t~ (one for the recipient and one for the change). Both outputs can use the same value of
5.5.2 Transactions with 3 or more outputs
Since there are no "main" addresses anymore, the
TX_EXTRA_TAG_PUBKEY field can be removed from transactions with 3 or more outputs.
Instead, all transactions with 3 or more outputs will require one 50-byte tuple
(De, t~) per output.
6. Address encoding
6.1 Address structure
An address has the following overall structure:
|Header||30*||human-readable address header (§ 6.2)|
||256||address key 1|
||255||address key 2|
||255||address key 3|
* The header and the checksum are already in base32 format
6.2 Address header
The address starts with a human-readable header, which has the following format consisting of 6 alphanumeric characters:
"xmra" <version char> <network type char>
Unlike the rest of the address, the header is never encoded and is the same for both the binary and textual representations. The string is not null terminated.
The software decoding an address shall abort if the first 4 bytes are not
0x78 0x6d 0x72 0x61 ("xmra").
The "xmra" prefix serves as a disambiguation from legacy addresses that start with "4" or "8". Additionally, base58 strings that start with the character
x are invalid due to overflow , so legacy Monero software can never accidentally decode a Jamtis address.
6.2.1 Version character
The version character is
"1". The software decoding an address shall abort if a different character is encountered.
6.2.2 Network type
|network char||network type|
The software decoding an address shall abort if an invalid network character is encountered.
The purpose of the checksum is to detect accidental corruption of the address. The checksum consists of 8 characters and is calculated with a cyclic code over GF(32) using the polynomial:
x8 + 3x7 + 11x6 + 18x5 + 5x4 + 25x3 + 21x2 + 12x + 1
The checksum can detect all errors affecting 5 or fewer characters. Arbitrary corruption of the address has a chance of less than 1 in 1012 of not being detected. The reference code how to calculate the checksum is in Appendix A.
6.4 Binary-to-text encoding
An address can be encoded into a string as follows:
address_string = header + base32(data) + checksum
header is the 6-character human-readable header string (already in base32),
data refers to the address tuple
(K1, D2, D3, t), encoded in 910 bits, and the
checksum is the 8-character checksum (already in base32). The total length of the encoded address 196 characters (=6+182+8).
6.4.1 QR Codes
While the canonical form of an address is lower case, when encoding an address into a QR code, the address should be converted to upper case to take advantage of the more efficient alphanumeric encoding mode.
6.5 Recipient authentication
7. Test vectors
- monero-project/meta#299 (comment)
Appendix A: Checksum
# Jamtis address checksum algorithm # cyclic code based on the generator 3BI5PLC1 # can detect 5 errors up to the length of 994 characters GEN=[0x1ae45cd581, 0x359aad8f02, 0x61754f9b24, 0xc2ba1bb368, 0xcd2623e3f0] M = 0xffffffffff def jamtis_polymod(data): c = 1 for v in data: b = (c >> 35) c = ((c & 0x07ffffffff) << 5) ^ v for i in range(5): c ^= GEN[i] if ((b >> i) & 1) else 0 return c def jamtis_verify_checksum(data): return jamtis_polymod(data) == M def jamtis_create_checksum(data): polymod = jamtis_polymod(data + [0,0,0,0,0,0,0,0]) ^ M return [(polymod >> 5 * (7 - i)) & 31 for i in range(8)] # test/example CHARSET = "xmrbase32cdfghijknpqtuwy01456789" addr_test = ( "xmra1mj0b1977bw3ympyh2yxd7hjymrw8crc9kin0dkm8d3" "wdu8jdhf3fkdpmgxfkbywbb9mdwkhkya4jtfn0d5h7s49bf" "yji1936w19tyf3906ypj09n64runqjrxwp6k2s3phxwm6wr" "b5c0b6c1ntrg2muge0cwdgnnr7u7bgknya9arksrj0re7wh") addr_data = [CHARSET.find(x) for x in addr_test] addr_enc = addr_data + jamtis_create_checksum(addr_data) addr = "".join([CHARSET[x] for x in addr_enc]) print(addr) print("len =", len(addr)) print("valid =", jamtis_verify_checksum(addr_enc))
I already foresee many confused devs taking a glance at this set, plugging their z-base32 code and wondering why it doesn't work. Maybe it's better to rearrange it back to sorted set abc...789? The only reason they reordered it in the original proposal was to have an "easy" character at the end, and in this case it's not even at the end becase 3 wallet keys are in the middle.