1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
use super::{Digest, Felt, Word};
use crate::{
assembly::{Assembler, AssemblyContext, ProgramAst},
notes::NoteId,
utils::collections::*,
vm::CodeBlock,
TransactionScriptError,
};
// TRANSACTION ARGS
// ================================================================================================
/// A struct that represents optional transaction arguments.
///
/// Transaction arguments consist of:
/// - Transaction script: a program that is executed in a transaction after all input notes
/// scripts have been executed..
/// - Note arguments: data put onto the the stack right before a note script is executed. These
/// are different from note inputs, as the executing account can specify arbitrary note args.
#[derive(Clone, Debug, Default)]
pub struct TransactionArgs {
tx_script: Option<TransactionScript>,
note_args: Option<BTreeMap<NoteId, Word>>,
}
impl TransactionArgs {
// CONSTRUCTORS
// --------------------------------------------------------------------------------------------
/// Returns a new instance of a [TransactionArgs] with the provided transaction script and note
/// arguments.
pub fn new(
tx_script: Option<TransactionScript>,
note_args: Option<BTreeMap<NoteId, Word>>,
) -> Self {
Self { tx_script, note_args }
}
pub fn with_tx_script(tx_script: TransactionScript) -> Self {
Self {
tx_script: Some(tx_script),
note_args: None,
}
}
pub fn with_note_args(not_args: BTreeMap<NoteId, Word>) -> Self {
Self {
tx_script: None,
note_args: Some(not_args),
}
}
// PUBLIC ACCESSORS
// --------------------------------------------------------------------------------------------
/// Returns a reference to the transaction script.
pub fn tx_script(&self) -> Option<&TransactionScript> {
self.tx_script.as_ref()
}
/// Returns a reference to the transaction script.
pub fn note_args(&self) -> Option<&BTreeMap<NoteId, Word>> {
self.note_args.as_ref()
}
/// Returns a reference to a specific note argument.
pub fn get_note_args(&self, note_id: NoteId) -> Option<&Word> {
self.note_args.as_ref().and_then(|map| map.get(¬e_id))
}
}
// TRANSACTION SCRIPT
// ================================================================================================
/// A struct that represents a transaction script.
///
/// A transaction script is a program that is executed in a transaction after all input notes
/// have been executed.
///
/// The [TransactionScript] object is composed of:
/// - [code](TransactionScript::code): the transaction script source code.
/// - [hash](TransactionScript::hash): the hash of the compiled transaction script.
/// - [inputs](TransactionScript::inputs): a map of key, value inputs that are loaded into the
/// advice map such that the transaction script can access them.
#[derive(Clone, Debug)]
pub struct TransactionScript {
code: ProgramAst,
hash: Digest,
inputs: BTreeMap<Digest, Vec<Felt>>,
}
impl TransactionScript {
// CONSTRUCTORS
// --------------------------------------------------------------------------------------------
/// Returns a new instance of a [TransactionScript] with the provided script and inputs and the
/// compiled script code block.
///
/// # Errors
/// Returns an error if script compilation fails.
pub fn new<T: IntoIterator<Item = (Word, Vec<Felt>)>>(
code: ProgramAst,
inputs: T,
assembler: &Assembler,
) -> Result<(Self, CodeBlock), TransactionScriptError> {
let code_block = assembler
.compile_in_context(&code, &mut AssemblyContext::for_program(Some(&code)))
.map_err(TransactionScriptError::ScriptCompilationError)?;
Ok((
Self {
code,
hash: code_block.hash(),
inputs: inputs.into_iter().map(|(k, v)| (k.into(), v)).collect(),
},
code_block,
))
}
/// Returns a new instance of a [TransactionScript] instantiated from the provided components.
///
/// Note: this constructor does not verify that a compiled code in fact results in the provided
/// hash.
pub fn from_parts<T: IntoIterator<Item = (Word, Vec<Felt>)>>(
code: ProgramAst,
hash: Digest,
inputs: T,
) -> Result<Self, TransactionScriptError> {
Ok(Self {
code,
hash,
inputs: inputs.into_iter().map(|(k, v)| (k.into(), v)).collect(),
})
}
// PUBLIC ACCESSORS
// --------------------------------------------------------------------------------------------
/// Returns a reference to the code.
pub fn code(&self) -> &ProgramAst {
&self.code
}
/// Returns a reference to the code hash.
pub fn hash(&self) -> &Digest {
&self.hash
}
/// Returns a reference to the inputs.
pub fn inputs(&self) -> &BTreeMap<Digest, Vec<Felt>> {
&self.inputs
}
}