/** *** Copyright (c) 2016-2019, Jaguar0625, gimre, BloodyRookie, Tech Bureau, Corp. *** Copyright (c) 2020-present, Jaguar0625, gimre, BloodyRookie. *** All rights reserved. *** *** This file is part of Catapult. *** *** Catapult is free software: you can redistribute it and/or modify *** it under the terms of the GNU Lesser General Public License as published by *** the Free Software Foundation, either version 3 of the License, or *** (at your option) any later version. *** *** Catapult is distributed in the hope that it will be useful, *** but WITHOUT ANY WARRANTY; without even the implied warranty of *** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *** GNU Lesser General Public License for more details. *** *** You should have received a copy of the GNU Lesser General Public License *** along with Catapult. If not, see . **/ import { CosignatureBuilder } from './CosignatureBuilder'; import { EmbeddedTransactionBuilder } from './EmbeddedTransactionBuilder'; import { EmbeddedTransactionHelper } from './EmbeddedTransactionHelper'; import { GeneratorUtils } from './GeneratorUtils'; import { Hash256Dto } from './Hash256Dto'; import { Serializer } from './Serializer'; /** * Shared content between AggregateCompleteTransaction and AggregateBondedTransaction. **/ export class AggregateTransactionBodyBuilder implements Serializer { /** Hash of the aggregate's transaction.. **/ readonly transactionsHash: Hash256Dto; /** Embedded transaction data. Transactions are variable-sized and the total payload size is in bytes. Embedded transactions cannot be aggregates.. **/ readonly transactions: EmbeddedTransactionBuilder[]; /** Cosignatures data. Fills up remaining body space after transactions.. **/ readonly cosignatures: CosignatureBuilder[]; /** * Constructor. * * @param transactionsHash Hash of the aggregate's transaction.. * @param transactions Embedded transaction data. Transactions are variable-sized and the total payload size is in bytes. Embedded transactions cannot be aggregates.. * @param cosignatures Cosignatures data. Fills up remaining body space after transactions.. */ public constructor(transactionsHash: Hash256Dto, transactions: EmbeddedTransactionBuilder[], cosignatures: CosignatureBuilder[]) { GeneratorUtils.notNull(transactionsHash, 'transactionsHash is null or undefined'); GeneratorUtils.notNull(transactions, 'transactions is null or undefined'); GeneratorUtils.notNull(cosignatures, 'cosignatures is null or undefined'); this.transactionsHash = transactionsHash; this.transactions = transactions; this.cosignatures = cosignatures; } /** * Load from binary array - Creates an object from payload. * * @param payload - Byte payload to use to serialize the object. */ public static loadFromBinary(payload: Uint8Array): AggregateTransactionBodyBuilder { const byteArray = Array.from(payload); const transactionsHash: Hash256Dto = Hash256Dto.loadFromBinary(Uint8Array.from(byteArray)); byteArray.splice(0, transactionsHash.getSize()); const payloadSize: number = GeneratorUtils.bufferToUint32(Uint8Array.from(byteArray)); byteArray.splice(0, 4); GeneratorUtils.bufferToUint32(Uint8Array.from(byteArray)); byteArray.splice(0, 4); const transactions: EmbeddedTransactionBuilder[] = GeneratorUtils.loadFromBinaryRemaining( EmbeddedTransactionHelper.loadFromBinary, Uint8Array.from(byteArray), payloadSize, 8, ); byteArray.splice( 0, transactions.reduce((sum, c) => sum + GeneratorUtils.getSizeWithPadding(c.getSize(), 8), 0), ); const cosignatures: CosignatureBuilder[] = GeneratorUtils.loadFromBinaryRemaining( CosignatureBuilder.loadFromBinary, Uint8Array.from(byteArray), byteArray.length, 0, ); byteArray.splice( 0, cosignatures.reduce((sum, c) => sum + GeneratorUtils.getSizeWithPadding(c.getSize(), 0), 0), ); return new AggregateTransactionBodyBuilder(transactionsHash, transactions, cosignatures); } /** * Creates an instance of AggregateTransactionBodyBuilder. * * @param transactionsHash Hash of the aggregate's transaction.. * @param transactions Embedded transaction data. Transactions are variable-sized and the total payload size is in bytes. Embedded transactions cannot be aggregates.. * @param cosignatures Cosignatures data. Fills up remaining body space after transactions.. * @return Instance of AggregateTransactionBodyBuilder. */ public static createAggregateTransactionBodyBuilder( transactionsHash: Hash256Dto, transactions: EmbeddedTransactionBuilder[], cosignatures: CosignatureBuilder[], ): AggregateTransactionBodyBuilder { return new AggregateTransactionBodyBuilder(transactionsHash, transactions, cosignatures); } /** * Gets Hash of the aggregate's transaction.. * * @return Hash of the aggregate's transaction.. */ public getTransactionsHash(): Hash256Dto { return this.transactionsHash; } /** * Gets Embedded transaction data. Transactions are variable-sized and the total payload size is in bytes. Embedded transactions cannot be aggregates.. * * @return Embedded transaction data. Transactions are variable-sized and the total payload size is in bytes. Embedded transactions cannot be aggregates.. */ public getTransactions(): EmbeddedTransactionBuilder[] { return this.transactions; } /** * Gets Cosignatures data. Fills up remaining body space after transactions.. * * @return Cosignatures data. Fills up remaining body space after transactions.. */ public getCosignatures(): CosignatureBuilder[] { return this.cosignatures; } /** * Gets the size of the object. * * @return Size in bytes. */ public getSize(): number { let size = 0; size += this.transactionsHash.getSize(); // transactionsHash size += 4; // payloadSize size += 4; // aggregateTransactionHeaderReserved1 size += this.transactions.reduce((sum, c) => sum + GeneratorUtils.getSizeWithPadding(c.getSize(), 8), 0); // transactions size += this.cosignatures.reduce((sum, c) => sum + GeneratorUtils.getSizeWithPadding(c.getSize(), 0), 0); // cosignatures return size; } /** * Serializes an object to bytes. * * @return Serialized bytes. */ public serialize(): Uint8Array { let newArray = Uint8Array.from([]); const transactionsHashBytes = this.transactionsHash.serialize(); newArray = GeneratorUtils.concatTypedArrays(newArray, transactionsHashBytes); const payloadSize = this.transactions.reduce((sum, c) => sum + GeneratorUtils.getSizeWithPadding(c.getSize(), 8), 0); const payloadSizeBytes = GeneratorUtils.uint32ToBuffer(payloadSize); newArray = GeneratorUtils.concatTypedArrays(newArray, payloadSizeBytes); const aggregateTransactionHeaderReserved1Bytes = GeneratorUtils.uint32ToBuffer(0); newArray = GeneratorUtils.concatTypedArrays(newArray, aggregateTransactionHeaderReserved1Bytes); const transactionsBytes = GeneratorUtils.writeList(this.transactions, 8); newArray = GeneratorUtils.concatTypedArrays(newArray, transactionsBytes); const cosignaturesBytes = GeneratorUtils.writeList(this.cosignatures, 0); newArray = GeneratorUtils.concatTypedArrays(newArray, cosignaturesBytes); return newArray; } }