0xPolygonMiden/miden-base

Add transaction info to the `Block` struct

Closed this issue · 2 comments

To support 0xPolygonMiden/miden-node#371, we need to modify the Block struct. Specifically, we need to make sure that information about which transactions updated a specific account is contained within the block.

One way to do it is to add something like transactions field to the BlockAccountUpdate struct. Specifically, this struct could look like so:

pub struct BlockAccountUpdate {
    account_id: AccountId,
    new_state_hash: Digest,
    details: AccountUpdateDetails,
    transactions: Vec<TransactionId>,
}

The reason for using Vec to keep track of transactions is that an account could be updated multiple times within a block and we need to keep track of all relevant transactions.

Another approach is to refactor the Block struct more radically so that it looks something like this:

pub struct Block {
    header: BlockHeader,
    batches: Vec<TransactionBatch>,
    proof: ExecutionProof,
}

pub type TransactionBatch = Vec<VerifiedTransaction>;

pub struct VerifiedTransaction {
    id: TransactionId,
    account_update: TxAccountUpdate,
    input_notes: InputNotes<Nullifier>,
    output_notes: OutputNotes,
}

Here, VerifiedTransaction is basically the same as the ProvenTransaction but without the proof and block_ref fields.

The benefit of this approach is that we retain all publicly available info about the transactions which went into the block. The downside is that the block becomes "heavier" because we keep info about "ephemeral" transactions. I am not yet sure which approach is better.

Effect on the BlockHeader

Regardless of the approach taken, we need to make sure that the BlockHeader structs contains a commitment to the transaction info. Specifically, given a block we need to make sure that a set of transactions mentioned in the block is consistent with the information in the block header.

For the first approach, this could be accomplished by changing batch_root to tx_hash which would be computed as a sequential hash of (transaction_id, account_id) tuples:

tx_hash = hash(transaction_id_0, account_id_0, ..., transaction_id_n, account_id_n)

This way, we'd be able to confirm that:

  1. No extra transactions were added added to BlockAccountUpdates and no transactions were omitted from them.
  2. Transactions were mapped to the accounts correctly.

For the second approach, we'd also rename batch_root into tx_hash, but now we'd only need to hash transaction IDs:

tx_hash = hash(transaction_id_0, ..., transaction_id_n)

This is sufficient because the VerifiedTransaction struct contains enough info to re-compute transaction_id based on other account update info and note commitments.

One potentially tricky aspect here would be to derive the note tree from the set of verified transactions. But I think if we assume that the output notes are inserted into the note tree in the order in which they appear in the list of transactions, and account for notes which were both created and consumed in the same batch, it should be doable.

@hackaugusto @igamigo any thoughts on the two approaches?

Closed by #734.