@tootallnate/ivfc 0.0.0 → 0.0.2
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/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +13 -0
- package/dist/index.js +19 -7
- package/dist/index.js.map +1 -1
- package/package.json +11 -6
- package/src/index.ts +20 -7
package/.turbo/turbo-build.log
CHANGED
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# @tootallnate/ivfc
|
|
2
|
+
|
|
3
|
+
## 0.0.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- e49c0ff: Optimize IVFC hash tree building by batching all per-level SHA-256 block hashes via `Promise.all` instead of sequential awaits, and skip redundant zero-fill for full blocks
|
|
8
|
+
|
|
9
|
+
## 0.0.1
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 1baf3af: Set up npm OIDC trusted publishing with provenance
|
package/dist/index.js
CHANGED
|
@@ -44,6 +44,9 @@ async function sha256(data, crypto = globalThis.crypto) {
|
|
|
44
44
|
/**
|
|
45
45
|
* Create an IVFC level: hash each block of the source data with SHA-256.
|
|
46
46
|
* Returns the hash data padded to the IVFC block size boundary.
|
|
47
|
+
*
|
|
48
|
+
* Optimized: hashes all blocks in parallel via Promise.all to reduce
|
|
49
|
+
* per-block async overhead, and avoids redundant zero-fill for full blocks.
|
|
47
50
|
*/
|
|
48
51
|
async function createLevel(sourceData, crypto = globalThis.crypto) {
|
|
49
52
|
const blockSize = IVFC_HASH_BLOCK_SIZE;
|
|
@@ -54,17 +57,26 @@ async function createLevel(sourceData, crypto = globalThis.crypto) {
|
|
|
54
57
|
// Pad to block size boundary
|
|
55
58
|
const paddedSize = align(hashDataSize, blockSize);
|
|
56
59
|
const hashes = new Uint8Array(paddedSize);
|
|
57
|
-
// Hash
|
|
58
|
-
const
|
|
60
|
+
// Hash all blocks in parallel
|
|
61
|
+
const hashPromises = [];
|
|
59
62
|
for (let i = 0; i < numBlocks; i++) {
|
|
60
63
|
const offset = i * blockSize;
|
|
61
64
|
const remaining = sourceSize - offset;
|
|
62
65
|
const readSize = Math.min(remaining, blockSize);
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
if (readSize === blockSize) {
|
|
67
|
+
// Full block — hash the subarray directly (no copy needed)
|
|
68
|
+
hashPromises.push(sha256(sourceData.subarray(offset, offset + blockSize), crypto));
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
// Partial (last) block — zero-pad a copy
|
|
72
|
+
const block = new Uint8Array(blockSize);
|
|
73
|
+
block.set(sourceData.subarray(offset, offset + readSize));
|
|
74
|
+
hashPromises.push(sha256(block.subarray(0, readSize), crypto));
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const hashResults = await Promise.all(hashPromises);
|
|
78
|
+
for (let i = 0; i < numBlocks; i++) {
|
|
79
|
+
hashes.set(hashResults[i], i * HASH_SIZE);
|
|
68
80
|
}
|
|
69
81
|
return { hashes, hashDataSize };
|
|
70
82
|
}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,wDAAwD;AACxD,MAAM,CAAC,MAAM,oBAAoB,GAAG,MAAM,CAAC;AAE3C,uDAAuD;AACvD,MAAM,eAAe,GAAG,CAAC,CAAC;AAE1B,yBAAyB;AACzB,MAAM,UAAU,GAAG,UAAU,CAAC;AAE9B,8BAA8B;AAC9B,MAAM,OAAO,GAAG,OAAO,CAAC;AAExB,wBAAwB;AACxB,MAAM,SAAS,GAAG,IAAI,CAAC;AAEvB,mCAAmC;AACnC,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC;AAErC;;GAEG;AACH,SAAS,KAAK,CAAC,KAAa,EAAE,SAAiB;IAC9C,MAAM,IAAI,GAAG,SAAS,GAAG,CAAC,CAAC;IAC3B,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;AAC/B,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,MAAM,CACpB,IAAgB,EAChB,SAAiB,UAAU,CAAC,MAAM;IAElC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACzD,OAAO,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC;AAC7B,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,17 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tootallnate/ivfc",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "IVFC (Integrity Verification File Collection) hash tree builder for Nintendo Switch",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
|
-
"scripts": {
|
|
8
|
-
"build": "tsc",
|
|
9
|
-
"test": "vitest run"
|
|
10
|
-
},
|
|
11
7
|
"keywords": [],
|
|
12
8
|
"author": "Nathan Rajlich <n@n8.io>",
|
|
13
9
|
"license": "MIT",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/TooTallNate/switch-tools",
|
|
13
|
+
"directory": "packages/ivfc"
|
|
14
|
+
},
|
|
14
15
|
"devDependencies": {
|
|
15
16
|
"typescript": "^5.3.3"
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc",
|
|
20
|
+
"test": "vitest run"
|
|
16
21
|
}
|
|
17
|
-
}
|
|
22
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -56,6 +56,9 @@ async function sha256(
|
|
|
56
56
|
/**
|
|
57
57
|
* Create an IVFC level: hash each block of the source data with SHA-256.
|
|
58
58
|
* Returns the hash data padded to the IVFC block size boundary.
|
|
59
|
+
*
|
|
60
|
+
* Optimized: hashes all blocks in parallel via Promise.all to reduce
|
|
61
|
+
* per-block async overhead, and avoids redundant zero-fill for full blocks.
|
|
59
62
|
*/
|
|
60
63
|
async function createLevel(
|
|
61
64
|
sourceData: Uint8Array,
|
|
@@ -72,19 +75,29 @@ async function createLevel(
|
|
|
72
75
|
const paddedSize = align(hashDataSize, blockSize);
|
|
73
76
|
const hashes = new Uint8Array(paddedSize);
|
|
74
77
|
|
|
75
|
-
// Hash
|
|
76
|
-
const
|
|
78
|
+
// Hash all blocks in parallel
|
|
79
|
+
const hashPromises: Promise<Uint8Array>[] = [];
|
|
77
80
|
for (let i = 0; i < numBlocks; i++) {
|
|
78
81
|
const offset = i * blockSize;
|
|
79
82
|
const remaining = sourceSize - offset;
|
|
80
83
|
const readSize = Math.min(remaining, blockSize);
|
|
81
84
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
+
if (readSize === blockSize) {
|
|
86
|
+
// Full block — hash the subarray directly (no copy needed)
|
|
87
|
+
hashPromises.push(
|
|
88
|
+
sha256(sourceData.subarray(offset, offset + blockSize), crypto)
|
|
89
|
+
);
|
|
90
|
+
} else {
|
|
91
|
+
// Partial (last) block — zero-pad a copy
|
|
92
|
+
const block = new Uint8Array(blockSize);
|
|
93
|
+
block.set(sourceData.subarray(offset, offset + readSize));
|
|
94
|
+
hashPromises.push(sha256(block.subarray(0, readSize), crypto));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
85
97
|
|
|
86
|
-
|
|
87
|
-
|
|
98
|
+
const hashResults = await Promise.all(hashPromises);
|
|
99
|
+
for (let i = 0; i < numBlocks; i++) {
|
|
100
|
+
hashes.set(hashResults[i], i * HASH_SIZE);
|
|
88
101
|
}
|
|
89
102
|
|
|
90
103
|
return { hashes, hashDataSize };
|