feat: encourage using random treasury id (#1465)

* Encourage random treasury id

* GO
This commit is contained in:
guibescos 2024-04-17 17:47:14 +01:00 committed by GitHub
parent ba435bac76
commit 56cbace282
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 37 additions and 31 deletions

View File

@ -3073,6 +3073,7 @@ dependencies = [
"program-simulator",
"pyth-solana-receiver-sdk",
"pythnet-sdk",
"rand 0.8.5",
"serde_wormhole",
"solana-program",
"solana-sdk",

View File

@ -17,8 +17,7 @@ use {
},
pyth_solana_receiver::sdk::{
deserialize_accumulator_update_data,
get_treasury_address,
DEFAULT_TREASURY_ID,
get_random_treasury_id,
},
pyth_solana_receiver_sdk::config::DataSource,
pythnet_sdk::wire::v1::MerklePriceUpdate,
@ -194,16 +193,9 @@ fn main() -> Result<()> {
},
);
// We need to send some rent to the treasury account, otherwise it won't be able to accept incoming transfers
let pay_treasury_rent = system_instruction::transfer(
&payer.pubkey(),
&get_treasury_address(DEFAULT_TREASURY_ID),
Rent::default().minimum_balance(0),
);
process_transaction(
&rpc_client,
vec![initialize_pyth_receiver_instruction, pay_treasury_rent],
vec![initialize_pyth_receiver_instruction],
&vec![&payer],
)?;
}
@ -268,7 +260,7 @@ pub fn process_post_price_update_atomic(
header.guardian_set_index,
serde_wormhole::to_vec(&(header, body)).unwrap(),
merkle_price_update.clone(),
DEFAULT_TREASURY_ID,
get_random_treasury_id(),
);
process_transaction(
@ -463,6 +455,7 @@ pub fn process_write_encoded_vaa_and_post_price_update(
encoded_vaa_keypair.pubkey(),
price_update_keypair.pubkey(),
merkle_price_update.clone(),
get_random_treasury_id(),
);
// 2nd transaction

View File

@ -23,6 +23,7 @@ byteorder = "1.4.3"
wormhole-core-bridge-solana = {workspace = true}
wormhole-raw-vaas = {version = "0.1.3", features = ["ruint", "on-chain"], default-features = false }
pyth-solana-receiver-sdk = { path = "../../pyth_solana_receiver_sdk"}
rand = "0.8.5"
[dev-dependencies]
solana-sdk = { workspace = true }

View File

@ -22,6 +22,7 @@ use {
MerklePriceUpdate,
Proof,
},
rand::Rng,
solana_program::instruction::Instruction,
wormhole_core_bridge_solana::state::GuardianSet,
};
@ -72,9 +73,10 @@ impl accounts::PostUpdate {
write_authority: Pubkey,
encoded_vaa: Pubkey,
price_update_account: Pubkey,
treasury_id: u8,
) -> Self {
let config = get_config_address();
let treasury = get_treasury_address(DEFAULT_TREASURY_ID);
let treasury = get_treasury_address(treasury_id);
accounts::PostUpdate {
payer,
encoded_vaa,
@ -128,12 +130,14 @@ impl instruction::PostUpdate {
encoded_vaa: Pubkey,
price_update_account: Pubkey,
merkle_price_update: MerklePriceUpdate,
treasury_id: u8,
) -> Instruction {
let post_update_accounts = accounts::PostUpdate::populate(
payer,
write_authority,
encoded_vaa,
price_update_account,
treasury_id,
)
.to_account_metas(None);
Instruction {
@ -142,7 +146,7 @@ impl instruction::PostUpdate {
data: instruction::PostUpdate {
params: PostUpdateParams {
merkle_price_update,
treasury_id: DEFAULT_TREASURY_ID,
treasury_id,
},
}
.data(),
@ -320,3 +324,7 @@ pub fn deserialize_accumulator_update_data(
Proof::WormholeMerkle { vaa, updates } => return Ok((vaa.as_ref().to_vec(), updates)),
}
}
pub fn get_random_treasury_id() -> u8 {
rand::thread_rng().gen()
}

View File

@ -14,6 +14,7 @@ use {
},
sdk::{
deserialize_accumulator_update_data,
get_random_treasury_id,
DEFAULT_TREASURY_ID,
},
},
@ -69,6 +70,7 @@ async fn test_post_update() {
encoded_vaa_addresses[0],
price_update_keypair.pubkey(),
merkle_price_updates[0].clone(),
DEFAULT_TREASURY_ID,
),
&vec![&poster, &price_update_keypair],
None,
@ -111,6 +113,7 @@ async fn test_post_update() {
encoded_vaa_addresses[0],
price_update_keypair.pubkey(),
merkle_price_updates[1].clone(),
DEFAULT_TREASURY_ID,
),
&vec![&poster, &price_update_keypair],
None,
@ -207,6 +210,7 @@ async fn test_post_update_wrong_encoded_vaa_owner() {
Pubkey::new_unique(), // Random pubkey instead of the encoded VAA address
price_update_keypair.pubkey(),
merkle_price_updates[0].clone(),
get_random_treasury_id()
),
&vec![&poster, &price_update_keypair],
None,
@ -247,6 +251,7 @@ async fn test_post_update_wrong_setup() {
encoded_vaa_addresses[0],
price_update_keypair.pubkey(),
merkle_price_updates[0].clone(),
get_random_treasury_id()
),
&vec![&poster, &price_update_keypair],
None,

View File

@ -16,10 +16,10 @@ import {
import {
DEFAULT_PUSH_ORACLE_PROGRAM_ID,
DEFAULT_RECEIVER_PROGRAM_ID,
DEFAULT_TREASURY_ID,
DEFAULT_WORMHOLE_PROGRAM_ID,
getConfigPda,
getGuardianSetPda,
getRandomTreasuryId,
getTreasuryPda,
} from "./address";
import { PublicKey, Keypair } from "@solana/web3.js";
@ -397,6 +397,8 @@ export class PythSolanaReceiver {
const priceFeedIdToPriceUpdateAccount: Record<string, PublicKey> = {};
const closeInstructions: InstructionWithEphemeralSigners[] = [];
const treasuryId = getRandomTreasuryId();
for (const priceUpdateData of priceUpdateDataArray) {
const accumulatorUpdateData = parseAccumulatorUpdateData(
Buffer.from(priceUpdateData, "base64")
@ -411,14 +413,11 @@ export class PythSolanaReceiver {
.postUpdateAtomic({
vaa: trimmedVaa,
merklePriceUpdate: update,
treasuryId: DEFAULT_TREASURY_ID,
treasuryId,
})
.accounts({
priceUpdateAccount: priceUpdateKeypair.publicKey,
treasury: getTreasuryPda(
DEFAULT_TREASURY_ID,
this.receiver.programId
),
treasury: getTreasuryPda(treasuryId, this.receiver.programId),
config: getConfigPda(this.receiver.programId),
guardianSet: getGuardianSetPda(
guardianSetIndex,
@ -536,6 +535,8 @@ export class PythSolanaReceiver {
const priceFeedIdToPriceUpdateAccount: Record<string, PublicKey> = {};
const closeInstructions: InstructionWithEphemeralSigners[] = [];
const treasuryId = getRandomTreasuryId();
for (const priceUpdateData of priceUpdateDataArray) {
const accumulatorUpdateData = parseAccumulatorUpdateData(
Buffer.from(priceUpdateData, "base64")
@ -555,15 +556,12 @@ export class PythSolanaReceiver {
instruction: await this.receiver.methods
.postUpdate({
merklePriceUpdate: update,
treasuryId: DEFAULT_TREASURY_ID,
treasuryId,
})
.accounts({
encodedVaa,
priceUpdateAccount: priceUpdateKeypair.publicKey,
treasury: getTreasuryPda(
DEFAULT_TREASURY_ID,
this.receiver.programId
),
treasury: getTreasuryPda(treasuryId, this.receiver.programId),
config: getConfigPda(this.receiver.programId),
})
.instruction(),
@ -610,6 +608,8 @@ export class PythSolanaReceiver {
const priceFeedIdToPriceUpdateAccount: Record<string, PublicKey> = {};
const closeInstructions: InstructionWithEphemeralSigners[] = [];
const treasuryId = getRandomTreasuryId();
for (const priceUpdateData of priceUpdateDataArray) {
const accumulatorUpdateData = parseAccumulatorUpdateData(
Buffer.from(priceUpdateData, "base64")
@ -625,13 +625,12 @@ export class PythSolanaReceiver {
for (const update of accumulatorUpdateData.updates) {
const feedId = parsePriceFeedMessage(update.message).feedId;
postInstructions.push({
instruction: await this.pushOracle.methods
.updatePriceFeed(
{
merklePriceUpdate: update,
treasuryId: DEFAULT_TREASURY_ID,
treasuryId,
},
shardId,
Array.from(feedId)
@ -643,10 +642,7 @@ export class PythSolanaReceiver {
shardId,
feedId
),
treasury: getTreasuryPda(
DEFAULT_TREASURY_ID,
this.receiver.programId
),
treasury: getTreasuryPda(treasuryId, this.receiver.programId),
config: getConfigPda(this.receiver.programId),
})
.instruction(),

View File

@ -38,7 +38,9 @@ export const getGuardianSetPda = (
* The Pyth Solana Receiver has one treasury account for each u8 `treasuryId`.
* This is meant to avoid write-locks on the treasury account by load-balancing the writes across multiple accounts.
*/
export const DEFAULT_TREASURY_ID = 0;
export function getRandomTreasuryId() {
return Math.floor(Math.random() * 256);
}
/**
* Returns the address of a treasury account from the Pyth Solana Receiver program.