From d2411b7d7f658f852eb9029b866e62e4d23d9812 Mon Sep 17 00:00:00 2001 From: guibescos <59208140+guibescos@users.noreply.github.com> Date: Mon, 23 Jan 2023 15:25:28 -0600 Subject: [PATCH] [xc-admin] CLI command to upgrade solana programs (#522) * Format checkpoint * Add comment * Add comment --- .../packages/xc-admin-cli/src/index.ts | 57 ++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/governance/xc-admin/packages/xc-admin-cli/src/index.ts b/governance/xc-admin/packages/xc-admin-cli/src/index.ts index e2c5091f..e0f7a503 100644 --- a/governance/xc-admin/packages/xc-admin-cli/src/index.ts +++ b/governance/xc-admin/packages/xc-admin-cli/src/index.ts @@ -1,4 +1,10 @@ -import { Keypair, PublicKey } from "@solana/web3.js"; +import { + Keypair, + PublicKey, + TransactionInstruction, + SYSVAR_RENT_PUBKEY, + SYSVAR_CLOCK_PUBKEY, +} from "@solana/web3.js"; import { program } from "commander"; import { PythCluster } from "@pythnetwork/client/lib/cluster"; import { getPythClusterApiUrl } from "@pythnetwork/client/lib/cluster"; @@ -95,4 +101,53 @@ mutlisigCommand( await proposeInstructions(squad, vault, [proposalInstruction], false); }); +mutlisigCommand("upgrade-program", "Upgrade a program from a buffer") + .requiredOption( + "-p, --program-id ", + "program that you want to upgrade" + ) + .requiredOption("-b, --buffer ", "buffer account") + + .action(async (options: any) => { + const wallet = new NodeWallet( + Keypair.fromSecretKey( + Uint8Array.from(JSON.parse(fs.readFileSync(options.wallet, "ascii"))) + ) + ); + const cluster: PythCluster = options.cluster; + const programId: PublicKey = new PublicKey(options.programId); + const buffer: PublicKey = new PublicKey(options.buffer); + const vault: PublicKey = new PublicKey(options.vault); + + const squad = SquadsMesh.endpoint(getPythClusterApiUrl(cluster), wallet); + const msAccount = await squad.getMultisig(vault); + const vaultAuthority = squad.getAuthorityPDA( + msAccount.publicKey, + msAccount.authorityIndex + ); + + const programDataAccount = PublicKey.findProgramAddressSync( + [programId.toBuffer()], + BPF_UPGRADABLE_LOADER + )[0]; + + // This is intruction is not in @solana/web3.js, source : https://docs.rs/solana-program/latest/src/solana_program/bpf_loader_upgradeable.rs.html#200 + const proposalInstruction: TransactionInstruction = { + programId: BPF_UPGRADABLE_LOADER, + // 4-bytes instruction discriminator, got it from https://docs.rs/solana-program/latest/src/solana_program/loader_upgradeable_instruction.rs.html#104 + data: Buffer.from([3, 0, 0, 0]), + keys: [ + { pubkey: programDataAccount, isSigner: false, isWritable: true }, + { pubkey: programId, isSigner: false, isWritable: true }, + { pubkey: buffer, isSigner: false, isWritable: true }, + { pubkey: wallet.publicKey, isSigner: false, isWritable: true }, + { pubkey: SYSVAR_RENT_PUBKEY, isSigner: false, isWritable: false }, + { pubkey: SYSVAR_CLOCK_PUBKEY, isSigner: false, isWritable: false }, + { pubkey: vaultAuthority, isSigner: true, isWritable: false }, + ], + }; + + await proposeInstructions(squad, vault, [proposalInstruction], false); + }); + program.parse();