# How are subaddresses and account addresses generated from master wallet keys?

I guess we have something similar to Bitocin HD wallet structure but the resources I found (https://monerodocs.org/public-address/subaddress/ and discussion in https://github.com/monero-project/research-lab/issues/7) seem to describe only a basic sub-address generation.

How is the account/subaddress structure built? For example, how can I compute subaddress `Sa(a,i)` where `a` is the account index and `i` is the subaddress index within the account?

how can I compute subaddress Sa(a,i) where a is the account index and i is the subaddress index within the account?

You're right, it is not fully explained in either of those links.

You'll see in the code that subaddress_index is a struct containing "major" and "minor", where major means the account index and minor means the subaddress index within that account. You'll also see the in second link that the string "SubAddr" is added into the mix.

Bringing it all together:

`m = Hs("SubAddr" || a || account_index || subaddress_index_within_account)`

Where `a` is a 32 byte scalar (the private view key), and `account_index` and `subaddress_index_within_account` are both 32 bit little endian unsigned integers.

Note that "SubAddr" needs to be a null terminated string, i.e. will be 8 bytes and not 7.

Finally, to get the wallet address for a subaddress, you need to follow the usual base58 procedure (which involves adding an identifier for the type of wallet address and adding a checksum) on the public view and spend keys (C, D), calculated as:

``````D = B + m*G
C = a*D
``````

Also note that there is a special case, where the first subaddress of the first account is not calculated using the formula above, and instead is simply the ordinary main wallet address (A, B).

Edit: See an example Javascript implementation of a subaddress generator here: https://github.com/knaccc/subaddress-js