var _a;
import { ClientIvcProof, Fr, PrivateKernelTailCircuitPublicInputs, PrivateLog, } from '@aztec/circuits.js';
import { Buffer32 } from '@aztec/foundation/buffer';
import { arraySerializedSizeOfNonEmpty } from '@aztec/foundation/collection';
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
import { z } from 'zod';
import { ContractClassTxL2Logs, UnencryptedTxL2Logs } from '../logs/tx_l2_logs.js';
import { Gossipable } from '../p2p/gossipable.js';
import { TopicType, createTopicString } from '../p2p/topic_type.js';
import { PublicExecutionRequest } from '../public_execution_request.js';
import { TxHash } from './tx_hash.js';
/**
 * The interface of an L2 transaction.
 */
export class Tx extends Gossipable {
    constructor(
    /**
     * Output of the private kernel circuit for this tx.
     */
    data, 
    /**
     * Proof from the private kernel circuit.
     * TODO(#7368): This client IVC object currently contains various VKs that will eventually be more like static data.
     *
     */
    clientIvcProof, 
    /**
     * Unencrypted logs generated by the tx.
     * NOTE: These do not get filled, but remain here so enqueued_calls_processor.ts can accumulate public logs
     */
    unencryptedLogs, 
    /**
     * Contract class logs generated by the tx.
     */
    contractClassLogs, 
    /**
     * Enqueued public functions from the private circuit to be run by the sequencer.
     */
    enqueuedPublicFunctionCalls, 
    /**
     * Public function call to be run by the sequencer as part of teardown.
     */
    publicTeardownFunctionCall) {
        super();
        this.data = data;
        this.clientIvcProof = clientIvcProof;
        this.unencryptedLogs = unencryptedLogs;
        this.contractClassLogs = contractClassLogs;
        this.enqueuedPublicFunctionCalls = enqueuedPublicFunctionCalls;
        this.publicTeardownFunctionCall = publicTeardownFunctionCall;
    }
    // Gossipable method
    p2pMessageIdentifier() {
        return new Buffer32(this.getTxHash().toBuffer());
    }
    hasPublicCalls() {
        return this.data.numberOfPublicCallRequests() > 0;
    }
    getNonRevertiblePublicExecutionRequests() {
        const numRevertible = this.data.numberOfRevertiblePublicCallRequests();
        return this.enqueuedPublicFunctionCalls.slice(numRevertible);
    }
    getRevertiblePublicExecutionRequests() {
        const numRevertible = this.data.numberOfRevertiblePublicCallRequests();
        return this.enqueuedPublicFunctionCalls.slice(0, numRevertible);
    }
    getPublicTeardownExecutionRequest() {
        return this.publicTeardownFunctionCall.isEmpty() ? undefined : this.publicTeardownFunctionCall;
    }
    /**
     * Deserializes the Tx object from a Buffer.
     * @param buffer - Buffer or BufferReader object to deserialize.
     * @returns An instance of Tx.
     */
    static fromBuffer(buffer) {
        const reader = BufferReader.asReader(buffer);
        return new _a(reader.readObject(PrivateKernelTailCircuitPublicInputs), reader.readObject(ClientIvcProof), reader.readObject(UnencryptedTxL2Logs), reader.readObject(ContractClassTxL2Logs), reader.readArray(reader.readNumber(), PublicExecutionRequest), reader.readObject(PublicExecutionRequest));
    }
    static newWithTxData(data, publicTeardownExecutionRequest) {
        return new _a(data, ClientIvcProof.empty(), UnencryptedTxL2Logs.empty(), ContractClassTxL2Logs.empty(), [], publicTeardownExecutionRequest ? publicTeardownExecutionRequest : PublicExecutionRequest.empty());
    }
    /**
     * Serializes the Tx object into a Buffer.
     * @returns Buffer representation of the Tx object.
     */
    toBuffer() {
        return serializeToBuffer([
            this.data,
            this.clientIvcProof,
            this.unencryptedLogs,
            this.contractClassLogs,
            this.enqueuedPublicFunctionCalls.length,
            this.enqueuedPublicFunctionCalls,
            this.publicTeardownFunctionCall,
        ]);
    }
    static get schema() {
        return z
            .object({
            data: PrivateKernelTailCircuitPublicInputs.schema,
            clientIvcProof: ClientIvcProof.schema,
            unencryptedLogs: UnencryptedTxL2Logs.schema,
            contractClassLogs: ContractClassTxL2Logs.schema,
            enqueuedPublicFunctionCalls: z.array(PublicExecutionRequest.schema),
            publicTeardownFunctionCall: PublicExecutionRequest.schema,
        })
            .transform(_a.from);
    }
    static from(fields) {
        return new _a(fields.data, fields.clientIvcProof, fields.unencryptedLogs, fields.contractClassLogs, fields.enqueuedPublicFunctionCalls, fields.publicTeardownFunctionCall);
    }
    /**
     * Gets unencrypted logs emitted by this tx.
     * @param logsSource - An instance of `L2LogsSource` which can be used to obtain the logs.
     * @returns The requested logs.
     */
    getUnencryptedLogs(logsSource) {
        return logsSource.getUnencryptedLogs({ txHash: this.getTxHash() });
    }
    /**
     * Construct & return transaction hash.
     * @returns The transaction's hash.
     */
    getTxHash() {
        // Private kernel functions are executed client side and for this reason tx hash is already set as first nullifier
        const firstNullifier = this.data.getNonEmptyNullifiers()[0];
        if (!firstNullifier || firstNullifier.isZero()) {
            throw new Error(`Cannot get tx hash since first nullifier is missing`);
        }
        return new TxHash(firstNullifier);
    }
    /** Returns the tx hash, or undefined if none is set. */
    tryGetTxHash() {
        try {
            return this.getTxHash();
        }
        catch {
            return undefined;
        }
    }
    /** Returns stats about this tx. */
    getStats() {
        return {
            txHash: this.getTxHash().toString(),
            unencryptedLogCount: this.unencryptedLogs.getTotalLogCount(),
            unencryptedLogSize: this.unencryptedLogs.getSerializedLength(),
            noteHashCount: this.data.getNonEmptyNoteHashes().length,
            nullifierCount: this.data.getNonEmptyNullifiers().length,
            privateLogCount: this.data.getNonEmptyPrivateLogs().length,
            proofSize: this.clientIvcProof.clientIvcProofBuffer.length,
            size: this.toBuffer().length,
            feePaymentMethod: 
            // needsTeardown? then we pay a fee
            this.data.forPublic?.needsTeardown
                ? // needsSetup? then we pay through a fee payment contract
                    this.data.forPublic?.needsSetup
                        ? // if the first call is to `approve_public_authwit`, then it's a public payment
                            this.data.getNonRevertiblePublicCallRequests().at(-1).functionSelector.toField().toBigInt() ===
                                0x43417bb1n
                                ? 'fpc_public'
                                : 'fpc_private'
                        : 'fee_juice'
                : 'none',
            classRegisteredCount: this.contractClassLogs.unrollLogs().length,
            contractClassLogSize: this.contractClassLogs.getSerializedLength(),
        };
    }
    getSize() {
        return (this.data.getSize() +
            this.clientIvcProof.clientIvcProofBuffer.length +
            this.unencryptedLogs.getSerializedLength() +
            this.contractClassLogs.getSerializedLength() +
            arraySerializedSizeOfNonEmpty(this.enqueuedPublicFunctionCalls) +
            arraySerializedSizeOfNonEmpty([this.publicTeardownFunctionCall]));
    }
    /**
     * Estimates the tx size based on its private effects. Note that the actual size of the tx
     * after processing will probably be larger, as public execution would generate more data.
     */
    getEstimatedPrivateTxEffectsSize() {
        return (this.unencryptedLogs.getSerializedLength() +
            this.contractClassLogs.getSerializedLength() +
            this.data.getNonEmptyNoteHashes().length * Fr.SIZE_IN_BYTES +
            this.data.getNonEmptyNullifiers().length * Fr.SIZE_IN_BYTES +
            this.data.getNonEmptyPrivateLogs().length * PrivateLog.SIZE_IN_BYTES);
    }
    /**
     * Convenience function to get a hash out of a tx or a tx-like.
     * @param tx - Tx-like object.
     * @returns - The hash.
     */
    static getHash(tx) {
        return hasHash(tx) ? tx.hash : tx.getTxHash();
    }
    /**
     * Convenience function to get array of hashes for an array of txs.
     * @param txs - The txs to get the hashes from.
     * @returns The corresponding array of hashes.
     */
    static getHashes(txs) {
        return txs.map(_a.getHash);
    }
    /**
     * Clones a tx, making a deep copy of all fields.
     * @param tx - The transaction to be cloned.
     * @returns The cloned transaction.
     */
    static clone(tx) {
        const publicInputs = PrivateKernelTailCircuitPublicInputs.fromBuffer(tx.data.toBuffer());
        const clientIvcProof = ClientIvcProof.fromBuffer(tx.clientIvcProof.toBuffer());
        const unencryptedLogs = UnencryptedTxL2Logs.fromBuffer(tx.unencryptedLogs.toBuffer());
        const contractClassLogs = ContractClassTxL2Logs.fromBuffer(tx.contractClassLogs.toBuffer());
        const enqueuedPublicFunctionCalls = tx.enqueuedPublicFunctionCalls.map(x => PublicExecutionRequest.fromBuffer(x.toBuffer()));
        const publicTeardownFunctionCall = PublicExecutionRequest.fromBuffer(tx.publicTeardownFunctionCall.toBuffer());
        return new _a(publicInputs, clientIvcProof, unencryptedLogs, contractClassLogs, enqueuedPublicFunctionCalls, publicTeardownFunctionCall);
    }
    static random() {
        return new _a(PrivateKernelTailCircuitPublicInputs.emptyWithNullifier(), ClientIvcProof.empty(), UnencryptedTxL2Logs.random(1, 1), ContractClassTxL2Logs.random(1, 1), [PublicExecutionRequest.random()], PublicExecutionRequest.random());
    }
    /**
     * Filters out logs from functions that are not present in the provided kernel output.
     *
     * The purpose of this is to remove logs that got dropped due to a revert,
     * in which case, we only have the kernel's hashes to go on, as opposed to
     * this grouping by function maintained in this class.
     *
     * The logic therefore is to drop all FunctionLogs if any constituent hash
     * does not appear in the provided hashes: it is impossible for part of a
     * function to revert.
     *
     * @param logHashes the individual log hashes we want to keep
     * @param out the output to put passing logs in, to keep this function abstract
     */
    filterRevertedLogs(privateNonRevertible, unencryptedLogsHashes) {
        this.contractClassLogs = this.contractClassLogs.filterScoped(privateNonRevertible.contractClassLogsHashes, ContractClassTxL2Logs.empty());
        this.unencryptedLogs = this.unencryptedLogs.filterScoped(unencryptedLogsHashes, UnencryptedTxL2Logs.empty());
    }
}
_a = Tx;
// Gossipable method
(() => {
    _a.p2pTopic = createTopicString(TopicType.tx);
})();
function hasHash(tx) {
    return tx.hash !== undefined;
}
//# sourceMappingURL=data:application/json;base64, 