From 3fd3a85a0ba43b7d0e9ade397cca182225ae4d2a Mon Sep 17 00:00:00 2001 From: Franco NG <franco.ng@lightcurve.io> Date: Tue, 6 Feb 2024 14:36:40 +0100 Subject: [PATCH 1/3] Uses native 64-bit number operations support --- packages/tree-builder/package.json | 1 + .../src/applications/example/create_accounts.ts | 8 +++----- packages/tree-builder/src/utils.ts | 5 +++++ .../tree-builder/test/applications/build_tree.test.ts | 6 +++--- yarn.lock | 5 +++++ 5 files changed, 17 insertions(+), 8 deletions(-) diff --git a/packages/tree-builder/package.json b/packages/tree-builder/package.json index 3307728..d674eee 100644 --- a/packages/tree-builder/package.json +++ b/packages/tree-builder/package.json @@ -48,6 +48,7 @@ "@oclif/core": "^3", "@oclif/plugin-help": "^6", "@openzeppelin/merkle-tree": "^1.0.6", + "bignumber.js": "^9.1.2", "ethereumjs-util": "^7.1.5", "ethers": "^6.8.1", "tweetnacl": "^1.0.3" diff --git a/packages/tree-builder/src/applications/example/create_accounts.ts b/packages/tree-builder/src/applications/example/create_accounts.ts index cfdad85..d593e51 100644 --- a/packages/tree-builder/src/applications/example/create_accounts.ts +++ b/packages/tree-builder/src/applications/example/create_accounts.ts @@ -1,9 +1,7 @@ import * as fs from 'fs'; import { address } from '@liskhq/lisk-cryptography'; import { Account, ExampleKey } from '../../interface'; - -// 1 LSK = 10^8 Beddows -const LSK_MULTIPLIER = 10 ** 8; +import { multiplyBeddows } from '../../utils'; // Balances are random between 0 - <RANDOM_RANGE> const RANDOM_RANGE = 10000; @@ -61,7 +59,7 @@ export function createAccounts(numberOfAccounts = 54) { for (let index = 0; index < numberOfAccounts - multiSigs.length; index++) { const account = sortedKeyPairs[index]; const balance = randomBalance(RANDOM_RANGE); - const balanceBeddows = Math.round(balance * LSK_MULTIPLIER); + const balanceBeddows = multiplyBeddows(balance); results.push({ lskAddress: account.address, @@ -72,7 +70,7 @@ export function createAccounts(numberOfAccounts = 54) { for (const multiSig of multiSigs) { const account = sortedKeyPairs[results.length]; const balance = randomBalance(RANDOM_RANGE); - const balanceBeddows = Math.round(balance * LSK_MULTIPLIER).toString(); + const balanceBeddows = multiplyBeddows(balance); results.push({ lskAddress: account.address, diff --git a/packages/tree-builder/src/utils.ts b/packages/tree-builder/src/utils.ts index ba9f6b8..e1fe3b0 100644 --- a/packages/tree-builder/src/utils.ts +++ b/packages/tree-builder/src/utils.ts @@ -1,5 +1,7 @@ import { utils } from '@liskhq/lisk-cryptography'; +import BigNumber from 'bignumber.js'; import { UserBalance } from './interface'; +import { LSK_MULTIPLIER } from './constants'; export function append0x(input: string | Buffer): string { if (input instanceof Buffer) { @@ -29,3 +31,6 @@ export function getTotalBalance(balance: UserBalance): bigint { balance.lockedBalances.reduce((acc, cur) => acc + cur.amount, BigInt(0)) ); } +export function multiplyBeddows(input: number): string { + return new BigNumber(input).multipliedBy(LSK_MULTIPLIER).toString(); +} diff --git a/packages/tree-builder/test/applications/build_tree.test.ts b/packages/tree-builder/test/applications/build_tree.test.ts index f6dd47f..e7f6563 100644 --- a/packages/tree-builder/test/applications/build_tree.test.ts +++ b/packages/tree-builder/test/applications/build_tree.test.ts @@ -6,9 +6,9 @@ import { StandardMerkleTree } from '@openzeppelin/merkle-tree'; import { defaultAbiCoder } from '@ethersproject/abi'; import { Account, ExampleKey } from '../../src/interface'; import { createPayload, buildTree } from '../../src/applications/generate-merkle-tree/build_tree'; -import { LEAF_ENCODING, LSK_MULTIPLIER } from '../../src/constants'; +import { LEAF_ENCODING } from '../../src/constants'; import { createKeyPairs } from '../../src/applications/example/create_key_pairs'; -import { append0x } from '../../src/utils'; +import { append0x, multiplyBeddows } from '../../src/utils'; describe('buildTree', () => { let accounts: Account[]; @@ -29,7 +29,7 @@ describe('buildTree', () => { const numberOfOptionalKeys = Math.floor(5 * Math.random()); return { lskAddress: key.address, - balanceBeddows: Math.floor(balance * LSK_MULTIPLIER).toString(), + balanceBeddows: multiplyBeddows(balance), numberOfSignatures: numberOfMandatoryKeys + numberOfOptionalKeys, mandatoryKeys: keyPairsSorted.slice(0, numberOfMandatoryKeys).map(key => key.publicKey), optionalKeys: keyPairsSorted diff --git a/yarn.lock b/yarn.lock index e7af807..ee0a14c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1585,6 +1585,11 @@ before-after-hook@^2.2.0: resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c" integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ== +bignumber.js@^9.1.2: + version "9.1.2" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c" + integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug== + bin-links@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-3.0.3.tgz#3842711ef3db2cd9f16a5f404a996a12db355a6e" From 3f35ac94c7e576d4cb4a56a285c0005daff86e5b Mon Sep 17 00:00:00 2001 From: Franco NG <franco.ng@lightcurve.io> Date: Tue, 6 Feb 2024 16:24:04 +0100 Subject: [PATCH 2/3] Remove bignumber.js, use new method for random int --- packages/tree-builder/package.json | 1 - .../src/applications/example/create_accounts.ts | 14 +++++--------- packages/tree-builder/src/constants.ts | 3 --- packages/tree-builder/src/utils.ts | 8 ++++---- .../test/applications/build_tree.test.ts | 5 ++--- yarn.lock | 5 ----- 6 files changed, 11 insertions(+), 25 deletions(-) diff --git a/packages/tree-builder/package.json b/packages/tree-builder/package.json index d674eee..3307728 100644 --- a/packages/tree-builder/package.json +++ b/packages/tree-builder/package.json @@ -48,7 +48,6 @@ "@oclif/core": "^3", "@oclif/plugin-help": "^6", "@openzeppelin/merkle-tree": "^1.0.6", - "bignumber.js": "^9.1.2", "ethereumjs-util": "^7.1.5", "ethers": "^6.8.1", "tweetnacl": "^1.0.3" diff --git a/packages/tree-builder/src/applications/example/create_accounts.ts b/packages/tree-builder/src/applications/example/create_accounts.ts index d593e51..49b39a4 100644 --- a/packages/tree-builder/src/applications/example/create_accounts.ts +++ b/packages/tree-builder/src/applications/example/create_accounts.ts @@ -1,10 +1,10 @@ import * as fs from 'fs'; import { address } from '@liskhq/lisk-cryptography'; import { Account, ExampleKey } from '../../interface'; -import { multiplyBeddows } from '../../utils'; +import { randomBalanceBeddows } from '../../utils'; -// Balances are random between 0 - <RANDOM_RANGE> -const RANDOM_RANGE = 10000; +// Random Balance in Beddows between 0 - 2 ** 8 * (RANDOM_BYTES_RANGE) +const RANDOM_BYTES_RANGE = 5; // Multisig Accounts // For each account it will use the address of the index as account holder, @@ -39,8 +39,6 @@ const multiSigs = [ }, ]; -const randomBalance = (range: number): number => Number((range * Math.random()).toFixed(8)); - export function createAccounts(numberOfAccounts = 54) { const keyPairs = JSON.parse( fs.readFileSync('../../data/example/key-pairs.json', 'utf-8'), @@ -58,8 +56,7 @@ export function createAccounts(numberOfAccounts = 54) { // Regular Accounts for (let index = 0; index < numberOfAccounts - multiSigs.length; index++) { const account = sortedKeyPairs[index]; - const balance = randomBalance(RANDOM_RANGE); - const balanceBeddows = multiplyBeddows(balance); + const balanceBeddows = randomBalanceBeddows(RANDOM_BYTES_RANGE); results.push({ lskAddress: account.address, @@ -69,8 +66,7 @@ export function createAccounts(numberOfAccounts = 54) { for (const multiSig of multiSigs) { const account = sortedKeyPairs[results.length]; - const balance = randomBalance(RANDOM_RANGE); - const balanceBeddows = multiplyBeddows(balance); + const balanceBeddows = randomBalanceBeddows(RANDOM_BYTES_RANGE); results.push({ lskAddress: account.address, diff --git a/packages/tree-builder/src/constants.ts b/packages/tree-builder/src/constants.ts index da9c525..35b5e38 100644 --- a/packages/tree-builder/src/constants.ts +++ b/packages/tree-builder/src/constants.ts @@ -1,8 +1,5 @@ import { computeStorePrefix } from './utils'; -// 1 LSK = 10^8 Beddows -export const LSK_MULTIPLIER = 10 ** 8; - // Each leaf will be encoded in the following order: // LSK_ADDRESS_IN_HEX: bytes20 // BALANCE_IN_BEDDOWS: uint64 diff --git a/packages/tree-builder/src/utils.ts b/packages/tree-builder/src/utils.ts index e1fe3b0..4662b33 100644 --- a/packages/tree-builder/src/utils.ts +++ b/packages/tree-builder/src/utils.ts @@ -1,7 +1,5 @@ import { utils } from '@liskhq/lisk-cryptography'; -import BigNumber from 'bignumber.js'; import { UserBalance } from './interface'; -import { LSK_MULTIPLIER } from './constants'; export function append0x(input: string | Buffer): string { if (input instanceof Buffer) { @@ -31,6 +29,8 @@ export function getTotalBalance(balance: UserBalance): bigint { balance.lockedBalances.reduce((acc, cur) => acc + cur.amount, BigInt(0)) ); } -export function multiplyBeddows(input: number): string { - return new BigNumber(input).multipliedBy(LSK_MULTIPLIER).toString(); + +// When bytes = 8, max value = 2 ** (8 * 8) - 1 +export function randomBalanceBeddows(maxBytes = 8): string { + return BigInt(append0x(utils.getRandomBytes(maxBytes))).toString(); } diff --git a/packages/tree-builder/test/applications/build_tree.test.ts b/packages/tree-builder/test/applications/build_tree.test.ts index e7f6563..8d3a938 100644 --- a/packages/tree-builder/test/applications/build_tree.test.ts +++ b/packages/tree-builder/test/applications/build_tree.test.ts @@ -8,7 +8,7 @@ import { Account, ExampleKey } from '../../src/interface'; import { createPayload, buildTree } from '../../src/applications/generate-merkle-tree/build_tree'; import { LEAF_ENCODING } from '../../src/constants'; import { createKeyPairs } from '../../src/applications/example/create_key_pairs'; -import { append0x, multiplyBeddows } from '../../src/utils'; +import { append0x, randomBalanceBeddows } from '../../src/utils'; describe('buildTree', () => { let accounts: Account[]; @@ -24,12 +24,11 @@ describe('buildTree', () => { // Create 5 accounts on the fly, they are all Multisig such that all fields are filled accounts = keyPairsSorted.slice(0, 5).map(key => { - const balance = Number((10000 * Math.random()).toFixed(8)); const numberOfMandatoryKeys = Math.floor(5 * Math.random()) + 1; const numberOfOptionalKeys = Math.floor(5 * Math.random()); return { lskAddress: key.address, - balanceBeddows: multiplyBeddows(balance), + balanceBeddows: randomBalanceBeddows(), numberOfSignatures: numberOfMandatoryKeys + numberOfOptionalKeys, mandatoryKeys: keyPairsSorted.slice(0, numberOfMandatoryKeys).map(key => key.publicKey), optionalKeys: keyPairsSorted diff --git a/yarn.lock b/yarn.lock index ee0a14c..e7af807 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1585,11 +1585,6 @@ before-after-hook@^2.2.0: resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c" integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ== -bignumber.js@^9.1.2: - version "9.1.2" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c" - integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug== - bin-links@^3.0.0: version "3.0.3" resolved "https://registry.yarnpkg.com/bin-links/-/bin-links-3.0.3.tgz#3842711ef3db2cd9f16a5f404a996a12db355a6e" From 6be97adab7d2c3f4690554cffd950f42fd6e4625 Mon Sep 17 00:00:00 2001 From: Franco NG <franco.ng@lightcurve.io> Date: Tue, 6 Feb 2024 17:24:15 +0100 Subject: [PATCH 3/3] Update example mnemonic to 12-word for Lisk Desktop testing purpose --- .../tree-builder/src/applications/example/create_key_pairs.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/tree-builder/src/applications/example/create_key_pairs.ts b/packages/tree-builder/src/applications/example/create_key_pairs.ts index 8fefcbf..5361187 100644 --- a/packages/tree-builder/src/applications/example/create_key_pairs.ts +++ b/packages/tree-builder/src/applications/example/create_key_pairs.ts @@ -5,10 +5,12 @@ import { ExampleKey } from '../../interface'; const initialPath = "m/44'/134'"; export async function createKeyPairs(amount = 100) { + const mnemonic = + 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about'; const keys: ExampleKey[] = []; for (let i = 0; i < amount; i++) { const keyPath = `${initialPath}/${i}'`; - const privateKey = await ed.getPrivateKeyFromPhraseAndPath('lisk', keyPath); + const privateKey = await ed.getPrivateKeyFromPhraseAndPath(mnemonic, keyPath); keys.push({ address: address.getLisk32AddressFromAddress(address.getAddressFromPrivateKey(privateKey)), keyPath,