// Specification of the Block Producer store RPC.
syntax = "proto3";
package block_producer_store;

import "google/protobuf/empty.proto";
import "types/account.proto";
import "types/blockchain.proto";
import "types/note.proto";
import "types/primitives.proto";
import "store/shared.proto";

// BLOCK PRODUCER STORE API
// ================================================================================================

// Store API for the BlockProducer component
service BlockProducer {
    // Applies changes of a new block to the DB and in-memory data structures.
    rpc ApplyBlock(blockchain.Block) returns (google.protobuf.Empty) {}

    // Retrieves block header by given block number. Optionally, it also returns the MMR path
    // and current chain length to authenticate the block's inclusion.
    rpc GetBlockHeaderByNumber(shared.BlockHeaderByNumberRequest) returns (shared.BlockHeaderByNumberResponse) {}

    // Returns data required to prove the next block.
    rpc GetBlockInputs(BlockInputsRequest) returns (BlockInputs) {}

    // Returns the inputs for a transaction batch.
    rpc GetBatchInputs(BatchInputsRequest) returns (BatchInputs) {}

    // Returns data required to validate a new transaction.
    rpc GetTransactionInputs(TransactionInputsRequest) returns (TransactionInputs) {}
}

// GET BLOCK INPUTS
// ================================================================================================

// Returns data required to prove the next block.
message BlockInputsRequest {
    // IDs of all accounts updated in the proposed block for which to retrieve account witnesses.
    repeated account.AccountId account_ids = 1;

    // Nullifiers of all notes consumed by the block for which to retrieve witnesses.
    //
    // Due to note erasure it will generally not be possible to know the exact set of nullifiers
    // a block will create, unless we pre-execute note erasure. So in practice, this set of
    // nullifiers will be the set of nullifiers of all proven batches in the block, which is a
    // superset of the nullifiers the block may create.
    //
    // However, if it is known that a certain note will be erased, it would not be necessary to
    // provide a nullifier witness for it.
    repeated primitives.Digest nullifiers = 2;

    // Array of note IDs for which to retrieve note inclusion proofs, **if they exist in the store**.
    repeated primitives.Digest unauthenticated_notes = 3;

    // Array of block numbers referenced by all batches in the block.
    repeated fixed32 reference_blocks = 4;
}

// Represents the result of getting block inputs.
message BlockInputs {
    // A nullifier returned as a response to the `GetBlockInputs`.
    message NullifierWitness {
        // The nullifier.
        primitives.Digest nullifier = 1;

        // The SMT proof to verify the nullifier's inclusion in the nullifier tree.
        primitives.SmtOpening opening = 2;
    }
    // The latest block header.
    blockchain.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 partial_block_chain = 3;

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

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

// GET BATCH INPUTS
// ================================================================================================

// Returns the inputs for a transaction batch.
message BatchInputsRequest {
  // List of unauthenticated note commitments to be queried from the database.
  repeated primitives.Digest note_commitments = 1;
  // Set of block numbers referenced by transactions.
  repeated fixed32 reference_blocks = 2;
}

// Represents the result of getting batch inputs.
message BatchInputs {
    // The block header that the transaction batch should reference.
    blockchain.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 partial_block_chain = 3;
}

// GET TRANSACTION INPUTS
// ================================================================================================

// Returns data required to validate a new transaction.
message TransactionInputsRequest {
    // ID of the account against which a transaction is executed.
    account.AccountId account_id = 1;
    // Set of nullifiers consumed by this transaction.
    repeated primitives.Digest nullifiers = 2;
    // Set of unauthenticated note commitments to check for existence on-chain.
    //
    // These are notes which were not on-chain at the state the transaction was proven,
    // but could by now be present.
    repeated primitives.Digest unauthenticated_notes = 3;
}

// Represents the result of getting transaction inputs.
message TransactionInputs {
    // 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.
        primitives.Digest account_commitment = 2;
    }

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

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

    // 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 primitives.Digest found_unauthenticated_notes = 3;

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

    // Whether the account ID prefix is unique. Only relevant for account creation requests.
    optional bool new_account_id_prefix_is_unique = 5; // TODO: Replace this with an error. When a general error message exists.
}
