Skip to content
Merged
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
56 changes: 55 additions & 1 deletion ledger-tool/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1516,6 +1516,14 @@ fn main() {
.long("enable-capitalization-change")
.takes_value(false)
.help("If snapshot creation should succeed with a capitalization delta."),
)
.arg(
Arg::with_name("fix_testnet_ed25519_precompile_account")
.long("fix-testnet-ed25519-precompile-account")
.help(
"correct misassigned owner and data on testnet ed25519 precompile \
account deployment",
),
),
)
.subcommand(
Expand Down Expand Up @@ -2072,6 +2080,9 @@ fn main() {
archive_format
};

let fix_testnet_ed25519_precompile_account =
arg_matches.is_present("fix_testnet_ed25519_precompile_account");

let genesis_config = open_genesis_config_by(&ledger_path, arg_matches);
let mut process_options = parse_process_options(&ledger_path, arg_matches);

Expand Down Expand Up @@ -2172,7 +2183,8 @@ fn main() {
|| !feature_gates_to_deactivate.is_empty()
|| !vote_accounts_to_destake.is_empty()
|| faucet_pubkey.is_some()
|| bootstrap_validator_pubkeys.is_some();
|| bootstrap_validator_pubkeys.is_some()
|| fix_testnet_ed25519_precompile_account;

if child_bank_required {
let mut child_bank = Bank::new_from_parent(
Expand Down Expand Up @@ -2284,6 +2296,48 @@ fn main() {
}
}

if fix_testnet_ed25519_precompile_account {
use solana_sdk_ids::{ed25519_program, native_loader, system_program};

if bank.cluster_type() != ClusterType::Testnet {
eprintln!(
"--fix-testnet-ed25519-precompile-account is incompatible with \
the supplied base snapshot"
);
std::process::exit(1);
}

let mut ed25519_program_account =
bank.get_account(&ed25519_program::id()).unwrap_or_else(|| {
eprintln!("Error: `{}` is not deployed", ed25519_program::id());
exit(1);
});

if ed25519_program_account.owner() != &system_program::id() {
eprintln!(
"Error: expected `{}` to be owned by `{}`, found `{}`",
ed25519_program::id(),
system_program::id(),
ed25519_program_account.owner(),
);
exit(1);
}

if !ed25519_program_account.data().is_empty() {
eprintln!(
"Error: expected `{}` account data to be empty, found {} bytes",
ed25519_program::id(),
ed25519_program_account.data().len(),
);
exit(1);
}

ed25519_program_account.set_owner(native_loader::id());
ed25519_program_account.set_data_from_slice(b"ed25519_program");

bank.store_account(&ed25519_program::id(), &ed25519_program_account);
Comment on lines +2335 to +2338
Copy link
Copy Markdown

@brooksprumo brooksprumo Dec 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR correctly sets child_bank_required (line 2187 above), so we're safe to make changes to accounts here. The child bank should compute the accounts lt hash correctly during bank freeze as part of taking the snapshot.

It looks like the existing account has no data (line 2325 above). So I would expect that we will need to also pass in --enable-capitalization-change as well, since iiuc the account data size will change on this account.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you should be right, but it's a builtin owned by native loader so subject to that stupid 1-lamport rent-exempt reserve special-case

}

if let Some(bootstrap_validator_pubkeys) = bootstrap_validator_pubkeys {
assert_eq!(bootstrap_validator_pubkeys.len() % 3, 0);

Expand Down
Loading