Skip to content

Commit

Permalink
Merge pull request #2564 from demox-labs/update-mapping-base-cost
Browse files Browse the repository at this point in the history
Reduce MAPPING_BASE_COST from 10_000 to 500
  • Loading branch information
zosorock authored Nov 13, 2024
2 parents 5443685 + 4cdb52f commit 79402b5
Show file tree
Hide file tree
Showing 10 changed files with 410 additions and 27 deletions.
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
39 changes: 39 additions & 0 deletions ledger/query/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,45 @@ impl<N: Network, B: BlockStorage<N>> QueryTrait<N> for Query<N, B> {
},
}
}

/// Returns a state path for the given `commitment`.
fn current_block_height(&self) -> Result<u32> {
match self {
Self::VM(block_store) => Ok(block_store.max_height().unwrap_or_default()),
Self::REST(url) => match N::ID {
console::network::MainnetV0::ID => {
Ok(Self::get_request(&format!("{url}/mainnet/block/height/latest"))?.into_json()?)
}
console::network::TestnetV0::ID => {
Ok(Self::get_request(&format!("{url}/testnet/block/height/latest"))?.into_json()?)
}
console::network::CanaryV0::ID => {
Ok(Self::get_request(&format!("{url}/canary/block/height/latest"))?.into_json()?)
}
_ => bail!("Unsupported network ID in inclusion query"),
},
}
}

/// Returns a state path for the given `commitment`.
#[cfg(feature = "async")]
async fn current_block_height_async(&self) -> Result<u32> {
match self {
Self::VM(block_store) => Ok(block_store.max_height().unwrap_or_default()),
Self::REST(url) => match N::ID {
console::network::MainnetV0::ID => {
Ok(Self::get_request_async(&format!("{url}/mainnet/block/height/latest")).await?.json().await?)
}
console::network::TestnetV0::ID => {
Ok(Self::get_request_async(&format!("{url}/testnet/block/height/latest")).await?.json().await?)
}
console::network::CanaryV0::ID => {
Ok(Self::get_request_async(&format!("{url}/canary/block/height/latest")).await?.json().await?)
}
_ => bail!("Unsupported network ID in inclusion query"),
},
}
}
}

impl<N: Network, B: BlockStorage<N>> Query<N, B> {
Expand Down
7 changes: 7 additions & 0 deletions ledger/query/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,11 @@ pub trait QueryTrait<N: Network> {
/// Returns a state path for the given `commitment`.
#[cfg(feature = "async")]
async fn get_state_path_for_commitment_async(&self, commitment: &Field<N>) -> Result<StatePath<N>>;

/// Returns the current block height
fn current_block_height(&self) -> Result<u32>;

/// Returns the current block height
#[cfg(feature = "async")]
async fn current_block_height_async(&self) -> Result<u32>;
}
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" ]
timer = [ "aleo-std/timer" ]
wasm = [
"process",
Expand Down
87 changes: 76 additions & 11 deletions synthesizer/process/src/cost.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ pub fn deployment_cost<N: Network>(deployment: &Deployment<N>) -> Result<(u64, (
}

/// Returns the *minimum* cost in microcredits to publish the given execution (total cost, (storage cost, finalize cost)).
pub fn execution_cost<N: Network>(process: &Process<N>, execution: &Execution<N>) -> Result<(u64, (u64, u64))> {
pub fn execution_cost_v2<N: Network>(process: &Process<N>, execution: &Execution<N>) -> Result<(u64, (u64, u64))> {
// Compute the storage cost in microcredits.
let storage_cost = execution_storage_cost::<N>(execution.size_in_bytes()?);

Expand All @@ -77,6 +77,26 @@ pub fn execution_cost<N: Network>(process: &Process<N>, execution: &Execution<N>
Ok((total_cost, (storage_cost, finalize_cost)))
}

/// Returns the *minimum* cost in microcredits to publish the given execution (total cost, (storage cost, finalize cost)).
pub fn execution_cost_v1<N: Network>(process: &Process<N>, execution: &Execution<N>) -> Result<(u64, (u64, u64))> {
// Compute the storage cost in microcredits.
let storage_cost = execution_storage_cost::<N>(execution.size_in_bytes()?);

// Get the root transition.
let transition = execution.peek()?;

// Get the finalize cost for the root transition.
let stack = process.get_stack(transition.program_id())?;
let finalize_cost = cost_in_microcredits_v1(stack, transition.function_name())?;

// Compute the total cost in microcredits.
let total_cost = storage_cost
.checked_add(finalize_cost)
.ok_or(anyhow!("The total cost computation overflowed for an execution"))?;

Ok((total_cost, (storage_cost, finalize_cost)))
}

/// Returns the storage cost in microcredits for a program execution.
fn execution_storage_cost<N: Network>(size_in_bytes: u64) -> u64 {
if size_in_bytes > N::EXECUTION_STORAGE_PENALTY_THRESHOLD {
Expand All @@ -101,7 +121,13 @@ const HASH_BHP_PER_BYTE_COST: u64 = 300;
const HASH_PSD_BASE_COST: u64 = 40_000;
const HASH_PSD_PER_BYTE_COST: u64 = 75;

const MAPPING_BASE_COST: u64 = 10_000;
pub enum ConsensusFeeVersion {
V1,
V2,
}

const MAPPING_BASE_COST_V1: u64 = 10_000;
const MAPPING_BASE_COST_V2: u64 = 1_500;
const MAPPING_PER_BYTE_COST: u64 = 10;

const SET_BASE_COST: u64 = 10_000;
Expand Down Expand Up @@ -168,7 +194,17 @@ fn cost_in_size<'a, N: Network>(
}

/// Returns the the cost of a command in a finalize scope.
pub fn cost_per_command<N: Network>(stack: &Stack<N>, finalize: &Finalize<N>, command: &Command<N>) -> Result<u64> {
pub fn cost_per_command<N: Network>(
stack: &Stack<N>,
finalize: &Finalize<N>,
command: &Command<N>,
consensus_fee_version: ConsensusFeeVersion,
) -> Result<u64> {
let mapping_base_cost = match consensus_fee_version {
ConsensusFeeVersion::V1 => MAPPING_BASE_COST_V1,
ConsensusFeeVersion::V2 => MAPPING_BASE_COST_V2,
};

match command {
Command::Instruction(Instruction::Abs(_)) => Ok(500),
Command::Instruction(Instruction::AbsWrapped(_)) => Ok(500),
Expand Down Expand Up @@ -348,16 +384,16 @@ pub fn cost_per_command<N: Network>(stack: &Stack<N>, finalize: &Finalize<N>, co
Command::Instruction(Instruction::Xor(_)) => Ok(500),
Command::Await(_) => Ok(500),
Command::Contains(command) => {
cost_in_size(stack, finalize, [command.key()], MAPPING_PER_BYTE_COST, MAPPING_BASE_COST)
cost_in_size(stack, finalize, [command.key()], MAPPING_PER_BYTE_COST, mapping_base_cost)
}
Command::Get(command) => {
cost_in_size(stack, finalize, [command.key()], MAPPING_PER_BYTE_COST, MAPPING_BASE_COST)
cost_in_size(stack, finalize, [command.key()], MAPPING_PER_BYTE_COST, mapping_base_cost)
}
Command::GetOrUse(command) => {
cost_in_size(stack, finalize, [command.key()], MAPPING_PER_BYTE_COST, MAPPING_BASE_COST)
cost_in_size(stack, finalize, [command.key()], MAPPING_PER_BYTE_COST, mapping_base_cost)
}
Command::RandChaCha(_) => Ok(25_000),
Command::Remove(_) => Ok(MAPPING_BASE_COST),
Command::Remove(_) => Ok(SET_BASE_COST),
Command::Set(command) => {
cost_in_size(stack, finalize, [command.key(), command.value()], SET_PER_BYTE_COST, SET_BASE_COST)
}
Expand All @@ -367,7 +403,7 @@ pub fn cost_per_command<N: Network>(stack: &Stack<N>, finalize: &Finalize<N>, co
}

/// Returns the minimum number of microcredits required to run the finalize.
pub fn cost_in_microcredits<N: Network>(stack: &Stack<N>, function_name: &Identifier<N>) -> Result<u64> {
pub fn cost_in_microcredits_v2<N: Network>(stack: &Stack<N>, function_name: &Identifier<N>) -> Result<u64> {
// Retrieve the finalize logic.
let Some(finalize) = stack.get_function_ref(function_name)?.finalize_logic() else {
// Return a finalize cost of 0, if the function does not have a finalize scope.
Expand All @@ -389,7 +425,36 @@ pub fn cost_in_microcredits<N: Network>(stack: &Stack<N>, function_name: &Identi
finalize
.commands()
.iter()
.map(|command| cost_per_command(stack, finalize, command))
.map(|command| cost_per_command(stack, finalize, command, ConsensusFeeVersion::V2))
.try_fold(future_cost, |acc, res| {
res.and_then(|x| acc.checked_add(x).ok_or(anyhow!("Finalize cost overflowed")))
})
}

/// Returns the minimum number of microcredits required to run the finalize (depcrated).
pub fn cost_in_microcredits_v1<N: Network>(stack: &Stack<N>, function_name: &Identifier<N>) -> Result<u64> {
// Retrieve the finalize logic.
let Some(finalize) = stack.get_function_ref(function_name)?.finalize_logic() else {
// Return a finalize cost of 0, if the function does not have a finalize scope.
return Ok(0);
};
// Get the cost of finalizing all futures.
let mut future_cost = 0u64;
for input in finalize.inputs() {
if let FinalizeType::Future(future) = input.finalize_type() {
// Get the external stack for the future.
let stack = stack.get_external_stack(future.program_id())?;
// Accumulate the finalize cost of the future.
future_cost = future_cost
.checked_add(cost_in_microcredits_v1(stack, future.resource())?)
.ok_or(anyhow!("Finalize cost overflowed"))?;
}
}
// Aggregate the cost of all commands in the program.
finalize
.commands()
.iter()
.map(|command| cost_per_command(stack, finalize, command, ConsensusFeeVersion::V1))
.try_fold(future_cost, |acc, res| {
res.and_then(|x| acc.checked_add(x).ok_or(anyhow!("Finalize cost overflowed")))
})
Expand Down Expand Up @@ -469,10 +534,10 @@ function over_five_thousand:
// Get execution and cost data.
let execution_under_5000 = get_execution(&mut process, &program, &under_5000, ["2group"].into_iter());
let execution_size_under_5000 = execution_under_5000.size_in_bytes().unwrap();
let (_, (storage_cost_under_5000, _)) = execution_cost(&process, &execution_under_5000).unwrap();
let (_, (storage_cost_under_5000, _)) = execution_cost_v2(&process, &execution_under_5000).unwrap();
let execution_over_5000 = get_execution(&mut process, &program, &over_5000, ["2group"].into_iter());
let execution_size_over_5000 = execution_over_5000.size_in_bytes().unwrap();
let (_, (storage_cost_over_5000, _)) = execution_cost(&process, &execution_over_5000).unwrap();
let (_, (storage_cost_over_5000, _)) = execution_cost_v2(&process, &execution_over_5000).unwrap();

// Ensure the sizes are below and above the threshold respectively.
assert!(execution_size_under_5000 < threshold);
Expand Down
2 changes: 1 addition & 1 deletion synthesizer/process/src/stack/helpers/initialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ impl<N: Network> Stack<N> {
stack.number_of_calls.insert(*function.name(), num_calls);

// Get the finalize cost.
let finalize_cost = cost_in_microcredits(&stack, function.name())?;
let finalize_cost = cost_in_microcredits_v2(&stack, function.name())?;
// Check that the finalize cost does not exceed the maximum.
ensure!(
finalize_cost <= N::TRANSACTION_SPEND_LIMIT,
Expand Down
2 changes: 1 addition & 1 deletion synthesizer/process/src/stack/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ mod evaluate;
mod execute;
mod helpers;

use crate::{CallMetrics, Process, Trace, cost_in_microcredits, traits::*};
use crate::{CallMetrics, Process, Trace, cost_in_microcredits_v2, traits::*};
use console::{
account::{Address, PrivateKey},
network::prelude::*,
Expand Down
Loading

0 comments on commit 79402b5

Please sign in to comment.