Private view key¶The subaddress private view key m is derived as follows:
m = Hs("SubAddr" || a || account_index || subaddress_index_within_account)
Where:
Hs is a Keccak-256 hash function interpreted as integer and modulo l (maximum edwards25519 scalar)
|| is a byte array concatenation operator
SubAddr is a 0-terminated fixed string (8 bytes total)
a is a private view key of the standard address (a 32 byte little endian unsigned integer)
account_index is index of an account (a 32 bit little endian unsigned integer)
subaddress_index_within_account is index of the subaddress within the account (a 32 bit little endian unsigned integer)
Deriving "sub view keys" from the main view key allows for creating a view only wallet that monitors the entire wallet including subaddresses.
Public spend key¶The subaddress public spend key D is derived as follows:
D = B + m*G
Where:
B is standard address public spend key
m is subaddress private view key
G is the "base point"; this is simply a constant specific to
edwards25519Public view key¶The subaddress public view key C is derived as follows:
C = a*D
Where:
a is a private view key of the standard address
D is a public spend key of the subaddress
Special case for (0, 0)¶The subaddress #0 on the account #0 is the
standard address. As standard address has different generation rules, this is simply implemented via an if statement.