Skip to content

Commit

Permalink
objects: add account/note details to ProvenTransaction #403 (#481)
Browse files Browse the repository at this point in the history
  • Loading branch information
hackaugusto authored Feb 28, 2024
1 parent 6da337c commit 595f0ae
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 15 deletions.
15 changes: 15 additions & 0 deletions objects/src/notes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,21 @@ pub const NOTE_LEAF_DEPTH: u8 = NOTE_TREE_DEPTH + 1;
// NOTE
// ================================================================================================

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum NoteType {
/// Notes with this type have only their hash published to the network.
OffChain,

/// Notes with type are shared with the network encrypted.
Encrypted,

/// Notes with this type are known by the network, intended to be used in local transactions.
Local,

/// Notes with this type are known by the network, intended for network transactions.
Network,
}

/// A note which can be used to transfer assets between accounts.
///
/// This struct is a full description of a note which is needed to execute a note in a transaction.
Expand Down
109 changes: 94 additions & 15 deletions objects/src/transaction/proven_tx.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,64 @@
use miden_verifier::ExecutionProof;

use super::{AccountId, Digest, InputNotes, NoteEnvelope, Nullifier, OutputNotes, TransactionId};
use crate::utils::serde::{
ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable,
use crate::{
accounts::{Account, AccountDelta},
notes::{Note, NoteId},
utils::{
collections::*,
format,
serde::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
},
};

// PROVEN TRANSACTION
// ================================================================================================

/// The result of executing and proving a transaction.
///
/// This struct contains all the data required to verify that a transaction was executed correctly.
/// Specifically:
/// - account_id: ID of the account that the transaction was executed against.
/// - initial_account_hash: the hash of the account before the transaction was executed.
/// - final_account_hash: the hash of the account after the transaction was executed.
/// - input_notes: a list of nullifier for all notes consumed by the transaction.
/// - output_notes: a list of (note_id, metadata) tuples for all notes created by the
/// transaction.
/// - tx_script_root: the script root of the transaction, if one was used.
/// - block_ref: the block hash of the last known block at the time the transaction was executed.
/// - proof: a STARK proof that attests to the correct execution of the transaction.
#[derive(Clone, Debug)]
pub enum AccountDetails {
/// The whole state is needed for new accounts
Full(Account),

/// For existing accounts, only the delta is needed.
Delta(AccountDelta),
}

/// Result of executing and proving a transaction. Contains all the data required to verify that a
/// transaction was executed correctly.
#[derive(Clone, Debug)]
pub struct ProvenTransaction {
/// A unique identifier for the transaction, see [TransactionId] for additional details.
id: TransactionId,

/// ID of the account that the transaction was executed against.
account_id: AccountId,

/// The hash of the account before the transaction was executed.
initial_account_hash: Digest,

/// The hash of the account after the transaction was executed.
final_account_hash: Digest,

/// Optional account state changes used for on-chain accounts, This data is used to update an
/// on-chain account's state after a local transaction execution.
account_details: Option<AccountDetails>,

/// A list of nullifier for all notes consumed by the transaction.
input_notes: InputNotes<Nullifier>,

/// The id and metadata of all notes created by the transaction.
output_notes: OutputNotes<NoteEnvelope>,

/// Optionally the output note's data, used to share the note with the network.
output_note_details: BTreeMap<NoteId, Note>,

/// The script root of the transaction, if one was used.
tx_script_root: Option<Digest>,

/// The block hash of the last known block at the time the transaction was executed.
block_ref: Digest,

/// A STARK proof that attests to the correct execution of the transaction.
proof: ExecutionProof,
}

Expand Down Expand Up @@ -62,8 +90,10 @@ impl ProvenTransaction {
account_id,
initial_account_hash,
final_account_hash,
account_details: None,
input_notes,
output_notes,
output_note_details: BTreeMap::new(),
tx_script_root,
block_ref,
proof,
Expand Down Expand Up @@ -93,6 +123,11 @@ impl ProvenTransaction {
self.final_account_hash
}

/// Returns the account details.
pub fn account_details(&self) -> Option<&AccountDetails> {
self.account_details.as_ref()
}

/// Returns a reference to the notes consumed by the transaction.
pub fn input_notes(&self) -> &InputNotes<Nullifier> {
&self.input_notes
Expand All @@ -103,6 +138,11 @@ impl ProvenTransaction {
&self.output_notes
}

/// Returns the [NoteId] details, if present.
pub fn get_output_note_details(&self, note_id: &NoteId) -> Option<&Note> {
self.output_note_details.get(note_id)
}

/// Returns the script root of the transaction.
pub fn tx_script_root(&self) -> Option<Digest> {
self.tx_script_root
Expand All @@ -122,13 +162,45 @@ impl ProvenTransaction {
// SERIALIZATION
// ================================================================================================

impl Serializable for AccountDetails {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
match self {
AccountDetails::Full(account) => {
0_u8.write_into(target);
account.write_into(target);
},
AccountDetails::Delta(delta) => {
1_u8.write_into(target);
delta.write_into(target);
},
}
}
}

impl Deserializable for AccountDetails {
fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
match u8::read_from(source)? {
0_u8 => Ok(Self::Full(Account::read_from(source)?)),
1_u8 => Ok(Self::Delta(AccountDelta::read_from(source)?)),
v => Err(DeserializationError::InvalidValue(format!(
"Unknown variant {v} for AccountDetails"
))),
}
}
}

impl Serializable for ProvenTransaction {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
self.account_id.write_into(target);
self.initial_account_hash.write_into(target);
self.final_account_hash.write_into(target);
self.account_details.write_into(target);
self.input_notes.write_into(target);
self.output_notes.write_into(target);

target.write_usize(self.output_note_details.len());
target.write_many(self.output_note_details.iter());

self.tx_script_root.write_into(target);
self.block_ref.write_into(target);
self.proof.write_into(target);
Expand All @@ -140,10 +212,15 @@ impl Deserializable for ProvenTransaction {
let account_id = AccountId::read_from(source)?;
let initial_account_hash = Digest::read_from(source)?;
let final_account_hash = Digest::read_from(source)?;
let account_details = <Option<AccountDetails>>::read_from(source)?;

let input_notes = InputNotes::<Nullifier>::read_from(source)?;
let output_notes = OutputNotes::<NoteEnvelope>::read_from(source)?;

let output_notes_details_len = usize::read_from(source)?;
let details = source.read_many(output_notes_details_len)?;
let output_note_details = BTreeMap::from_iter(details);

let tx_script_root = Deserializable::read_from(source)?;

let block_ref = Digest::read_from(source)?;
Expand All @@ -161,8 +238,10 @@ impl Deserializable for ProvenTransaction {
account_id,
initial_account_hash,
final_account_hash,
account_details,
input_notes,
output_notes,
output_note_details,
tx_script_root,
block_ref,
proof,
Expand Down

0 comments on commit 595f0ae

Please sign in to comment.