This library is a command-line service that builds a Merkle tree from a snapshot and computes the Merkle root.
cd packages/tree-builder
# Lisk Token Migration
./bin/run.js generate-merkle-tree --db-path <value> [--output-path <value>] [--token-id <value>] [excluded-addresses-path <value>]
# Migration Airdrop
./bin/run.js generate-airdrop-merkle-tree --db-path <value> [--output-path <value>] [--token-id <value>] [--cutoff <value>] [--whale-cap <value>] [--airdrop-percent <value>] [--excluded-addresses-path <value>]
Name | Description | Generated By |
---|---|---|
/data/<network>/accounts.json |
Stores addresses, balances, and multisig details(If any) per account after a snapshot is taken, addresses must be sorted in ascending order. Will be used for MerkleTree computation. | Snapshot |
/data/<network>/merkle-tree-result-detailed.json |
Stores MerkleRoot, and leaves for each account. Will be used for examination by 3rd Party or public, also used by Claim Backend API. | ./bin/run.js generate-merkle-tree --network=<network> |
/data/<network>/merkle-tree-result.json |
Stores MerkleRoot, and leaves for each account. A lightweight version of merkle-tree-result-detailed.json . Will be used for testing of Claim Contract. |
./bin/run.js generate-merkle-tree --network=<network> |
/data/<network>/merkle-root.json |
Stores MerkleRoot only. Will be used for deployment of Claim Contract. | ./bin/run.js generate-merkle-tree --network=<network> |
Each leaf will be encoded as ABI-format, structure of Merkle Tree may vary and depends on usage
LSK_ADDRESS_IN_HEX: bytes20
BALANCE_IN_BEDDOWS: uint64
NUMBER_OF_SIGNATURES: uint32
MANDATORY_KEYS: bytes32[]
OPTIONAL_KEYS: bytes32[]
If the address is not a multisig address, NUMBER_OF_SIGNATURES
would be 0,
MANDATORY_KEYS
and OPTIONAL_KEYS
be []
LSK_ADDRESS_IN_HEX: bytes20
BALANCE_IN_WEI: uint256
Note that Balance is represented in Wei(2**18) and in uint256
format.
For both Lisk Token Migration
and Migration Airdrop
, a merkle-root.json
will be generated.
merkle-root.json:
{
merkleRoot: string;
}
For other files, refer to the table below:
accounts.json:
{
lskAddress: string;
balance: number;
balanceBeddows: number;
numberOfSignatures?: number;
mandatoryKeys?: string[];
optionalKeys?: string[];
}
merkle-tree-result-detailed.json:
{
merkleRoot: string;
leaves: {
lskAddress: string;
address: string;
balance: number;
balanceBeddows: number;
numberOfSignatures: number;
mandatoryKeys: string[];
optionalKeys: string[];
hash: string;
proof: string[];
}[];
}
merkle-tree-result.json:
{
merkleRoot: string;
leaves: {
b32Address: string;
balanceBeddows: number;
mandatoryKeys: string[];
numberOfSignatures: number;
optionalKeys: string[];
proof: string[];
}[];
}
# `address` is a reserved in solidity, hence `b32Address` here
accounts.json:
{
lskAddress: string;
balanceWei: number;
}
merkle-tree-result-detailed.json:
{
merkleRoot: string;
leaves: {
lskAddress: string;
address: string;
balanceWei: number;
hash: string;
proof: string[];
}[];
}
merkle-tree-result.json:
{
merkleRoot: string;
leaves: {
b32Address: string;
balanceWei: number;
proof: string[];
}[];
}
signatures.json:
{
message: string;
sigs: {
pubKey: string
r: string
s: string
}[];
}[];
./bin/run.js example [--amountOfLeaves <value>] [--recipient <value>]
# FLAGS
# --amountOfLeaves=<value> [default: 100] Amount of leaves in the tree
# --recipient=<value> [default: 0x34A1D3fff3958843C43aD80F30b94c510645C316] Destination address at signing stage. Default is the contract address created by default mnemonic in Anvil/Ganache when nonce=0
By running the command above, it will, at data/example
folder:
- Create
key-pairs.json
, which stores public-private key pairs, along with the corresponding address and path - Create
accounts.json
using addresses inkey-pairs.json
, with random LSK balance. - Create
merkle-root.json
,merkle-tree-result.json
,merkle-tree-result-detailed.json
using the accounts above (Equivalent to./bin/run.js generate-merkle-tree --network=example
). - Sign every leaf using the private keys in
key-pairs.json
and output tosignatures.json
.