syntax = "proto3";
package responses;

import "account.proto";
import "block.proto";
import "digest.proto";
import "merkle.proto";
import "mmr.proto";
import "note.proto";
import "smt.proto";
import "transaction.proto";

// Represents the result of applying a block.
message ApplyBlockResponse {}

// Represents the result of checking nullifiers.
message CheckNullifiersResponse {
    // Each requested nullifier has its corresponding nullifier proof at the same position.
    repeated smt.SmtOpening proofs = 1;
}

// Represents the result of checking nullifiers by prefix.
message CheckNullifiersByPrefixResponse {
    // List of nullifiers matching the prefixes specified in the request.
    repeated NullifierUpdate nullifiers = 1;
}

// Represents the result of getting a block header by block number.
message GetBlockHeaderByNumberResponse {
    // The requested block header.
    block.BlockHeader block_header = 1;

    // Merkle path to verify the block's inclusion in the MMR at the returned `chain_length`.
    optional merkle.MerklePath mmr_path = 2;

    // Current chain length.
    optional fixed32 chain_length = 3;
}

// Represents a single nullifier update.
message NullifierUpdate {
    // Nullifier ID.
    digest.Digest nullifier = 1;

    // Block number.
    fixed32 block_num = 2;
}

// Represents the result of syncing state request.
message SyncStateResponse {
    // Number of the latest block in the chain.
    fixed32 chain_tip = 1;

    // Block header of the block with the first note matching the specified criteria.
    block.BlockHeader block_header = 2;

    // Data needed to update the partial MMR from `request.block_num + 1` to `response.block_header.block_num`.
    mmr.MmrDelta mmr_delta = 3;

    // List of account commitments updated after `request.block_num + 1` but not after `response.block_header.block_num`.
    repeated account.AccountSummary accounts = 5;

    // List of transactions executed against requested accounts between `request.block_num + 1` and
    // `response.block_header.block_num`.
    repeated transaction.TransactionSummary transactions = 6;

    // List of all notes together with the Merkle paths from `response.block_header.note_root`.
    repeated note.NoteSyncRecord notes = 7;
}

// Represents the result of syncing notes request.
message SyncNoteResponse {
    // Number of the latest block in the chain.
    fixed32 chain_tip = 1;

    // Block header of the block with the first note matching the specified criteria.
    block.BlockHeader block_header = 2;

    // Merkle path to verify the block's inclusion in the MMR at the returned `chain_tip`.
    //
    // An MMR proof can be constructed for the leaf of index `block_header.block_num` of
    // an MMR of forest `chain_tip` with this path.
    merkle.MerklePath mmr_path = 3;

    // List of all notes together with the Merkle paths from `response.block_header.note_root`.
    repeated note.NoteSyncRecord notes = 4;
}

// An account returned as a response to the `GetBlockInputs`.
message AccountWitness {
    // The account ID.
    account.AccountId account_id = 1;

    // The latest account state commitment used as the initial state of the requested block.
    // This will be the zero digest if the account doesn't exist.
    digest.Digest initial_state_commitment = 2;

    // Merkle path to verify the account's inclusion in the account tree.
    merkle.MerklePath proof = 3;
}

// A nullifier returned as a response to the `GetBlockInputs`.
message NullifierWitness {
    // The nullifier.
    digest.Digest nullifier = 1;

    // The SMT proof to verify the nullifier's inclusion in the nullifier tree.
    smt.SmtOpening opening = 2;
}

// Represents the result of getting block inputs.
message GetBlockInputsResponse {
    // The latest block header.
    block.BlockHeader latest_block_header = 1;

    // Proof of each requested unauthenticated note's inclusion in a block, **if it existed in
    // the store**.
    repeated note.NoteInclusionInBlockProof unauthenticated_note_proofs = 2;

    // The serialized chain MMR which includes proofs for all blocks referenced by the
    // above note inclusion proofs as well as proofs for inclusion of the requested blocks
    // referenced by the batches in the block.
    bytes chain_mmr = 3;

    // The state commitments of the requested accounts and their authentication paths.
    repeated AccountWitness account_witnesses = 4;

    // The requested nullifiers and their authentication paths.
    repeated NullifierWitness nullifier_witnesses = 5;
}

// Represents the result of getting batch inputs.
message GetBatchInputsResponse {
  // The block header that the transaction batch should reference.
  block.BlockHeader batch_reference_block_header = 1;

  // Proof of each _found_ unauthenticated note's inclusion in a block.
  repeated note.NoteInclusionInBlockProof note_proofs = 2;

  // The serialized chain MMR which includes proofs for all blocks referenced by the
  // above note inclusion proofs as well as proofs for inclusion of the blocks referenced
  // by the transactions in the batch.
  bytes chain_mmr = 3;
}

// An account returned as a response to the `GetTransactionInputs`.
message AccountTransactionInputRecord {
    // The account ID.
    account.AccountId account_id = 1;

    // The latest account commitment, zero commitment if the account doesn't exist.
    digest.Digest account_commitment = 2;
}

// A nullifier returned as a response to the `GetTransactionInputs`.
message NullifierTransactionInputRecord {
    // The nullifier ID.
    digest.Digest nullifier = 1;

    // The block at which the nullifier has been consumed, zero if not consumed.
    fixed32 block_num = 2;
}

// Represents the result of getting transaction inputs.
message GetTransactionInputsResponse {
    // Account state proof.
    AccountTransactionInputRecord account_state = 1;

    // List of nullifiers that have been consumed.
    repeated NullifierTransactionInputRecord nullifiers = 2;

    // List of unauthenticated notes that were not found in the database.
    repeated digest.Digest found_unauthenticated_notes = 3;

    // The node's current block height.
    fixed32 block_height = 4;
}

// Represents the result of submitting proven transaction.
message SubmitProvenTransactionResponse {
    // The node's current block height.
    fixed32 block_height = 1;
}

// Represents the result of getting notes by IDs.
message GetNotesByIdResponse {
    // Lists Note's returned by the database.
    repeated note.Note notes = 1;
}

// Represents the result of getting account details.
message GetAccountDetailsResponse {
    // Account info (with details for public accounts).
    account.AccountInfo details = 1;
}

// Represents the result of getting block by number.
message GetBlockByNumberResponse {
    // The requested block data encoded using [winter_utils::Serializable] implementation for
    // [miden_objects::block::Block].
    optional bytes block = 1;
}

// Represents the result of getting account state delta.
message GetAccountStateDeltaResponse {
    // The calculated account delta encoded using [winter_utils::Serializable] implementation
    // for [miden_objects::account::delta::AccountDelta].
    optional bytes delta = 1;
}

// Represents the result of getting account proofs.
message GetAccountProofsResponse {
    // Block number at which the state of the account was returned.
    fixed32 block_num = 1;
    // List of account state infos for the requested account keys.
    repeated AccountProofsResponse account_proofs = 2;
}

// A single account proof returned as a response to the `GetAccountProofs`.
message AccountProofsResponse {
    // Account ID.
    account.AccountId account_id = 1;
    // Account commitment.
    digest.Digest account_commitment = 2;
    // Authentication path from the `account_root` of the block header to the account.
    merkle.MerklePath account_proof = 3;
    // State header for public accounts. Filled only if `include_headers` flag is set to `true`.
    optional AccountStateHeader state_header = 4;
}

// State header for public accounts.
message AccountStateHeader {
    // Account header.
    account.AccountHeader header = 1;

    // Values of all account storage slots (max 255).
    bytes storage_header = 2;

    // Account code, returned only when none of the request's code commitments match
    // the current one.
    optional bytes account_code = 3;

    // Storage slots information for this account
    repeated StorageSlotMapProof storage_maps = 4;
}

// Represents a single storage slot with the reuqested keys and their respective values.
message StorageSlotMapProof {
    // The storage slot index ([0..255]).
    uint32 storage_slot = 1;

    // Merkle proof of the map value
    bytes smt_proof = 2;
}
