Skip to content

Commit

Permalink
tx-prover: Add account on-chain state tracking
Browse files Browse the repository at this point in the history
  • Loading branch information
hackaugusto committed Mar 8, 2024
1 parent 64cf9a6 commit 41aa4ce
Show file tree
Hide file tree
Showing 19 changed files with 232 additions and 258 deletions.
1 change: 0 additions & 1 deletion miden-tx/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ miden-objects = { package = "miden-objects", path = "../objects", version = "0.1
miden-prover = { workspace = true }
miden-verifier = { workspace = true }
vm-processor = { workspace = true }
thiserror = { version = "1.0" }

[dev-dependencies]
mock = { package = "miden-mock", path = "../mock", default-features = false }
35 changes: 25 additions & 10 deletions miden-tx/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use core::fmt;
use core::fmt::{self, Display};

use miden_objects::{
assembly::AssemblyError, notes::NoteId, transaction::ProvenTransactionBuilderError, Felt,
NoteError, TransactionInputError, TransactionOutputError,
assembly::AssemblyError, notes::NoteId, Felt, NoteError, ProvenTransactionError,
TransactionInputError, TransactionOutputError,
};
use miden_verifier::VerificationError;

Expand Down Expand Up @@ -70,16 +70,31 @@ impl std::error::Error for TransactionExecutorError {}
// ================================================================================================

#[derive(Debug)]
#[cfg_attr(feature = "std", derive(thiserror::Error))]
pub enum TransactionProverError {
#[error("Proving transaction failed: {0}")]
ProveTransactionProgramFailed(#[from] ExecutionError),
#[error("Transaction ouptut invalid: {0}")]
InvalidTransactionOutput(#[from] TransactionOutputError),
#[error("Building proven transaction error: {0}")]
ProvenTransactionBuilderError(#[from] ProvenTransactionBuilderError),
ProveTransactionProgramFailed(ExecutionError),
InvalidTransactionOutput(TransactionOutputError),
ProvenTransactionError(ProvenTransactionError),
}

impl Display for TransactionProverError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TransactionProverError::ProveTransactionProgramFailed(inner) => {
write!(f, "Proving transaction failed: {}", inner)
},
TransactionProverError::InvalidTransactionOutput(inner) => {
write!(f, "Transaction ouptut invalid: {}", inner)
},
TransactionProverError::ProvenTransactionError(inner) => {
write!(f, "Building proven transaction error: {}", inner)
},
}
}
}

#[cfg(feature = "std")]
impl std::error::Error for TransactionProverError {}

// TRANSACTION VERIFIER ERROR
// ================================================================================================

Expand Down
38 changes: 27 additions & 11 deletions miden-tx/src/prover/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use miden_lib::transaction::{ToTransactionKernelInputs, TransactionKernel};
use miden_objects::{
notes::{NoteEnvelope, Nullifier},
transaction::{InputNotes, ProvenTransaction, ProvenTransactionBuilder, TransactionWitness},
transaction::{
AccountDetails, InputNotes, ProvenTransaction, ProvenTransactionBuilder, TransactionWitness,
},
};
use miden_prover::prove;
pub use miden_prover::ProvingOptions;
Expand Down Expand Up @@ -57,7 +59,7 @@ impl TransactionProver {
.map_err(TransactionProverError::ProveTransactionProgramFailed)?;

// extract transaction outputs and process transaction data
let (advice_provider, _event_handler) = host.into_parts();
let (advice_provider, account_delta) = host.into_parts();
let (_, map, _) = advice_provider.into_parts();
let tx_outputs = TransactionKernel::parse_transaction_outputs(&stack_outputs, &map.into())
.map_err(TransactionProverError::InvalidTransactionOutput)?;
Expand All @@ -68,20 +70,34 @@ impl TransactionProver {
initial_account_hash
};

let builder = ProvenTransactionBuilder::new()
.account_id(account_id)
.initial_account_hash(initial_hash)
.final_account_hash(tx_outputs.account.hash())
.add_input_notes(input_notes)
.add_output_notes(tx_outputs.output_notes.into_iter().map(NoteEnvelope::from))
.block_ref(block_hash)
.proof(proof);
let builder = ProvenTransactionBuilder::new(
account_id,
initial_hash,
tx_outputs.account.hash(),
block_hash,
proof,
)
.add_input_notes(input_notes)
.add_output_notes(tx_outputs.output_notes.into_iter().map(NoteEnvelope::from));

let builder = match tx_script_root {
Some(tx_script_root) => builder.tx_script_root(tx_script_root),
_ => builder,
};

Ok(builder.build()?)
let builder = match account_id.is_on_chain() {
true => {
let account_details = if tx_witness.account().is_new() {
AccountDetails::Full(tx_witness.account().clone())
} else {
AccountDetails::Delta(account_delta)
};

builder.account_details(account_details)
},
false => builder,
};

builder.build().map_err(TransactionProverError::ProvenTransactionError)
}
}
4 changes: 2 additions & 2 deletions miden-tx/tests/integration/scripts/faucet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use miden_objects::{
Felt, Word, ZERO,
};
use miden_tx::TransactionExecutor;
use mock::{mock::account::ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN, utils::prepare_word};
use mock::{mock::account::ACCOUNT_ID_FUNGIBLE_FAUCET_OFF_CHAIN, utils::prepare_word};

use crate::{
get_new_key_pair_with_advice_map, get_note_with_fungible_asset_and_script,
Expand Down Expand Up @@ -264,7 +264,7 @@ fn get_faucet_account_with_max_supply_and_total_issuance(
max_supply: u64,
total_issuance: Option<u64>,
) -> Account {
let faucet_account_id = AccountId::try_from(ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN).unwrap();
let faucet_account_id = AccountId::try_from(ACCOUNT_ID_FUNGIBLE_FAUCET_OFF_CHAIN).unwrap();
let faucet_account_code_src =
include_str!("../../../../miden-lib/asm/miden/contracts/faucets/basic_fungible.masm");
let faucet_account_code_ast = ModuleAst::parse(faucet_account_code_src).unwrap();
Expand Down
3 changes: 2 additions & 1 deletion miden-tx/tests/integration/scripts/p2id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use miden_objects::{
use miden_tx::TransactionExecutor;
use mock::mock::account::{
ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN, ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_2,
ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN,
ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_ON_CHAIN, ACCOUNT_ID_SENDER, DEFAULT_AUTH_SCRIPT,
};

Expand All @@ -33,7 +34,7 @@ fn prove_p2id_script() {
let sender_account_id = AccountId::try_from(ACCOUNT_ID_SENDER).unwrap();

let target_account_id =
AccountId::try_from(ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_ON_CHAIN).unwrap();
AccountId::try_from(ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN).unwrap();
let (target_pub_key, target_sk_pk_felt) = get_new_key_pair_with_advice_map();
let target_account =
get_account_with_default_account_code(target_account_id, target_pub_key, None);
Expand Down
4 changes: 2 additions & 2 deletions miden-tx/tests/integration/scripts/swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use miden_objects::{
};
use miden_tx::TransactionExecutor;
use mock::mock::account::{
ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_ON_CHAIN,
ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN,
ACCOUNT_ID_SENDER, DEFAULT_AUTH_SCRIPT,
};

Expand All @@ -36,7 +36,7 @@ fn prove_swap_script() {
let sender_account_id = AccountId::try_from(ACCOUNT_ID_SENDER).unwrap();

let target_account_id =
AccountId::try_from(ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_ON_CHAIN).unwrap();
AccountId::try_from(ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN).unwrap();
let (target_pub_key, target_sk_felt) = get_new_key_pair_with_advice_map();
let target_account = get_account_with_default_account_code(
target_account_id,
Expand Down
9 changes: 5 additions & 4 deletions miden-tx/tests/integration/wallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ use miden_objects::{
use miden_tx::TransactionExecutor;
use mock::{
mock::account::{
ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN, ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_ON_CHAIN,
ACCOUNT_ID_SENDER, DEFAULT_AUTH_SCRIPT,
ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN, ACCOUNT_ID_OFF_CHAIN_SENDER,
ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN, ACCOUNT_ID_SENDER,
DEFAULT_AUTH_SCRIPT,
},
utils::prepare_word,
};
Expand All @@ -29,7 +30,7 @@ fn prove_receive_asset_via_wallet() {
let fungible_asset_1 = FungibleAsset::new(faucet_id_1, 100).unwrap();

let target_account_id =
AccountId::try_from(ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_ON_CHAIN).unwrap();
AccountId::try_from(ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN).unwrap();
let (target_pub_key, target_keypair_felt) = get_new_key_pair_with_advice_map();
let target_account =
get_account_with_default_account_code(target_account_id, target_pub_key, None);
Expand Down Expand Up @@ -108,7 +109,7 @@ fn prove_send_asset_via_wallet() {
let faucet_id_1 = AccountId::try_from(ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN).unwrap();
let fungible_asset_1: Asset = FungibleAsset::new(faucet_id_1, 100).unwrap().into();

let sender_account_id = AccountId::try_from(ACCOUNT_ID_SENDER).unwrap();
let sender_account_id = AccountId::try_from(ACCOUNT_ID_OFF_CHAIN_SENDER).unwrap();
let (sender_pub_key, sender_keypair_felt) = get_new_key_pair_with_advice_map();
let sender_account = get_account_with_default_account_code(
sender_account_id,
Expand Down
Binary file modified mock/data/scenario1.bin
Binary file not shown.
5 changes: 4 additions & 1 deletion mock/src/builders/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,10 @@ impl<T: Rng> AccountBuilder<T> {
let inner_storage = self.storage_builder.build();

for (key, value) in inner_storage.slots().leaves() {
storage.set_item(key as u8, *value).map_err(AccountBuilderError::AccountError)?;
if key != 255 {
// don't copy the reserved key
storage.set_item(key as u8, *value).map_err(AccountBuilderError::AccountError)?;
}
}

self.account_id_builder.code(&self.code);
Expand Down
2 changes: 0 additions & 2 deletions mock/src/builders/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ mod error;
mod fungible_asset;
mod nonfungible_asset;
mod note;
mod tx;

// RE-EXPORTS
// ================================================================================================
Expand All @@ -20,7 +19,6 @@ pub use error::AccountBuilderError;
pub use fungible_asset::FungibleAssetBuilder;
pub use nonfungible_asset::{NonFungibleAssetBuilder, NonFungibleAssetDetailsBuilder};
pub use note::NoteBuilder;
pub use tx::ProvenTransactionBuilder;

pub fn str_to_account_code(source: &str) -> Result<AccountCode, AccountError> {
let assembler = TransactionKernel::assembler();
Expand Down
68 changes: 0 additions & 68 deletions mock/src/builders/tx.rs

This file was deleted.

21 changes: 3 additions & 18 deletions mock/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use miden_mock::mock::{
account::DEFAULT_ACCOUNT_CODE,
chain::{Immutable, MockChain, OnChain},
};
use miden_objects::{Digest, FieldElement, Word};
use miden_objects::Digest;
use rand::SeedableRng;
use rand_pcg::Pcg64;

Expand Down Expand Up @@ -80,12 +80,8 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut mock_chain = MockChain::new(small_rng);
let start = Instant::now();

let faucet = mock_chain.build_fungible_faucet_with_seed(
seed_to_word("3ef982ea3dca3f89179e1e86ef1c263896ef1e07e76325ce7c69825046bf75ec"),
OnChain::Yes,
DEFAULT_FAUCET_CODE,
Digest::default(),
);
let faucet =
mock_chain.build_fungible_faucet(OnChain::Yes, DEFAULT_FAUCET_CODE, Digest::default());
println!("Fungible faucet created {} [took: {}s]", faucet, start.elapsed().as_secs());
mock_chain.seal_block();

Expand Down Expand Up @@ -126,17 +122,6 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
Ok(())
}

// HELPER FUNCTIONS
// ===============================================================================================

fn seed_to_word(seed: &str) -> Word {
let seed_bytes = hex::decode(seed).unwrap();
let data = unsafe { FieldElement::bytes_as_elements(&seed_bytes) }.unwrap();
let seed: Word = [data[0], data[1], data[2], data[3]];

seed
}

// TESTS
// ===============================================================================================

Expand Down
18 changes: 16 additions & 2 deletions mock/src/mock/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,15 @@ use crate::{
// ================================================================================================

pub const ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_ON_CHAIN: u64 = 3238098370154045919;
pub const ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN: u64 = 932255360940351967;

pub const ACCOUNT_ID_SENDER: u64 = 0b0110111011u64 << 54;
pub const ACCOUNT_ID_OFF_CHAIN_SENDER: u64 = 0b0100111011u64 << 54;
pub const ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN: u64 = 0b1010111100 << 54;
pub const ACCOUNT_ID_FUNGIBLE_FAUCET_OFF_CHAIN: u64 = 0b1000111100 << 54;
pub const ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN: u64 = 0b1110011100 << 54;
pub const ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN_1: u64 = 0b1110011101 << 54;

pub const ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_1: u64 =
0b1010010001111111010110100011011110101011010001101111110110111100u64;
pub const ACCOUNT_ID_FUNGIBLE_FAUCET_ON_CHAIN_2: u64 =
Expand Down Expand Up @@ -188,7 +193,7 @@ pub enum MockAccountType {

pub fn mock_new_account(assembler: &Assembler) -> Account {
let (acct_id, _account_seed) =
generate_account_seed(AccountSeedType::RegularAccountUpdatableCodeOnChain);
generate_account_seed(AccountSeedType::RegularAccountUpdatableCodeOffChain);
let account_storage = mock_account_storage();
let account_code = mock_account_code(assembler);
Account::new(acct_id, AssetVault::default(), account_storage, account_code, Felt::ZERO)
Expand Down Expand Up @@ -263,6 +268,7 @@ pub enum AccountSeedType {
NonFungibleFaucetInvalidReservedSlot,
NonFungibleFaucetValidReservedSlot,
RegularAccountUpdatableCodeOnChain,
RegularAccountUpdatableCodeOffChain,
}

/// Returns the account id and seed for the specified account type.
Expand Down Expand Up @@ -309,7 +315,15 @@ pub fn generate_account_seed(account_seed_type: AccountSeedType) -> (AccountId,
),
AccountSeedType::RegularAccountUpdatableCodeOnChain => (
mock_account(
ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_ON_CHAIN,
ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN,
Felt::ONE,
mock_account_code(&assembler),
),
AccountType::RegularAccountUpdatableCode,
),
AccountSeedType::RegularAccountUpdatableCodeOffChain => (
mock_account(
ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_OFF_CHAIN,
Felt::ONE,
mock_account_code(&assembler),
),
Expand Down
Loading

0 comments on commit 41aa4ce

Please sign in to comment.