"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.downloadSingleOwnerChunk = exports.uploadSingleOwnerChunkData = exports.uploadSingleOwnerChunk = exports.makeSingleOwnerChunk = exports.makeSOCAddress = exports.makeSingleOwnerChunkFromData = void 0; const bytes_1 = require("../utils/bytes"); const bmt_1 = require("./bmt"); const signer_1 = require("./signer"); const hash_1 = require("../utils/hash"); const span_1 = require("./span"); const serialize_1 = require("./serialize"); const error_1 = require("../utils/error"); const cac_1 = require("./cac"); const hex_1 = require("../utils/hex"); const socAPI = __importStar(require("../modules/soc")); const chunkAPI = __importStar(require("../modules/chunk")); const type_1 = require("../utils/type"); const IDENTIFIER_SIZE = 32; const SIGNATURE_SIZE = 65; const SOC_IDENTIFIER_OFFSET = 0; const SOC_SIGNATURE_OFFSET = SOC_IDENTIFIER_OFFSET + IDENTIFIER_SIZE; const SOC_SPAN_OFFSET = SOC_SIGNATURE_OFFSET + SIGNATURE_SIZE; const SOC_PAYLOAD_OFFSET = SOC_SPAN_OFFSET + span_1.SPAN_SIZE; function recoverChunkOwner(data) { const cacData = data.slice(SOC_SPAN_OFFSET); const chunkAddress = (0, bmt_1.bmtHash)(cacData); const signature = (0, bytes_1.bytesAtOffset)(data, SOC_SIGNATURE_OFFSET, SIGNATURE_SIZE); const identifier = (0, bytes_1.bytesAtOffset)(data, SOC_IDENTIFIER_OFFSET, IDENTIFIER_SIZE); const digest = (0, hash_1.keccak256Hash)(identifier, chunkAddress); const ownerAddress = (0, signer_1.recoverAddress)(signature, digest); return ownerAddress; } /** * Verifies if the data is a valid single owner chunk * * @param data The chunk data * @param address The address of the single owner chunk * * @returns a single owner chunk or throws error */ function makeSingleOwnerChunkFromData(data, address) { const ownerAddress = recoverChunkOwner(data); const identifier = (0, bytes_1.bytesAtOffset)(data, SOC_IDENTIFIER_OFFSET, IDENTIFIER_SIZE); const socAddress = (0, hash_1.keccak256Hash)(identifier, ownerAddress); if (!(0, bytes_1.bytesEqual)(address, socAddress)) { throw new error_1.BeeError('SOC Data does not match given address!'); } const signature = () => (0, bytes_1.bytesAtOffset)(data, SOC_SIGNATURE_OFFSET, SIGNATURE_SIZE); const span = () => (0, bytes_1.bytesAtOffset)(data, SOC_SPAN_OFFSET, span_1.SPAN_SIZE); const payload = () => (0, bytes_1.flexBytesAtOffset)(data, SOC_PAYLOAD_OFFSET, cac_1.MIN_PAYLOAD_SIZE, cac_1.MAX_PAYLOAD_SIZE); return { data, identifier: () => identifier, signature, span, payload, address: () => socAddress, owner: () => ownerAddress, }; } exports.makeSingleOwnerChunkFromData = makeSingleOwnerChunkFromData; function makeSOCAddress(identifier, address) { return (0, hash_1.keccak256Hash)(identifier, address); } exports.makeSOCAddress = makeSOCAddress; /** * Creates a single owner chunk object * * @param chunk A chunk object used for the span and payload * @param identifier The identifier of the chunk * @param signer The singer interface for signing the chunk */ function makeSingleOwnerChunk(chunk, identifier, signer) { return __awaiter(this, void 0, void 0, function* () { const chunkAddress = chunk.address(); (0, cac_1.assertValidChunkData)(chunk.data, chunkAddress); const digest = (0, hash_1.keccak256Hash)(identifier, chunkAddress); const signature = yield (0, signer_1.sign)(signer, digest); const data = (0, serialize_1.serializeBytes)(identifier, signature, chunk.span(), chunk.payload()); const address = makeSOCAddress(identifier, signer.address); return { data, identifier: () => identifier, signature: () => signature, span: () => chunk.span(), payload: () => chunk.payload(), address: () => address, owner: () => signer.address, }; }); } exports.makeSingleOwnerChunk = makeSingleOwnerChunk; /** * Helper function to upload a chunk. * * It uses the Chunk API and calculates the address before uploading. * * @param ky Ky instance * @param chunk A chunk object * @param postageBatchId Postage BatchId that will be assigned to uploaded data * @param options Upload options */ function uploadSingleOwnerChunk(ky, chunk, postageBatchId, options) { return __awaiter(this, void 0, void 0, function* () { const owner = (0, hex_1.bytesToHex)(chunk.owner()); const identifier = (0, hex_1.bytesToHex)(chunk.identifier()); const signature = (0, hex_1.bytesToHex)(chunk.signature()); const data = (0, serialize_1.serializeBytes)(chunk.span(), chunk.payload()); return socAPI.upload(ky, owner, identifier, signature, data, postageBatchId, options); }); } exports.uploadSingleOwnerChunk = uploadSingleOwnerChunk; /** * Helper function to create and upload SOC. * * @param ky Ky instance * @param signer The singer interface for signing the chunk * @param postageBatchId * @param identifier The identifier of the chunk * @param data The chunk data * @param options */ function uploadSingleOwnerChunkData(ky, signer, postageBatchId, identifier, data, options) { return __awaiter(this, void 0, void 0, function* () { (0, type_1.assertAddress)(postageBatchId); const cac = (0, cac_1.makeContentAddressedChunk)(data); const soc = yield makeSingleOwnerChunk(cac, identifier, signer); return uploadSingleOwnerChunk(ky, soc, postageBatchId, options); }); } exports.uploadSingleOwnerChunkData = uploadSingleOwnerChunkData; /** * Helper function to download SOC. * * @param url The url of the Bee service * @param ownerAddress The singer interface for signing the chunk * @param identifier The identifier of the chunk */ function downloadSingleOwnerChunk(ky, ownerAddress, identifier) { return __awaiter(this, void 0, void 0, function* () { const address = makeSOCAddress(identifier, ownerAddress); const data = yield chunkAPI.download(ky, (0, hex_1.bytesToHex)(address)); return makeSingleOwnerChunkFromData(data, address); }); } exports.downloadSingleOwnerChunk = downloadSingleOwnerChunk;