solana-genesis: add support for initializing upgradeable programs (#29994)
This commit is contained in:
parent
75ba03b8d2
commit
24905432c4
|
@ -5509,6 +5509,7 @@ name = "solana-genesis"
|
||||||
version = "1.15.0"
|
version = "1.15.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.13.0",
|
"base64 0.13.0",
|
||||||
|
"bincode",
|
||||||
"clap 2.33.3",
|
"clap 2.33.3",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
upgradeableLoader=BPFLoaderUpgradeab1e11111111111111111111111
|
||||||
|
|
||||||
fetch_program() {
|
fetch_program() {
|
||||||
declare name=$1
|
declare name=$1
|
||||||
declare version=$2
|
declare version=$2
|
||||||
|
@ -14,7 +16,11 @@ fetch_program() {
|
||||||
|
|
||||||
declare so=spl_$name-$version.so
|
declare so=spl_$name-$version.so
|
||||||
|
|
||||||
|
if [[ $loader == "$upgradeableLoader" ]]; then
|
||||||
|
genesis_args+=(--upgradeable-program "$address" "$loader" "$so" none)
|
||||||
|
else
|
||||||
genesis_args+=(--bpf-program "$address" "$loader" "$so")
|
genesis_args+=(--bpf-program "$address" "$loader" "$so")
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ -r $so ]]; then
|
if [[ -r $so ]]; then
|
||||||
return
|
return
|
||||||
|
@ -39,7 +45,7 @@ fetch_program() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch_program token 3.5.0 TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA BPFLoader2111111111111111111111111111111111
|
fetch_program token 3.5.0 TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA BPFLoader2111111111111111111111111111111111
|
||||||
fetch_program token-2022 0.5.0 TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb BPFLoader2111111111111111111111111111111111
|
fetch_program token-2022 0.5.0 TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb BPFLoaderUpgradeab1e11111111111111111111111
|
||||||
fetch_program memo 1.0.0 Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo BPFLoader1111111111111111111111111111111111
|
fetch_program memo 1.0.0 Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo BPFLoader1111111111111111111111111111111111
|
||||||
fetch_program memo 3.0.0 MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr BPFLoader2111111111111111111111111111111111
|
fetch_program memo 3.0.0 MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr BPFLoader2111111111111111111111111111111111
|
||||||
fetch_program associated-token-account 1.1.2 ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL BPFLoader2111111111111111111111111111111111
|
fetch_program associated-token-account 1.1.2 ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL BPFLoader2111111111111111111111111111111111
|
||||||
|
|
|
@ -11,6 +11,7 @@ documentation = "https://docs.rs/solana-genesis"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
base64 = "0.13.0"
|
base64 = "0.13.0"
|
||||||
|
bincode = "1.3.3"
|
||||||
clap = "2.33.1"
|
clap = "2.33.1"
|
||||||
serde = "1.0.144"
|
serde = "1.0.144"
|
||||||
serde_json = "1.0.83"
|
serde_json = "1.0.83"
|
||||||
|
|
|
@ -17,6 +17,7 @@ use {
|
||||||
solana_runtime::hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE,
|
solana_runtime::hardened_unpack::MAX_GENESIS_ARCHIVE_UNPACKED_SIZE,
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
account::{Account, AccountSharedData, ReadableAccount, WritableAccount},
|
account::{Account, AccountSharedData, ReadableAccount, WritableAccount},
|
||||||
|
bpf_loader_upgradeable::UpgradeableLoaderState,
|
||||||
clock,
|
clock,
|
||||||
epoch_schedule::EpochSchedule,
|
epoch_schedule::EpochSchedule,
|
||||||
fee_calculator::FeeRateGovernor,
|
fee_calculator::FeeRateGovernor,
|
||||||
|
@ -27,6 +28,7 @@ use {
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
rent::Rent,
|
rent::Rent,
|
||||||
signature::{Keypair, Signer},
|
signature::{Keypair, Signer},
|
||||||
|
signer::keypair::read_keypair_file,
|
||||||
stake::state::StakeState,
|
stake::state::StakeState,
|
||||||
system_program, timing,
|
system_program, timing,
|
||||||
},
|
},
|
||||||
|
@ -376,6 +378,15 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
.multiple(true)
|
.multiple(true)
|
||||||
.help("Install a SBF program at the given address"),
|
.help("Install a SBF program at the given address"),
|
||||||
)
|
)
|
||||||
|
.arg(
|
||||||
|
Arg::with_name("upgradeable_program")
|
||||||
|
.long("upgradeable-program")
|
||||||
|
.value_name("ADDRESS UPGRADEABLE_LOADER BPF_PROGRAM.SO UPGRADE_AUTHORITY")
|
||||||
|
.takes_value(true)
|
||||||
|
.number_of_values(4)
|
||||||
|
.multiple(true)
|
||||||
|
.help("Install an upgradeable SBF program at the given address with the given upgrade authority (or \"none\")"),
|
||||||
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::with_name("inflation")
|
Arg::with_name("inflation")
|
||||||
.required(false)
|
.required(false)
|
||||||
|
@ -585,21 +596,14 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
|
|
||||||
add_genesis_accounts(&mut genesis_config, issued_lamports - faucet_lamports);
|
add_genesis_accounts(&mut genesis_config, issued_lamports - faucet_lamports);
|
||||||
|
|
||||||
if let Some(values) = matches.values_of("bpf_program") {
|
let parse_address = |address: &str, input_type: &str| {
|
||||||
let values: Vec<&str> = values.collect::<Vec<_>>();
|
address.parse::<Pubkey>().unwrap_or_else(|err| {
|
||||||
for address_loader_program in values.chunks(3) {
|
eprintln!("Error: invalid {input_type} {address}: {err}");
|
||||||
match address_loader_program {
|
|
||||||
[address, loader, program] => {
|
|
||||||
let address = address.parse::<Pubkey>().unwrap_or_else(|err| {
|
|
||||||
eprintln!("Error: invalid address {address}: {err}");
|
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
});
|
})
|
||||||
|
};
|
||||||
let loader = loader.parse::<Pubkey>().unwrap_or_else(|err| {
|
|
||||||
eprintln!("Error: invalid loader {loader}: {err}");
|
|
||||||
process::exit(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
let parse_program_data = |program: &str| {
|
||||||
let mut program_data = vec![];
|
let mut program_data = vec![];
|
||||||
File::open(program)
|
File::open(program)
|
||||||
.and_then(|mut file| file.read_to_end(&mut program_data))
|
.and_then(|mut file| file.read_to_end(&mut program_data))
|
||||||
|
@ -607,6 +611,17 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
eprintln!("Error: failed to read {program}: {err}");
|
eprintln!("Error: failed to read {program}: {err}");
|
||||||
process::exit(1);
|
process::exit(1);
|
||||||
});
|
});
|
||||||
|
program_data
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(values) = matches.values_of("bpf_program") {
|
||||||
|
let values: Vec<&str> = values.collect::<Vec<_>>();
|
||||||
|
for address_loader_program in values.chunks(3) {
|
||||||
|
match address_loader_program {
|
||||||
|
[address, loader, program] => {
|
||||||
|
let address = parse_address(address, "address");
|
||||||
|
let loader = parse_address(loader, "loader");
|
||||||
|
let program_data = parse_program_data(program);
|
||||||
genesis_config.add_account(
|
genesis_config.add_account(
|
||||||
address,
|
address,
|
||||||
AccountSharedData::from(Account {
|
AccountSharedData::from(Account {
|
||||||
|
@ -623,6 +638,65 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(values) = matches.values_of("upgradeable_program") {
|
||||||
|
let values: Vec<&str> = values.collect::<Vec<_>>();
|
||||||
|
for address_loader_program_upgrade_authority in values.chunks(4) {
|
||||||
|
match address_loader_program_upgrade_authority {
|
||||||
|
[address, loader, program, upgrade_authority] => {
|
||||||
|
let address = parse_address(address, "address");
|
||||||
|
let loader = parse_address(loader, "loader");
|
||||||
|
let program_data_elf = parse_program_data(program);
|
||||||
|
let upgrade_authority_address = if *upgrade_authority == "none" {
|
||||||
|
Pubkey::default()
|
||||||
|
} else {
|
||||||
|
upgrade_authority.parse::<Pubkey>().unwrap_or_else(|_| {
|
||||||
|
read_keypair_file(upgrade_authority).map(|keypair| keypair.pubkey()).unwrap_or_else(|err| {
|
||||||
|
eprintln!("Error: invalid upgrade_authority {upgrade_authority}: {err}");
|
||||||
|
process::exit(1);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
let (programdata_address, _) =
|
||||||
|
Pubkey::find_program_address(&[address.as_ref()], &loader);
|
||||||
|
let mut program_data =
|
||||||
|
bincode::serialize(&UpgradeableLoaderState::ProgramData {
|
||||||
|
slot: 0,
|
||||||
|
upgrade_authority_address: Some(upgrade_authority_address),
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
program_data.extend_from_slice(&program_data_elf);
|
||||||
|
genesis_config.add_account(
|
||||||
|
programdata_address,
|
||||||
|
AccountSharedData::from(Account {
|
||||||
|
lamports: genesis_config.rent.minimum_balance(program_data.len()),
|
||||||
|
data: program_data,
|
||||||
|
owner: loader,
|
||||||
|
executable: false,
|
||||||
|
rent_epoch: 0,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
let program_data = bincode::serialize(&UpgradeableLoaderState::Program {
|
||||||
|
programdata_address,
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
genesis_config.add_account(
|
||||||
|
address,
|
||||||
|
AccountSharedData::from(Account {
|
||||||
|
lamports: genesis_config.rent.minimum_balance(program_data.len()),
|
||||||
|
data: program_data,
|
||||||
|
owner: loader,
|
||||||
|
executable: true,
|
||||||
|
rent_epoch: 0,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
solana_logger::setup();
|
solana_logger::setup();
|
||||||
create_new_ledger(
|
create_new_ledger(
|
||||||
&ledger_path,
|
&ledger_path,
|
||||||
|
|
Loading…
Reference in New Issue