Skip to content

Latest commit

 

History

History
318 lines (197 loc) · 16.6 KB

tip-102.md

File metadata and controls

318 lines (197 loc) · 16.6 KB
TIP: 102
Title: Hierarchical Deterministic Wallet
Author: federico<[email protected]>
discussions-to: https://github.com/tronprotocol/tips/issues/102
status: Last Call
type: Standards Track
category: TRC
Created: 2019-10-22

Simple Summary

This proposal defines a mechanism for extending hierarchical deterministic wallets, as described in BIP32 and BIP44, to support both Tron's transparent and shielded addresses.

Abstract

BIP32 and BIP44 are the standard mechanism by which wallets for Bitcoin and its derivatives generate keys and addresses deterministically. However, they only support the transparent address generation. This specification will provide support for the hierarchically shielded addresses derivation in a similar way as BIP32, which can offer users better privacy protection.

Motivation

At present, Tron network has scheduled to support the shielded addresses by ZK-SNARKs, so it is necessary to provide the standard compatibility for shielded hierarchical deterministic wallets.

Specification

In this specification, transparent address indicates the address which is public in the transaction, while the shielded address stands for the address which is not available from the transaction.

Wallet Key Path

Existing HD wallets all use BIP44 to organize their derived keys. In order to improve existing user experiences, we broadly follow BIP 44's design here. However, we have altered the design where it makes sense to leverage features of shielded addresses.

m / purpose' / coin_type' / account' / transparent' / change / address_index

Apostrophe in the path indicates that BIP32 hardened derivation is used.

  • m: a seed generated by the mnemonic codes to generate the master key.

  • purpose: a constant set to 102' (or 0x80000066) following the BIP43 recommendation. It indicates that the subtree of this node is used according to this specification.

  • coin_type: a constant identifying the cybercoin that this subtree's keys are used with. For Tron, coin_type is 195 as assigned in SLIP44.

  • account: numbered from index 0 in sequentially increasing manner. Defined as in BIP44.

  • transparent: for transparent addresses, transparent is set 1; for the shielded addresses, transparent is set 0;

  • change: for transparent addresses, constant 0 is used for external chain and constant 1 for internal chain (also known as change addresses) as in BIP44; for shielded addresses, change field is omitted, because shielded addresses are never publicly visible in transactions.

  • address_index: numbered from index 0 in sequentially increasing manner. Defined as in BIP44.

Mnemonic Codes

BIP39 should be used to derive binary seed from a mnemonic code.

We strongly recommend using 24 word mnemonic (256 bits of entropy).

Transparent Multi-Account Hierarchy for Deterministic Wallets

We adapt BIP44 for generating transparent address, except an extra transparent field is added. This is an upgrade of TIP001. We will focus on the shielded addresses derivation in the following section.

Hierarchical Derivation for Shielded Addresses

The shielded addresses derivation process described here are mainly based on the ZIP32 standard proposed by Zcash team.

Conventions

Most of the notation and functions used in this TIP are defined here for convenience:

  • truncatek(S) means the sequence formed from the first k elements of S.

  • a || b means the concatenation of sequences a then b.

  • [k] P means scalar multiplication of the elliptic curve point P by the scalar k.

  • LEOS2IPl (S) is the integer in range {0..2l -1} represented in little-endian order by the byte sequence S of length l/8.

  • I2LEBSPl (k) is the sequence of l bits representing k in little-endian order.

  • LEBS2OSPl (B) is defined as follows when l is a multiple of 8: convert each group of 8 bits in B to a byte value with the least significant bit first, and concatenate the resulting bytes in the same order as the groups.

  • reprJ (P) is the representation of the Jubjub elliptic curve point P as a bit sequence.

  • BLAKE2b-256(p, x) refers to unkeyed BLAKE2b-256 in sequential mode, with an output digest length of 32 bytes, 16-byte personalization string p, and input x.

  • BLAKE2b-512(p, x) refers to unkeyed BLAKE2b-512 in sequential mode, with an output digest length of 64 bytes, 16-byte personalization string p, and input x.

  • PRFexpand (sk, t) := BLAKE2b-512("Tron_ExpandSeed", sk || t )

  • ToScalar(x) := LEOS2IP512 (x) (mod rJ ), where rJ is the order of the Jubjub large prime subgroup.

  • DiversifyHash(d) maps a diversifier d to a base point on the Jubjub elliptic curve, or to ⊥ if the diversifier is invalid.

The following FPE algorithm standardized is used:

  • FF1-AES256.Encrypt(key, tweak, x) refers to the FF1 encryption algorithm using AES with a 256-bit key, and parameters radix = 2, minlen = 88, maxlen = 88. It will be used only with the empty string "" as the tweak. x is a sequence of 88 bits, as is the output.

We also define the following conversion function:

  • I2LEOSPl (k) is the byte sequence S of length l/8 representing in little-endian order the integer k in range {0..2l -1}. It is the reverse operation of LEOS2IPl (S).

We adapt the path notation of BIP32 to describe shielded HD paths, using apostrophes to indicate hardened derivation (i' = i + 231 ) as in BIP44:

  • CDKsk(CDKsk(CDKsk(m, a'), b), c) is written as m / a' / b / c
  • CDKfvk(CDKfvk(CDKfvk(M, a), b), c) is written as M / a / b / c

Specification: Key Derivation

Extended Keys

BIP 32 defines a method to derive a number of child keys from a parent key. In order to prevent these from depending solely on the parent key itself, both the private and public keys are extended with a 32-byte chain code. We similarly extend Sapling keys with a chain code here. However, the concepts of "private" and "public" keys in BIP 32 do not map cleanly to shielded key components. We take the following approach:

  • We derive child expanded spending keys, rather than spending keys. This enables us to implement both hardened and non-hardened derivation modes.

  • We do not derive public keys directly, as this would prevent the use of diversified addresses. Instead, we derive full viewing keys, from which payment addresses can be generated. This maintains the trust semantics of BIP 32: someone with access to a BIP 32 extended public key is able to view all transactions involving that address, which a full viewing key also enables.

We represent a extended spending key as (ask, nsk, ovk, dk, c), where (ask, nsk, ovk) is the normal expanded spending key, dk is a diversifier key, and c is the chain code.

We represent a extended full viewing key as (ak, nk, ovk, dk, c), where (ak, nk, ovk) is the normal full viewing key, dk is the same diversifier key as above, and c is the chain code.

The helper functions

Define EncodeExtSKParts(ask, nsk, ovk, dk) := I2LEOSP256 (ask) || I2LEOSP256 (nsk) || ovk || dk.

Define EncodeExtFVKParts(ak, nk, ovk, dk) := LEBS2OSP256 (reprJ (ak)) || LEBS2OSP256 (reprJ (nk)) || ovk || dk.

Master Key Generation

Let pathi= m / xx' / 195' / i' / 0', i denotes the i-th account. Let skpathi, pkpathi, cpathi denotes the private key, public key and chain code at pathi derived by BIP32.

  • Calculate I = BLAKE2b-512 ("TronIP102", skpathi || pkpathi || cpathi ).

  • Split I into two 32-byte sequences, IL and IR .

  • Use IL as the master spending key skm , and IR as the master chain code cm.

  • Calculate askm , nskm , and ovkm via the standard derivation function:

    • askm = ToScalar(PRFexpand (skm , [0x00]))
    • nskm = ToScalar(PRFexpand (skm , [0x01]))
    • ovkm = truncate32 (PRFexpand (skm , [0x02]))
  • Calculate dkm similarly:

    • dkm = truncate32 (PRFexpand (skm , [0x10]))
  • Return (askm , nskm , ovkm , dkm , cm ) as the master extended spending key m.

Child Key Derivation

As in BIP 32, the method for deriving a child extended key, given a parent extended key and an index i, depends on the type of key being derived, and whether this is a hardened or non-hardened derivation.

Deriving a child extended spending key

CDKsk((askpar , nskpar , ovkpar , dkpar , cpar ), i) → (aski , nski , ovki , dki , ci )

  • Check whether i ≥ 231 (whether the child is a hardened key).

    • If so (hardened child): let I = PRFexpand (cpar , [0x11] || EncodeExtSKParts(askpar , nskpar , ovkpar , dkpar ) || I2LEOSP32 (i))
    • If not (normal child): let I = PRFexpand (cpar , [0x12] || EncodeExtFVKParts(akpar , nkpar , ovkpar , dkpar ) || I2LEOSP32 (i)) where (nkpar , akpar , ovkpar ) is the full viewing key derived from (askpar , nskpar , ovkpar ).
  • Split I into two 32-byte sequences, IL and IR .

  • Let Iask = ToScalar(PRFexpand (IL , [0x13]))

  • Let Insk = ToScalar(PRFexpand (IL , [0x14]))

  • Return:

    • aski = Iask + askpar
    • nski = Insk + nskpar
    • ovki = truncate32 (PRFexpand (IL , [0x15] || ovkpar ))
    • dki = truncate32 (PRFexpand (IL , [0x16] || dkpar ))
    • ci = IR

Deriving a child extended full viewing key

Let G and H be the base point in elliptic curve.

CDKfvk((akpar , nkpar , ovkpar , dkpar , cpar ), i) → (aki , nki , ovki , dki , ci )

  • Check whether i ≥ 231 (whether the child is a hardened key).

    • If so (hardened child): return failure
    • If not (normal child): let I = PRFexpand (cpar , [0x12] || EncodeExtFVKParts(akpar , nkpar , ovkpar , dkpar ) || I2LEOSP32 (i))
  • Split I into two 32-byte sequences, IL and IR .

  • Let Iask = ToScalar(PRFexpand (IL , [0x13]))

  • Let Insk = ToScalar(PRFexpand (IL , [0x14]))

  • Return:

    • aki = [Iask] G + akpar
    • nki = [Insk] H + nkpar
    • ovki = truncate32 (PRFexpand (IL , [0x15] || ovkpar ))
    • dki = truncate32 (PRFexpand (IL , [0x16] || dkpar ))
    • ci = IR

Diversifier derivation

The 88-bit diversifiers for a extended key are derived from its diversifier key dk. To prevent the diversifier leaking how many diversified addresses have already been generated for an account, we make the sequence of diversifiers pseudorandom and uncorrelated to that of any other account. In order to reach the maximum possible diversifier range without running into repetitions due to the birthday bound, we use FF1-AES256 as a Pseudo-Random Permutation as follows:

  • Let j be the index of the desired diversifier, in the range 0 .. 288 -1.
  • dj = FF1-AES256.Encrypt(dk, "", I2LEBSP88 (j)).

A valid diversifier dj is one for which DiversifyHash(dj) ≠ ⊥. For a given dk, approximately half of the possible values of j yield valid diversifiers.

The default diversifier for an extended key is defined to be dj , where j is the least nonnegative integer yielding a valid diversifier.

Fingerprints and Tags

Full Viewing Key Fingerprints and Tags

A full viewing key fingerprint with raw encoding FVK is given by:

BLAKE2b-256("TronFVFP", FVK)

It MAY be used to uniquely identify a particular full viewing key.

A "full viewing key tag" is the first 4 bytes of the corresponding full viewing key fingerprint. It is intended for optimizing performance of key lookups, and MUST NOT be assumed to uniquely identify a particular key.

Key Encodings

The following encodings are analogous to the xprv and xpub encodings defined in BIP 32 for transparent keys and addresses. Each key type has a raw representation and a Bech32 encoding.

Extended Spending Keys

An extended spending key (ask, nsk, ovk, dk, c), at some path, with parent full viewing key tag parent_fvk_tag and child number i, is represented as a byte sequence:

I2LEOSP8 (depth) || parent_fvk_tag || I2LEOSP32 (i) || c || EncodeExtSKParts(ask, nsk, ovk, dk)

For the master extended spending key, depth is 0, parent_fvk_tag is 4 zero bytes, and i is 0.

When encoded as Bech32, the Human-Readable Part is secret-extended-key-main for the production network, or secret-extended-key-test for the test network.

Extended full viewing keys

A extended full viewing key (ak, nk, ovk, dk, c), at depth depth, with parent full viewing key tag parent_fvk_tag and child number i, is represented as a byte sequence:

I2LEOSP8 (depth) || parent_fvk_tag || I2LEOSP32 (i) || c || EncodeExtFVKParts(ak, nk, ovk, dk)

For the master extended full viewing key, depth is 0, parent_fvk_tag is 4 zero bytes, and i is 0.

When encoded as Bech32, the Human-Readable Part is txviews for the production network, or txviewtest for the test network.

Rationale

Based on BIP32, BIP44 and ZIP32, We provide a standard mechanism for both transparent and shielded hierarchical deterministic wallets for Tron.

Implementation

None

Reference