From d63f93375b7ffe72b379d61427f13d6ec8a141bb Mon Sep 17 00:00:00 2001 From: guibescos <59208140+guibescos@users.noreply.github.com> Date: Thu, 19 Sep 2024 17:58:34 +0100 Subject: [PATCH] feat(xc_admin_cli): support idl upgrades (#1935) * go * go * fix: ts-node to devdependencies --- .../packages/xc_admin_cli/package.json | 3 ++ .../packages/xc_admin_cli/src/index.ts | 25 ++++++++++ .../MessageBufferMultisigInstruction.ts | 23 ++++++++- .../src/multisig_transaction/anchor.ts | 37 ++++++++++++++- .../src/multisig_transaction/index.ts | 1 + pnpm-lock.yaml | 47 ++++++++++--------- 6 files changed, 111 insertions(+), 25 deletions(-) diff --git a/governance/xc_admin/packages/xc_admin_cli/package.json b/governance/xc_admin/packages/xc_admin_cli/package.json index 70309a1886..c2da03c62b 100644 --- a/governance/xc_admin/packages/xc_admin_cli/package.json +++ b/governance/xc_admin/packages/xc_admin_cli/package.json @@ -32,5 +32,8 @@ "@sqds/mesh": "^1.0.6", "commander": "^9.5.0", "typescript": "^4.9.4" + }, + "dev-dependencies": { + "ts-node": "^10.9.2" } } 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 68c0eacb1b..ae273f0938 100644 --- a/governance/xc_admin/packages/xc_admin_cli/src/index.ts +++ b/governance/xc_admin/packages/xc_admin_cli/src/index.ts @@ -44,6 +44,7 @@ import { findDetermisticStakeAccountAddress, getMultisigCluster, getProposalInstructions, + idlSetBuffer, isPriceStorePublisherInitialized, } from "@pythnetwork/xc-admin-common"; @@ -284,6 +285,30 @@ multisigCommand("upgrade-program", "Upgrade a program from a buffer") ); }); +multisigCommand("upgrade-idl", "Upgrade an Anchor Idl from a bufffer") + .requiredOption( + "-p, --program-id ", + "program whose idl you want to upgrade" + ) + .requiredOption("-b, --buffer ", "buffer account") + .action(async (options: any) => { + const vault = await loadVaultFromOptions(options); + const cluster: PythCluster = options.cluster; + const programId: PublicKey = new PublicKey(options.programId); + const buffer: PublicKey = new PublicKey(options.buffer); + + const proposalInstruction: TransactionInstruction = await idlSetBuffer( + programId, + buffer, + await vault.getVaultAuthorityPDA(cluster) + ); + + await vault.proposeInstructions( + [proposalInstruction], + cluster, + DEFAULT_PRIORITY_FEE_CONFIG + ); + }); async function closeProgramOrBuffer( vault: MultisigVault, cluster: PythCluster, diff --git a/governance/xc_admin/packages/xc_admin_common/src/multisig_transaction/MessageBufferMultisigInstruction.ts b/governance/xc_admin/packages/xc_admin_common/src/multisig_transaction/MessageBufferMultisigInstruction.ts index 966e96166e..3141de2a5f 100644 --- a/governance/xc_admin/packages/xc_admin_common/src/multisig_transaction/MessageBufferMultisigInstruction.ts +++ b/governance/xc_admin/packages/xc_admin_common/src/multisig_transaction/MessageBufferMultisigInstruction.ts @@ -4,7 +4,11 @@ import { UNRECOGNIZED_INSTRUCTION, UnrecognizedProgram, } from "."; -import { AnchorAccounts, resolveAccountNames } from "./anchor"; +import { + AnchorAccounts, + IDL_SET_BUFFER_DISCRIMINATOR, + resolveAccountNames, +} from "./anchor"; import messageBufferIdl from "message_buffer/idl/message_buffer.json"; import { PublicKey, TransactionInstruction } from "@solana/web3.js"; import { Idl, BorshCoder } from "@coral-xyz/anchor"; @@ -66,6 +70,23 @@ export class AnchorMultisigInstruction implements MultisigInstruction { default: return UnrecognizedProgram.fromTransactionInstruction(instruction); } + + /// Special case for IDL instructions that all programs have + if (instruction.data.equals(IDL_SET_BUFFER_DISCRIMINATOR)) { + return new AnchorMultisigInstruction( + program, + "IdlSetBuffer", + {}, + { + named: { + buffer: instruction.keys[0], + idlAccount: instruction.keys[1], + idlAuthority: instruction.keys[2], + }, + remaining: instruction.keys.slice(3), + } + ); + } const instructionCoder = new BorshCoder(idl).instruction; const deserializedData = instructionCoder.decode(instruction.data); diff --git a/governance/xc_admin/packages/xc_admin_common/src/multisig_transaction/anchor.ts b/governance/xc_admin/packages/xc_admin_common/src/multisig_transaction/anchor.ts index 15a3629642..b33beb0214 100644 --- a/governance/xc_admin/packages/xc_admin_common/src/multisig_transaction/anchor.ts +++ b/governance/xc_admin/packages/xc_admin_common/src/multisig_transaction/anchor.ts @@ -1,5 +1,9 @@ import { Idl } from "@coral-xyz/anchor"; -import { AccountMeta, TransactionInstruction } from "@solana/web3.js"; +import { + AccountMeta, + PublicKey, + TransactionInstruction, +} from "@solana/web3.js"; type NamedAccounts = Record; type RemainingAccounts = AccountMeta[]; @@ -28,3 +32,34 @@ export function resolveAccountNames( }); return { named, remaining }; } + +export const IDL_SET_BUFFER_DISCRIMINATOR = Buffer.from( + "40f4bc78a7e9690a03", + "hex" +); + +async function getIdlAddress(programId: PublicKey): Promise { + const programSigner = PublicKey.findProgramAddressSync([], programId)[0]; + return PublicKey.createWithSeed(programSigner, "anchor:idl", programId); +} + +export async function idlSetBuffer( + programId: PublicKey, + buffer: PublicKey, + idlAuthority: PublicKey +): Promise { + let idlAddress = await getIdlAddress(programId); + return { + programId, + data: IDL_SET_BUFFER_DISCRIMINATOR, + keys: [ + { pubkey: buffer, isSigner: false, isWritable: true }, + { pubkey: idlAddress, isSigner: false, isWritable: true }, + { + pubkey: idlAuthority, + isSigner: true, + isWritable: true, + }, + ], + }; +} diff --git a/governance/xc_admin/packages/xc_admin_common/src/multisig_transaction/index.ts b/governance/xc_admin/packages/xc_admin_common/src/multisig_transaction/index.ts index 51a69938a8..a8c86c8e8c 100644 --- a/governance/xc_admin/packages/xc_admin_common/src/multisig_transaction/index.ts +++ b/governance/xc_admin/packages/xc_admin_common/src/multisig_transaction/index.ts @@ -167,6 +167,7 @@ export class MultisigParser { } } +export { idlSetBuffer } from "./anchor"; export { WormholeMultisigInstruction } from "./WormholeMultisigInstruction"; export { PythMultisigInstruction } from "./PythMultisigInstruction"; export { AnchorMultisigInstruction } from "./MessageBufferMultisigInstruction"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f1ab8a754c..d935eb0efc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -314,7 +314,7 @@ importers: version: 2.8.8 ts-jest: specifier: ^29.1.1 - version: 29.1.2(@babel/core@7.24.7)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@22.5.1)(ts-node@10.9.1(@types/node@22.5.1)(typescript@5.4.5)))(typescript@5.4.5) + version: 29.1.2(@babel/core@7.24.7)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(esbuild@0.22.0)(jest@29.7.0(@types/node@22.5.1)(ts-node@10.9.1(@types/node@22.5.1)(typescript@5.4.5)))(typescript@5.4.5) ts-node: specifier: ^10.9.1 version: 10.9.1(@types/node@22.5.1)(typescript@5.4.5) @@ -36141,14 +36141,14 @@ snapshots: dependencies: acorn: 8.12.1 - acorn-jsx@5.3.2(acorn@8.11.3): - dependencies: - acorn: 8.11.3 - acorn-jsx@5.3.2(acorn@8.12.0): dependencies: acorn: 8.12.0 + acorn-jsx@5.3.2(acorn@8.12.1): + dependencies: + acorn: 8.12.1 + acorn-node@1.8.2: dependencies: acorn: 7.4.1 @@ -40231,8 +40231,8 @@ snapshots: espree@9.6.1: dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) + acorn: 8.12.1 + acorn-jsx: 5.3.2(acorn@8.12.1) eslint-visitor-keys: 3.4.3 esprima@4.0.1: {} @@ -50342,28 +50342,29 @@ snapshots: dependencies: tslib: 2.6.3 - ts-jest@29.1.2(@babel/core@7.24.7)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@16.18.101)(ts-node@10.9.2(@types/node@16.18.101)(typescript@4.9.5)))(typescript@4.9.5): + ts-jest@29.1.2(@babel/core@7.24.7)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(esbuild@0.22.0)(jest@29.7.0(@types/node@22.5.1)(ts-node@10.9.1(@types/node@22.5.1)(typescript@5.4.5)))(typescript@5.4.5): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@16.18.101)(ts-node@10.9.2(@types/node@16.18.101)(typescript@4.9.5)) + jest: 29.7.0(@types/node@22.5.1)(ts-node@10.9.1(@types/node@22.5.1)(typescript@5.4.5)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 semver: 7.6.0 - typescript: 4.9.5 + typescript: 5.4.5 yargs-parser: 21.1.1 optionalDependencies: '@babel/core': 7.24.7 '@jest/types': 29.6.3 babel-jest: 29.7.0(@babel/core@7.24.7) + esbuild: 0.22.0 - ts-jest@29.1.2(@babel/core@7.24.7)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@18.11.18)(ts-node@10.9.2(@types/node@18.11.18)(typescript@4.9.5)))(typescript@4.9.5): + ts-jest@29.1.2(@babel/core@7.24.7)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@16.18.101)(ts-node@10.9.2(@types/node@16.18.101)(typescript@4.9.5)))(typescript@4.9.5): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@18.11.18)(ts-node@10.9.2(@types/node@18.11.18)(typescript@4.9.5)) + jest: 29.7.0(@types/node@16.18.101)(ts-node@10.9.2(@types/node@16.18.101)(typescript@4.9.5)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -50376,45 +50377,45 @@ snapshots: '@jest/types': 29.6.3 babel-jest: 29.7.0(@babel/core@7.24.7) - ts-jest@29.1.2(@babel/core@7.24.7)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@18.11.18)(ts-node@10.9.2(@types/node@18.11.18)(typescript@5.4.5)))(typescript@5.4.5): + ts-jest@29.1.2(@babel/core@7.24.7)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@18.11.18)(ts-node@10.9.2(@types/node@18.11.18)(typescript@4.9.5)))(typescript@4.9.5): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@18.11.18)(ts-node@10.9.2(@types/node@18.11.18)(typescript@5.4.5)) + jest: 29.7.0(@types/node@18.11.18)(ts-node@10.9.2(@types/node@18.11.18)(typescript@4.9.5)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 semver: 7.6.0 - typescript: 5.4.5 + typescript: 4.9.5 yargs-parser: 21.1.1 optionalDependencies: '@babel/core': 7.24.7 '@jest/types': 29.6.3 babel-jest: 29.7.0(@babel/core@7.24.7) - ts-jest@29.1.2(@babel/core@7.24.7)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@18.19.34)(ts-node@10.9.2(@types/node@18.19.34)(typescript@4.9.5)))(typescript@4.9.5): + ts-jest@29.1.2(@babel/core@7.24.7)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@18.11.18)(ts-node@10.9.2(@types/node@18.11.18)(typescript@5.4.5)))(typescript@5.4.5): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@18.19.34)(ts-node@10.9.2(@types/node@18.19.34)(typescript@4.9.5)) + jest: 29.7.0(@types/node@18.11.18)(ts-node@10.9.2(@types/node@18.11.18)(typescript@5.4.5)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 semver: 7.6.0 - typescript: 4.9.5 + typescript: 5.4.5 yargs-parser: 21.1.1 optionalDependencies: '@babel/core': 7.24.7 '@jest/types': 29.6.3 babel-jest: 29.7.0(@babel/core@7.24.7) - ts-jest@29.1.2(@babel/core@7.24.7)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@20.14.2)(ts-node@10.9.2(@types/node@20.14.2)(typescript@4.9.5)))(typescript@4.9.5): + ts-jest@29.1.2(@babel/core@7.24.7)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@18.19.34)(ts-node@10.9.2(@types/node@18.19.34)(typescript@4.9.5)))(typescript@4.9.5): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@20.14.2)(ts-node@10.9.2(@types/node@20.14.2)(typescript@4.9.5)) + jest: 29.7.0(@types/node@18.19.34)(ts-node@10.9.2(@types/node@18.19.34)(typescript@4.9.5)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -50427,17 +50428,17 @@ snapshots: '@jest/types': 29.6.3 babel-jest: 29.7.0(@babel/core@7.24.7) - ts-jest@29.1.2(@babel/core@7.24.7)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@22.5.1)(ts-node@10.9.1(@types/node@22.5.1)(typescript@5.4.5)))(typescript@5.4.5): + ts-jest@29.1.2(@babel/core@7.24.7)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.7))(jest@29.7.0(@types/node@20.14.2)(ts-node@10.9.2(@types/node@20.14.2)(typescript@4.9.5)))(typescript@4.9.5): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@22.5.1)(ts-node@10.9.1(@types/node@22.5.1)(typescript@5.4.5)) + jest: 29.7.0(@types/node@20.14.2)(ts-node@10.9.2(@types/node@20.14.2)(typescript@4.9.5)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 semver: 7.6.0 - typescript: 5.4.5 + typescript: 4.9.5 yargs-parser: 21.1.1 optionalDependencies: '@babel/core': 7.24.7