UNPKG

arweave-stream-tx

Version:

[![npm](https://img.shields.io/npm/v/arweave-stream-tx)](https://www.npmjs.com/package/arweave-stream-tx) [![tests](https://github.com/CDDelta/arweave-stream-tx/workflows/tests/badge.svg)](https://github.com/CDDelta/arweave-stream-tx/actions?query=workflo

93 lines (92 loc) 5.13 kB
"use strict"; var __asyncValues = (this && this.__asyncValues) || function (o) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var m = o[Symbol.asyncIterator], i; return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.generateTransactionChunksAsync = void 0; const arweave_1 = __importDefault(require("arweave")); const merkle_1 = require("arweave/node/lib/merkle"); const promises_1 = require("stream/promises"); const common_1 = require("./common"); /** * Generates the Arweave transaction chunk information from the piped data stream. */ function generateTransactionChunksAsync() { return async (source) => { const chunks = []; /** * @param chunkByteIndex the index the start of the specified chunk is located at within its original data stream. */ async function addChunk(chunkByteIndex, chunk) { const dataHash = await arweave_1.default.crypto.hash(chunk); const chunkRep = { dataHash, minByteRange: chunkByteIndex, maxByteRange: chunkByteIndex + chunk.byteLength, }; chunks.push(chunkRep); return chunkRep; } let chunkStreamByteIndex = 0; let previousDataChunk; let expectChunkGenerationCompleted = false; await promises_1.pipeline(source, common_1.chunker(merkle_1.MAX_CHUNK_SIZE, { flush: true }), async (chunkedSource) => { var e_1, _a; try { for (var chunkedSource_1 = __asyncValues(chunkedSource), chunkedSource_1_1; chunkedSource_1_1 = await chunkedSource_1.next(), !chunkedSource_1_1.done;) { const chunk = chunkedSource_1_1.value; if (expectChunkGenerationCompleted) { throw Error('Expected chunk generation to have completed.'); } if (chunk.byteLength >= merkle_1.MIN_CHUNK_SIZE && chunk.byteLength <= merkle_1.MAX_CHUNK_SIZE) { await addChunk(chunkStreamByteIndex, chunk); } else if (chunk.byteLength < merkle_1.MIN_CHUNK_SIZE) { if (previousDataChunk) { // If this final chunk is smaller than the minimum chunk size, rebalance this final chunk and // the previous chunk to keep the final chunk size above the minimum threshold. const remainingBytes = Buffer.concat([previousDataChunk, chunk], previousDataChunk.byteLength + chunk.byteLength); const rebalancedSizeForPreviousChunk = Math.ceil(remainingBytes.byteLength / 2); const previousChunk = chunks.pop(); const rebalancedPreviousChunk = await addChunk(previousChunk.minByteRange, remainingBytes.slice(0, rebalancedSizeForPreviousChunk)); await addChunk(rebalancedPreviousChunk.maxByteRange, remainingBytes.slice(rebalancedSizeForPreviousChunk)); } else { // This entire stream should be smaller than the minimum chunk size, just add the chunk in. await addChunk(chunkStreamByteIndex, chunk); } expectChunkGenerationCompleted = true; } else if (chunk.byteLength > merkle_1.MAX_CHUNK_SIZE) { throw Error('Encountered chunk larger than max chunk size.'); } chunkStreamByteIndex += chunk.byteLength; previousDataChunk = chunk; } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (chunkedSource_1_1 && !chunkedSource_1_1.done && (_a = chunkedSource_1.return)) await _a.call(chunkedSource_1); } finally { if (e_1) throw e_1.error; } } }); const leaves = await merkle_1.generateLeaves(chunks); const root = await merkle_1.buildLayers(leaves); const proofs = merkle_1.generateProofs(root); return { data_root: root.id, chunks, proofs, }; }; } exports.generateTransactionChunksAsync = generateTransactionChunksAsync;