Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion lazer/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion lazer/contracts/solana/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"test:format": "prettier --check **/*.*",
"test:anchor": "CARGO_TARGET_DIR=\"$PWD/target\" anchor test",
"test": "pnpm run test:format && pnpm run test:anchor",
"setup": "anchor build && pnpm ts-node scripts/setup.ts"
"setup": "anchor build && pnpm ts-node scripts/setup.ts",
"migrate_from_0_1_0": "pnpm ts-node scripts/migrate_from_0_1_0.ts"
},
"dependencies": {
"@coral-xyz/anchor": "^0.30.1"
Expand Down
75 changes: 75 additions & 0 deletions lazer/contracts/solana/scripts/migrate_from_0_1_0.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import * as anchor from "@coral-xyz/anchor";
import { Program } from "@coral-xyz/anchor";
import { PythLazerSolanaContract } from "../target/types/pyth_lazer_solana_contract";
import * as pythLazerSolanaContractIdl from "../target/idl/pyth_lazer_solana_contract.json";
import yargs from "yargs/yargs";
import { readFileSync } from "fs";
import NodeWallet from "@coral-xyz/anchor/dist/cjs/nodewallet";

// This script tops up the storage PDA and calls `migrateFrom010` on the contract.
async function main() {
let argv = await yargs(process.argv.slice(2))
.options({
url: { type: "string", demandOption: true },
"keypair-path": { type: "string", demandOption: true },
treasury: { type: "string", demandOption: true },
})
.parse();

const keypair = anchor.web3.Keypair.fromSecretKey(
new Uint8Array(JSON.parse(readFileSync(argv.keypairPath, "ascii")))
);
const wallet = new NodeWallet(keypair);
const connection = new anchor.web3.Connection(argv.url, {
commitment: "confirmed",
});
const provider = new anchor.AnchorProvider(connection, wallet);

const program: Program<PythLazerSolanaContract> = new Program(
pythLazerSolanaContractIdl as PythLazerSolanaContract,
provider
);

const storagePdaKey = new anchor.web3.PublicKey(
"3rdJbqfnagQ4yx9HXJViD4zc4xpiSqmFsKpPuSCQVyQL"
);
const storagePdaInfo = await provider.connection.getAccountInfo(
storagePdaKey
);
const newStorageSize = 381;
if (storagePdaInfo.data.length == newStorageSize) {
console.log("Already migrated");
const storage = await program.account.storage.all();
console.log("storage account: ", storage);
return;
}
const minBalance =
await provider.connection.getMinimumBalanceForRentExemption(newStorageSize);
if (storagePdaInfo.lamports < minBalance) {
console.log("storage PDA needs top-up");
const transaction = new anchor.web3.Transaction().add(
anchor.web3.SystemProgram.transfer({
fromPubkey: keypair.publicKey,
toPubkey: storagePdaKey,
lamports: minBalance - storagePdaInfo.lamports,
})
);
const signature = await anchor.web3.sendAndConfirmTransaction(
provider.connection,
transaction,
[keypair]
);
console.log("signature:", signature);
} else {
console.log("storage PDA doesn't need top-up");
}

console.log("executing migration");
const signature2 = await program.methods
.migrateFrom010(new anchor.web3.PublicKey(argv.treasury))
.accounts({})
.rpc();
console.log("signature:", signature2);
}

main();
2 changes: 1 addition & 1 deletion lazer/sdk/rust/protocol/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "pyth-lazer-protocol"
version = "0.1.1"
version = "0.1.2"
edition = "2021"
description = "Pyth Lazer SDK - protocol types."
license = "Apache-2.0"
Expand Down
1 change: 1 addition & 0 deletions lazer/sdk/rust/protocol/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Protocol types.

pub mod message;
pub mod payload;
pub mod publisher;
pub mod router;
Expand Down
89 changes: 89 additions & 0 deletions lazer/sdk/rust/protocol/src/message.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
use {
crate::payload::{EVM_FORMAT_MAGIC, SOLANA_FORMAT_MAGIC_LE},
anyhow::bail,
byteorder::{ReadBytesExt, WriteBytesExt, BE, LE},
std::io::{Cursor, Read, Write},
};

/// EVM signature enveope.
#[derive(Debug, Clone)]
pub struct EvmMessage {
pub payload: Vec<u8>,
pub signature: [u8; 64],
pub recovery_id: u8,
}

impl EvmMessage {
pub fn serialize(&self, mut writer: impl Write) -> anyhow::Result<()> {
writer.write_u32::<BE>(EVM_FORMAT_MAGIC)?;
writer.write_all(&self.signature)?;
writer.write_u8(self.recovery_id)?;
writer.write_u16::<BE>(self.payload.len().try_into()?)?;
writer.write_all(&self.payload)?;
Ok(())
}

pub fn deserialize_slice(data: &[u8]) -> anyhow::Result<Self> {
Self::deserialize(Cursor::new(data))
}

pub fn deserialize(mut reader: impl Read) -> anyhow::Result<Self> {
let magic = reader.read_u32::<BE>()?;
if magic != EVM_FORMAT_MAGIC {
bail!("magic mismatch");
}
let mut signature = [0u8; 64];
reader.read_exact(&mut signature)?;
let recovery_id = reader.read_u8()?;
let payload_len: usize = reader.read_u16::<BE>()?.into();
let mut payload = vec![0u8; payload_len];
reader.read_exact(&mut payload)?;
Ok(Self {
payload,
signature,
recovery_id,
})
}
}

/// Solana signature envelope.
#[derive(Debug, Clone)]
pub struct SolanaMessage {
pub payload: Vec<u8>,
pub signature: [u8; 64],
pub public_key: [u8; 32],
}

impl SolanaMessage {
pub fn serialize(&self, mut writer: impl Write) -> anyhow::Result<()> {
writer.write_u32::<LE>(SOLANA_FORMAT_MAGIC_LE)?;
writer.write_all(&self.signature)?;
writer.write_all(&self.public_key)?;
writer.write_u16::<LE>(self.payload.len().try_into()?)?;
writer.write_all(&self.payload)?;
Ok(())
}

pub fn deserialize_slice(data: &[u8]) -> anyhow::Result<Self> {
Self::deserialize(Cursor::new(data))
}

pub fn deserialize(mut reader: impl Read) -> anyhow::Result<Self> {
let magic = reader.read_u32::<LE>()?;
if magic != SOLANA_FORMAT_MAGIC_LE {
bail!("magic mismatch");
}
let mut signature = [0u8; 64];
reader.read_exact(&mut signature)?;
let mut public_key = [0u8; 32];
reader.read_exact(&mut public_key)?;
let payload_len: usize = reader.read_u16::<LE>()?.into();
let mut payload = vec![0u8; payload_len];
reader.read_exact(&mut payload)?;
Ok(Self {
payload,
signature,
public_key,
})
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Maybe these are somewhere else but i think having round-trip ser/de tests are good to have.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added.

Loading