From fd5ee7d90416aea8635d11a6749a7f25645eae7d Mon Sep 17 00:00:00 2001 From: Hardhat Chad Date: Wed, 30 Oct 2024 17:33:20 +0000 Subject: [PATCH 1/7] pool account migration phase 1 --- api/src/consts.rs | 6 +++++ api/src/instruction.rs | 10 ++++++++ api/src/state/pool.rs | 3 +++ program/src/lib.rs | 47 +++++++++++++++++++++---------------- program/src/migrate_pool.rs | 16 +++++++++++++ 5 files changed, 62 insertions(+), 20 deletions(-) create mode 100644 program/src/migrate_pool.rs diff --git a/api/src/consts.rs b/api/src/consts.rs index d01ae90..3314d1f 100644 --- a/api/src/consts.rs +++ b/api/src/consts.rs @@ -1,3 +1,6 @@ +use solana_program::pubkey; +use steel::Pubkey; + /// The seed of the member account PDA. pub const MEMBER: &[u8] = b"member"; @@ -6,3 +9,6 @@ pub const POOL: &[u8] = b"pool"; /// The seed of the share account PDA. pub const SHARE: &[u8] = b"share"; + +/// The authority allowed to run migrations. +pub const ADMIN_ADDRESS: Pubkey = pubkey!("HBUh9g46wk2X89CvaNN15UmsznP59rh6od1h8JwYAopk"); diff --git a/api/src/instruction.rs b/api/src/instruction.rs index 190e1de..3bd5dfc 100644 --- a/api/src/instruction.rs +++ b/api/src/instruction.rs @@ -20,6 +20,9 @@ pub enum PoolInstruction { #[deprecated(since = "0.3.0", note = "Staking has moved to the global boost program")] OpenStake = 103, Submit = 104, + + // Migration + MigratePool = 200, } #[repr(C)] @@ -87,6 +90,12 @@ pub struct Unstake { pub amount: [u8; 8], } +#[repr(C)] +#[derive(Clone, Copy, Debug, Pod, Zeroable)] +pub struct MigratePool { + pub claimable_rewards: [u8; 8], +} + instruction!(PoolInstruction, Attribute); instruction!(PoolInstruction, Claim); instruction!(PoolInstruction, Commit); @@ -97,3 +106,4 @@ instruction!(PoolInstruction, Join); instruction!(PoolInstruction, Stake); instruction!(PoolInstruction, Submit); instruction!(PoolInstruction, Unstake); +instruction!(PoolInstruction, MigratePool); diff --git a/api/src/state/pool.rs b/api/src/state/pool.rs index f7a7040..987576d 100644 --- a/api/src/state/pool.rs +++ b/api/src/state/pool.rs @@ -32,6 +32,9 @@ pub struct Pool { // The total number of members in this pool at the last submission. pub last_total_members: u64, + // TODO enable in phase 2 + // The total claimable rewards in the pool. + // pub claimable_rewards: u64, } account!(AccountDiscriminator, Pool); diff --git a/program/src/lib.rs b/program/src/lib.rs index ff99c36..ab75174 100644 --- a/program/src/lib.rs +++ b/program/src/lib.rs @@ -3,22 +3,24 @@ mod claim; mod commit; mod join; mod launch; +mod migrate_pool; mod open_share; mod open_stake; mod stake; mod submit; mod unstake; -use attribute::*; -use claim::*; -use commit::*; -use join::*; -use launch::*; -use open_share::*; -use open_stake::*; -use stake::*; -use submit::*; -use unstake::*; +// use attribute::*; +// use claim::*; +// use commit::*; +// use join::*; +// use launch::*; +use migrate_pool::*; +// use open_share::*; +// use open_stake::*; +// use stake::*; +// use submit::*; +// use unstake::*; use ore_pool_api::prelude::*; use steel::*; @@ -32,18 +34,23 @@ pub fn process_instruction( let (ix, data) = parse_instruction(&ore_pool_api::ID, program_id, data)?; match ix { // User - PoolInstruction::Join => process_join(accounts, data)?, - PoolInstruction::Claim => process_claim(accounts, data)?, - PoolInstruction::OpenShare => process_open_share(accounts, data)?, - PoolInstruction::Stake => process_stake(accounts, data)?, - PoolInstruction::Unstake => process_unstake(accounts, data)?, + // PoolInstruction::Join => process_join(accounts, data)?, + // PoolInstruction::Claim => process_claim(accounts, data)?, + // PoolInstruction::OpenShare => process_open_share(accounts, data)?, + // PoolInstruction::Stake => process_stake(accounts, data)?, + // PoolInstruction::Unstake => process_unstake(accounts, data)?, // Admin - PoolInstruction::Attribute => process_attribute(accounts, data)?, - PoolInstruction::Commit => process_commit(accounts, data)?, - PoolInstruction::Launch => process_launch(accounts, data)?, - PoolInstruction::OpenStake => process_open_stake(accounts, data)?, - PoolInstruction::Submit => process_submit(accounts, data)?, + // PoolInstruction::Attribute => process_attribute(accounts, data)?, + // PoolInstruction::Commit => process_commit(accounts, data)?, + // PoolInstruction::Launch => process_launch(accounts, data)?, + // PoolInstruction::OpenStake => process_open_stake(accounts, data)?, + // PoolInstruction::Submit => process_submit(accounts, data)?, + + // Migration + PoolInstruction::MigratePool => process_migrate_pool(accounts, data)?, + PoolInstruction::MigratePool => process_migrate_pool(accounts, data)?, + _ => panic!("Temporarily disabled for migration."), } Ok(()) } diff --git a/program/src/migrate_pool.rs b/program/src/migrate_pool.rs new file mode 100644 index 0000000..5499302 --- /dev/null +++ b/program/src/migrate_pool.rs @@ -0,0 +1,16 @@ +use ore_pool_api::prelude::*; +use steel::*; + +pub fn process_migrate_pool(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResult { + // Load accounts. + let [signer_info, pool_info] = accounts else { + return Err(ProgramError::NotEnoughAccountKeys); + }; + signer_info.is_signer()?.has_address(&ADMIN_ADDRESS)?; + pool_info.as_account_mut::(&ore_pool_api::ID)?; + + // Allocate space for new data field. + pool_info.realloc(pool_info.data.borrow().len() + 8, true)?; + + Ok(()) +} From 4bffbfc70da64e5e6b3cfeef935808ba469deaf0 Mon Sep 17 00:00:00 2001 From: Hardhat Chad Date: Wed, 30 Oct 2024 17:46:21 +0000 Subject: [PATCH 2/7] migration phase 1 --- api/src/consts.rs | 3 +++ api/src/instruction.rs | 10 ++++++--- api/src/state/migration.rs | 12 +++++++++++ api/src/state/mod.rs | 9 ++++++++ api/src/state/pool.rs | 2 +- program/src/lib.rs | 25 +++++++++++---------- program/src/migrate_member_balance.rs | 31 +++++++++++++++++++++++++++ program/src/migrate_pool.rs | 19 +++++++++++++++- 8 files changed, 95 insertions(+), 16 deletions(-) create mode 100644 api/src/state/migration.rs create mode 100644 program/src/migrate_member_balance.rs diff --git a/api/src/consts.rs b/api/src/consts.rs index 3314d1f..286b4c3 100644 --- a/api/src/consts.rs +++ b/api/src/consts.rs @@ -10,5 +10,8 @@ pub const POOL: &[u8] = b"pool"; /// The seed of the share account PDA. pub const SHARE: &[u8] = b"share"; +/// The seed of the migration account PDA. +pub const MIGRATION: &[u8] = b"migration"; + /// The authority allowed to run migrations. pub const ADMIN_ADDRESS: Pubkey = pubkey!("HBUh9g46wk2X89CvaNN15UmsznP59rh6od1h8JwYAopk"); diff --git a/api/src/instruction.rs b/api/src/instruction.rs index 3bd5dfc..94a95cf 100644 --- a/api/src/instruction.rs +++ b/api/src/instruction.rs @@ -23,6 +23,7 @@ pub enum PoolInstruction { // Migration MigratePool = 200, + MigrateMemberBalance = 201, } #[repr(C)] @@ -92,9 +93,11 @@ pub struct Unstake { #[repr(C)] #[derive(Clone, Copy, Debug, Pod, Zeroable)] -pub struct MigratePool { - pub claimable_rewards: [u8; 8], -} +pub struct MigratePool {} + +#[repr(C)] +#[derive(Clone, Copy, Debug, Pod, Zeroable)] +pub struct MigrateMemberBalance {} instruction!(PoolInstruction, Attribute); instruction!(PoolInstruction, Claim); @@ -107,3 +110,4 @@ instruction!(PoolInstruction, Stake); instruction!(PoolInstruction, Submit); instruction!(PoolInstruction, Unstake); instruction!(PoolInstruction, MigratePool); +instruction!(PoolInstruction, MigrateMemberBalance); diff --git a/api/src/state/migration.rs b/api/src/state/migration.rs new file mode 100644 index 0000000..fd6c14b --- /dev/null +++ b/api/src/state/migration.rs @@ -0,0 +1,12 @@ +use steel::*; + +use super::AccountDiscriminator; + +#[repr(C)] +#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)] +pub struct Migration { + pub pool: Pubkey, + pub members_migrated: u64, +} + +account!(AccountDiscriminator, Migration); diff --git a/api/src/state/mod.rs b/api/src/state/mod.rs index 765ce89..fd86786 100644 --- a/api/src/state/mod.rs +++ b/api/src/state/mod.rs @@ -1,8 +1,10 @@ mod member; +mod migration; mod pool; mod share; pub use member::*; +pub use migration::*; pub use pool::*; pub use share::*; @@ -16,12 +18,19 @@ pub enum AccountDiscriminator { Member = 100, Pool = 101, Share = 102, + + // Migration account + Migration = 200, } pub fn pool_pda(authority: Pubkey) -> (Pubkey, u8) { Pubkey::find_program_address(&[POOL, authority.as_ref()], &crate::id()) } +pub fn migration_pda(pool: Pubkey) -> (Pubkey, u8) { + Pubkey::find_program_address(&[MIGRATION, pool.as_ref()], &crate::id()) +} + pub fn pool_proof_pda(pool: Pubkey) -> (Pubkey, u8) { Pubkey::find_program_address(&[ore_api::consts::PROOF, pool.as_ref()], &ore_api::id()) } diff --git a/api/src/state/pool.rs b/api/src/state/pool.rs index 987576d..7158987 100644 --- a/api/src/state/pool.rs +++ b/api/src/state/pool.rs @@ -32,7 +32,7 @@ pub struct Pool { // The total number of members in this pool at the last submission. pub last_total_members: u64, - // TODO enable in phase 2 + // TODO Uncomment in phase 2 // The total claimable rewards in the pool. // pub claimable_rewards: u64, } diff --git a/program/src/lib.rs b/program/src/lib.rs index ab75174..14f19d1 100644 --- a/program/src/lib.rs +++ b/program/src/lib.rs @@ -1,20 +1,22 @@ -mod attribute; -mod claim; -mod commit; -mod join; -mod launch; +// mod attribute; +// mod claim; +// mod commit; +// mod join; +// mod launch; +// mod migrate_member_balance; mod migrate_pool; -mod open_share; -mod open_stake; -mod stake; -mod submit; -mod unstake; +// mod open_share; +// mod open_stake; +// mod stake; +// mod submit; +// mod unstake; // use attribute::*; // use claim::*; // use commit::*; // use join::*; // use launch::*; +// use migrate_member_balance::*; use migrate_pool::*; // use open_share::*; // use open_stake::*; @@ -49,7 +51,8 @@ pub fn process_instruction( // Migration PoolInstruction::MigratePool => process_migrate_pool(accounts, data)?, - PoolInstruction::MigratePool => process_migrate_pool(accounts, data)?, + PoolInstruction::MigrateMemberBalance => panic!("Not live yet"), + // PoolInstruction::MigrateMemberBalance => process_migrate_member_balance(accounts, data)?, _ => panic!("Temporarily disabled for migration."), } Ok(()) diff --git a/program/src/migrate_member_balance.rs b/program/src/migrate_member_balance.rs new file mode 100644 index 0000000..9a75754 --- /dev/null +++ b/program/src/migrate_member_balance.rs @@ -0,0 +1,31 @@ +use ore_pool_api::prelude::*; +use steel::*; + +pub fn process_migrate_member_balance(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResult { + // Load accounts. + let [signer_info, pool_info, member_info, migration_info] = accounts else { + return Err(ProgramError::NotEnoughAccountKeys); + }; + signer_info.is_signer()?.has_address(&ADMIN_ADDRESS)?; + let pool = pool_info.as_account_mut::(&ore_pool_api::ID)?; + let member = member_info + .as_account::(&ore_pool_api::ID)? + .assert(|m| m.pool == *pool_info.key)?; + let migration = migration_info + .as_account_mut::(&ore_pool_api::ID)? + .assert_mut(|m| m.pool == *pool_info.key)? + .assert_mut(|m| m.members_migrated == member.id)?; + + // Increment pool claimable balance + pool.claimable_rewards += member.balance; + + // Increment migrated balance + migration.members_migrated += 1; + + // End migration if done, + if migration.members_migrated == pool.total_members { + migration_info.close(signer_info)?; + } + + Ok(()) +} diff --git a/program/src/migrate_pool.rs b/program/src/migrate_pool.rs index 5499302..bf5d88a 100644 --- a/program/src/migrate_pool.rs +++ b/program/src/migrate_pool.rs @@ -3,14 +3,31 @@ use steel::*; pub fn process_migrate_pool(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResult { // Load accounts. - let [signer_info, pool_info] = accounts else { + let [signer_info, pool_info, migration_info, system_program] = accounts else { return Err(ProgramError::NotEnoughAccountKeys); }; signer_info.is_signer()?.has_address(&ADMIN_ADDRESS)?; pool_info.as_account_mut::(&ore_pool_api::ID)?; + migration_info + .is_empty()? + .is_writable()? + .has_seeds(&[MIGRATION, pool_info.key.as_ref()], &ore_pool_api::ID)?; + system_program.is_program(&system_program::ID)?; // Allocate space for new data field. pool_info.realloc(pool_info.data.borrow().len() + 8, true)?; + // Create migration account + create_account::( + migration_info, + system_program, + signer_info, + &ore_pool_api::ID, + &[MIGRATION, pool_info.key.as_ref()], + )?; + let migration = migration_info.as_account_mut::(&ore_pool_api::ID)?; + migration.pool = *pool_info.key; + migration.members_migrated = 0; + Ok(()) } From c2e92aaa43e6f4fb93a7ae93ae9805e41c2f4a7b Mon Sep 17 00:00:00 2001 From: Hardhat Chad Date: Fri, 1 Nov 2024 23:09:46 +0000 Subject: [PATCH 3/7] migration script --- Cargo.lock | 36 +++++++++ Cargo.toml | 3 +- api/src/sdk.rs | 31 +++++++- migration/Cargo.toml | 36 +++++++++ migration/src/main.rs | 102 ++++++++++++++++++++++++++ program/src/migrate_member_balance.rs | 3 +- 6 files changed, 208 insertions(+), 3 deletions(-) create mode 100644 migration/Cargo.toml create mode 100644 migration/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 09f2bfb..0151773 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3165,6 +3165,42 @@ dependencies = [ "thiserror", ] +[[package]] +name = "ore-pool-migration" +version = "0.0.1" +dependencies = [ + "actix-cors", + "actix-web", + "base64 0.22.1", + "bincode", + "bytemuck", + "deadpool-postgres", + "drillx", + "env_logger 0.11.5", + "futures", + "futures-channel", + "futures-util", + "log", + "ore-api", + "ore-boost-api", + "ore-pool-api", + "ore-pool-types", + "postgres-types", + "rand 0.8.5", + "reqwest 0.12.4", + "serde", + "serde_json", + "sha3 0.10.8", + "solana-account-decoder", + "solana-client", + "solana-sdk", + "solana-transaction-status", + "steel", + "thiserror", + "tokio", + "tokio-postgres", +] + [[package]] name = "ore-pool-program" version = "0.2.2" diff --git a/Cargo.toml b/Cargo.toml index 13ee2dc..9eba9ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [workspace] resolver = "2" -members = ["admin", "api", "program", "server", "types"] +members = ["admin", "api", "program", "server", "types", "migration"] [workspace.package] version = "0.2.2" @@ -39,6 +39,7 @@ reqwest = { version = "0.12", features = ["json"] } serde = { features = ["derive"], version = "1.0" } serde_json = "1.0" sha3 = "0.10" +solana-account-decoder = "^1.18" solana-client = "^1.18" solana-program = "^1.18" solana-sdk = "^1.18" diff --git a/api/src/sdk.rs b/api/src/sdk.rs index f911850..82a7c8c 100644 --- a/api/src/sdk.rs +++ b/api/src/sdk.rs @@ -5,7 +5,7 @@ use steel::*; use crate::{ error::ApiError, instruction::*, - state::{member_pda, pool_pda, pool_proof_pda, share_pda}, + state::{member_pda, migration_pda, pool_pda, pool_proof_pda, share_pda}, }; /// Builds a launch instruction. @@ -287,6 +287,35 @@ pub fn open_stake(signer: Pubkey, mint: Pubkey) -> Instruction { } } +pub fn migrate_pool(signer: Pubkey, pool: Pubkey) -> Instruction { + let (migration_address, _) = migration_pda(pool); + Instruction { + program_id: crate::ID, + accounts: vec![ + AccountMeta::new(signer, true), + AccountMeta::new(pool, false), + AccountMeta::new(migration_address, false), + AccountMeta::new_readonly(system_program::ID, false), + ], + data: MigratePool {}.to_bytes(), + } +} + +pub fn migrate_member_balance(signer: Pubkey, pool: Pubkey, member: Pubkey) -> Instruction { + let (migration_address, _) = migration_pda(pool); + Instruction { + program_id: crate::ID, + accounts: vec![ + AccountMeta::new(signer, true), + AccountMeta::new(pool, false), + AccountMeta::new_readonly(member, false), + AccountMeta::new(migration_address, false), + AccountMeta::new_readonly(system_program::ID, false), + ], + data: MigrateMemberBalance {}.to_bytes(), + } +} + fn url_to_bytes(input: &str) -> Result<[u8; 128], ApiError> { let bytes = input.as_bytes(); let len = bytes.len(); diff --git a/migration/Cargo.toml b/migration/Cargo.toml new file mode 100644 index 0000000..20d04f1 --- /dev/null +++ b/migration/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "ore-pool-migration" +version = "0.0.1" +edition = "2021" + +[dependencies] +actix-cors = { workspace = true } +actix-web = { workspace = true } +base64 = { workspace = true } +bincode = { workspace = true } +bytemuck = { workspace = true } +deadpool-postgres = { workspace = true } +drillx = { workspace = true } +env_logger = { workspace = true } +futures = { workspace = true } +futures-channel = { workspace = true } +futures-util = { workspace = true } +log = { workspace = true } +ore-api = { workspace = true } +ore-boost-api = { workspace = true } +ore-pool-api = { workspace = true } +ore-pool-types = { workspace = true } +postgres-types = { workspace = true } +reqwest = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +sha3 = { workspace = true } +solana-account-decoder = { workspace = true } +solana-client = { workspace = true } +solana-sdk = { workspace = true } +solana-transaction-status = { workspace = true } +steel = { workspace = true } +thiserror = { workspace = true } +tokio = { workspace = true } +tokio-postgres = { workspace = true } +rand = "0.8.5" diff --git a/migration/src/main.rs b/migration/src/main.rs new file mode 100644 index 0000000..3bab2aa --- /dev/null +++ b/migration/src/main.rs @@ -0,0 +1,102 @@ +use ore_pool_api::state::{Member, Pool}; +use solana_account_decoder::UiAccountEncoding; +use solana_client::{ + nonblocking::rpc_client::RpcClient, + rpc_config::{RpcAccountInfoConfig, RpcProgramAccountsConfig}, + rpc_filter::{Memcmp, RpcFilterType}, +}; +use solana_sdk::{ + commitment_config::CommitmentConfig, compute_budget::ComputeBudgetInstruction, + signature::read_keypair_file, signer::Signer, transaction::Transaction, +}; +use steel::{AccountDeserialize, Discriminator}; + +#[tokio::main] +pub async fn main() { + // Create client + let signer = read_keypair_file("../migration-admin-key.json").unwrap(); + let url = "https://mainnet.helius-rpc.com/?api-key=TODO"; + let rpc = RpcClient::new_with_commitment(url.to_owned(), CommitmentConfig::confirmed()); + + // Fetch pools + let pool_filter = RpcFilterType::Memcmp(Memcmp::new_raw_bytes( + 0, + Pool::discriminator().to_le_bytes().to_vec(), + )); + let Ok(pools) = rpc + .get_program_accounts_with_config( + &ore_pool_api::ID, + RpcProgramAccountsConfig { + filters: Some(vec![pool_filter]), + account_config: RpcAccountInfoConfig { + encoding: Some(UiAccountEncoding::Base64), + data_slice: None, + commitment: None, + min_context_slot: None, + }, + with_context: None, + }, + ) + .await + else { + return; + }; + println!("Pools {:?}\n", pools.len()); + + // TODO Phase 1: Initialize migration + for pool in pools { + let ix = ore_pool_api::sdk::migrate_pool(signer.pubkey(), pool.0); + let cu_limit_ix = ComputeBudgetInstruction::set_compute_unit_limit(200_000); + let cu_price_ix = ComputeBudgetInstruction::set_compute_unit_price(10_000); + let final_ixs = &[cu_limit_ix, cu_price_ix, ix]; + let hash = rpc.get_latest_blockhash().await.unwrap(); + let mut tx = Transaction::new_with_payer(final_ixs.as_slice(), Some(&signer.pubkey())); + tx.sign(&[&signer], hash); + rpc.send_transaction(&tx).await.unwrap(); + } + + // TODO: Phase 2: Migrate member balances + // for pool in pools { + // // Fetch members of the given pool + // let member_filter = RpcFilterType::Memcmp(Memcmp::new_raw_bytes( + // 0, + // Member::discriminator().to_le_bytes().to_vec(), + // )); + // let pool_member_filter = + // RpcFilterType::Memcmp(Memcmp::new_raw_bytes(16, pool.0.to_bytes().to_vec())); + // let Ok(members) = rpc + // .get_program_accounts_with_config( + // &ore_pool_api::ID, + // RpcProgramAccountsConfig { + // filters: Some(vec![member_filter, pool_member_filter]), + // account_config: RpcAccountInfoConfig { + // encoding: Some(UiAccountEncoding::Base64), + // data_slice: None, + // commitment: None, + // min_context_slot: None, + // }, + // with_context: None, + // }, + // ) + // .await + // else { + // return; + // }; + // let pool_account = Pool::try_from_bytes(&pool.1.data).unwrap(); + // println!("Pool: {}", pool.0); + // println!("Expected members: {}", pool_account.total_members); + // println!("Actual members: {}\n", members.len()); + + // // Migrate each member balance + // for member in members { + // let ix = ore_pool_api::sdk::migrate_member_balance(signer.pubkey(), pool.0, member.0); + // let cu_limit_ix = ComputeBudgetInstruction::set_compute_unit_limit(200_000); + // let cu_price_ix = ComputeBudgetInstruction::set_compute_unit_price(10_000); + // let final_ixs = &[cu_limit_ix, cu_price_ix, ix]; + // let hash = rpc.get_latest_blockhash().await.unwrap(); + // let mut tx = Transaction::new_with_payer(final_ixs.as_slice(), Some(&signer.pubkey())); + // tx.sign(&[&signer], hash); + // rpc.send_transaction(&tx).await.unwrap(); + // } + // } +} diff --git a/program/src/migrate_member_balance.rs b/program/src/migrate_member_balance.rs index 9a75754..0aaeb9e 100644 --- a/program/src/migrate_member_balance.rs +++ b/program/src/migrate_member_balance.rs @@ -3,7 +3,7 @@ use steel::*; pub fn process_migrate_member_balance(accounts: &[AccountInfo<'_>], _data: &[u8]) -> ProgramResult { // Load accounts. - let [signer_info, pool_info, member_info, migration_info] = accounts else { + let [signer_info, pool_info, member_info, migration_info, system_program] = accounts else { return Err(ProgramError::NotEnoughAccountKeys); }; signer_info.is_signer()?.has_address(&ADMIN_ADDRESS)?; @@ -15,6 +15,7 @@ pub fn process_migrate_member_balance(accounts: &[AccountInfo<'_>], _data: &[u8] .as_account_mut::(&ore_pool_api::ID)? .assert_mut(|m| m.pool == *pool_info.key)? .assert_mut(|m| m.members_migrated == member.id)?; + system_program.is_program(&system_program::ID)?; // Increment pool claimable balance pool.claimable_rewards += member.balance; From ec74250c23db1550b532aac0de28021036fa4fca Mon Sep 17 00:00:00 2001 From: Hardhat Chad Date: Mon, 2 Dec 2024 18:59:19 +0000 Subject: [PATCH 4/7] bump version --- Cargo.lock | 52 +++++++++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0151773..c0318ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -631,9 +631,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.84" +version = "0.1.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1244b10dcd56c92219da4e14caa97e312079e185f04ba3eea25061561dc0a0" +checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" dependencies = [ "proc-macro2", "quote", @@ -2680,9 +2680,9 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "litemap" @@ -3176,7 +3176,7 @@ dependencies = [ "bytemuck", "deadpool-postgres", "drillx", - "env_logger 0.11.5", + "env_logger 0.11.6", "futures", "futures-channel", "futures-util", @@ -3343,27 +3343,27 @@ dependencies = [ [[package]] name = "phf" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ "phf_shared", ] [[package]] name = "phf_shared" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ - "siphasher", + "siphasher 1.0.1", ] [[package]] name = "pin-project-lite" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -3918,9 +3918,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.42" +version = "0.38.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" +checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6" dependencies = [ "bitflags 2.6.0", "errno", @@ -4059,9 +4059,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.13.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1863fd3768cd83c56a7f60faa4dc0d403f1b6df0a38c3c25f44b7894e45370d5" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys", "libc", @@ -4104,9 +4104,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.134" +version = "1.0.135" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d" +checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" dependencies = [ "itoa", "memchr", @@ -4244,6 +4244,12 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "sized-chunks" version = "0.6.5" @@ -4783,7 +4789,7 @@ dependencies = [ "serde_with", "sha2 0.10.8", "sha3 0.10.8", - "siphasher", + "siphasher 0.3.11", "solana-frozen-abi", "solana-frozen-abi-macro", "solana-logger", @@ -5530,9 +5536,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.42.0" +version = "1.43.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" dependencies = [ "backtrace", "bytes", @@ -5548,9 +5554,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", From a2ead039ada28d51a578b844e941be20392d7953 Mon Sep 17 00:00:00 2001 From: Hardhat Chad Date: Thu, 9 Jan 2025 09:43:09 -0800 Subject: [PATCH 5/7] repurpose rewards field and remove realloc --- api/src/state/pool.rs | 7 ++----- migration/src/main.rs | 4 +++- program/src/migrate_member_balance.rs | 4 ++-- program/src/migrate_pool.rs | 4 ++-- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/api/src/state/pool.rs b/api/src/state/pool.rs index 7158987..9aeee3c 100644 --- a/api/src/state/pool.rs +++ b/api/src/state/pool.rs @@ -21,8 +21,8 @@ pub struct Pool { /// Foreign key to the ORE proof account. pub last_hash_at: i64, - /// The reward from the most recent solution. - pub reward: u64, + // The total claimable rewards in the pool. + pub total_rewards: u64, /// The total number of hashes this pool has submitted. pub total_submissions: u64, @@ -32,9 +32,6 @@ pub struct Pool { // The total number of members in this pool at the last submission. pub last_total_members: u64, - // TODO Uncomment in phase 2 - // The total claimable rewards in the pool. - // pub claimable_rewards: u64, } account!(AccountDiscriminator, Pool); diff --git a/migration/src/main.rs b/migration/src/main.rs index 3bab2aa..2db21b8 100644 --- a/migration/src/main.rs +++ b/migration/src/main.rs @@ -45,6 +45,7 @@ pub async fn main() { // TODO Phase 1: Initialize migration for pool in pools { + println!("Pool: {:?}", pool.0); let ix = ore_pool_api::sdk::migrate_pool(signer.pubkey(), pool.0); let cu_limit_ix = ComputeBudgetInstruction::set_compute_unit_limit(200_000); let cu_price_ix = ComputeBudgetInstruction::set_compute_unit_price(10_000); @@ -52,7 +53,8 @@ pub async fn main() { let hash = rpc.get_latest_blockhash().await.unwrap(); let mut tx = Transaction::new_with_payer(final_ixs.as_slice(), Some(&signer.pubkey())); tx.sign(&[&signer], hash); - rpc.send_transaction(&tx).await.unwrap(); + println!("{:?}", tx); + // rpc.send_transaction(&tx).await.unwrap(); } // TODO: Phase 2: Migrate member balances diff --git a/program/src/migrate_member_balance.rs b/program/src/migrate_member_balance.rs index 0aaeb9e..90834bc 100644 --- a/program/src/migrate_member_balance.rs +++ b/program/src/migrate_member_balance.rs @@ -17,8 +17,8 @@ pub fn process_migrate_member_balance(accounts: &[AccountInfo<'_>], _data: &[u8] .assert_mut(|m| m.members_migrated == member.id)?; system_program.is_program(&system_program::ID)?; - // Increment pool claimable balance - pool.claimable_rewards += member.balance; + // Increment pool total rewards counter + pool.total_rewards += member.balance; // Increment migrated balance migration.members_migrated += 1; diff --git a/program/src/migrate_pool.rs b/program/src/migrate_pool.rs index bf5d88a..9f1b32c 100644 --- a/program/src/migrate_pool.rs +++ b/program/src/migrate_pool.rs @@ -7,7 +7,7 @@ pub fn process_migrate_pool(accounts: &[AccountInfo<'_>], _data: &[u8]) -> Progr return Err(ProgramError::NotEnoughAccountKeys); }; signer_info.is_signer()?.has_address(&ADMIN_ADDRESS)?; - pool_info.as_account_mut::(&ore_pool_api::ID)?; + let pool = pool_info.as_account_mut::(&ore_pool_api::ID)?; migration_info .is_empty()? .is_writable()? @@ -15,7 +15,7 @@ pub fn process_migrate_pool(accounts: &[AccountInfo<'_>], _data: &[u8]) -> Progr system_program.is_program(&system_program::ID)?; // Allocate space for new data field. - pool_info.realloc(pool_info.data.borrow().len() + 8, true)?; + pool.total_rewards = 0; // Create migration account create_account::( From 1d2492369c3409bfcd4a9be2589f887f8e2c8e97 Mon Sep 17 00:00:00 2001 From: Hardhat Chad Date: Thu, 9 Jan 2025 09:54:07 -0800 Subject: [PATCH 6/7] clean up migration script --- migration/src/main.rs | 46 +++++++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/migration/src/main.rs b/migration/src/main.rs index 2db21b8..73480e0 100644 --- a/migration/src/main.rs +++ b/migration/src/main.rs @@ -14,8 +14,8 @@ use steel::{AccountDeserialize, Discriminator}; #[tokio::main] pub async fn main() { // Create client - let signer = read_keypair_file("../migration-admin-key.json").unwrap(); - let url = "https://mainnet.helius-rpc.com/?api-key=TODO"; + let signer = read_keypair_file("~/.config/solana/id.json").unwrap(); // TODO + let url = "https://devnet.helius-rpc.com/?api-key=TODO"; // TODO Mainnet let rpc = RpcClient::new_with_commitment(url.to_owned(), CommitmentConfig::confirmed()); // Fetch pools @@ -23,7 +23,7 @@ pub async fn main() { 0, Pool::discriminator().to_le_bytes().to_vec(), )); - let Ok(pools) = rpc + let pools = match rpc .get_program_accounts_with_config( &ore_pool_api::ID, RpcProgramAccountsConfig { @@ -38,10 +38,16 @@ pub async fn main() { }, ) .await - else { - return; + { + Ok(pools) => { + println!("Num pools {:?}\n", pools.len()); + pools + } + Err(e) => { + println!("Error fetching pools: {:?}", e); + return; + } }; - println!("Pools {:?}\n", pools.len()); // TODO Phase 1: Initialize migration for pool in pools { @@ -59,6 +65,10 @@ pub async fn main() { // TODO: Phase 2: Migrate member balances // for pool in pools { + // // Fetch pool + // let pool_account = Pool::try_from_bytes(&pool.1.data).unwrap(); + // println!("Pool: {}", pool.0); + // // Fetch members of the given pool // let member_filter = RpcFilterType::Memcmp(Memcmp::new_raw_bytes( // 0, @@ -66,7 +76,7 @@ pub async fn main() { // )); // let pool_member_filter = // RpcFilterType::Memcmp(Memcmp::new_raw_bytes(16, pool.0.to_bytes().to_vec())); - // let Ok(members) = rpc + // let members = match rpc // .get_program_accounts_with_config( // &ore_pool_api::ID, // RpcProgramAccountsConfig { @@ -81,13 +91,17 @@ pub async fn main() { // }, // ) // .await - // else { - // return; - // }; - // let pool_account = Pool::try_from_bytes(&pool.1.data).unwrap(); - // println!("Pool: {}", pool.0); - // println!("Expected members: {}", pool_account.total_members); - // println!("Actual members: {}\n", members.len()); + // { + // Ok(members) => { + // println!("Expected members: {}", pool_account.total_members); + // println!("Actual members: {}\n", members.len()); + // members + // } + // Err(e) => { + // println!("Error fetching members: {:?}", e); + // return; + // } + // }; // // Migrate each member balance // for member in members { @@ -98,7 +112,9 @@ pub async fn main() { // let hash = rpc.get_latest_blockhash().await.unwrap(); // let mut tx = Transaction::new_with_payer(final_ixs.as_slice(), Some(&signer.pubkey())); // tx.sign(&[&signer], hash); - // rpc.send_transaction(&tx).await.unwrap(); + // println!("Migrate member balance: {:?}", tx); + // // rpc.send_transaction(&tx).await.unwrap(); // } // } } + From 6b01a5b18b936766797af43f2168fd3d6160e6e7 Mon Sep 17 00:00:00 2001 From: Hardhat Chad Date: Thu, 9 Jan 2025 10:14:20 -0800 Subject: [PATCH 7/7] comment --- api/src/state/pool.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/state/pool.rs b/api/src/state/pool.rs index 9aeee3c..67b0804 100644 --- a/api/src/state/pool.rs +++ b/api/src/state/pool.rs @@ -21,7 +21,7 @@ pub struct Pool { /// Foreign key to the ORE proof account. pub last_hash_at: i64, - // The total claimable rewards in the pool. + /// The total claimable rewards in the pool. pub total_rewards: u64, /// The total number of hashes this pool has submitted.