3️⃣Merkle Tree
Last updated
Last updated
This section is made up of 6 preparatory steps, all aimed at creating a list of customer account balances (by each individual customer). This is likely the most time-consuming part of the preparation processes. Typically, the engineering team has to create a "custom" report to be used by the finance team for Proof of Reserves purposes. However, once the report has been configured, the parameters can be used for all future Proof of Reserves.
Once the CLE has been provided to the attest provider, they will generate the Merkle Tree, along with the Merkle Root Hash, by inputting the CLE into the Merkle Tree Generator.
Multiple variations of Merkle Tree Generators exist. The engaging party and attest provider should agree on the Merkle Tree Generator to be used for the PoR.
The Merkle Tree Generator used for TNF attestation engagements is available on GitHub here:
Prior to inputting the CLE, you have one more set of decisions to make, determining whether to “pad” the dataset and how to distribute that “padding.”
The term "Padding" in the context of a Merkle Tree refers to the inclusion of artificial records into the dataset, which can serve two main purposes:
Concealing the actual count of customer accounts for competitive and/or privacy reasons.
Creating symmetry within the Merkle Tree, which ensures balanced and efficient data querying. When querying the Merkle Tree, the Merkle Tree Search tool returns the Level and Position of the Customers Merkle Leaf in the Merkle Tree. A non-symmetrical Merkle Tree results in Customers returning varying Levels on their leaf on the Merkle Tree. While this is not necessarily an issue, it may reduce potential confusion or unnecessary scrutiny on the Merkle Tree
To determine the number of “padding” or “dummy records,” an additional set of determinations must be made.
The first is determining how many “dummy records” to add to the dataset. To create a symmetrical Merkle Tree, the Total Number of Records should adhere to the formula 2^x. For example, the following amounts of Total records would result in a symmetrical Merkle Tree.
2; 4; 8; 16; 32; 64; 128; 256; 512; 1,012; 2,408…524,288; 1,048,576; 2,097,152
After determining the Total Number of Records to include in the Merkle Tree, You and/or the Attest Provider should subtract the total number of real records to derive the total amount of “dummy records” to add to the data set. For example, if the desired Number of Total Records is 64, the following calculation would take place:
64 - [Total Number of “Real” Customer Records] = Number of “Dummy” Records to add to the dataset
The general formula is:
Desired Number of Total Records - Total Number of “Real” Customer Records = Number of “Dummy” Records to add to the dataset
The final decision is to determine how to distribute the padded rows. The most popular options are:
Option 1: Adding all of the “dummy records” to the end of the dataset
Option 2: Distributing the records throughout the “real” customer records
If this option is selected, a “seed” value must be provided, that is used to distribute the records throughout the dataset. This seed also enables you and the attest provider to “re-create” the padding version of the dataset from the original CLE is desired.
The technical implementation of these determinations are available here:
Once these determinations are made, the dataset is ready to be input into the Merkle Tree Generator to produce the Merkle Tree and associated Merkle Root Hash.
Example 2: Demonstrating How Customers view there Level and Position in the Merkle Tree
Example 3b(ii): Padding Distributed throughout the Dataset
While it is not required, you also have the option of generating the Merkle Tree yourself to essentially “check the work” of the attestation provider.
The Merkle Tree Generator used for TNF attestation engagements is available on GitHub here:
In all cases, we recommend that you inspect and understand the logic used to generate the Merkle Tree.
The verification process of a user's account balance in the Proof of Reserves is both straightforward and user-centric. It begins when a user logs into their account on the Exchange Platform, where they'll need to navigate to the "Proof of Reserves (PoR)" section. Crucially, this implies that you, as the platform, have the responsibility to provide pertinent information to your users within their account on your platform. At the very least, the platform needs to make available the user’s Hashed User ID. After obtaining their Hashed User ID from this section, the user then visits an independently hosted dashboard managed by The Network Firm, accessible through a link on your platform's website. Upon entering their Hashed User ID into the Merkle Verification Form on The Network Firm's dashboard and submitting it, they can swiftly verify that their account balance has been properly included. This easy-to-follow process ensures a seamless user experience in account balance verification.
Using Kraken as an example, here's a quick run-through of the process:
User Details Availability on Your Platform: Users should be able to access their specific details, including their Hashed User ID, on your platform.
Navigation to Widget & User Details Input: From there, users should navigate to The Network Firm's independent PoR widget. They then input their user details, specifically the Hashed User ID.
Receiving Results: After successfully inputting their Hashed User ID, users can promptly receive and verify their account balance. This transparency enables trust and confidence between users and the platform.