Skip to content

Commit 0929a8b

Browse files
authored
Merge pull request #4061 from tippenein/satoshis-per-byte-current-4047
Feat: reload from config for up-to-date `satoshis_per_byte`
2 parents df1972f + a6a75f2 commit 0929a8b

File tree

3 files changed

+72
-15
lines changed

3 files changed

+72
-15
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ StackerDB replicas in their config files.
2121
- Message definitions and codecs for Stacker DB, a replicated off-chain DB
2222
hosted by subscribed Stacks nodes and controlled by smart contracts
2323
- Added 3 new public and regionally diverse bootstrap nodes: est.stacksnodes.org, cet.stacksnodes.org, sgt.stacksnodes.org
24+
- satoshis_per_byte can be changed in the config file and miners will always use
25+
the most up to date value
2426

2527
### Changed
2628

testnet/stacks-node/src/burnchains/bitcoin_regtest_controller.rs

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,44 @@ pub fn make_bitcoin_indexer(
154154
burnchain_indexer
155155
}
156156

157+
pub fn get_satoshis_per_byte(config: &Config) -> u64 {
158+
match config.get_burnchain_config() {
159+
Ok(s) => s.satoshis_per_byte,
160+
Err(_) => {
161+
info!("No config found. Using previous configuration.");
162+
config.burnchain.satoshis_per_byte
163+
}
164+
}
165+
}
166+
167+
#[cfg(test)]
168+
mod tests {
169+
use crate::config::DEFAULT_SATS_PER_VB;
170+
171+
use super::*;
172+
use std::env::temp_dir;
173+
use std::fs::File;
174+
use std::io::Write;
175+
176+
#[test]
177+
fn test_get_satoshis_per_byte() {
178+
let dir = temp_dir();
179+
let file_path = dir.as_path().join("config.toml");
180+
181+
let mut config = Config::default();
182+
183+
let satoshis_per_byte = get_satoshis_per_byte(&config);
184+
assert_eq!(satoshis_per_byte, DEFAULT_SATS_PER_VB);
185+
186+
let mut file = File::create(&file_path).unwrap();
187+
writeln!(file, "[burnchain]").unwrap();
188+
writeln!(file, "satoshis_per_byte = 51").unwrap();
189+
config.config_path = Some(file_path.to_str().unwrap().to_string());
190+
191+
assert_eq!(get_satoshis_per_byte(&config), 51);
192+
}
193+
}
194+
157195
impl LeaderBlockCommitFees {
158196
pub fn fees_from_previous_tx(
159197
&self,
@@ -182,7 +220,7 @@ impl LeaderBlockCommitFees {
182220
let value_per_transfer = payload.burn_fee / number_of_transfers;
183221
let sortition_fee = value_per_transfer * number_of_transfers;
184222
let spent_in_attempts = 0;
185-
let fee_rate = config.burnchain.satoshis_per_byte;
223+
let fee_rate = get_satoshis_per_byte(config);
186224
let default_tx_size = config.burnchain.block_commit_tx_estimated_size;
187225

188226
LeaderBlockCommitFees {
@@ -796,8 +834,9 @@ impl BitcoinRegtestController {
796834
) -> Option<Transaction> {
797835
let public_key = signer.get_public_key();
798836

799-
let btc_miner_fee = self.config.burnchain.leader_key_tx_estimated_size
800-
* self.config.burnchain.satoshis_per_byte;
837+
// reload the config to find satoshis_per_byte changes
838+
let satoshis_per_byte = get_satoshis_per_byte(&self.config);
839+
let btc_miner_fee = self.config.burnchain.leader_key_tx_estimated_size * satoshis_per_byte;
801840
let budget_for_outputs = DUST_UTXO_LIMIT;
802841
let total_required = btc_miner_fee + budget_for_outputs;
803842

@@ -825,7 +864,7 @@ impl BitcoinRegtestController {
825864

826865
tx.output = vec![consensus_output];
827866

828-
let fee_rate = self.config.burnchain.satoshis_per_byte;
867+
let fee_rate = satoshis_per_byte;
829868

830869
self.finalize_tx(
831870
epoch_id,
@@ -919,7 +958,7 @@ impl BitcoinRegtestController {
919958
) -> Option<Transaction> {
920959
let public_key = signer.get_public_key();
921960
let max_tx_size = 230;
922-
961+
let satoshis_per_byte = get_satoshis_per_byte(&self.config);
923962
let (mut tx, mut utxos) = if let Some(utxo) = utxo_to_use {
924963
(
925964
Transaction {
@@ -937,7 +976,7 @@ impl BitcoinRegtestController {
937976
self.prepare_tx(
938977
epoch_id,
939978
&public_key,
940-
DUST_UTXO_LIMIT + max_tx_size * self.config.burnchain.satoshis_per_byte,
979+
DUST_UTXO_LIMIT + max_tx_size * satoshis_per_byte,
941980
None,
942981
None,
943982
0,
@@ -965,13 +1004,14 @@ impl BitcoinRegtestController {
9651004
.to_bitcoin_tx_out(DUST_UTXO_LIMIT),
9661005
);
9671006

1007+
let satoshis_per_byte = get_satoshis_per_byte(&self.config);
9681008
self.finalize_tx(
9691009
epoch_id,
9701010
&mut tx,
9711011
DUST_UTXO_LIMIT,
9721012
0,
9731013
max_tx_size,
974-
self.config.burnchain.satoshis_per_byte,
1014+
satoshis_per_byte,
9751015
&mut utxos,
9761016
signer,
9771017
)?;
@@ -1020,7 +1060,7 @@ impl BitcoinRegtestController {
10201060
self.prepare_tx(
10211061
epoch_id,
10221062
&public_key,
1023-
DUST_UTXO_LIMIT + max_tx_size * self.config.burnchain.satoshis_per_byte,
1063+
DUST_UTXO_LIMIT + max_tx_size * get_satoshis_per_byte(&self.config),
10241064
None,
10251065
None,
10261066
0,
@@ -1054,7 +1094,7 @@ impl BitcoinRegtestController {
10541094
DUST_UTXO_LIMIT,
10551095
0,
10561096
max_tx_size,
1057-
self.config.burnchain.satoshis_per_byte,
1097+
get_satoshis_per_byte(&self.config),
10581098
&mut utxos,
10591099
signer,
10601100
)?;
@@ -1089,7 +1129,7 @@ impl BitcoinRegtestController {
10891129
let public_key = signer.get_public_key();
10901130
let max_tx_size = 280;
10911131

1092-
let output_amt = DUST_UTXO_LIMIT + max_tx_size * self.config.burnchain.satoshis_per_byte;
1132+
let output_amt = DUST_UTXO_LIMIT + max_tx_size * get_satoshis_per_byte(&self.config);
10931133
let (mut tx, mut utxos) =
10941134
self.prepare_tx(epoch_id, &public_key, output_amt, None, None, 0)?;
10951135

@@ -1118,7 +1158,7 @@ impl BitcoinRegtestController {
11181158
output_amt,
11191159
0,
11201160
max_tx_size,
1121-
self.config.burnchain.satoshis_per_byte,
1161+
get_satoshis_per_byte(&self.config),
11221162
&mut utxos,
11231163
signer,
11241164
)?;
@@ -1319,7 +1359,7 @@ impl BitcoinRegtestController {
13191359

13201360
// Stop as soon as the fee_rate is ${self.config.burnchain.max_rbf} percent higher, stop RBF
13211361
if ongoing_op.fees.fee_rate
1322-
> (self.config.burnchain.satoshis_per_byte * self.config.burnchain.max_rbf / 100)
1362+
> (get_satoshis_per_byte(&self.config) * self.config.burnchain.max_rbf / 100)
13231363
{
13241364
warn!(
13251365
"RBF'd block commits reached {}% satoshi per byte fee rate, not resubmitting",

testnet/stacks-node/src/config.rs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use stacks_common::util::get_epoch_time_ms;
3131
use stacks_common::util::hash::hex_bytes;
3232
use stacks_common::util::secp256k1::{Secp256k1PrivateKey, Secp256k1PublicKey};
3333

34-
const DEFAULT_SATS_PER_VB: u64 = 50;
34+
pub const DEFAULT_SATS_PER_VB: u64 = 50;
3535
const DEFAULT_MAX_RBF_RATE: u64 = 150; // 1.5x
3636
const DEFAULT_RBF_FEE_RATE_INCREMENT: u64 = 5;
3737
const LEADER_KEY_TX_ESTIM_SIZE: u64 = 290;
@@ -40,6 +40,7 @@ const INV_REWARD_CYCLES_TESTNET: u64 = 6;
4040

4141
#[derive(Clone, Deserialize, Default, Debug)]
4242
pub struct ConfigFile {
43+
pub __path: Option<String>, // Only used for config file reloads
4344
pub burnchain: Option<BurnchainConfigFile>,
4445
pub node: Option<NodeConfigFile>,
4546
pub ustx_balance: Option<Vec<InitialBalanceFile>>,
@@ -171,7 +172,9 @@ mod tests {
171172
impl ConfigFile {
172173
pub fn from_path(path: &str) -> Result<ConfigFile, String> {
173174
let content = fs::read_to_string(path).map_err(|e| format!("Invalid path: {}", &e))?;
174-
Self::from_str(&content)
175+
let mut f = Self::from_str(&content)?;
176+
f.__path = Some(path.to_string());
177+
Ok(f)
175178
}
176179

177180
pub fn from_str(content: &str) -> Result<ConfigFile, String> {
@@ -346,6 +349,7 @@ impl ConfigFile {
346349

347350
#[derive(Clone, Debug)]
348351
pub struct Config {
352+
pub config_path: Option<String>,
349353
pub burnchain: BurnchainConfig,
350354
pub node: NodeConfig,
351355
pub initial_balances: Vec<InitialBalance>,
@@ -388,6 +392,16 @@ lazy_static! {
388392
}
389393

390394
impl Config {
395+
/// get the up-to-date burnchain from the config
396+
pub fn get_burnchain_config(&self) -> Result<BurnchainConfig, String> {
397+
if let Some(path) = &self.config_path {
398+
let config_file = ConfigFile::from_path(path.as_str())?;
399+
let config = Config::from_config_file(config_file)?;
400+
Ok(config.burnchain)
401+
} else {
402+
Ok(self.burnchain.clone())
403+
}
404+
}
391405
/// Apply any test settings to this burnchain config struct
392406
fn apply_test_settings(&self, burnchain: &mut Burnchain) {
393407
if self.burnchain.get_bitcoin_network().1 == BitcoinNetworkType::Mainnet {
@@ -1160,6 +1174,7 @@ impl Config {
11601174
.map_err(|e| format!("Atlas config error: {e}"))?;
11611175

11621176
Ok(Config {
1177+
config_path: config_file.__path,
11631178
node,
11641179
burnchain,
11651180
initial_balances,
@@ -1328,6 +1343,7 @@ impl std::default::Default for Config {
13281343
let mainnet = burnchain.mode == "mainnet";
13291344

13301345
Config {
1346+
config_path: None,
13311347
burnchain,
13321348
node,
13331349
initial_balances: vec![],
@@ -1407,7 +1423,6 @@ impl BurnchainConfig {
14071423
ast_precheck_size_height: None,
14081424
}
14091425
}
1410-
14111426
pub fn get_rpc_url(&self, wallet: Option<String>) -> String {
14121427
let scheme = match self.rpc_ssl {
14131428
true => "https://",

0 commit comments

Comments
 (0)