pshenmic-dpp 2.0.0-dev.27 → 2.0.0-dev.29
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/binaries/bindingsTypes.d.ts +369 -2
- package/dist/binaries/bindingsTypes.js +11 -0
- package/dist/binaries/native/aarch64-apple-darwin/pshenmic_dpp.node +0 -0
- package/dist/binaries/native/aarch64-pc-windows-msvc/pshenmic_dpp.node +0 -0
- package/dist/binaries/native/aarch64-unknown-linux-gnu/pshenmic_dpp.node +0 -0
- package/dist/binaries/native/aarch64-unknown-linux-musl/pshenmic_dpp.node +0 -0
- package/dist/binaries/native/x86_64-apple-darwin/pshenmic_dpp.node +0 -0
- package/dist/binaries/native/x86_64-pc-windows-msvc/pshenmic_dpp.node +0 -0
- package/dist/binaries/native/x86_64-unknown-linux-gnu/pshenmic_dpp.node +0 -0
- package/dist/binaries/native/x86_64-unknown-linux-musl/pshenmic_dpp.node +0 -0
- package/dist/binaries/pshenmic_dpp.android.node/arm64-v8a/libpshenmic_dpp.so +0 -0
- package/dist/binaries/pshenmic_dpp.apple.node/ios-arm64-simulator/libpshenmic_dpp.framework/libpshenmic_dpp +0 -0
- package/dist/binaries/pshenmic_dpp.d.ts +21 -0
- package/dist/binaries/pshenmic_dpp.js +1 -1
- package/dist/binaries/wasm/wasmBytes.cjs +1 -1
- package/dist/binaries/wasm.d.ts +21 -0
- package/dist/binaries/wasm.js +1 -1
- package/dist/src/dpp/dpp.d.ts +7 -0
- package/dist/src/dpp/dpp.js +7 -0
- package/dist/src/dpp/enums.d.ts +1 -1
- package/dist/src/dpp/enums.js +1 -1
- package/dist/src/dpp/structs/Orchard/FullViewingKey.d.ts +27 -0
- package/dist/src/dpp/structs/Orchard/FullViewingKey.js +45 -0
- package/dist/src/dpp/structs/Orchard/IncomingViewingKey.d.ts +29 -0
- package/dist/src/dpp/structs/Orchard/IncomingViewingKey.js +44 -0
- package/dist/src/dpp/structs/Orchard/OrchardAddress.d.ts +14 -2
- package/dist/src/dpp/structs/Orchard/OrchardAddress.js +16 -2
- package/dist/src/dpp/structs/Orchard/ShieldedBuilder.d.ts +17 -0
- package/dist/src/dpp/structs/Orchard/ShieldedBuilder.js +18 -0
- package/dist/src/dpp/structs/Orchard/ShieldedOutput.d.ts +23 -0
- package/dist/src/dpp/structs/Orchard/ShieldedOutput.js +41 -0
- package/dist/src/dpp/types.d.ts +84 -1
- package/dist/src/dpp/verify/AddressFunds/utils.d.ts +5 -0
- package/dist/src/dpp/verify/AddressFunds/utils.js +28 -0
- package/dist/src/dpp/verify/AddressFunds/verifyAddressesBranchState.d.ts +12 -0
- package/dist/src/dpp/verify/AddressFunds/verifyAddressesBranchState.js +29 -0
- package/dist/src/dpp/verify/AddressFunds/verifyAddressesTrunkState.d.ts +9 -0
- package/dist/src/dpp/verify/AddressFunds/verifyAddressesTrunkState.js +30 -0
- package/dist/src/dpp/verify/AddressFunds/verifyRecentAddressBalanceChanges.d.ts +9 -0
- package/dist/src/dpp/verify/AddressFunds/verifyRecentAddressBalanceChanges.js +24 -0
- package/dist/src/dpp/verify/AddressFunds/verifyRecentCompactedAddressBalanceChanges.d.ts +10 -0
- package/dist/src/dpp/verify/AddressFunds/verifyRecentCompactedAddressBalanceChanges.js +30 -0
- package/package.json +1 -1
- package/tests/unit/Shielded.spec.ts +176 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export function mapGroveElementEntry(entry) {
|
|
2
|
+
const { element } = entry;
|
|
3
|
+
return {
|
|
4
|
+
key: entry.key,
|
|
5
|
+
element: {
|
|
6
|
+
type: element.type,
|
|
7
|
+
wrapper: element.wrapper != null ? element.wrapper : undefined,
|
|
8
|
+
value: element.value ?? undefined,
|
|
9
|
+
sum: element.sum != null ? BigInt(element.sum) : undefined,
|
|
10
|
+
count: element.count != null ? BigInt(element.count) : undefined
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export function mapGroveLeafInfo(info) {
|
|
15
|
+
return {
|
|
16
|
+
key: info.key,
|
|
17
|
+
hash: info.hash,
|
|
18
|
+
count: info.count != null ? BigInt(info.count) : undefined
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
export function mapGroveAncestor(ancestor) {
|
|
22
|
+
return {
|
|
23
|
+
levelsUp: ancestor.levelsUp,
|
|
24
|
+
count: BigInt(ancestor.count),
|
|
25
|
+
key: ancestor.key,
|
|
26
|
+
hash: ancestor.hash
|
|
27
|
+
};
|
|
28
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { PlatformVersionLike, VerifiedAddressesBranchState } from '../../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Verifies a branch chunk proof for the address funds tree.
|
|
4
|
+
*
|
|
5
|
+
* `expectedRootHash` must be the `hash` the parent trunk or branch reported for
|
|
6
|
+
* `key`; it is what anchors this subtree to the proven root, so the result
|
|
7
|
+
* carries no root hash of its own.
|
|
8
|
+
*
|
|
9
|
+
* `depth` is validated against an allowed range, so take it from the parent
|
|
10
|
+
* trunk's `chunkDepths` rather than picking a value.
|
|
11
|
+
*/
|
|
12
|
+
export declare function verifyAddressesBranchState(proof: Uint8Array, key: Uint8Array, depth: number, expectedRootHash: Uint8Array, platformVersion: PlatformVersionLike): VerifiedAddressesBranchState;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { dppProvider } from '../../provider.js';
|
|
2
|
+
import { valueToDynamicValue } from '../../utils.js';
|
|
3
|
+
import { mapGroveAncestor, mapGroveElementEntry, mapGroveLeafInfo } from './utils.js';
|
|
4
|
+
/**
|
|
5
|
+
* Verifies a branch chunk proof for the address funds tree.
|
|
6
|
+
*
|
|
7
|
+
* `expectedRootHash` must be the `hash` the parent trunk or branch reported for
|
|
8
|
+
* `key`; it is what anchors this subtree to the proven root, so the result
|
|
9
|
+
* carries no root hash of its own.
|
|
10
|
+
*
|
|
11
|
+
* `depth` is validated against an allowed range, so take it from the parent
|
|
12
|
+
* trunk's `chunkDepths` rather than picking a value.
|
|
13
|
+
*/
|
|
14
|
+
export function verifyAddressesBranchState(proof, key, depth, expectedRootHash, platformVersion) {
|
|
15
|
+
const result = dppProvider.dpp.verifyAddressesBranchState(proof, key, depth, expectedRootHash, valueToDynamicValue(platformVersion));
|
|
16
|
+
return {
|
|
17
|
+
elements: result.elements.map(mapGroveElementEntry),
|
|
18
|
+
leafKeys: result.leafKeys.map(mapGroveLeafInfo),
|
|
19
|
+
branchRootHash: result.branchRootHash,
|
|
20
|
+
traceKeyToLeaf: (traced) => {
|
|
21
|
+
const leaf = result.traceKeyToLeaf(traced);
|
|
22
|
+
return leaf != null ? mapGroveLeafInfo(leaf) : undefined;
|
|
23
|
+
},
|
|
24
|
+
getAncestor: (leafKey, minPrivacyTreeCount) => {
|
|
25
|
+
const ancestor = result.getAncestor(leafKey, minPrivacyTreeCount.toString());
|
|
26
|
+
return ancestor != null ? mapGroveAncestor(ancestor) : undefined;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { PlatformVersionLike, VerifiedAddressesTrunkState } from '../../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Verifies a trunk chunk proof for the address funds tree.
|
|
4
|
+
*
|
|
5
|
+
* The trunk covers the top of the tree only. Subtrees below it are truncated
|
|
6
|
+
* and listed in `leafKeys`; use `traceKeyToLeaf` to find which one holds an
|
|
7
|
+
* address, then fetch it with `verifyAddressesBranchState`.
|
|
8
|
+
*/
|
|
9
|
+
export declare function verifyAddressesTrunkState(proof: Uint8Array, platformVersion: PlatformVersionLike): VerifiedAddressesTrunkState;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { dppProvider } from '../../provider.js';
|
|
2
|
+
import { valueToDynamicValue } from '../../utils.js';
|
|
3
|
+
import { mapGroveAncestor, mapGroveElementEntry, mapGroveLeafInfo } from './utils.js';
|
|
4
|
+
/**
|
|
5
|
+
* Verifies a trunk chunk proof for the address funds tree.
|
|
6
|
+
*
|
|
7
|
+
* The trunk covers the top of the tree only. Subtrees below it are truncated
|
|
8
|
+
* and listed in `leafKeys`; use `traceKeyToLeaf` to find which one holds an
|
|
9
|
+
* address, then fetch it with `verifyAddressesBranchState`.
|
|
10
|
+
*/
|
|
11
|
+
export function verifyAddressesTrunkState(proof, platformVersion) {
|
|
12
|
+
const result = dppProvider.dpp.verifyAddressesTrunkState(proof, valueToDynamicValue(platformVersion));
|
|
13
|
+
return {
|
|
14
|
+
rootHash: result.rootHash,
|
|
15
|
+
elements: result.elements.map(mapGroveElementEntry),
|
|
16
|
+
leafKeys: result.leafKeys.map(mapGroveLeafInfo),
|
|
17
|
+
chunkDepths: result.chunkDepths,
|
|
18
|
+
maxTreeDepth: result.maxTreeDepth,
|
|
19
|
+
// These close over the verified result because tracing walks the proof's
|
|
20
|
+
// reconstructed tree, which is not projected into plain data.
|
|
21
|
+
traceKeyToLeaf: (key) => {
|
|
22
|
+
const leaf = result.traceKeyToLeaf(key);
|
|
23
|
+
return leaf != null ? mapGroveLeafInfo(leaf) : undefined;
|
|
24
|
+
},
|
|
25
|
+
getAncestor: (leafKey, minPrivacyTreeCount) => {
|
|
26
|
+
const ancestor = result.getAncestor(leafKey, minPrivacyTreeCount.toString());
|
|
27
|
+
return ancestor != null ? mapGroveAncestor(ancestor) : undefined;
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { PlatformVersionLike, VerifiedRecentAddressBalanceChanges } from '../../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Verifies a proof of the address balance changes from a block height onwards.
|
|
4
|
+
*
|
|
5
|
+
* `startHeightExclusive` must match the flag the proof was requested with: it
|
|
6
|
+
* selects a range starting just past `startBlockHeight` rather than at it, and
|
|
7
|
+
* the two produce different queries, so a mismatch fails verification.
|
|
8
|
+
*/
|
|
9
|
+
export declare function verifyRecentAddressBalanceChanges(proof: Uint8Array, startBlockHeight: bigint, startHeightExclusive: boolean, limit: number | undefined, verifySubsetOfProof: boolean, platformVersion: PlatformVersionLike): VerifiedRecentAddressBalanceChanges;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { dppProvider } from '../../provider.js';
|
|
2
|
+
import { valueToDynamicValue } from '../../utils.js';
|
|
3
|
+
import { PlatformAddressWASM } from '../../structs/PlatformAddress/PlatformAddress.js';
|
|
4
|
+
/**
|
|
5
|
+
* Verifies a proof of the address balance changes from a block height onwards.
|
|
6
|
+
*
|
|
7
|
+
* `startHeightExclusive` must match the flag the proof was requested with: it
|
|
8
|
+
* selects a range starting just past `startBlockHeight` rather than at it, and
|
|
9
|
+
* the two produce different queries, so a mismatch fails verification.
|
|
10
|
+
*/
|
|
11
|
+
export function verifyRecentAddressBalanceChanges(proof, startBlockHeight, startHeightExclusive, limit, verifySubsetOfProof, platformVersion) {
|
|
12
|
+
const result = dppProvider.dpp.verifyRecentAddressBalanceChanges(proof, startBlockHeight.toString(), startHeightExclusive, limit, verifySubsetOfProof, valueToDynamicValue(platformVersion));
|
|
13
|
+
return {
|
|
14
|
+
rootHash: result.rootHash,
|
|
15
|
+
blocks: result.blocks.map((block) => ({
|
|
16
|
+
blockHeight: BigInt(block.blockHeight),
|
|
17
|
+
changes: block.changes.map((change) => ({
|
|
18
|
+
address: PlatformAddressWASM.createFromRawInstance(change.address),
|
|
19
|
+
operation: change.operation,
|
|
20
|
+
credits: BigInt(change.credits)
|
|
21
|
+
}))
|
|
22
|
+
}))
|
|
23
|
+
};
|
|
24
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PlatformVersionLike, VerifiedRecentCompactedAddressBalanceChanges } from '../../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Verifies a proof of the compacted address balance changes from a block height
|
|
4
|
+
* onwards, where each entry merges a range of blocks.
|
|
5
|
+
*
|
|
6
|
+
* There is no subset flag here: the proof is a self-contained envelope whose
|
|
7
|
+
* predecessor half authenticates which range covers the requested height, so
|
|
8
|
+
* the forward half has nothing to be a subset of.
|
|
9
|
+
*/
|
|
10
|
+
export declare function verifyRecentCompactedAddressBalanceChanges(proof: Uint8Array, startBlockHeight: bigint, limit: number | undefined, platformVersion: PlatformVersionLike): VerifiedRecentCompactedAddressBalanceChanges;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { dppProvider } from '../../provider.js';
|
|
2
|
+
import { valueToDynamicValue } from '../../utils.js';
|
|
3
|
+
import { PlatformAddressWASM } from '../../structs/PlatformAddress/PlatformAddress.js';
|
|
4
|
+
/**
|
|
5
|
+
* Verifies a proof of the compacted address balance changes from a block height
|
|
6
|
+
* onwards, where each entry merges a range of blocks.
|
|
7
|
+
*
|
|
8
|
+
* There is no subset flag here: the proof is a self-contained envelope whose
|
|
9
|
+
* predecessor half authenticates which range covers the requested height, so
|
|
10
|
+
* the forward half has nothing to be a subset of.
|
|
11
|
+
*/
|
|
12
|
+
export function verifyRecentCompactedAddressBalanceChanges(proof, startBlockHeight, limit, platformVersion) {
|
|
13
|
+
const result = dppProvider.dpp.verifyRecentCompactedAddressBalanceChanges(proof, startBlockHeight.toString(), limit, valueToDynamicValue(platformVersion));
|
|
14
|
+
return {
|
|
15
|
+
rootHash: result.rootHash,
|
|
16
|
+
ranges: result.ranges.map((range) => ({
|
|
17
|
+
startBlockHeight: BigInt(range.startBlockHeight),
|
|
18
|
+
endBlockHeight: BigInt(range.endBlockHeight),
|
|
19
|
+
changes: range.changes.map((change) => ({
|
|
20
|
+
address: PlatformAddressWASM.createFromRawInstance(change.address),
|
|
21
|
+
operation: change.operation,
|
|
22
|
+
setCredits: change.setCredits != null ? BigInt(change.setCredits) : undefined,
|
|
23
|
+
addToCreditsOperations: change.addToCreditsOperations.map((operation) => ({
|
|
24
|
+
blockHeight: BigInt(operation.blockHeight),
|
|
25
|
+
credits: BigInt(operation.credits)
|
|
26
|
+
}))
|
|
27
|
+
}))
|
|
28
|
+
}))
|
|
29
|
+
};
|
|
30
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ShieldedMemoWASM,
|
|
3
3
|
OrchardAddressWASM,
|
|
4
|
+
FullViewingKeyWASM,
|
|
5
|
+
IncomingViewingKeyWASM,
|
|
4
6
|
orchardOvkFromSeed,
|
|
5
7
|
NoteWASM,
|
|
6
8
|
MerklePathWASM,
|
|
@@ -169,6 +171,180 @@ describe('OrchardAddress', function () {
|
|
|
169
171
|
expect(ovk.length).toEqual(32)
|
|
170
172
|
})
|
|
171
173
|
})
|
|
174
|
+
|
|
175
|
+
describe('fromFullViewingKey', function () {
|
|
176
|
+
test('should match the address derived from the same seed', function () {
|
|
177
|
+
const fvk = FullViewingKeyWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT)
|
|
178
|
+
|
|
179
|
+
expect(OrchardAddressWASM.fromFullViewingKey(fvk).bytes())
|
|
180
|
+
.toEqual(OrchardAddressWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT).bytes())
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
test('should derive a different address per diversifier index', function () {
|
|
184
|
+
const fvk = FullViewingKeyWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT)
|
|
185
|
+
|
|
186
|
+
expect(OrchardAddressWASM.fromFullViewingKey(fvk, 1).bytes())
|
|
187
|
+
.not.toEqual(OrchardAddressWASM.fromFullViewingKey(fvk, 0).bytes())
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
test('should derive a different address per scope', function () {
|
|
191
|
+
const fvk = FullViewingKeyWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT)
|
|
192
|
+
|
|
193
|
+
expect(OrchardAddressWASM.fromFullViewingKey(fvk, 0, 'internal').bytes())
|
|
194
|
+
.not.toEqual(OrchardAddressWASM.fromFullViewingKey(fvk, 0, 'external').bytes())
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
test('should reject an unknown scope', function () {
|
|
198
|
+
const fvk = FullViewingKeyWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT)
|
|
199
|
+
|
|
200
|
+
expect(() => OrchardAddressWASM.fromFullViewingKey(fvk, 0, 'nope' as any)).toThrow()
|
|
201
|
+
})
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
describe('fromIncomingViewingKey', function () {
|
|
205
|
+
test('should match the address derived from the same seed', function () {
|
|
206
|
+
const ivk = IncomingViewingKeyWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT)
|
|
207
|
+
|
|
208
|
+
expect(OrchardAddressWASM.fromIncomingViewingKey(ivk).bytes())
|
|
209
|
+
.toEqual(OrchardAddressWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT).bytes())
|
|
210
|
+
})
|
|
211
|
+
|
|
212
|
+
test('should derive a different address per diversifier index', function () {
|
|
213
|
+
const ivk = IncomingViewingKeyWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT)
|
|
214
|
+
|
|
215
|
+
expect(OrchardAddressWASM.fromIncomingViewingKey(ivk, 7).bytes())
|
|
216
|
+
.not.toEqual(OrchardAddressWASM.fromIncomingViewingKey(ivk, 0).bytes())
|
|
217
|
+
})
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
describe('fromSeed scope', function () {
|
|
221
|
+
test('should derive the internal-scope address', function () {
|
|
222
|
+
const fvk = FullViewingKeyWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT)
|
|
223
|
+
|
|
224
|
+
expect(OrchardAddressWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT, 0, 'internal').bytes())
|
|
225
|
+
.toEqual(OrchardAddressWASM.fromFullViewingKey(fvk, 0, 'internal').bytes())
|
|
226
|
+
})
|
|
227
|
+
})
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
describe('FullViewingKey', function () {
|
|
231
|
+
describe('fromSeed', function () {
|
|
232
|
+
test('should derive a 96-byte key deterministically', function () {
|
|
233
|
+
const fvk = FullViewingKeyWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT)
|
|
234
|
+
|
|
235
|
+
expect(fvk).toBeInstanceOf(FullViewingKeyWASM)
|
|
236
|
+
expect(fvk.bytes().length).toEqual(96)
|
|
237
|
+
expect(fvk.bytes()).toEqual(FullViewingKeyWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT).bytes())
|
|
238
|
+
})
|
|
239
|
+
|
|
240
|
+
test('should differ per account', function () {
|
|
241
|
+
expect(FullViewingKeyWASM.fromSeed(SEED, COIN_TYPE, 1).bytes())
|
|
242
|
+
.not.toEqual(FullViewingKeyWASM.fromSeed(SEED, COIN_TYPE, 0).bytes())
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
test('should reject a hardened account index', function () {
|
|
246
|
+
expect(() => FullViewingKeyWASM.fromSeed(SEED, COIN_TYPE, 0x80000000)).toThrow()
|
|
247
|
+
})
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
describe('serialization', function () {
|
|
251
|
+
test('should roundtrip through bytes', function () {
|
|
252
|
+
const fvk = FullViewingKeyWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT)
|
|
253
|
+
|
|
254
|
+
expect(FullViewingKeyWASM.fromBytes(fvk.bytes()).bytes()).toEqual(fvk.bytes())
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
test('should reject bytes of the wrong length', function () {
|
|
258
|
+
expect(() => FullViewingKeyWASM.fromBytes(new Uint8Array(64))).toThrow()
|
|
259
|
+
})
|
|
260
|
+
|
|
261
|
+
test('should reject bytes that are not a valid key', function () {
|
|
262
|
+
expect(() => FullViewingKeyWASM.fromBytes(new Uint8Array(96).fill(0xff))).toThrow()
|
|
263
|
+
})
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
describe('toOvk', function () {
|
|
267
|
+
test('should match orchardOvkFromSeed for the external scope', function () {
|
|
268
|
+
const fvk = FullViewingKeyWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT)
|
|
269
|
+
|
|
270
|
+
expect(fvk.toOvk()).toEqual(orchardOvkFromSeed(SEED, COIN_TYPE, ACCOUNT))
|
|
271
|
+
expect(fvk.toOvk('internal')).not.toEqual(fvk.toOvk('external'))
|
|
272
|
+
})
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
describe('toIvk', function () {
|
|
276
|
+
test('should derive the same key as IncomingViewingKey.fromSeed', function () {
|
|
277
|
+
const fvk = FullViewingKeyWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT)
|
|
278
|
+
|
|
279
|
+
expect(fvk.toIvk().bytes())
|
|
280
|
+
.toEqual(IncomingViewingKeyWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT).bytes())
|
|
281
|
+
expect(fvk.toIvk('internal').bytes()).not.toEqual(fvk.toIvk('external').bytes())
|
|
282
|
+
})
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
describe('scopeForAddress', function () {
|
|
286
|
+
test('should report the scope of its own addresses', function () {
|
|
287
|
+
const fvk = FullViewingKeyWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT)
|
|
288
|
+
|
|
289
|
+
expect(fvk.scopeForAddress(fvk.address(0, 'external'))).toEqual('External')
|
|
290
|
+
expect(fvk.scopeForAddress(fvk.address(0, 'internal'))).toEqual('Internal')
|
|
291
|
+
})
|
|
292
|
+
|
|
293
|
+
test('should return null for a foreign address', function () {
|
|
294
|
+
const fvk = FullViewingKeyWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT)
|
|
295
|
+
const other = FullViewingKeyWASM.fromSeed(SEED, COIN_TYPE, 1)
|
|
296
|
+
|
|
297
|
+
expect(fvk.scopeForAddress(other.address())).toBeNull()
|
|
298
|
+
})
|
|
299
|
+
})
|
|
300
|
+
})
|
|
301
|
+
|
|
302
|
+
describe('IncomingViewingKey', function () {
|
|
303
|
+
describe('fromSeed', function () {
|
|
304
|
+
test('should derive a 64-byte key deterministically', function () {
|
|
305
|
+
const ivk = IncomingViewingKeyWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT)
|
|
306
|
+
|
|
307
|
+
expect(ivk).toBeInstanceOf(IncomingViewingKeyWASM)
|
|
308
|
+
expect(ivk.bytes().length).toEqual(64)
|
|
309
|
+
expect(ivk.bytes()).toEqual(IncomingViewingKeyWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT).bytes())
|
|
310
|
+
})
|
|
311
|
+
})
|
|
312
|
+
|
|
313
|
+
describe('fromFullViewingKey', function () {
|
|
314
|
+
test('should match the key derived from the same seed', function () {
|
|
315
|
+
const fvk = FullViewingKeyWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT)
|
|
316
|
+
|
|
317
|
+
expect(IncomingViewingKeyWASM.fromFullViewingKey(fvk).bytes())
|
|
318
|
+
.toEqual(IncomingViewingKeyWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT).bytes())
|
|
319
|
+
})
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
describe('serialization', function () {
|
|
323
|
+
test('should roundtrip through bytes', function () {
|
|
324
|
+
const ivk = IncomingViewingKeyWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT)
|
|
325
|
+
|
|
326
|
+
expect(IncomingViewingKeyWASM.fromBytes(ivk.bytes()).bytes()).toEqual(ivk.bytes())
|
|
327
|
+
})
|
|
328
|
+
|
|
329
|
+
test('should reject bytes of the wrong length', function () {
|
|
330
|
+
expect(() => IncomingViewingKeyWASM.fromBytes(new Uint8Array(96))).toThrow()
|
|
331
|
+
})
|
|
332
|
+
})
|
|
333
|
+
|
|
334
|
+
describe('diversifierIndex', function () {
|
|
335
|
+
test('should recover the index of its own address', function () {
|
|
336
|
+
const ivk = IncomingViewingKeyWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT)
|
|
337
|
+
|
|
338
|
+
expect(ivk.diversifierIndex(ivk.address(5))).toEqual(5)
|
|
339
|
+
})
|
|
340
|
+
|
|
341
|
+
test('should return null for a foreign address', function () {
|
|
342
|
+
const ivk = IncomingViewingKeyWASM.fromSeed(SEED, COIN_TYPE, ACCOUNT)
|
|
343
|
+
const other = IncomingViewingKeyWASM.fromSeed(SEED, COIN_TYPE, 1)
|
|
344
|
+
|
|
345
|
+
expect(ivk.diversifierIndex(other.address())).toBeNull()
|
|
346
|
+
})
|
|
347
|
+
})
|
|
172
348
|
})
|
|
173
349
|
|
|
174
350
|
describe('Note', function () {
|