diff --git a/Cargo.lock b/Cargo.lock index 9d9dd7a10..84d06b92b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2666,7 +2666,7 @@ dependencies = [ [[package]] name = "mc-full-service" -version = "1.9.1" +version = "1.9.2" dependencies = [ "anyhow", "base64 0.13.0", diff --git a/full-service/Cargo.toml b/full-service/Cargo.toml index 55066128c..e95d01574 100644 --- a/full-service/Cargo.toml +++ b/full-service/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mc-full-service" -version = "1.9.1" +version = "1.9.2" authors = ["MobileCoin"] edition = "2018" build = "build.rs" diff --git a/full-service/src/bin/main.rs b/full-service/src/bin/main.rs index c30dd0475..8127ef5b2 100644 --- a/full-service/src/bin/main.rs +++ b/full-service/src/bin/main.rs @@ -13,6 +13,7 @@ use mc_fog_report_validation::FogResolver; use mc_full_service::{ check_host, config::APIConfig, + service::address::AddressService, wallet::{consensus_backed_rocket, validator_backed_rocket, APIKeyState, WalletState}, ValidatorLedgerSyncThread, WalletDb, WalletService, }; @@ -102,7 +103,8 @@ fn consensus_backed_full_service( // Verifier let mut mr_signer_verifier = MrSignerVerifier::from(mc_consensus_enclave_measurement::sigstruct()); - mr_signer_verifier.allow_hardening_advisories(mc_consensus_enclave_measurement::HARDENING_ADVISORIES); + mr_signer_verifier + .allow_hardening_advisories(mc_consensus_enclave_measurement::HARDENING_ADVISORIES); let mut verifier = Verifier::default(); verifier.mr_signer(mr_signer_verifier).debug(DEBUG_ENCLAVE); @@ -163,6 +165,11 @@ fn consensus_backed_full_service( config.offline, logger, ); + + service + .assign_missing_reserved_subaddresses_for_accounts() + .unwrap(); + let state = WalletState { service }; let rocket = consensus_backed_rocket(rocket_config, state); @@ -250,6 +257,11 @@ fn validator_backed_full_service( false, logger, ); + + service + .assign_missing_reserved_subaddresses_for_accounts() + .unwrap(); + let state = WalletState { service }; let rocket = validator_backed_rocket(rocket_config, state); diff --git a/full-service/src/config.rs b/full-service/src/config.rs index 07fa6ae7d..195e46a0f 100644 --- a/full-service/src/config.rs +++ b/full-service/src/config.rs @@ -93,7 +93,9 @@ impl APIConfig { self.fog_ingest_enclave_css.as_ref().map(|signature| { let mr_signer_verifier = { let mut mr_signer_verifier = MrSignerVerifier::from(signature); - mr_signer_verifier.allow_hardening_advisories(mc_consensus_enclave_measurement::HARDENING_ADVISORIES); + mr_signer_verifier.allow_hardening_advisories( + mc_consensus_enclave_measurement::HARDENING_ADVISORIES, + ); mr_signer_verifier }; diff --git a/full-service/src/db/account.rs b/full-service/src/db/account.rs index bc895ac9a..e060e52e3 100644 --- a/full-service/src/db/account.rs +++ b/full-service/src/db/account.rs @@ -25,6 +25,7 @@ use mc_account_keys::{ }; use mc_account_keys_slip10::Slip10Key; use mc_crypto_digestible::{Digestible, MerlinTranscript}; +use mc_ledger_db::LedgerDB; use std::fmt; #[derive(Debug, Clone, Eq, PartialEq, Hash)] @@ -70,6 +71,7 @@ pub trait AccountModel { fog_report_url: String, fog_report_id: String, fog_authority_spki: String, + ledger_db: &LedgerDB, conn: &Conn, ) -> Result<(AccountID, String), WalletDbError>; @@ -87,6 +89,7 @@ pub trait AccountModel { fog_report_url: String, fog_report_id: String, fog_authority_spki: String, + ledger_db: &LedgerDB, conn: &Conn, ) -> Result<(AccountID, String), WalletDbError>; @@ -104,6 +107,7 @@ pub trait AccountModel { next_subaddress_index: Option, name: &str, fog_enabled: bool, + ledger_db: &LedgerDB, conn: &Conn, ) -> Result<(AccountID, String), WalletDbError>; @@ -118,6 +122,7 @@ pub trait AccountModel { fog_report_url: String, fog_report_id: String, fog_authority_spki: String, + ledger_db: &LedgerDB, conn: &Conn, ) -> Result; @@ -132,6 +137,7 @@ pub trait AccountModel { fog_report_url: String, fog_report_id: String, fog_authority_spki: String, + ledger_db: &LedgerDB, conn: &Conn, ) -> Result; @@ -176,6 +182,7 @@ impl AccountModel for Account { fog_report_url: String, fog_report_id: String, fog_authority_spki: String, + ledger_db: &LedgerDB, conn: &Conn, ) -> Result<(AccountID, String), WalletDbError> { let fog_enabled = !fog_report_url.is_empty(); @@ -195,6 +202,7 @@ impl AccountModel for Account { next_subaddress_index, name, fog_enabled, + ledger_db, conn, ) } @@ -208,6 +216,7 @@ impl AccountModel for Account { fog_report_url: String, fog_report_id: String, fog_authority_spki: String, + ledger_db: &LedgerDB, conn: &Conn, ) -> Result<(AccountID, String), WalletDbError> { let fog_enabled = !fog_report_url.is_empty(); @@ -229,6 +238,7 @@ impl AccountModel for Account { next_subaddress_index, name, fog_enabled, + ledger_db, conn, ) } @@ -242,6 +252,7 @@ impl AccountModel for Account { next_subaddress_index: Option, name: &str, fog_enabled: bool, + ledger_db: &LedgerDB, conn: &Conn, ) -> Result<(AccountID, String), WalletDbError> { use crate::db::schema::accounts; @@ -295,6 +306,7 @@ impl AccountModel for Account { * always for main? */ DEFAULT_SUBADDRESS_INDEX, "Main", + ledger_db, conn, )?; if !fog_enabled { @@ -303,6 +315,7 @@ impl AccountModel for Account { None, LEGACY_CHANGE_SUBADDRESS_INDEX, "Legacy Change", + ledger_db, conn, )?; @@ -312,11 +325,19 @@ impl AccountModel for Account { * always for main? */ CHANGE_SUBADDRESS_INDEX, "Change", + ledger_db, conn, )?; for subaddress_index in 2..next_subaddress_index { - AssignedSubaddress::create(account_key, None, subaddress_index as u64, "", conn)?; + AssignedSubaddress::create( + account_key, + None, + subaddress_index as u64, + "", + ledger_db, + conn, + )?; } } @@ -332,6 +353,7 @@ impl AccountModel for Account { fog_report_url: String, fog_report_id: String, fog_authority_spki: String, + ledger_db: &LedgerDB, conn: &Conn, ) -> Result { let (account_id, _public_address_b58) = Account::create_from_mnemonic( @@ -343,6 +365,7 @@ impl AccountModel for Account { fog_report_url, fog_report_id, fog_authority_spki, + ledger_db, conn, )?; Account::get(&account_id, conn) @@ -357,6 +380,7 @@ impl AccountModel for Account { fog_report_url: String, fog_report_id: String, fog_authority_spki: String, + ledger_db: &LedgerDB, conn: &Conn, ) -> Result { let (account_id, _public_address_b58) = Account::create_from_root_entropy( @@ -368,6 +392,7 @@ impl AccountModel for Account { fog_report_url, fog_report_id, fog_authority_spki, + ledger_db, conn, )?; Account::get(&account_id, conn) @@ -460,7 +485,7 @@ impl AccountModel for Account { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::WalletDbTestContext; + use crate::test_utils::{get_test_ledger, WalletDbTestContext}; use mc_account_keys::RootIdentity; use mc_common::logger::{test_with_logger, Logger}; use mc_util_from_random::FromRandom; @@ -473,6 +498,7 @@ mod tests { let db_test_context = WalletDbTestContext::default(); let wallet_db = db_test_context.get_db_instance(logger); + let ledger_db = get_test_ledger(5, &[], 12, &mut rng); let root_id = RootIdentity::from_random(&mut rng); let account_key = AccountKey::from(&root_id); @@ -487,6 +513,7 @@ mod tests { "".to_string(), "".to_string(), "".to_string(), + &ledger_db, &conn, ) .unwrap(); @@ -557,6 +584,7 @@ mod tests { "".to_string(), "".to_string(), "".to_string(), + &ledger_db, &wallet_db.get_conn().unwrap(), ) .unwrap(); @@ -620,6 +648,7 @@ mod tests { let db_test_context = WalletDbTestContext::default(); let wallet_db = db_test_context.get_db_instance(logger); + let ledger_db = get_test_ledger(5, &[], 12, &mut rng); // Test providing entropy. let root_id = RootIdentity::from_random(&mut rng); @@ -635,6 +664,7 @@ mod tests { "".to_string(), "".to_string(), "".to_string(), + &ledger_db, &conn, ) .unwrap(); @@ -653,6 +683,7 @@ mod tests { let db_test_context = WalletDbTestContext::default(); let wallet_db = db_test_context.get_db_instance(logger); + let ledger_db = get_test_ledger(5, &[], 12, &mut rng); let root_id = RootIdentity::from_random(&mut rng); let account_id_hex = { @@ -666,6 +697,7 @@ mod tests { "fog//some.fog.url".to_string(), "".to_string(), "DefinitelyARealFOGAuthoritySPKI".to_string(), + &ledger_db, &conn, ) .unwrap(); @@ -683,13 +715,13 @@ mod tests { id: 1, account_id_hex: account_id_hex.to_string(), account_key: [ - 10, 34, 10, 32, 129, 223, 141, 215, 200, 104, 120, 117, 123, 154, 151, 210, 253, - 23, 148, 151, 2, 18, 182, 100, 83, 138, 144, 99, 225, 74, 214, 14, 175, 68, 167, 4, - 18, 34, 10, 32, 24, 98, 18, 92, 9, 50, 142, 184, 114, 99, 34, 125, 211, 54, 146, - 33, 98, 71, 179, 56, 136, 67, 98, 97, 230, 228, 31, 194, 119, 169, 189, 8, 26, 17, - 102, 111, 103, 47, 47, 115, 111, 109, 101, 46, 102, 111, 103, 46, 117, 114, 108, - 42, 23, 13, 231, 226, 158, 43, 94, 151, 32, 17, 121, 169, 69, 56, 96, 46, 182, 26, - 43, 138, 220, 146, 60, 162, + 10, 34, 10, 32, 135, 37, 92, 17, 29, 203, 205, 96, 6, 72, 229, 193, 11, 153, 50, 3, + 233, 116, 186, 132, 203, 190, 186, 77, 17, 15, 246, 254, 22, 4, 161, 13, 18, 34, + 10, 32, 207, 106, 86, 24, 232, 51, 148, 230, 19, 117, 228, 119, 164, 182, 133, 190, + 22, 197, 0, 66, 5, 57, 33, 188, 231, 11, 121, 197, 253, 113, 40, 3, 26, 17, 102, + 111, 103, 47, 47, 115, 111, 109, 101, 46, 102, 111, 103, 46, 117, 114, 108, 42, 23, + 13, 231, 226, 158, 43, 94, 151, 32, 17, 121, 169, 69, 56, 96, 46, 182, 26, 43, 138, + 220, 146, 60, 162, ] .to_vec(), entropy: root_id.root_entropy.bytes.to_vec(), @@ -703,6 +735,7 @@ mod tests { name: "Alice's FOG Account".to_string(), fog_enabled: true, }; + assert_eq!(expected_account, acc); } } diff --git a/full-service/src/db/assigned_subaddress.rs b/full-service/src/db/assigned_subaddress.rs index 159fe2230..86fd50d6e 100644 --- a/full-service/src/db/assigned_subaddress.rs +++ b/full-service/src/db/assigned_subaddress.rs @@ -42,6 +42,7 @@ pub trait AssignedSubaddressModel { address_book_entry: Option, subaddress_index: u64, comment: &str, + ledger_db: &LedgerDB, conn: &Conn, ) -> Result; @@ -94,12 +95,19 @@ impl AssignedSubaddressModel for AssignedSubaddress { address_book_entry: Option, subaddress_index: u64, comment: &str, + ledger_db: &LedgerDB, conn: &Conn, ) -> Result { - use crate::db::schema::assigned_subaddresses; + use crate::db::schema::{ + assigned_subaddresses, + transaction_logs::dsl::{ + account_id_hex as tx_log_account_id_hex, + transaction_id_hex as tx_log_transaction_id_hex, transaction_logs, + }, + }; let account_id = AccountID::from(account_key); - + let view_private_key = account_key.view_private_key(); let subaddress = account_key.subaddress(subaddress_index); let subaddress_b58 = b58_encode_public_address(&subaddress)?; @@ -116,6 +124,64 @@ impl AssignedSubaddressModel for AssignedSubaddress { diesel::insert_into(assigned_subaddresses::table) .values(&subaddress_entry) .execute(conn)?; + + // Find and repair orphaned txos at this subaddress. + let orphaned_txos = Txo::list_orphaned(&account_id.to_string(), None, None, None, conn)?; + + for orphaned_txo in orphaned_txos.iter() { + let tx_out_target_key: RistrettoPublic = + mc_util_serial::decode(&orphaned_txo.target_key).unwrap(); + let tx_public_key: RistrettoPublic = + mc_util_serial::decode(&orphaned_txo.public_key).unwrap(); + let txo_public_key = CompressedRistrettoPublic::from(tx_public_key); + + let txo_subaddress_spk: RistrettoPublic = recover_public_subaddress_spend_key( + view_private_key, + &tx_out_target_key, + &tx_public_key, + ); + + if txo_subaddress_spk == *subaddress.spend_public_key() { + let onetime_private_key = recover_onetime_private_key( + &tx_public_key, + account_key.view_private_key(), + &account_key.subaddress_spend_private(subaddress_index), + ); + + let key_image = KeyImage::from(&onetime_private_key); + + if ledger_db.contains_key_image(&key_image)? { + let txo_index = ledger_db.get_tx_out_index_by_public_key(&txo_public_key)?; + let block_index = ledger_db.get_block_index_by_tx_out_index(txo_index)?; + diesel::update(orphaned_txo) + .set( + crate::db::schema::txos::spent_block_index.eq(Some(block_index as i64)), + ) + .execute(conn)?; + } + + let key_image_bytes = mc_util_serial::encode(&key_image); + + // Update the account status mapping. + diesel::update(orphaned_txo) + .set(( + crate::db::schema::txos::subaddress_index.eq(subaddress_index as i64), + crate::db::schema::txos::key_image.eq(key_image_bytes), + )) + .execute(conn)?; + + diesel::update( + transaction_logs + .filter(tx_log_transaction_id_hex.eq(&orphaned_txo.txo_id_hex)) + .filter(tx_log_account_id_hex.eq(&account_id.to_string())), + ) + .set( + (crate::db::schema::transaction_logs::assigned_subaddress_b58 + .eq(&subaddress_b58),), + ) + .execute(conn)?; + } + } Ok(subaddress_b58) } diff --git a/full-service/src/db/transaction_log.rs b/full-service/src/db/transaction_log.rs index caa0c423a..5e05747dc 100644 --- a/full-service/src/db/transaction_log.rs +++ b/full-service/src/db/transaction_log.rs @@ -585,6 +585,7 @@ mod tests { let db_test_context = WalletDbTestContext::default(); let wallet_db = db_test_context.get_db_instance(logger); + let ledger_db = get_test_ledger(5, &[], 12, &mut rng); let root_id = RootIdentity::from_random(&mut rng); let account_key = AccountKey::from(&root_id); @@ -597,6 +598,7 @@ mod tests { "".to_string(), "".to_string(), "".to_string(), + &ledger_db, &wallet_db.get_conn().unwrap(), ) .unwrap(); @@ -906,6 +908,7 @@ mod tests { let db_test_context = WalletDbTestContext::default(); let wallet_db = db_test_context.get_db_instance(logger.clone()); + let ledger_db = get_test_ledger(5, &[], 12, &mut rng); // Populate our DB with some received txos in the same block. // Do this for two different accounts. @@ -922,6 +925,7 @@ mod tests { "".to_string(), "".to_string(), "".to_string(), + &ledger_db, &wallet_db.get_conn().unwrap(), ) .unwrap(); @@ -1269,6 +1273,7 @@ mod tests { let db_test_context = WalletDbTestContext::default(); let wallet_db = db_test_context.get_db_instance(logger); + let ledger_db = get_test_ledger(5, &[], 12, &mut rng); let root_id = RootIdentity::from_random(&mut rng); let account_key = AccountKey::from(&root_id); @@ -1281,6 +1286,7 @@ mod tests { "".to_string(), "".to_string(), "".to_string(), + &ledger_db, &wallet_db.get_conn().unwrap(), ) .unwrap(); diff --git a/full-service/src/db/txo.rs b/full-service/src/db/txo.rs index f450a04cd..34e6cc783 100644 --- a/full-service/src/db/txo.rs +++ b/full-service/src/db/txo.rs @@ -1185,6 +1185,7 @@ mod tests { "".to_string(), "".to_string(), "".to_string(), + &ledger_db, &wallet_db.get_conn().unwrap(), ) .unwrap(); @@ -1467,6 +1468,7 @@ mod tests { "".to_string(), "".to_string(), "".to_string(), + &ledger_db, &wallet_db.get_conn().unwrap(), ) .unwrap(); @@ -1520,6 +1522,7 @@ mod tests { let db_test_context = WalletDbTestContext::default(); let wallet_db = db_test_context.get_db_instance(logger); + let ledger_db = get_test_ledger(5, &[], 12, &mut rng); let root_id = RootIdentity::from_random(&mut rng); let account_key = AccountKey::from(&root_id); @@ -1532,6 +1535,7 @@ mod tests { "".to_string(), "".to_string(), "".to_string(), + &ledger_db, &wallet_db.get_conn().unwrap(), ) .unwrap(); @@ -1635,6 +1639,7 @@ mod tests { let db_test_context = WalletDbTestContext::default(); let wallet_db = db_test_context.get_db_instance(logger); + let ledger_db = get_test_ledger(5, &[], 12, &mut rng); let root_id = RootIdentity::from_random(&mut rng); let account_key = AccountKey::from(&root_id); @@ -1647,6 +1652,7 @@ mod tests { "".to_string(), "".to_string(), "".to_string(), + &ledger_db, &wallet_db.get_conn().unwrap(), ) .unwrap(); @@ -1698,6 +1704,7 @@ mod tests { let db_test_context = WalletDbTestContext::default(); let wallet_db = db_test_context.get_db_instance(logger); + let ledger_db = get_test_ledger(5, &[], 12, &mut rng); let root_id = RootIdentity::from_random(&mut rng); let account_key = AccountKey::from(&root_id); @@ -1710,6 +1717,7 @@ mod tests { "".to_string(), "".to_string(), "".to_string(), + &ledger_db, &wallet_db.get_conn().unwrap(), ) .unwrap(); @@ -1768,6 +1776,7 @@ mod tests { "".to_string(), "".to_string(), "".to_string(), + &ledger_db, &wallet_db.get_conn().unwrap(), ) .unwrap(); @@ -1833,6 +1842,7 @@ mod tests { "".to_string(), "".to_string(), "".to_string(), + &ledger_db, &wallet_db.get_conn().unwrap(), ) .unwrap(); @@ -1964,6 +1974,8 @@ mod tests { let db_test_context = WalletDbTestContext::default(); let wallet_db = db_test_context.get_db_instance(logger); + let known_recipients: Vec = Vec::new(); + let ledger_db = get_test_ledger(5, &known_recipients, 12, &mut rng); let root_id = RootIdentity::from_random(&mut rng); let account_key = AccountKey::from(&root_id); @@ -1976,6 +1988,7 @@ mod tests { "".to_string(), "".to_string(), "".to_string(), + &ledger_db, &wallet_db.get_conn().unwrap(), ) .unwrap(); @@ -2015,6 +2028,7 @@ mod tests { let db_test_context = WalletDbTestContext::default(); let wallet_db = db_test_context.get_db_instance(logger); + let ledger_db = get_test_ledger(5, &[], 12, &mut rng); let root_id = RootIdentity::from_random(&mut rng); let account_key = AccountKey::from(&root_id); @@ -2027,6 +2041,7 @@ mod tests { "".to_string(), "".to_string(), "".to_string(), + &ledger_db, &wallet_db.get_conn().unwrap(), ) .unwrap(); @@ -2099,6 +2114,7 @@ mod tests { let db_test_context = WalletDbTestContext::default(); let wallet_db = db_test_context.get_db_instance(logger); let conn = wallet_db.get_conn().unwrap(); + let ledger_db = get_test_ledger(5, &[], 12, &mut rng); let root_id = RootIdentity::from_random(&mut rng); let account_key = AccountKey::from(&root_id); @@ -2111,6 +2127,7 @@ mod tests { "".to_string(), "".to_string(), "".to_string(), + &ledger_db, &conn, ) .unwrap(); @@ -2147,6 +2164,7 @@ mod tests { let db_test_context = WalletDbTestContext::default(); let wallet_db = db_test_context.get_db_instance(logger); let conn = wallet_db.get_conn().unwrap(); + let ledger_db = get_test_ledger(5, &[], 12, &mut rng); let root_id = RootIdentity::from_random(&mut rng); let account_key = AccountKey::from(&root_id); @@ -2159,6 +2177,7 @@ mod tests { "".to_string(), "".to_string(), "".to_string(), + &ledger_db, &conn, ) .unwrap(); @@ -2192,6 +2211,7 @@ mod tests { let db_test_context = WalletDbTestContext::default(); let wallet_db = db_test_context.get_db_instance(logger); let conn = wallet_db.get_conn().unwrap(); + let ledger_db = get_test_ledger(5, &[], 12, &mut rng); let root_id = RootIdentity::from_random(&mut rng); let account_key = AccountKey::from(&root_id); @@ -2204,6 +2224,7 @@ mod tests { "".to_string(), "".to_string(), "".to_string(), + &ledger_db, &conn, ) .unwrap(); @@ -2277,6 +2298,7 @@ mod tests { let db_test_context = WalletDbTestContext::default(); let wallet_db = db_test_context.get_db_instance(logger); + let ledger_db = get_test_ledger(5, &[], 12, &mut rng); let root_id = RootIdentity::from_random(&mut rng); let account_key = AccountKey::from(&root_id); @@ -2289,6 +2311,7 @@ mod tests { "".to_string(), "".to_string(), "".to_string(), + &ledger_db, &wallet_db.get_conn().unwrap(), ) .unwrap(); diff --git a/full-service/src/json_rpc/txo.rs b/full-service/src/json_rpc/txo.rs index 274ac7c91..6ea62f7f3 100644 --- a/full-service/src/json_rpc/txo.rs +++ b/full-service/src/json_rpc/txo.rs @@ -170,7 +170,7 @@ mod tests { use crate::{ db, db::{account::AccountModel, models::Account, txo::TxoModel}, - test_utils::{create_test_received_txo, WalletDbTestContext, MOB}, + test_utils::{create_test_received_txo, get_test_ledger, WalletDbTestContext, MOB}, }; use mc_account_keys::{AccountKey, RootIdentity}; use mc_common::logger::{test_with_logger, Logger}; @@ -184,6 +184,7 @@ mod tests { let db_test_context = WalletDbTestContext::default(); let wallet_db = db_test_context.get_db_instance(logger); + let ledger_db = get_test_ledger(5, &[], 12, &mut rng); let root_id = RootIdentity::from_random(&mut rng); let account_key = AccountKey::from(&root_id); @@ -196,6 +197,7 @@ mod tests { "".to_string(), "".to_string(), "".to_string(), + &ledger_db, &wallet_db.get_conn().unwrap(), ) .unwrap(); diff --git a/full-service/src/service/account.rs b/full-service/src/service/account.rs index e8b1fefed..14efc40af 100644 --- a/full-service/src/service/account.rs +++ b/full-service/src/service/account.rs @@ -211,6 +211,7 @@ where fog_report_url, fog_report_id, fog_authority_spki, + &self.ledger_db, &conn, )?; let account = Account::get(&account_id, &conn)?; @@ -267,6 +268,7 @@ where fog_report_url, fog_report_id, fog_authority_spki, + &self.ledger_db, &conn, )?) }) @@ -307,6 +309,7 @@ where fog_report_url, fog_report_id, fog_authority_spki, + &self.ledger_db, &conn, )?) }) diff --git a/full-service/src/service/address.rs b/full-service/src/service/address.rs index 1605888e6..1b28246b9 100644 --- a/full-service/src/service/address.rs +++ b/full-service/src/service/address.rs @@ -4,9 +4,9 @@ use crate::{ db::{ - account::AccountID, + account::{AccountID, AccountModel}, assigned_subaddress::AssignedSubaddressModel, - models::{AssignedSubaddress, ViewOnlySubaddress}, + models::{Account, AssignedSubaddress, ViewOnlySubaddress}, transaction, view_only_subaddress::ViewOnlySubaddressModel, WalletDbError, @@ -14,6 +14,7 @@ use crate::{ service::WalletService, util::b58::b58_decode_public_address, }; +use mc_account_keys::{AccountKey, CHANGE_SUBADDRESS_INDEX}; use mc_common::logger::log; use mc_connection::{BlockchainConnection, UserTxConnection}; use mc_fog_report_validation::FogPubkeyResolver; @@ -83,6 +84,8 @@ pub trait AddressService { /// Verifies whether an address can be decoded from b58. fn verify_address(&self, public_address: &str) -> Result; + + fn assign_missing_reserved_subaddresses_for_accounts(&self) -> Result<(), AddressServiceError>; } impl AddressService for WalletService @@ -189,6 +192,33 @@ where } } } + + fn assign_missing_reserved_subaddresses_for_accounts(&self) -> Result<(), AddressServiceError> { + let conn = self.wallet_db.get_conn()?; + let accounts = Account::list_all(&conn)?; + + for account in accounts.iter() { + if AssignedSubaddress::get_for_account_by_index( + &account.account_id_hex, + CHANGE_SUBADDRESS_INDEX as i64, + &conn, + ) + .is_err() + { + let account_key: AccountKey = mc_util_serial::decode(&account.account_key).unwrap(); + AssignedSubaddress::create( + &account_key, + None, + CHANGE_SUBADDRESS_INDEX, + "Change", + &self.ledger_db, + &conn, + )?; + }; + } + + Ok(()) + } } #[cfg(test)] diff --git a/full-service/src/test_utils.rs b/full-service/src/test_utils.rs index a84d8ecf0..dfb25bbba 100644 --- a/full-service/src/test_utils.rs +++ b/full-service/src/test_utils.rs @@ -605,6 +605,7 @@ pub fn random_account_with_seed_values( "".to_string(), "".to_string(), "".to_string(), + &ledger_db, &wallet_db.get_conn().unwrap(), ) .unwrap(); diff --git a/validator/service/src/bin/main.rs b/validator/service/src/bin/main.rs index cade69522..4c76411d1 100644 --- a/validator/service/src/bin/main.rs +++ b/validator/service/src/bin/main.rs @@ -35,7 +35,8 @@ fn main() { // Create enclave verifier. let mut mr_signer_verifier = MrSignerVerifier::from(mc_consensus_enclave_measurement::sigstruct()); - mr_signer_verifier.allow_hardening_advisories(mc_consensus_enclave_measurement::HARDENING_ADVISORIES); + mr_signer_verifier + .allow_hardening_advisories(mc_consensus_enclave_measurement::HARDENING_ADVISORIES); let mut verifier = Verifier::default(); verifier.mr_signer(mr_signer_verifier).debug(DEBUG_ENCLAVE);