mainnet prep: tighten max_send_lovelace default + cost model docs

max_send_lovelace default is now network-aware: mainnet 10 ADA,
preprod/preview 100 (t)ADA. Mainnet handles real value, so the cap
should bite earlier — anything > 10 ADA needs explicit force=true.
Test ada on preprod/preview is faucet-replaceable, no need to
sand off the test surface. New regression
mainnet_default_max_send_is_tighter locks the rule in.

PLUTUS_V3_COST_MODEL_PREPROD docstring updated: confirmed identical
to mainnet PV3 cost model (preprod epoch 286 = mainnet epoch 629,
both 297 params, byte-identical). Cost models are protocol-version
parameters, not network parameters; using the same constant on
both is correct. Re-snapshot from mainnet Koios after any major
hard fork. Naming kept as _PREPROD for git churn reasons.
This commit is contained in:
Kayos 2026-05-04 21:09:31 -07:00
parent e4914a14ba
commit d5fb00c9f5
2 changed files with 43 additions and 4 deletions

View file

@ -1,5 +1,17 @@
// Conway-era preprod Plutus V3 cost model, epoch 286 (2026-05).
// 297 params. Pull fresh via koios epoch_params after major hard forks.
// Conway-era Plutus V3 cost model, 297 params. Snapshot from preprod
// epoch 286 (2026-05) but **identical to mainnet epoch 629** —
// confirmed 2026-05-04 by parallel Koios `epoch_params` fetch from
// `api.koios.rest` and `preprod.koios.rest`. Cost models are
// protocol-version parameters, not network parameters; they only
// diverge if a network does an experimental hard fork off-cycle.
//
// Used by both preprod and mainnet Plutus paths today. Re-snapshot
// from mainnet Koios after any major hard fork. If preprod and
// mainnet ever diverge, split into two constants and select by
// `Network`.
//
// Naming kept as `_PREPROD` for git churn reasons; treat as
// "current Plutus V3 protocol parameters."
pub const PLUTUS_V3_COST_MODEL_PREPROD: [i64; 297] = [
100788, 420, 1, 1, 1000, 173, 0, 1,
1000, 59957, 4, 1, 11183, 32, 201305, 8356,

View file

@ -25,11 +25,22 @@ pub struct Config {
pub data_dir: PathBuf,
/// Hard cap on outbound `wallet.send` lovelace. Tools must
/// reject sends above this unless the caller passes `force=true`.
/// Default 100 ADA (100_000_000 lovelace). Override via TOML or
/// Default is network-aware: mainnet 10 ADA (real value, tighter
/// blast radius), preprod/preview 100 tADA (test ADA is
/// faucet-replaceable). Override via TOML or
/// `ALDABRA_MAX_SEND_LOVELACE`.
pub max_send_lovelace: u64,
}
/// Network-aware default for `max_send_lovelace`. See the docstring on
/// `Config::max_send_lovelace`.
fn default_max_send_for(network: Network) -> u64 {
match network {
Network::Mainnet => 10_000_000,
Network::Preview | Network::Preprod => 100_000_000,
}
}
#[derive(Debug, Default, Deserialize)]
struct FileConfig {
#[serde(default)]
@ -146,7 +157,9 @@ impl Config {
var: "ALDABRA_MAX_SEND_LOVELACE",
value: s,
})?,
Err(_) => file_cfg.max_send_lovelace.unwrap_or(100_000_000),
Err(_) => file_cfg
.max_send_lovelace
.unwrap_or_else(|| default_max_send_for(network)),
};
Ok(Self {
@ -207,4 +220,18 @@ mod tests {
assert!(default_koios_for(Network::Preprod).contains("preprod.koios.rest"));
assert!(default_koios_for(Network::Preview).contains("preview.koios.rest"));
}
#[test]
fn mainnet_default_max_send_is_tighter() {
// Mainnet handles real value, so the default cap is 10 ADA.
// Preprod/preview are faucet-replaceable, so 100 (t)ADA is fine.
assert_eq!(default_max_send_for(Network::Mainnet), 10_000_000);
assert_eq!(default_max_send_for(Network::Preprod), 100_000_000);
assert_eq!(default_max_send_for(Network::Preview), 100_000_000);
assert!(
default_max_send_for(Network::Mainnet)
< default_max_send_for(Network::Preprod),
"mainnet default must be strictly tighter than preprod"
);
}
}