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

refactor: improve price cap configuration #101

Merged
merged 1 commit into from
Dec 13, 2023
Merged
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 Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "pyth-agent"
version = "2.4.2"
version = "2.4.3"
edition = "2021"

[[bin]]
Expand Down
11 changes: 2 additions & 9 deletions config/config.sample.pythnet.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,8 @@ exporter.compute_unit_limit = 20000
# during periods of high network congestion.
exporter.dynamic_compute_unit_pricing_enabled = true

# Maximum slot gap between the current slot and the oldest slot amongst all the accounts in
# the batch. This is used to calculate the dynamic price per compute unit. When the slot gap
# reaches this number we will use the maximum total_compute_fee for the transaction.
exporter.maximum_slot_gap_for_dynamic_compute_unit_price = 40

# The interval with which to poll account information. We are adding it as an extra
# layer of protection to ensure we get the latest account information if there are
# any issues with the ws subscription.
oracle.poll_interval_duration = "5s"
# Price per compute unit offered for update_price transactions
exporter.compute_unit_price_micro_lamports = 1000

# Configuration for the JRPC API
[pythd_adapter]
Expand Down
8 changes: 4 additions & 4 deletions config/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ key_store.mapping_key = "RelevantOracleMappingAddress"
# calculated based on the network previous prioritization fees.
# exporter.dynamic_compute_unit_pricing_enabled = false

# Maximum total compute unit fee paid for a single transaction. Defaults to 0.001 SOL. This
# is a safety measure while using dynamic compute price to prevent the exporter from paying
# too much for a single transaction. The default is 10**12 micro lamports (0.001 SOL).
# exporter.maximum_total_compute_fee_micro_lamports = 1000000000000
# Maximum compute unit price offered for update_price transactions. Defaults to
# 1 million microlamports. This is a safety measure while using dynamic compute
# price to prevent the exporter from paying too much for a single transaction.
# exporter.maximum_compute_unit_price_micro_lamports = 1000000

# Maximum slot gap between the current slot and the oldest slot amongst all the accounts in
# the batch. This is used to calculate the dynamic price per compute unit. When the slot gap
Expand Down
24 changes: 12 additions & 12 deletions src/agent/solana/exporter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ pub struct Config {
/// Maximum total compute unit fee paid for a single transaction. Defaults to 0.001 SOL. This
/// is a safety measure while using dynamic compute price to prevent the exporter from paying
/// too much for a single transaction
pub maximum_total_compute_fee_micro_lamports: u64,
pub maximum_compute_unit_price_micro_lamports: u64,
/// Maximum slot gap between the current slot and the oldest slot amongst all the accounts in
/// the batch. This is used to calculate the dynamic price per compute unit. When the slot gap
/// reaches this number we will use the maximum total_compute_fee for the transaction.
Expand All @@ -156,12 +156,12 @@ impl Default for Config {
compute_unit_limit: 40000,
compute_unit_price_micro_lamports: None,
dynamic_compute_unit_pricing_enabled: false,
// Maximum total compute unit fee paid for a single transaction (0.00003 SOL)
maximum_total_compute_fee_micro_lamports: 30_000_000_000,
// Maximum compute unit price (as a cap on the dynamic price)
maximum_compute_unit_price_micro_lamports: 1_000_000,
// A publisher update is not included if it is 25 slots behind the current slot.
// Due to the delay in the network (until a block gets confirmed) we add 5 slots
// to make sure we do not overpay.
maximum_slot_gap_for_dynamic_compute_unit_price: 30,
// Due to the delay in the network (until a block gets confirmed) and potential
// ws issues we add 15 slots to make sure we do not overpay.
maximum_slot_gap_for_dynamic_compute_unit_price: 40,
}
}
}
Expand Down Expand Up @@ -710,17 +710,14 @@ impl Exporter {
// keep the uptime high during congestion whereas without it we would publish price after a
// large gap and then we can publish it again after the next large gap.
if self.config.dynamic_compute_unit_pricing_enabled {
let maximum_unit_price =
self.config.maximum_total_compute_fee_micro_lamports / total_compute_limit as u64;

// Use the estimated previous price if it is higher
// than the current price.
if let Some(estimated_recent_price) = self.recent_compute_unit_price_micro_lamports {
// Get the estimated compute unit price and wrap it so it stays below the maximum
// total compute unit fee. We additionally divide such price by 2 to create an
// exponential decay. This will make sure that a spike doesn't get propagated
// forever.
let estimated_price = (estimated_recent_price >> 1).min(maximum_unit_price);
let estimated_price = estimated_recent_price >> 1;

compute_unit_price_micro_lamports = compute_unit_price_micro_lamports
.map(|price| price.max(estimated_price))
Expand Down Expand Up @@ -770,7 +767,7 @@ impl Exporter {
// 15 : 3_906
// 13 : 976
// 10 : 122
let exponential_price = maximum_unit_price
let exponential_price = self.config.maximum_compute_unit_price_micro_lamports
>> self
.config
.maximum_slot_gap_for_dynamic_compute_unit_price
Expand All @@ -782,7 +779,10 @@ impl Exporter {
}
}

if let Some(compute_unit_price_micro_lamports) = compute_unit_price_micro_lamports {
if let Some(mut compute_unit_price_micro_lamports) = compute_unit_price_micro_lamports {
compute_unit_price_micro_lamports = compute_unit_price_micro_lamports
.min(self.config.maximum_compute_unit_price_micro_lamports);

debug!(self.logger, "setting compute unit price"; "unit_price" => compute_unit_price_micro_lamports);
instructions.push(ComputeBudgetInstruction::set_compute_unit_price(
compute_unit_price_micro_lamports,
Expand Down
2 changes: 1 addition & 1 deletion src/agent/solana/oracle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ impl Default for Config {
fn default() -> Self {
Self {
commitment: CommitmentLevel::Confirmed,
poll_interval_duration: Duration::from_secs(2 * 60),
poll_interval_duration: Duration::from_secs(5),
subscriber_enabled: true,
updates_channel_capacity: 10000,
data_channel_capacity: 10000,
Expand Down
Loading