@interest-protocol/vortex-sdk 2.0.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/entities/merkle-tree.d.ts +3 -80
- package/dist/entities/merkle-tree.d.ts.map +1 -1
- package/dist/index.js +13 -203
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +13 -203
- package/dist/index.mjs.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/vortex.types.d.ts +1 -1
- package/dist/vortex.types.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/deposit.ts +1 -1
- package/src/entities/merkle-tree.ts +9 -251
- package/src/utils/index.ts +6 -6
- package/src/vortex.types.ts +1 -1
- package/src/withdraw.ts +1 -1
- package/dist/__tests__/vortex.test.d.ts +0 -2
- package/dist/__tests__/vortex.test.d.ts.map +0 -1
- package/src/__tests__/vortex.test.ts +0 -25
|
@@ -1,81 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
*/
|
|
5
|
-
export declare class MerkleTree {
|
|
6
|
-
levels: number;
|
|
7
|
-
capacity: number;
|
|
8
|
-
zeroElement: bigint;
|
|
9
|
-
private zeros;
|
|
10
|
-
private subtrees;
|
|
11
|
-
private _nextIndex;
|
|
12
|
-
private leaves;
|
|
13
|
-
private _root;
|
|
14
|
-
constructor(levels: number);
|
|
15
|
-
/**
|
|
16
|
-
* Returns the current Merkle root
|
|
17
|
-
*/
|
|
18
|
-
root(): bigint;
|
|
19
|
-
/**
|
|
20
|
-
* Insert elements in bulk (must be even number for pairing)
|
|
21
|
-
*/
|
|
22
|
-
bulkInsert(elements: bigint[]): void;
|
|
23
|
-
/**
|
|
24
|
-
* Insert a pair of leaves (Nova style)
|
|
25
|
-
* This is the primary insertion method
|
|
26
|
-
*/
|
|
27
|
-
insertPair(leaf1: bigint, leaf2: bigint): void;
|
|
28
|
-
/**
|
|
29
|
-
* Insert a single leaf (for backward compatibility)
|
|
30
|
-
* Pairs it with a zero leaf
|
|
31
|
-
*/
|
|
32
|
-
insert(leaf: bigint): void;
|
|
33
|
-
/**
|
|
34
|
-
* Generate Merkle path for a leaf at given index
|
|
35
|
-
* Returns sibling hashes and indices for verification
|
|
36
|
-
*/
|
|
37
|
-
path(index: number): {
|
|
38
|
-
pathElements: bigint[];
|
|
39
|
-
pathIndices: number[];
|
|
40
|
-
};
|
|
41
|
-
/**
|
|
42
|
-
* Get all leaves in the tree
|
|
43
|
-
*/
|
|
44
|
-
elements(): bigint[];
|
|
45
|
-
/**
|
|
46
|
-
* Find the index of a specific leaf
|
|
47
|
-
*/
|
|
48
|
-
indexOf(element: bigint, comparator?: Function | null): number;
|
|
49
|
-
/**
|
|
50
|
-
* Serialize tree state
|
|
51
|
-
*/
|
|
52
|
-
serialize(): {
|
|
53
|
-
levels: number;
|
|
54
|
-
zeros: bigint[];
|
|
55
|
-
subtrees: bigint[];
|
|
56
|
-
nextIndex: number;
|
|
57
|
-
leaves: bigint[];
|
|
58
|
-
root: bigint;
|
|
59
|
-
};
|
|
60
|
-
/**
|
|
61
|
-
* Verify a Merkle path is valid for a given leaf and root
|
|
62
|
-
*/
|
|
63
|
-
verify(leaf: bigint, pathElements: bigint[], pathIndices: number[], root: bigint): boolean;
|
|
64
|
-
/**
|
|
65
|
-
* Get the current number of leaves in the tree
|
|
66
|
-
*/
|
|
67
|
-
get nextIndex(): number;
|
|
68
|
-
/**
|
|
69
|
-
* Check if the tree is full
|
|
70
|
-
*/
|
|
71
|
-
isFull(): boolean;
|
|
72
|
-
/**
|
|
73
|
-
* Get the maximum capacity of the tree
|
|
74
|
-
*/
|
|
75
|
-
getCapacity(): number;
|
|
76
|
-
/**
|
|
77
|
-
* Get the current fill percentage
|
|
78
|
-
*/
|
|
79
|
-
getFillPercentage(): number;
|
|
80
|
-
}
|
|
1
|
+
import { MerkleTree as FixedMerkleTree } from 'fixed-merkle-tree';
|
|
2
|
+
export declare const buildMerkleTree: () => FixedMerkleTree;
|
|
3
|
+
export type MerkleTree = FixedMerkleTree;
|
|
81
4
|
//# sourceMappingURL=merkle-tree.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merkle-tree.d.ts","sourceRoot":"","sources":["../../src/entities/merkle-tree.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"merkle-tree.d.ts","sourceRoot":"","sources":["../../src/entities/merkle-tree.ts"],"names":[],"mappings":"AAIA,OAAO,EAAW,UAAU,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAE3E,eAAO,MAAM,eAAe,uBAKxB,CAAC;AAEL,MAAM,MAAM,UAAU,GAAG,eAAe,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var suitcaseCore = require('@polymedia/suitcase-core');
|
|
4
4
|
var invariant = require('tiny-invariant');
|
|
5
5
|
var ramda = require('ramda');
|
|
6
|
+
var fixedMerkleTree = require('fixed-merkle-tree');
|
|
6
7
|
var require$$0 = require('fs');
|
|
7
8
|
var bn_js = require('bn.js');
|
|
8
9
|
|
|
@@ -38843,201 +38844,10 @@ _VortexKeypair_instances = new WeakSet(), _VortexKeypair_decrypt = function _Vor
|
|
|
38843
38844
|
};
|
|
38844
38845
|
|
|
38845
38846
|
// packages/vortex/src/entities/merkle-tree.ts
|
|
38846
|
-
|
|
38847
|
-
|
|
38848
|
-
|
|
38849
|
-
|
|
38850
|
-
class MerkleTree {
|
|
38851
|
-
constructor(levels) {
|
|
38852
|
-
this.levels = levels;
|
|
38853
|
-
this.capacity = 2 ** levels;
|
|
38854
|
-
this.zeroElement = ZERO_VALUE;
|
|
38855
|
-
this.zeros = [];
|
|
38856
|
-
this.subtrees = [];
|
|
38857
|
-
this._nextIndex = 0;
|
|
38858
|
-
this.leaves = [];
|
|
38859
|
-
// Initialize zero hashes (0 to levels, inclusive)
|
|
38860
|
-
// We need levels+1 elements: zeros[0] through zeros[levels]
|
|
38861
|
-
for (let i = 0; i <= levels; i++) {
|
|
38862
|
-
this.zeros[i] = EMPTY_SUBTREE_HASHES[i];
|
|
38863
|
-
}
|
|
38864
|
-
// Initialize subtrees[0..levels-1] (matching Nova's filledSubtrees)
|
|
38865
|
-
// subtrees[0] is initialized but never used (Nova quirk)
|
|
38866
|
-
for (let i = 0; i < levels; i++) {
|
|
38867
|
-
this.subtrees[i] = this.zeros[i];
|
|
38868
|
-
}
|
|
38869
|
-
// Empty root is zeros[levels]
|
|
38870
|
-
this._root = this.zeros[levels];
|
|
38871
|
-
}
|
|
38872
|
-
/**
|
|
38873
|
-
* Returns the current Merkle root
|
|
38874
|
-
*/
|
|
38875
|
-
root() {
|
|
38876
|
-
return this._root;
|
|
38877
|
-
}
|
|
38878
|
-
/**
|
|
38879
|
-
* Insert elements in bulk (must be even number for pairing)
|
|
38880
|
-
*/
|
|
38881
|
-
bulkInsert(elements) {
|
|
38882
|
-
if (elements.length % 2 !== 0) {
|
|
38883
|
-
throw new Error('Must insert even number of elements (pairs)');
|
|
38884
|
-
}
|
|
38885
|
-
for (let i = 0; i < elements.length; i += 2) {
|
|
38886
|
-
this.insertPair(elements[i], elements[i + 1]);
|
|
38887
|
-
}
|
|
38888
|
-
}
|
|
38889
|
-
/**
|
|
38890
|
-
* Insert a pair of leaves (Nova style)
|
|
38891
|
-
* This is the primary insertion method
|
|
38892
|
-
*/
|
|
38893
|
-
insertPair(leaf1, leaf2) {
|
|
38894
|
-
if (this._nextIndex >= this.capacity) {
|
|
38895
|
-
throw new Error('Merkle tree is full. No more leaves can be added');
|
|
38896
|
-
}
|
|
38897
|
-
// Store both leaves
|
|
38898
|
-
this.leaves.push(leaf1, leaf2);
|
|
38899
|
-
// Start by hashing the pair (level 0)
|
|
38900
|
-
let currentIndex = Math.floor(this._nextIndex / 2);
|
|
38901
|
-
let currentLevelHash = poseidon2(leaf1, leaf2);
|
|
38902
|
-
// Increment by 2 since we're inserting a pair
|
|
38903
|
-
this._nextIndex += 2;
|
|
38904
|
-
// Process levels 1 to levels-1 (matching Nova: for i = 1; i < levels)
|
|
38905
|
-
for (let i = 1; i < this.levels; i++) {
|
|
38906
|
-
let left;
|
|
38907
|
-
let right;
|
|
38908
|
-
if (currentIndex % 2 === 0) {
|
|
38909
|
-
// Current is left child
|
|
38910
|
-
left = currentLevelHash;
|
|
38911
|
-
right = this.zeros[i];
|
|
38912
|
-
this.subtrees[i] = currentLevelHash; // Cache left subtree
|
|
38913
|
-
}
|
|
38914
|
-
else {
|
|
38915
|
-
// Current is right child
|
|
38916
|
-
left = this.subtrees[i]; // Get cached left subtree
|
|
38917
|
-
right = currentLevelHash;
|
|
38918
|
-
}
|
|
38919
|
-
currentLevelHash = poseidon2(left, right);
|
|
38920
|
-
currentIndex = Math.floor(currentIndex / 2);
|
|
38921
|
-
}
|
|
38922
|
-
// Update root
|
|
38923
|
-
this._root = currentLevelHash;
|
|
38924
|
-
}
|
|
38925
|
-
/**
|
|
38926
|
-
* Insert a single leaf (for backward compatibility)
|
|
38927
|
-
* Pairs it with a zero leaf
|
|
38928
|
-
*/
|
|
38929
|
-
insert(leaf) {
|
|
38930
|
-
this.insertPair(leaf, this.zeros[0]);
|
|
38931
|
-
}
|
|
38932
|
-
/**
|
|
38933
|
-
* Generate Merkle path for a leaf at given index
|
|
38934
|
-
* Returns sibling hashes and indices for verification
|
|
38935
|
-
*/
|
|
38936
|
-
path(index) {
|
|
38937
|
-
if (index < 0 || index >= this._nextIndex) {
|
|
38938
|
-
throw new Error(`Index out of bounds: ${index} (tree has ${this._nextIndex} leaves)`);
|
|
38939
|
-
}
|
|
38940
|
-
const pathElements = [];
|
|
38941
|
-
const pathIndices = [];
|
|
38942
|
-
// Level 0: Get sibling leaf
|
|
38943
|
-
const isLeftAtLevel0 = index % 2 === 0;
|
|
38944
|
-
pathIndices.push(isLeftAtLevel0 ? 0 : 1);
|
|
38945
|
-
const siblingIndex = isLeftAtLevel0 ? index + 1 : index - 1;
|
|
38946
|
-
const sibling = siblingIndex < this._nextIndex
|
|
38947
|
-
? this.leaves[siblingIndex]
|
|
38948
|
-
: this.zeros[0];
|
|
38949
|
-
pathElements.push(sibling);
|
|
38950
|
-
// Levels 1 to levels-1 (matching Nova's loop structure)
|
|
38951
|
-
let currentIndex = Math.floor(index / 2);
|
|
38952
|
-
for (let i = 1; i < this.levels; i++) {
|
|
38953
|
-
const isLeft = currentIndex % 2 === 0;
|
|
38954
|
-
pathIndices.push(isLeft ? 0 : 1);
|
|
38955
|
-
if (isLeft) {
|
|
38956
|
-
// We're left child, sibling is right (zero hash)
|
|
38957
|
-
pathElements.push(this.zeros[i]);
|
|
38958
|
-
}
|
|
38959
|
-
else {
|
|
38960
|
-
// We're right child, sibling is the cached left subtree
|
|
38961
|
-
pathElements.push(this.subtrees[i]);
|
|
38962
|
-
}
|
|
38963
|
-
currentIndex = Math.floor(currentIndex / 2);
|
|
38964
|
-
}
|
|
38965
|
-
return { pathElements, pathIndices };
|
|
38966
|
-
}
|
|
38967
|
-
/**
|
|
38968
|
-
* Get all leaves in the tree
|
|
38969
|
-
*/
|
|
38970
|
-
elements() {
|
|
38971
|
-
return this.leaves;
|
|
38972
|
-
}
|
|
38973
|
-
/**
|
|
38974
|
-
* Find the index of a specific leaf
|
|
38975
|
-
*/
|
|
38976
|
-
indexOf(element, comparator = null) {
|
|
38977
|
-
if (comparator) {
|
|
38978
|
-
return this.leaves.findIndex((leaf) => comparator(element, leaf));
|
|
38979
|
-
}
|
|
38980
|
-
return this.leaves.findIndex((leaf) => leaf === element);
|
|
38981
|
-
}
|
|
38982
|
-
/**
|
|
38983
|
-
* Serialize tree state
|
|
38984
|
-
*/
|
|
38985
|
-
serialize() {
|
|
38986
|
-
return {
|
|
38987
|
-
levels: this.levels,
|
|
38988
|
-
zeros: this.zeros,
|
|
38989
|
-
subtrees: this.subtrees,
|
|
38990
|
-
nextIndex: this._nextIndex,
|
|
38991
|
-
leaves: this.leaves,
|
|
38992
|
-
root: this._root,
|
|
38993
|
-
};
|
|
38994
|
-
}
|
|
38995
|
-
/**
|
|
38996
|
-
* Verify a Merkle path is valid for a given leaf and root
|
|
38997
|
-
*/
|
|
38998
|
-
verify(leaf, pathElements, pathIndices, root) {
|
|
38999
|
-
if (pathElements.length !== this.levels ||
|
|
39000
|
-
pathIndices.length !== this.levels) {
|
|
39001
|
-
return false;
|
|
39002
|
-
}
|
|
39003
|
-
let currentHash = leaf;
|
|
39004
|
-
for (let i = 0; i < this.levels; i++) {
|
|
39005
|
-
const sibling = pathElements[i];
|
|
39006
|
-
const isLeft = pathIndices[i] === 0;
|
|
39007
|
-
if (isLeft) {
|
|
39008
|
-
currentHash = poseidon2(currentHash, sibling);
|
|
39009
|
-
}
|
|
39010
|
-
else {
|
|
39011
|
-
currentHash = poseidon2(sibling, currentHash);
|
|
39012
|
-
}
|
|
39013
|
-
}
|
|
39014
|
-
return currentHash === root;
|
|
39015
|
-
}
|
|
39016
|
-
/**
|
|
39017
|
-
* Get the current number of leaves in the tree
|
|
39018
|
-
*/
|
|
39019
|
-
get nextIndex() {
|
|
39020
|
-
return this._nextIndex;
|
|
39021
|
-
}
|
|
39022
|
-
/**
|
|
39023
|
-
* Check if the tree is full
|
|
39024
|
-
*/
|
|
39025
|
-
isFull() {
|
|
39026
|
-
return this._nextIndex >= this.capacity;
|
|
39027
|
-
}
|
|
39028
|
-
/**
|
|
39029
|
-
* Get the maximum capacity of the tree
|
|
39030
|
-
*/
|
|
39031
|
-
getCapacity() {
|
|
39032
|
-
return this.capacity;
|
|
39033
|
-
}
|
|
39034
|
-
/**
|
|
39035
|
-
* Get the current fill percentage
|
|
39036
|
-
*/
|
|
39037
|
-
getFillPercentage() {
|
|
39038
|
-
return (this._nextIndex / this.capacity) * 100;
|
|
39039
|
-
}
|
|
39040
|
-
}
|
|
38847
|
+
const buildMerkleTree = () => new fixedMerkleTree.MerkleTree(MERKLE_TREE_HEIGHT, [], {
|
|
38848
|
+
hashFunction: (left, right) => poseidon2(BigInt(left), BigInt(right)).toString(),
|
|
38849
|
+
zeroElement: ZERO_VALUE.toString(),
|
|
38850
|
+
});
|
|
39041
38851
|
|
|
39042
38852
|
class Utxo {
|
|
39043
38853
|
constructor({ amount, blinding, keypair, index }) {
|
|
@@ -39612,7 +39422,7 @@ function getMerklePath(merkleTree, utxo) {
|
|
|
39612
39422
|
.map(() => [ZERO_VALUE.toString(), ZERO_VALUE.toString()]);
|
|
39613
39423
|
}
|
|
39614
39424
|
const utxoIndex = Number(utxo.index);
|
|
39615
|
-
const treeSize = merkleTree.elements
|
|
39425
|
+
const treeSize = merkleTree.elements.length;
|
|
39616
39426
|
// For deposits, input UTXOs don't exist yet
|
|
39617
39427
|
if (utxoIndex < 0 || utxoIndex >= treeSize) {
|
|
39618
39428
|
return Array(MERKLE_TREE_HEIGHT)
|
|
@@ -39623,13 +39433,13 @@ function getMerklePath(merkleTree, utxo) {
|
|
|
39623
39433
|
const { pathElements, pathIndices } = merkleTree.path(utxoIndex);
|
|
39624
39434
|
const commitment = utxo.commitment();
|
|
39625
39435
|
// Verify commitment matches what's in the tree
|
|
39626
|
-
const storedCommitment = merkleTree.elements
|
|
39436
|
+
const storedCommitment = BigInt(merkleTree.elements[utxoIndex]);
|
|
39627
39437
|
invariant(storedCommitment === commitment, `Commitment mismatch at index ${utxoIndex}: expected ${commitment}, got ${storedCommitment}`);
|
|
39628
39438
|
// Build WASM-compatible path (always [left, right] format)
|
|
39629
39439
|
const wasmPath = [];
|
|
39630
39440
|
let currentHash = commitment;
|
|
39631
39441
|
for (let i = 0; i < MERKLE_TREE_HEIGHT; i++) {
|
|
39632
|
-
const sibling = pathElements[i];
|
|
39442
|
+
const sibling = BigInt(pathElements[i]);
|
|
39633
39443
|
const isLeft = pathIndices[i] === 0;
|
|
39634
39444
|
invariant(sibling !== undefined, `Sibling undefined at level ${i}`);
|
|
39635
39445
|
const leftHash = isLeft ? currentHash : sibling;
|
|
@@ -39643,13 +39453,13 @@ function getMerklePath(merkleTree, utxo) {
|
|
|
39643
39453
|
currentHash = nextHash;
|
|
39644
39454
|
}
|
|
39645
39455
|
const calculatedRoot = currentHash;
|
|
39646
|
-
const expectedRoot = merkleTree.root
|
|
39456
|
+
const expectedRoot = BigInt(merkleTree.root);
|
|
39647
39457
|
invariant(calculatedRoot === expectedRoot, `Root mismatch: calculated ${calculatedRoot}, expected ${expectedRoot}`);
|
|
39648
39458
|
return wasmPath;
|
|
39649
39459
|
}
|
|
39650
39460
|
const toProveInput = ({ merkleTree, publicAmount, extDataHash, nullifier0, nullifier1, commitment0, commitment1, vortexKeypair, inputUtxo0, inputUtxo1, outputUtxo0, outputUtxo1, }) => {
|
|
39651
39461
|
return {
|
|
39652
|
-
root: merkleTree.root
|
|
39462
|
+
root: BigInt(merkleTree.root),
|
|
39653
39463
|
publicAmount,
|
|
39654
39464
|
extDataHash,
|
|
39655
39465
|
inputNullifier0: nullifier0,
|
|
@@ -39761,7 +39571,7 @@ const deposit = async ({ tx = new Transaction(), amount, unspentUtxos = [], vort
|
|
|
39761
39571
|
const { proof: moveProof, tx: tx3 } = vortex.newProof({
|
|
39762
39572
|
tx: tx2,
|
|
39763
39573
|
proofPoints: fromHex('0x' + proof.proofSerializedHex),
|
|
39764
|
-
root: merkleTree.root
|
|
39574
|
+
root: BigInt(merkleTree.root),
|
|
39765
39575
|
publicValue: amountMinusFrontendFee,
|
|
39766
39576
|
action: exports.Action.Deposit,
|
|
39767
39577
|
extDataHash: extDataHashBigInt,
|
|
@@ -39862,7 +39672,7 @@ const withdraw = async ({ tx = new Transaction(), amount, unspentUtxos = [], vor
|
|
|
39862
39672
|
const { proof: moveProof, tx: tx3 } = vortex.newProof({
|
|
39863
39673
|
tx: tx2,
|
|
39864
39674
|
proofPoints: fromHex('0x' + proof.proofSerializedHex),
|
|
39865
|
-
root: merkleTree.root
|
|
39675
|
+
root: BigInt(merkleTree.root),
|
|
39866
39676
|
publicValue: amount + relayerFee,
|
|
39867
39677
|
action: exports.Action.Withdraw,
|
|
39868
39678
|
extDataHash: extDataHashBigInt,
|
|
@@ -39891,7 +39701,6 @@ exports.INITIAL_SHARED_VERSION = INITIAL_SHARED_VERSION;
|
|
|
39891
39701
|
exports.LSK_ENCRYPTED_OUTPUTS = LSK_ENCRYPTED_OUTPUTS;
|
|
39892
39702
|
exports.LSK_FETCH_OFFSET = LSK_FETCH_OFFSET;
|
|
39893
39703
|
exports.MERKLE_TREE_HEIGHT = MERKLE_TREE_HEIGHT;
|
|
39894
|
-
exports.MerkleTree = MerkleTree;
|
|
39895
39704
|
exports.OPT = OPT;
|
|
39896
39705
|
exports.REGISTRY_OBJECT_ID = REGISTRY_OBJECT_ID;
|
|
39897
39706
|
exports.ROOT_HISTORY_SIZE = ROOT_HISTORY_SIZE;
|
|
@@ -39904,6 +39713,7 @@ exports.VORTEX_SIGNATURE_DOMAIN = VORTEX_SIGNATURE_DOMAIN;
|
|
|
39904
39713
|
exports.Vortex = Vortex;
|
|
39905
39714
|
exports.VortexKeypair = VortexKeypair;
|
|
39906
39715
|
exports.ZERO_VALUE = ZERO_VALUE;
|
|
39716
|
+
exports.buildMerkleTree = buildMerkleTree;
|
|
39907
39717
|
exports.bytesToBigInt = bytesToBigInt;
|
|
39908
39718
|
exports.computeExtDataHash = computeExtDataHash;
|
|
39909
39719
|
exports.deposit = deposit;
|