Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Fix] Selection of transition ID in finalize. #27

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,7 @@ jobs:
resource_class: << pipeline.parameters.twoxlarge >>
steps:
- run_serial:
flags: --test '*' -- --test-threads=8
flags: --test '*' --features test -- --test-threads=8
workspace_member: synthesizer
cache_key: v1.0.0-rust-1.81.0-snarkvm-synthesizer-integration-cache

Expand Down
2 changes: 1 addition & 1 deletion console/network/src/canary_v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ impl Network for CanaryV0 {
// TODO (raychu86): Update this value based on the desired canary height.
/// The block height from which consensus V2 rules apply.
#[cfg(any(test, feature = "test"))]
const CONSENSUS_V2_HEIGHT: u32 = 0;
const CONSENSUS_V2_HEIGHT: u32 = 10;
/// The network edition.
const EDITION: u16 = 0;
/// The genesis block coinbase target.
Expand Down
2 changes: 1 addition & 1 deletion console/network/src/mainnet_v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ impl Network for MainnetV0 {
// TODO (raychu86): Update this value based on the desired mainnet height.
/// The block height from which consensus V2 rules apply.
#[cfg(any(test, feature = "test"))]
const CONSENSUS_V2_HEIGHT: u32 = 0;
const CONSENSUS_V2_HEIGHT: u32 = 10;
/// The network edition.
const EDITION: u16 = 0;
/// The genesis block coinbase target.
Expand Down
2 changes: 1 addition & 1 deletion synthesizer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ serial = [
"synthesizer-snark/serial"
]
setup = [ ]
test = [ ]
test = [ "console/test", "ledger-block/test", "ledger-store/test" ]
timer = [ "aleo-std/timer" ]
wasm = [
"process",
Expand Down
56 changes: 40 additions & 16 deletions synthesizer/process/src/finalize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,11 @@ impl<N: Network> Process<N> {
lap!(timer, "Verify the number of transitions");

// Construct the call graph.
let call_graph = self.construct_call_graph(execution)?;
let call_graph = if state.block_height() >= N::CONSENSUS_V2_HEIGHT {
Default::default()
} else {
self.construct_call_graph(execution)?
};

atomic_batch_scope!(store, {
// Finalize the root transition.
Expand Down Expand Up @@ -160,9 +164,13 @@ fn finalize_fee_transition<N: Network, P: FinalizeStorage<N>>(
fee: &Fee<N>,
) -> Result<Vec<FinalizeOperation<N>>> {
// Construct the call graph.
let mut call_graph = HashMap::new();
// Insert the fee transition.
call_graph.insert(*fee.transition_id(), Vec::new());
let call_graph = if state.block_height() >= N::CONSENSUS_V2_HEIGHT {
Default::default()
} else {
let mut call_graph = HashMap::new();
call_graph.insert(*fee.transition_id(), vec![]);
call_graph
};

// Finalize the transition.
match finalize_transition(state, store, stack, fee, call_graph) {
Expand Down Expand Up @@ -208,8 +216,11 @@ fn finalize_transition<N: Network, P: FinalizeStorage<N>>(
// Initialize a stack of active finalize states.
let mut states = Vec::new();

// Initialize a nonce for the finalize registers.
let mut nonce = 0;

// Initialize the top-level finalize state.
states.push(initialize_finalize_state(state, future, stack, *transition.id())?);
states.push(initialize_finalize_state(state, future, stack, *transition.id(), nonce)?);

// While there are active finalize states, finalize them.
'outer: while let Some(FinalizeState {
Expand Down Expand Up @@ -263,20 +274,30 @@ fn finalize_transition<N: Network, P: FinalizeStorage<N>>(
await_.register()
);

// Get the current transition ID.
let transition_id = registers.transition_id();
// Get the child transition ID.
let child_transition_id = match call_graph.get(transition_id) {
Some(transitions) => match transitions.get(call_counter) {
Some(transition_id) => *transition_id,
None => bail!("Child transition ID not found."),
},
None => bail!("Transition ID '{transition_id}' not found in call graph"),
// Get the transition ID used to initialize the finalize registers.
// If the block height is greater than the consensus V2 height, return the main transition ID.
// Otherwise, query the call graph for the child transition ID corresponding to the future that is being awaited.
let transition_id = if state.block_height() >= N::CONSENSUS_V2_HEIGHT {
*transition.id()
} else {
// Get the current transition ID.
let transition_id = registers.transition_id();
// Get the child transition ID.
match call_graph.get(transition_id) {
Some(transitions) => match transitions.get(call_counter) {
Some(transition_id) => *transition_id,
None => bail!("Child transition ID not found."),
},
None => bail!("Transition ID '{transition_id}' not found in call graph"),
}
};

// Increment the nonce.
nonce += 1;

// Set up the finalize state for the await.
let callee_state =
match try_vm_runtime!(|| setup_await(state, await_, stack, &registers, child_transition_id)) {
match try_vm_runtime!(|| setup_await(state, await_, stack, &registers, transition_id, nonce)) {
Ok(Ok(callee_state)) => callee_state,
// If the evaluation fails, bail and return the error.
Ok(Err(error)) => bail!("'finalize' failed to evaluate command ({command}): {error}"),
Expand Down Expand Up @@ -357,6 +378,7 @@ fn initialize_finalize_state<'a, N: Network>(
future: &Future<N>,
stack: &'a Stack<N>,
transition_id: N::TransitionID,
nonce: u64,
) -> Result<FinalizeState<'a, N>> {
// Get the finalize logic and the stack.
let (finalize, stack) = match stack.program_id() == future.program_id() {
Expand All @@ -381,6 +403,7 @@ fn initialize_finalize_state<'a, N: Network>(
transition_id,
*future.function_name(),
stack.get_finalize_types(future.function_name())?.clone(),
nonce,
);

// Store the inputs.
Expand All @@ -402,14 +425,15 @@ fn setup_await<'a, N: Network>(
stack: &'a Stack<N>,
registers: &FinalizeRegisters<N>,
transition_id: N::TransitionID,
nonce: u64,
) -> Result<FinalizeState<'a, N>> {
// Retrieve the input as a future.
let future = match registers.load(stack, &Operand::Register(await_.register().clone()))? {
Value::Future(future) => future,
_ => bail!("The input to 'await' is not a future"),
};
// Initialize the state.
initialize_finalize_state(state, &future, stack, transition_id)
initialize_finalize_state(state, &future, stack, transition_id, nonce)
}

// A helper function that returns the index to branch to.
Expand Down
19 changes: 18 additions & 1 deletion synthesizer/process/src/stack/finalize_registers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ pub struct FinalizeRegisters<N: Network> {
finalize_types: FinalizeTypes<N>,
/// The mapping of assigned registers to their values.
registers: IndexMap<u64, Value<N>>,
/// A nonce for finalize registers.
nonce: u64,
/// The tracker for the last register locator.
last_register: Option<u64>,
}
Expand All @@ -58,8 +60,17 @@ impl<N: Network> FinalizeRegisters<N> {
transition_id: N::TransitionID,
function_name: Identifier<N>,
finalize_types: FinalizeTypes<N>,
nonce: u64,
) -> Self {
Self { state, transition_id, finalize_types, function_name, registers: IndexMap::new(), last_register: None }
Self {
state,
transition_id,
finalize_types,
function_name,
registers: IndexMap::new(),
nonce,
last_register: None,
}
}
}

Expand All @@ -81,4 +92,10 @@ impl<N: Network> FinalizeRegistersState<N> for FinalizeRegisters<N> {
fn function_name(&self) -> &Identifier<N> {
&self.function_name
}

/// Returns the nonce for the finalize registers.
#[inline]
fn nonce(&self) -> u64 {
self.nonce
}
}
2 changes: 1 addition & 1 deletion synthesizer/process/src/stack/register_types/initialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ impl<N: Network> RegisterTypes<N> {
}

/* Additional checks. */
// - All futures produces before the `async` call must be consumed by the `async` call.
// - All futures produced before the `async` call must be consumed by the `async` call.

// Get all registers containing futures.
let mut future_registers: IndexSet<(Register<N>, Locator<N>)> = register_types
Expand Down
31 changes: 22 additions & 9 deletions synthesizer/program/src/logic/command/rand_chacha.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,28 @@ impl<N: Network> RandChaCha<N> {
let seeds: Vec<_> = self.operands.iter().map(|operand| registers.load(stack, operand)).try_collect()?;

// Construct the random seed.
let preimage = to_bits_le![
registers.state().random_seed(),
**registers.transition_id(),
stack.program_id(),
registers.function_name(),
self.destination.locator(),
self.destination_type.type_id(),
seeds
];
let preimage = if registers.state().block_height() >= N::CONSENSUS_V2_HEIGHT {
to_bits_le![
registers.state().random_seed(),
**registers.transition_id(),
stack.program_id(),
registers.function_name(),
registers.nonce(),
self.destination.locator(),
self.destination_type.type_id(),
seeds
]
} else {
to_bits_le![
registers.state().random_seed(),
**registers.transition_id(),
stack.program_id(),
registers.function_name(),
self.destination.locator(),
self.destination_type.type_id(),
seeds
]
};

// Hash the preimage.
let digest = N::hash_bhp1024(&preimage)?.to_bytes_le()?;
Expand Down
3 changes: 3 additions & 0 deletions synthesizer/program/src/traits/stack_and_registers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ pub trait FinalizeRegistersState<N: Network> {

/// Returns the function name for the finalize scope.
fn function_name(&self) -> &Identifier<N>;

/// Returns the nonce for the finalize registers.
fn nonce(&self) -> u64;
}

pub trait RegistersSigner<N: Network> {
Expand Down
1 change: 1 addition & 0 deletions synthesizer/program/tests/helpers/sample.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ pub fn sample_finalize_registers(
<CurrentNetwork as Network>::TransitionID::default(),
*function_name,
stack.get_finalize_types(function_name)?.clone(),
0u64,
);

// For each literal,
Expand Down
Loading