@web3-storage/data-segment
Advanced tools
Comparing version 1.0.1 to 2.0.0-dev
@@ -48,5 +48,16 @@ /** | ||
} | ||
export interface AggreateState { | ||
capacity: number; | ||
offset: number; | ||
parts: MerkleTreeNodeSource[]; | ||
} | ||
export interface Vector<T> extends Iterable<T> { | ||
append(value: T): Vector<T>; | ||
} | ||
export type PaddedPieceSize = New<{ | ||
PaddedPieceSize: number; | ||
}>; | ||
export type UnpaddedPieceSize = New<{ | ||
UnpaddedPieceSize: number; | ||
}>; | ||
export type Fr23Padded = New<{ | ||
@@ -56,10 +67,4 @@ Fr23Padded: Uint8Array; | ||
export interface IndexData { | ||
entries: SegmentDescriptor[]; | ||
entries: SegmentInfo[]; | ||
} | ||
export interface SegmentDescriptor { | ||
commDs: MerkleTreeNode; | ||
offset: number; | ||
size: number; | ||
checksum: Uint8Array; | ||
} | ||
export interface MerkleTree { | ||
@@ -72,2 +77,61 @@ depth: number; | ||
} | ||
export interface PieceInfo { | ||
/** | ||
* Commitment to the data segment (Merkle node which is the root of the | ||
* subtree containing all the nodes making up the data segment) | ||
*/ | ||
root: MerkleTreeNode; | ||
/** | ||
* Offset is the offset from the start of the deal in padded bytes | ||
*/ | ||
size: PaddedPieceSize; | ||
} | ||
export interface Segment { | ||
/** | ||
* Commitment to the data segment (Merkle node which is the root of the | ||
* subtree containing all the nodes making up the data segment) | ||
*/ | ||
root: MerkleTreeNode; | ||
/** | ||
* Offset is the offset from the start of the deal in padded bytes | ||
*/ | ||
offset: number; | ||
/** | ||
* Size is the number of padded bytes that is contained in the sub-deal | ||
* reflected by this segment. | ||
*/ | ||
size: number; | ||
} | ||
/** | ||
* Segment contains a data segment description to be contained as two Fr32 | ||
* elements in 2 leaf nodes of the data segment index. | ||
*/ | ||
export interface SegmentInfo extends Segment { | ||
/** | ||
* Checksum is a 126 bit checksum (SHA256) computes on `[...root, offset, size]` | ||
*/ | ||
checksum: Checksum<Segment, 16>; | ||
} | ||
export type Checksum<Payload = unknown, Size extends number = number> = New<{ | ||
Checksum: SizedUint8Array<number>; | ||
}, Payload>; | ||
export type SizedUint8Array<Size extends number> = New<{ | ||
SizedUint8Array: Uint8Array & { | ||
length: Size; | ||
}; | ||
}>; | ||
/** | ||
* Represents a location in a Merkle tree. | ||
*/ | ||
export interface MerkleTreeLocation { | ||
level: number; | ||
index: number; | ||
} | ||
/** | ||
* Represents a commitment and its location in a Merkle tree. | ||
*/ | ||
export interface MerkleTreeNodeSource { | ||
node: MerkleTreeNode; | ||
location: MerkleTreeLocation; | ||
} | ||
export interface MerkleProof { | ||
@@ -74,0 +138,0 @@ /** |
@@ -1,3 +0,4 @@ | ||
export function build(source: Uint8Array): Promise<CommP>; | ||
export function build(source: Uint8Array): CommP; | ||
export function toCID(root: Uint8Array): Link.Link<unknown, 61697, 4114, 1>; | ||
export function fromLink(cid: Link.Link): API.MerkleTreeNode; | ||
declare class CommP { | ||
@@ -15,2 +16,3 @@ /** | ||
tree: API.MerkleTree; | ||
get root(): API.MerkleTreeNode; | ||
get paddedSize(): number; | ||
@@ -17,0 +19,0 @@ get pieceSize(): number; |
export const Size: 32; | ||
export function of(...bytes: number[]): API.MerkleTreeNode; | ||
export function from(bytes: Iterable<number>): API.MerkleTreeNode; | ||
export function empty(): API.MerkleTreeNode; | ||
export function isEmpty(node: API.MerkleTreeNode): boolean; | ||
import * as API from './api.js'; | ||
//# sourceMappingURL=node.d.ts.map |
@@ -5,5 +5,5 @@ /** | ||
* @param {API.ProofData} proofData | ||
* @returns {Promise<API.Result<void, Error>>} | ||
* @returns {API.Result<void, Error>} | ||
*/ | ||
export function validateLeaf(data: Uint8Array, root: API.MerkleTreeNode, proofData: API.ProofData): Promise<API.Result<void, Error>>; | ||
export function validateLeaf(data: Uint8Array, root: API.MerkleTreeNode, proofData: API.ProofData): API.Result<void, Error>; | ||
/** | ||
@@ -13,11 +13,11 @@ * @param {API.MerkleTreeNode} subtree | ||
* @param {API.ProofData} proofData | ||
* @returns {Promise<API.Result<void, Error>>} | ||
* @returns {API.Result<void, Error>} | ||
*/ | ||
export function validateSubtree(subtree: API.MerkleTreeNode, root: API.MerkleTreeNode, proofData: API.ProofData): Promise<API.Result<void, Error>>; | ||
export function validateSubtree(subtree: API.MerkleTreeNode, root: API.MerkleTreeNode, proofData: API.ProofData): API.Result<void, Error>; | ||
/** | ||
* @param {API.MerkleTreeNode} subtree | ||
* @param {API.ProofData} proofData | ||
* @returns {Promise<API.Result<API.MerkleTreeNode, Error>>} | ||
* @returns {API.Result<API.MerkleTreeNode, Error>} | ||
*/ | ||
export function computeRoot(subtree: API.MerkleTreeNode, proofData: API.ProofData): Promise<API.Result<API.MerkleTreeNode, Error>>; | ||
export function computeRoot(subtree: API.MerkleTreeNode, proofData: API.ProofData): API.Result<API.MerkleTreeNode, Error>; | ||
/** | ||
@@ -27,5 +27,5 @@ * @param {API.MerkleTreeNode} subtree | ||
* @param {API.ProofData} proofData | ||
* @returns {Promise<API.Result<void, Error>>} | ||
* @returns {API.Result<void, Error>} | ||
*/ | ||
export function validateProof(subtree: API.MerkleTreeNode, root: API.MerkleTreeNode, proofData: API.ProofData): Promise<API.Result<void, Error>>; | ||
export function validateProof(subtree: API.MerkleTreeNode, root: API.MerkleTreeNode, proofData: API.ProofData): API.Result<void, Error>; | ||
/** | ||
@@ -38,5 +38,5 @@ * @param {API.ProofData} proofData | ||
* @param {Uint8Array} payload | ||
* @returns {Promise<API.MerkleTreeNode>} | ||
* @returns {API.MerkleTreeNode} | ||
*/ | ||
export function truncatedHash(payload: Uint8Array): Promise<API.MerkleTreeNode>; | ||
export function truncatedHash(payload: Uint8Array): API.MerkleTreeNode; | ||
/** | ||
@@ -48,4 +48,4 @@ * @param {API.MerkleTreeNode} node | ||
export function depth(proofData: API.ProofData): number; | ||
export function computeNode(left: API.MerkleTreeNode, right: API.MerkleTreeNode): Promise<API.MerkleTreeNode>; | ||
export function computeNode(left: API.MerkleTreeNode, right: API.MerkleTreeNode): API.MerkleTreeNode; | ||
import * as API from './api.js'; | ||
//# sourceMappingURL=proof.d.ts.map |
@@ -16,5 +16,5 @@ /** | ||
export function split(source: Uint8Array): API.MerkleTreeNode[]; | ||
export function compile(source: API.Fr23Padded): Promise<API.MerkleTree>; | ||
export function buildFromChunks(chunks: API.MerkleTreeNode[]): Promise<API.MerkleTree>; | ||
export function buildFromLeafs(leafs: API.MerkleTreeNode[]): Promise<API.MerkleTree>; | ||
export function compile(source: API.Fr23Padded): API.MerkleTree; | ||
export function buildFromChunks(chunks: API.MerkleTreeNode[]): API.MerkleTree; | ||
export function buildFromLeafs(leafs: API.MerkleTreeNode[]): API.MerkleTree; | ||
export function padLeafs(leafs: API.MerkleTreeNode[]): API.MerkleTreeNode[]; | ||
@@ -21,0 +21,0 @@ import * as API from './api.js'; |
{ | ||
"name": "@web3-storage/data-segment", | ||
"description": "Implementation of [FRC-0058](https://github.com/filecoin-project/FIPs/blob/master/FRCs/frc-0058.md) verifiable aggregation scheme", | ||
"version": "1.0.1", | ||
"version": "2.0.0-dev", | ||
"keywords": [ | ||
@@ -26,2 +26,3 @@ "FRC-0058", | ||
"dependencies": { | ||
"@noble/hashes": "^1.3.1", | ||
"multiformats": "^11.0.2" | ||
@@ -34,3 +35,3 @@ }, | ||
"@types/node": "20.2.3", | ||
"c8": "^7.13.0", | ||
"c8": "^7.14.0", | ||
"chai": "^4.3.7", | ||
@@ -41,3 +42,3 @@ "mocha": "^10.2.0", | ||
"prettier": "2.8.8", | ||
"typescript": "^5.0.4" | ||
"typescript": "^5.1.3" | ||
}, | ||
@@ -44,0 +45,0 @@ "type": "module", |
@@ -51,3 +51,14 @@ /** | ||
export interface AggreateState { | ||
capacity: number | ||
offset: number | ||
parts: MerkleTreeNodeSource[] | ||
} | ||
export interface Vector<T> extends Iterable<T> { | ||
append(value: T): Vector<T> | ||
} | ||
export type PaddedPieceSize = New<{ PaddedPieceSize: number }> | ||
export type UnpaddedPieceSize = New<{ UnpaddedPieceSize: number }> | ||
@@ -57,12 +68,5 @@ export type Fr23Padded = New<{ Fr23Padded: Uint8Array }> | ||
export interface IndexData { | ||
entries: SegmentDescriptor[] | ||
entries: SegmentInfo[] | ||
} | ||
export interface SegmentDescriptor { | ||
commDs: MerkleTreeNode | ||
offset: number | ||
size: number | ||
checksum: Uint8Array | ||
} | ||
export interface MerkleTree { | ||
@@ -77,2 +81,68 @@ depth: number | ||
export interface PieceInfo { | ||
/** | ||
* Commitment to the data segment (Merkle node which is the root of the | ||
* subtree containing all the nodes making up the data segment) | ||
*/ | ||
root: MerkleTreeNode | ||
/** | ||
* Offset is the offset from the start of the deal in padded bytes | ||
*/ | ||
size: PaddedPieceSize | ||
} | ||
export interface Segment { | ||
/** | ||
* Commitment to the data segment (Merkle node which is the root of the | ||
* subtree containing all the nodes making up the data segment) | ||
*/ | ||
root: MerkleTreeNode | ||
/** | ||
* Offset is the offset from the start of the deal in padded bytes | ||
*/ | ||
offset: number | ||
/** | ||
* Size is the number of padded bytes that is contained in the sub-deal | ||
* reflected by this segment. | ||
*/ | ||
size: number | ||
} | ||
/** | ||
* Segment contains a data segment description to be contained as two Fr32 | ||
* elements in 2 leaf nodes of the data segment index. | ||
*/ | ||
export interface SegmentInfo extends Segment { | ||
/** | ||
* Checksum is a 126 bit checksum (SHA256) computes on `[...root, offset, size]` | ||
*/ | ||
checksum: Checksum<Segment, 16> | ||
} | ||
export type Checksum<Payload = unknown, Size extends number = number> = New< | ||
{ Checksum: SizedUint8Array<number> }, | ||
Payload | ||
> | ||
export type SizedUint8Array<Size extends number> = New<{ | ||
SizedUint8Array: Uint8Array & { length: Size } | ||
}> | ||
/** | ||
* Represents a location in a Merkle tree. | ||
*/ | ||
export interface MerkleTreeLocation { | ||
level: number | ||
index: number | ||
} | ||
/** | ||
* Represents a commitment and its location in a Merkle tree. | ||
*/ | ||
export interface MerkleTreeNodeSource { | ||
node: MerkleTreeNode | ||
location: MerkleTreeLocation | ||
} | ||
export interface MerkleProof { | ||
@@ -79,0 +149,0 @@ /** |
@@ -36,3 +36,3 @@ import * as API from './api.js' | ||
*/ | ||
export const build = async (source) => { | ||
export const build = (source) => { | ||
if (source.byteLength < Fr32.MIN_PIECE_SIZE) { | ||
@@ -44,3 +44,3 @@ throw new RangeError( | ||
const tree = await Tree.compile(Fr32.pad(source)) | ||
const tree = Tree.compile(Fr32.pad(source)) | ||
@@ -73,2 +73,5 @@ return new CommP({ tree, size: source.byteLength }) | ||
} | ||
get root() { | ||
return this.tree.root | ||
} | ||
get paddedSize() { | ||
@@ -92,1 +95,16 @@ return Fr32.toZeroPaddedSize(this.size) | ||
} | ||
/** | ||
* @param {Link.Link} cid | ||
* @returns {API.MerkleTreeNode} | ||
*/ | ||
export const fromLink = (cid) => { | ||
const { code, multihash } = cid | ||
if (code !== FilCommitmentUnsealed) { | ||
throw new RangeError( | ||
`Invalid CID code ${code}, expected ${FilCommitmentUnsealed}` | ||
) | ||
} | ||
return multihash.digest | ||
} |
@@ -28,1 +28,25 @@ import * as API from './api.js' | ||
} | ||
export const empty = () => EMPTY | ||
/** | ||
* | ||
* @param {API.MerkleTreeNode} node | ||
* @returns | ||
*/ | ||
export const isEmpty = (node) => { | ||
if (node === EMPTY) { | ||
return true | ||
} else if (node.length === Size) { | ||
for (const byte of node) { | ||
if (byte !== 0) { | ||
return false | ||
} | ||
} | ||
return true | ||
} | ||
return false | ||
} | ||
const EMPTY = from(new Uint8Array(Size).fill(0)) | ||
Object.freeze(EMPTY.buffer) |
import * as API from './api.js' | ||
import { sha256 } from 'multiformats/hashes/sha2' | ||
// import { sha256 } from 'multiformats/hashes/sha2' | ||
import { sha256 } from '@noble/hashes/sha256' | ||
import { Size as NodeSize } from './node.js' | ||
@@ -17,7 +18,7 @@ | ||
* @param {API.ProofData} proofData | ||
* @returns {Promise<API.Result<void, Error>>} | ||
* @returns {API.Result<void, Error>} | ||
*/ | ||
export async function validateLeaf(data, root, proofData) { | ||
const leaf = await truncatedHash(data) | ||
return await validateSubtree(leaf, root, proofData) | ||
export function validateLeaf(data, root, proofData) { | ||
const leaf = truncatedHash(data) | ||
return validateSubtree(leaf, root, proofData) | ||
} | ||
@@ -29,5 +30,5 @@ | ||
* @param {API.ProofData} proofData | ||
* @returns {Promise<API.Result<void, Error>>} | ||
* @returns {API.Result<void, Error>} | ||
*/ | ||
export async function validateSubtree(subtree, root, proofData) { | ||
export function validateSubtree(subtree, root, proofData) { | ||
// Validate the structure first to avoid panics | ||
@@ -42,3 +43,3 @@ const structureValidation = validateProofStructure(proofData) | ||
} | ||
return await validateProof(subtree, root, proofData) | ||
return validateProof(subtree, root, proofData) | ||
} | ||
@@ -51,5 +52,5 @@ | ||
* @param {API.ProofData} proofData | ||
* @returns {Promise<API.Result<API.MerkleTreeNode, Error>>} | ||
* @returns {API.Result<API.MerkleTreeNode, Error>} | ||
*/ | ||
export async function computeRoot(subtree, proofData) { | ||
export function computeRoot(subtree, proofData) { | ||
if (subtree === null) { | ||
@@ -75,4 +76,3 @@ return { error: new Error('nil subtree cannot be used') } | ||
;[right, index] = [index & 1, index >> 1] | ||
carry = | ||
right === 1 ? await computeNode(p, carry) : await computeNode(carry, p) | ||
carry = right === 1 ? computeNode(p, carry) : computeNode(carry, p) | ||
} | ||
@@ -87,6 +87,6 @@ | ||
* @param {API.ProofData} proofData | ||
* @returns {Promise<API.Result<void, Error>>} | ||
* @returns {API.Result<void, Error>} | ||
*/ | ||
export async function validateProof(subtree, root, proofData) { | ||
const computedRoot = await computeRoot(subtree, proofData) | ||
export function validateProof(subtree, root, proofData) { | ||
const computedRoot = computeRoot(subtree, proofData) | ||
if (computedRoot.error) { | ||
@@ -119,6 +119,6 @@ return { error: new Error(`computing root: ${computedRoot.error.message}`) } | ||
* @param {Uint8Array} payload | ||
* @returns {Promise<API.MerkleTreeNode>} | ||
* @returns {API.MerkleTreeNode} | ||
*/ | ||
export async function truncatedHash(payload) { | ||
const { digest } = await sha256.digest(payload) | ||
export function truncatedHash(payload) { | ||
const digest = sha256(payload) | ||
return truncate(digest) | ||
@@ -130,3 +130,3 @@ } | ||
* @param {API.MerkleTreeNode} right | ||
* @returns {Promise<API.MerkleTreeNode>} | ||
* @returns {API.MerkleTreeNode} | ||
*/ | ||
@@ -133,0 +133,0 @@ export const computeNode = (left, right) => { |
@@ -70,3 +70,3 @@ import * as API from './api.js' | ||
*/ | ||
export const buildFromChunks = async (chunks) => { | ||
export const buildFromChunks = (chunks) => { | ||
if (chunks.length === 0) { | ||
@@ -77,3 +77,3 @@ throw new RangeError('Empty source') | ||
const leafs = chunks //await Promise.all(chunks.map(truncatedHash)) | ||
return await buildFromLeafs(leafs) | ||
return buildFromLeafs(leafs) | ||
} | ||
@@ -83,5 +83,5 @@ | ||
* @param {API.MerkleTreeNode[]} leafs | ||
* @returns {Promise<API.MerkleTree>} | ||
* @returns {API.MerkleTree} | ||
*/ | ||
export const buildFromLeafs = async (leafs) => { | ||
export const buildFromLeafs = (leafs) => { | ||
const tree = newBareTree(leafs.length) | ||
@@ -98,3 +98,3 @@ // Set the padded leaf nodes | ||
for (let i = 0; i + 1 < parentNodes.length; i = i + 2) { | ||
currentLevel[Math.floor(i / 2)] = await Proof.computeNode( | ||
currentLevel[Math.floor(i / 2)] = Proof.computeNode( | ||
parentNodes[i], | ||
@@ -101,0 +101,0 @@ parentNodes[i + 1] |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
86985
57
2282
2
1
1
1
+ Added@noble/hashes@^1.3.1
+ Added@noble/hashes@1.7.1(transitive)