diff --git a/mobile_packet_verifier/src/burner.rs b/mobile_packet_verifier/src/burner.rs index f1408d35a..df04a4ca0 100644 --- a/mobile_packet_verifier/src/burner.rs +++ b/mobile_packet_verifier/src/burner.rs @@ -53,6 +53,7 @@ pub struct Burner { program_cache: BurnProgramCache, keypair: [u8; 64], cluster: String, + enable_dc_burn: bool, } #[derive(thiserror::Error, Debug)] @@ -92,6 +93,7 @@ impl Burner { valid_sessions, keypair: keypair.to_bytes(), cluster: settings.cluster.clone(), + enable_dc_burn: settings.enable_dc_burn, }) } @@ -119,99 +121,12 @@ impl Burner { }, ) in payer_totals.into_iter() { - // Fetch the sub dao epoch info: - const EPOCH_LENGTH: u64 = 60 * 60 * 24; - let epoch = SystemTime::now() - .duration_since(SystemTime::UNIX_EPOCH)? - .as_secs() - / EPOCH_LENGTH; - let (sub_dao_epoch_info, _) = Pubkey::find_program_address( - &[ - "sub_dao_epoch_info".as_bytes(), - self.program_cache.sub_dao.as_ref(), - &epoch.to_le_bytes(), - ], - &helium_sub_daos::ID, - ); - let amount = bytes_to_dc(total_bytes); - // Burn the DC for the payer - let ddc_key = crate::pdas::delegated_data_credits(&self.program_cache.sub_dao, &payer); - let account_data = self.provider.get_account_data(&ddc_key).await?; - let mut account_data = account_data.as_ref(); - let escrow_account = - DelegatedDataCreditsV0::try_deserialize(&mut account_data)?.escrow_account; - - tracing::info!("Burning {} DC from {}", amount, payer); - - let instructions = { - let request = RequestBuilder::from( - data_credits::id(), - &self.cluster, - std::rc::Rc::new(Keypair::from_bytes(&self.keypair).unwrap()), - Some(CommitmentConfig::confirmed()), - RequestNamespace::Global, - ); - - let accounts = accounts::BurnDelegatedDataCreditsV0 { - sub_dao_epoch_info, - dao: self.program_cache.dao, - sub_dao: self.program_cache.sub_dao, - account_payer: self.program_cache.account_payer, - data_credits: self.program_cache.data_credits, - delegated_data_credits: ddc_key, - token_program: spl_token::id(), - helium_sub_daos_program: helium_sub_daos::id(), - system_program: solana_program::system_program::id(), - dc_burn_authority: self.program_cache.dc_burn_authority, - dc_mint: self.program_cache.dc_mint, - escrow_account, - registrar: self.program_cache.registrar, - }; - let args = instruction::BurnDelegatedDataCreditsV0 { - args: data_credits::BurnDelegatedDataCreditsArgsV0 { amount }, - }; - - // As far as I can tell, the instructions function does not actually have any - // error paths. - request - .accounts(accounts) - .args(args) - .instructions() - .unwrap() - }; - - let blockhash = self.provider.get_latest_blockhash().await?; - let signer = Keypair::from_bytes(&self.keypair).unwrap(); - - let tx = SolanaTransaction::new_signed_with_payer( - &instructions, - Some(&signer.pubkey()), - &[&signer], - blockhash, - ); - - // Preflight can be flakey, so we skip it for now - let config = RpcSendTransactionConfig { - skip_preflight: true, - ..Default::default() - }; - let signature = self - .provider - .send_transaction_with_config(&tx, config) - .await?; - let result = self.provider.confirm_transaction(&signature).await?; - - if !result { - return Err(BurnError::TransactionFailed(signature)); + if self.enable_dc_burn { + self.burn_data_credits(&payer, amount).await?; } - tracing::info!( - "Successfully burned data credits. Transaction: {}", - signature - ); - // Delete from the data transfer session and write out to S3 sqlx::query("DELETE FROM data_tranfer_sessions WHERE payer = $1") @@ -239,6 +154,105 @@ impl Burner { Ok(()) } + + async fn burn_data_credits( + &self, + payer: &PublicKeyBinary, + amount: u64, + ) -> Result<(), BurnError> { + tracing::info!("Burning {} DC from {}", amount, payer); + + // Fetch the sub dao epoch info: + const EPOCH_LENGTH: u64 = 60 * 60 * 24; + let epoch = SystemTime::now() + .duration_since(SystemTime::UNIX_EPOCH)? + .as_secs() + / EPOCH_LENGTH; + let (sub_dao_epoch_info, _) = Pubkey::find_program_address( + &[ + "sub_dao_epoch_info".as_bytes(), + self.program_cache.sub_dao.as_ref(), + &epoch.to_le_bytes(), + ], + &helium_sub_daos::ID, + ); + + // Burn the DC for the payer + let ddc_key = crate::pdas::delegated_data_credits(&self.program_cache.sub_dao, payer); + let account_data = self.provider.get_account_data(&ddc_key).await?; + let mut account_data = account_data.as_ref(); + let escrow_account = + DelegatedDataCreditsV0::try_deserialize(&mut account_data)?.escrow_account; + + let instructions = { + let request = RequestBuilder::from( + data_credits::id(), + &self.cluster, + std::rc::Rc::new(Keypair::from_bytes(&self.keypair).unwrap()), + Some(CommitmentConfig::confirmed()), + RequestNamespace::Global, + ); + + let accounts = accounts::BurnDelegatedDataCreditsV0 { + sub_dao_epoch_info, + dao: self.program_cache.dao, + sub_dao: self.program_cache.sub_dao, + account_payer: self.program_cache.account_payer, + data_credits: self.program_cache.data_credits, + delegated_data_credits: ddc_key, + token_program: spl_token::id(), + helium_sub_daos_program: helium_sub_daos::id(), + system_program: solana_program::system_program::id(), + dc_burn_authority: self.program_cache.dc_burn_authority, + dc_mint: self.program_cache.dc_mint, + escrow_account, + registrar: self.program_cache.registrar, + }; + let args = instruction::BurnDelegatedDataCreditsV0 { + args: data_credits::BurnDelegatedDataCreditsArgsV0 { amount }, + }; + + // As far as I can tell, the instructions function does not actually have any + // error paths. + request + .accounts(accounts) + .args(args) + .instructions() + .unwrap() + }; + + let blockhash = self.provider.get_latest_blockhash().await?; + let signer = Keypair::from_bytes(&self.keypair).unwrap(); + + let tx = SolanaTransaction::new_signed_with_payer( + &instructions, + Some(&signer.pubkey()), + &[&signer], + blockhash, + ); + + // Preflight can be flakey, so we skip it for now + let config = RpcSendTransactionConfig { + skip_preflight: true, + ..Default::default() + }; + let signature = self + .provider + .send_transaction_with_config(&tx, config) + .await?; + let result = self.provider.confirm_transaction(&signature).await?; + + if !result { + return Err(BurnError::TransactionFailed(signature)); + } + + tracing::info!( + "Successfully burned data credits. Transaction: {}", + signature + ); + + Ok(()) + } } const BYTES_PER_DC: u64 = 20_000; diff --git a/mobile_packet_verifier/src/settings.rs b/mobile_packet_verifier/src/settings.rs index 25a473605..c9c1b8bc5 100644 --- a/mobile_packet_verifier/src/settings.rs +++ b/mobile_packet_verifier/src/settings.rs @@ -26,6 +26,8 @@ pub struct Settings { pub ingest: file_store::Settings, pub output: file_store::Settings, pub metrics: poc_metrics::Settings, + #[serde(default)] + pub enable_dc_burn: bool, } pub fn default_url() -> http::Uri {