Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(remote_executor): update eclipse_mainnet #1813

Merged
merged 5 commits into from
Aug 6, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pythnet = []
pythtest = []
eclipse_devnet = []
eclipse_testnet = []
eclipse_mainnet = []

[dependencies]
anchor-lang = {version = "0.25.0", features = ["init-if-needed"]}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub const CHAIN_ID_ARRAY: &[(&str, u16)] = &[
("pythtest", 26),
("eclipse_devnet", 40001),
("eclipse_testnet", 40002),
("eclipse_mainnet", 40003),
];

#[cfg(any(feature = "pythnet", feature = "pythtest"))]
Expand All @@ -30,6 +31,9 @@ pub const CHAIN_ID: u16 = 40001;
#[cfg(feature = "eclipse_testnet")]
pub const CHAIN_ID: u16 = 40002;

#[cfg(feature = "eclipse_mainnet")]
pub const CHAIN_ID: u16 = 40003;

#[derive(AnchorDeserialize, AnchorSerialize, Debug, PartialEq, Eq)]
pub struct ExecutorPayload {
pub header: GovernanceHeader,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,11 @@ impl Owner for AnchorVaa {
Pubkey::from_str("EUrRARh92Cdc54xrDn6qzaqjA77NRrCcfbr8kPwoTL4z").unwrap()
}

#[cfg(any(feature = "eclipse_devnet", feature = "eclipse_testnet"))]
#[cfg(any(
feature = "eclipse_devnet",
feature = "eclipse_testnet",
feature = "eclipse_mainnet"
))]
fn owner() -> Pubkey {
Pubkey::from_str("HDwcJBJXjL9FpJ7UBsYBtaDjsBUhuLCUYoz3zr8SWWaQ").unwrap()
}
Expand Down
5 changes: 3 additions & 2 deletions governance/xc_admin/packages/xc_admin_cli/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {
MultisigParser,
MultisigVault,
PROGRAM_AUTHORITY_ESCROW,
SvmCluster,
getMultisigCluster,
getProposalInstructions,
} from "@pythnetwork/xc-admin-common";
Expand Down Expand Up @@ -69,7 +70,7 @@ async function loadVaultFromOptions(options: any): Promise<MultisigVault> {
options.ledgerDerivationChange
);
// This is the cluster where we want to perform the action
const cluster: PythCluster = options.cluster;
const cluster: SvmCluster = options.cluster;
// This is the cluster where the multisig lives that can perform actions on ^
const multisigCluster = getMultisigCluster(cluster);
const vault: PublicKey = new PublicKey(options.vault);
Expand Down Expand Up @@ -171,7 +172,7 @@ multisigCommand(
"Accept governance authority transfer for the solana receiver program"
).action(async (options: any) => {
const vault = await loadVaultFromOptions(options);
const targetCluster: PythCluster = options.cluster;
const targetCluster: SvmCluster = options.cluster;

const programSolanaReceiver = new Program(
pythSolanaReceiverIdl,
Expand Down
5 changes: 5 additions & 0 deletions governance/xc_admin/packages/xc_admin_common/src/chains.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ export const RECEIVER_CHAINS = {
arbitrum: 23,
optimism: 24,

// SVM chains
eclipse_devnet: 40001,
eclipse_testnet: 40002,
eclipse_mainnet: 40003,

cronos: 60001,
kcc: 60002,
zksync: 60003,
Expand Down
6 changes: 5 additions & 1 deletion governance/xc_admin/packages/xc_admin_common/src/cluster.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { PythCluster } from "@pythnetwork/client/lib/cluster";
import { Cluster } from "@solana/web3.js";

export type NonPythnetSvmCluster = "eclipse_mainnet";
export type SvmCluster = PythCluster | NonPythnetSvmCluster;

/**
* Return whether the cluster is governed remotely or not. For example Pythnet is governed remotely by a mainnet multisig.
*/
Expand All @@ -15,9 +18,10 @@ export function isRemoteCluster(cluster: PythCluster) {
/**
* For cluster that are governed remotely (ex : Pythnet from Mainnet) return the network where the multisig lives
*/
export function getMultisigCluster(cluster: PythCluster): Cluster | "localnet" {
export function getMultisigCluster(cluster: SvmCluster): Cluster | "localnet" {
switch (cluster) {
case "pythnet":
case "eclipse_mainnet":
return "mainnet-beta";
case "pythtest-conformance":
return "devnet";
Expand Down
19 changes: 13 additions & 6 deletions governance/xc_admin/packages/xc_admin_common/src/propose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import {
PriorityFeeConfig,
} from "@pythnetwork/solana-utils";
import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet";
import { SvmCluster } from "./cluster";
import { ChainName } from "./chains";

export const MAX_EXECUTOR_PAYLOAD_SIZE =
PACKET_DATA_SIZE_WITH_ROOM_FOR_COMPUTE_BUDGET - 687; // Bigger payloads won't fit in one addInstruction call when adding to the proposal
Expand Down Expand Up @@ -84,9 +86,9 @@ export class MultisigVault {
* is the PDA of the remote executor program representing the vault's Wormhole emitter address.
* @param cluster
*/
public async getVaultAuthorityPDA(cluster?: PythCluster): Promise<PublicKey> {
public async getVaultAuthorityPDA(cluster?: SvmCluster): Promise<PublicKey> {
const msAccount = await this.getMultisigAccount();
const localAuthorityPDA = await this.squad.getAuthorityPDA(
const localAuthorityPDA = this.squad.getAuthorityPDA(
msAccount.publicKey,
msAccount.authorityIndex
);
Expand Down Expand Up @@ -288,7 +290,7 @@ export class MultisigVault {
*/
public async proposeInstructions(
instructions: TransactionInstruction[],
targetCluster: PythCluster,
targetCluster: SvmCluster,
priorityFeeConfig: PriorityFeeConfig = {}
): Promise<PublicKey[]> {
const msAccount = await this.getMultisigAccount();
Expand Down Expand Up @@ -321,7 +323,8 @@ export class MultisigVault {
newProposalAddress,
batch,
i + 1,
this.wormholeAddress()!
this.wormholeAddress()!,
targetCluster
);
ixToSend.push(
await this.squad.buildAddInstruction(
Expand Down Expand Up @@ -473,9 +476,13 @@ export async function wrapAsRemoteInstruction(
proposalAddress: PublicKey,
instructions: TransactionInstruction[],
instructionIndex: number,
wormholeAddress: PublicKey
wormholeAddress: PublicKey,
targetCluster: SvmCluster
): Promise<SquadInstruction> {
const buffer: Buffer = new ExecutePostedVaa("pythnet", instructions).encode();
const buffer: Buffer = new ExecutePostedVaa(
targetCluster as ChainName,
cctdaniel marked this conversation as resolved.
Show resolved Hide resolved
instructions
).encode();
return await getPostMessageInstruction(
squad,
vault,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
MultisigInstruction,
MultisigParser,
PythMultisigInstruction,
SvmCluster,
WormholeMultisigInstruction,
getManyProposalsInstructions,
getMultisigCluster,
Expand All @@ -37,11 +38,16 @@ import Spinner from '../../common/Spinner'
import Loadbar from '../../loaders/Loadbar'

import { Wallet } from '@coral-xyz/anchor'
import { PythCluster, getPythProgramKeyForCluster } from '@pythnetwork/client'
import { getPythProgramKeyForCluster } from '@pythnetwork/client'
import { TransactionBuilder, sendTransactions } from '@pythnetwork/solana-utils'
import { getMappingCluster, isPubkey } from '../../InstructionViews/utils'
import { StatusTag } from './StatusTag'
import { getProposalStatus } from './utils'
import {
getProposalStatus,
getPythnetCluster,
isSolanaPullProgram,
isSvmChainId,
} from './utils'

import VerifiedIcon from '@images/icons/verified.inline.svg'
import VotedIcon from '@images/icons/voted.inline.svg'
Expand Down Expand Up @@ -140,25 +146,30 @@ export const Proposal = ({
const [isTransactionLoading, setIsTransactionLoading] = useState(false)
const { cluster: contextCluster } = useContext(ClusterContext)
const multisigCluster = getMultisigCluster(contextCluster)
const targetClusters: (PythCluster | 'unknown')[] = []
const targetClusters: (SvmCluster | 'unknown')[] = []
instructions.map((ix) => {
if (!(ix instanceof WormholeMultisigInstruction)) {
targetClusters.push(multisigCluster)
} else if (
ix instanceof WormholeMultisigInstruction &&
ix.governanceAction instanceof ExecutePostedVaa
) {
ix.governanceAction.instructions.map((ix) => {
const remoteClusters: PythCluster[] = [
ix.governanceAction.instructions.map((innerIx) => {
const remoteClusters: SvmCluster[] = [
'pythnet',
'pythtest-conformance',
'pythtest-crosschain',
'eclipse_mainnet',
]
for (const remoteCluster of remoteClusters) {
if (
multisigCluster === getMultisigCluster(remoteCluster) &&
(ix.programId.equals(getPythProgramKeyForCluster(remoteCluster)) ||
ix.programId.equals(SystemProgram.programId))
ix.governanceAction?.targetChainId === remoteCluster &&
(innerIx.programId.equals(
getPythProgramKeyForCluster(getPythnetCluster(remoteCluster))
) ||
innerIx.programId.equals(SystemProgram.programId) ||
isSolanaPullProgram(innerIx.programId))
cctdaniel marked this conversation as resolved.
Show resolved Hide resolved
) {
targetClusters.push(remoteCluster)
}
Expand Down Expand Up @@ -203,7 +214,10 @@ export const Proposal = ({
ix.name === 'postMessage' &&
ix.governanceAction instanceof ExecutePostedVaa &&
ix.governanceAction.instructions.every((remoteIx) => {
const innerMultisigParser = MultisigParser.fromCluster(cluster)
console.log(getPythnetCluster(cluster))
cctdaniel marked this conversation as resolved.
Show resolved Hide resolved
const innerMultisigParser = MultisigParser.fromCluster(
getPythnetCluster(cluster)
)
const parsedRemoteInstruction =
innerMultisigParser.parseInstruction({
programId: remoteIx.programId,
Expand All @@ -215,7 +229,7 @@ export const Proposal = ({
parsedRemoteInstruction instanceof AnchorMultisigInstruction
)
}) &&
ix.governanceAction.targetChainId === 'pythnet')
isSvmChainId(ix.governanceAction.targetChainId))
)

const voted =
Expand Down Expand Up @@ -488,7 +502,10 @@ export const Proposal = ({
</h4>
<hr className="border-gray-700" />
<h4 className="h4 text-[20px] font-semibold">Summary</h4>
<InstructionsSummary instructions={instructions} cluster={cluster} />
<InstructionsSummary
instructions={instructions}
cluster={getPythnetCluster(cluster)}
/>
<hr className="border-gray-700" />
{instructions?.map((instruction, index) => (
<Fragment key={index}>
Expand Down Expand Up @@ -549,7 +566,7 @@ export const Proposal = ({
{typeof instruction.args[key] === 'string'
? instruction.args[key]
: instruction.args[key] instanceof Uint8Array
? instruction.args[key].toString('hex')
? instruction.args[key].toString()
: typeof instruction.args[key] === 'bigint'
? instruction.args[key].toString()
: JSON.stringify(instruction.args[key])}
Expand All @@ -576,7 +593,7 @@ export const Proposal = ({
)}
{instruction instanceof WormholeMultisigInstruction && (
<WormholeInstructionView
cluster={cluster}
cluster={getPythnetCluster(cluster)}
instruction={instruction}
/>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
MultisigParser,
PythGovernanceActionImpl,
SetDataSources,
SvmCluster,
WormholeMultisigInstruction,
} from '@pythnetwork/xc-admin-common'

Expand Down Expand Up @@ -117,3 +118,24 @@ const getTransactionSummary = (instruction: MultisigInstruction) => {
} as const
}
}

export const isSolanaPullProgram = (programId: PublicKey) => {
const solanaPullProgramIds = [
new PublicKey('rec5EKMGg6MxZYaMdyBfgwp4d5rB9T1VQH5pJv5LtFJ'),
new PublicKey('HDwcJBJXjL9FpJ7UBsYBtaDjsBUhuLCUYoz3zr8SWWaQ'),
new PublicKey('pythWSnswVUd12oZpeFP8e9CVaEqJg25g1Vtc2biRsT'),
]
cctdaniel marked this conversation as resolved.
Show resolved Hide resolved
return solanaPullProgramIds.some((id) => programId.equals(id))
}

export const isSvmChainId = (chainId: string) => {
const svmChainIds = ['pythnet', 'eclipse_mainnet']
return svmChainIds.includes(chainId)
}

export const getPythnetCluster = (cluster: SvmCluster): PythCluster => {
if (isSvmChainId(cluster)) {
return 'pythnet'
cctdaniel marked this conversation as resolved.
Show resolved Hide resolved
}
return cluster as PythCluster
}
Loading