diff --git a/.license.ignore b/.license.ignore index 6551ee1d09..29d4233595 100644 --- a/.license.ignore +++ b/.license.ignore @@ -12,6 +12,7 @@ ./applications/tari_base_node/osx-pkg/scripts/preinstall ./applications/tari_console_wallet/linux/start_tari_console_wallet ./base_layer/key_manager/Makefile +./base_layer/wallet/src/schema.rs ./base_layer/p2p/src/dns/roots/tls.rs ./buildtools/docker/torrc ./docs/src/theme/book.js diff --git a/Cargo.lock b/Cargo.lock index 9aa326db51..f944c83b16 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2877,9 +2877,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "111.22.0+1.1.1q" +version = "111.24.0+1.1.1s" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f31f0d509d1c1ae9cada2f9539ff8f37933831fd5098879e482aa687d659853" +checksum = "3498f259dab01178c6228c6b00dcef0ed2a2d5e20d648c017861227773ea4abd" dependencies = [ "cc", ] @@ -4516,6 +4516,7 @@ dependencies = [ "lazy_static", "rand 0.7.3", "serde", + "tari_common", "tari_crypto", "tari_utilities", "thiserror", diff --git a/applications/tari_app_grpc/proto/wallet.proto b/applications/tari_app_grpc/proto/wallet.proto index 417b9dc439..d695a9ea72 100644 --- a/applications/tari_app_grpc/proto/wallet.proto +++ b/applications/tari_app_grpc/proto/wallet.proto @@ -169,8 +169,8 @@ message GetTransactionInfoResponse { message TransactionInfo { uint64 tx_id = 1; - bytes source_pk = 2; - bytes dest_pk = 3; + bytes source_address = 2; + bytes dest_address = 3; TransactionStatus status = 4; TransactionDirection direction = 5; uint64 amount = 6; @@ -310,8 +310,8 @@ message TransactionEventRequest{ message TransactionEvent { string event = 1; string tx_id = 2; - bytes source_pk = 3; - bytes dest_pk = 4; + bytes source_address = 3; + bytes dest_address = 4; string status = 5; string direction = 6; uint64 amount = 7; diff --git a/applications/tari_console_wallet/src/automation/commands.rs b/applications/tari_console_wallet/src/automation/commands.rs index cab0fe61f2..497988fb48 100644 --- a/applications/tari_console_wallet/src/automation/commands.rs +++ b/applications/tari_console_wallet/src/automation/commands.rs @@ -40,6 +40,7 @@ use strum_macros::{Display, EnumIter, EnumString}; use tari_app_grpc::authentication::salted_password::create_salted_hashed_password; use tari_common_types::{ emoji::EmojiId, + tari_address::TariAddress, transaction::TxId, types::{CommitmentFactory, FixedHash, PublicKey, Signature}, }; @@ -112,12 +113,12 @@ pub async fn send_tari( mut wallet_transaction_service: TransactionServiceHandle, fee_per_gram: u64, amount: MicroTari, - dest_pubkey: PublicKey, + destination: TariAddress, message: String, ) -> Result { wallet_transaction_service .send_transaction( - dest_pubkey, + destination, amount, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -146,11 +147,11 @@ pub async fn init_sha_atomic_swap( fee_per_gram: u64, amount: MicroTari, selection_criteria: UtxoSelectionCriteria, - dest_pubkey: PublicKey, + dest_address: TariAddress, message: String, ) -> Result<(TxId, PublicKey, TransactionOutput), CommandError> { let (tx_id, pre_image, output) = wallet_transaction_service - .send_sha_atomic_swap_transaction(dest_pubkey, amount, selection_criteria, fee_per_gram * uT, message) + .send_sha_atomic_swap_transaction(dest_address, amount, selection_criteria, fee_per_gram * uT, message) .await .map_err(CommandError::TransactionServiceError)?; Ok((tx_id, pre_image, output)) @@ -217,12 +218,12 @@ pub async fn send_one_sided( fee_per_gram: u64, amount: MicroTari, selection_criteria: UtxoSelectionCriteria, - dest_pubkey: PublicKey, + dest_address: TariAddress, message: String, ) -> Result { wallet_transaction_service .send_one_sided_transaction( - dest_pubkey, + dest_address, amount, selection_criteria, OutputFeatures::default(), @@ -238,12 +239,12 @@ pub async fn send_one_sided_to_stealth_address( fee_per_gram: u64, amount: MicroTari, selection_criteria: UtxoSelectionCriteria, - dest_pubkey: PublicKey, + dest_address: TariAddress, message: String, ) -> Result { wallet_transaction_service .send_one_sided_to_stealth_address_transaction( - dest_pubkey, + dest_address, amount, selection_criteria, OutputFeatures::default(), @@ -340,7 +341,7 @@ pub async fn make_it_rain( start_amount: MicroTari, increase_amount: MicroTari, start_time: DateTime, - destination: PublicKey, + destination: TariAddress, transaction_type: MakeItRainTransactionType, message: String, ) -> Result<(), CommandError> { @@ -403,14 +404,14 @@ pub async fn make_it_rain( let delayed_for = Instant::now(); let sender_clone = sender.clone(); let fee = fee_per_gram; - let pk = destination.clone(); + let address = destination.clone(); let msg = message.clone(); tokio::task::spawn(async move { let spawn_start = Instant::now(); // Send transaction let tx_id = match transaction_type { MakeItRainTransactionType::Interactive => { - send_tari(tx_service, fee, amount, pk.clone(), msg.clone()).await + send_tari(tx_service, fee, amount, address.clone(), msg.clone()).await }, MakeItRainTransactionType::OneSided => { send_one_sided( @@ -418,7 +419,7 @@ pub async fn make_it_rain( fee, amount, UtxoSelectionCriteria::default(), - pk.clone(), + address.clone(), msg.clone(), ) .await @@ -429,7 +430,7 @@ pub async fn make_it_rain( fee, amount, UtxoSelectionCriteria::default(), - pk.clone(), + address.clone(), msg.clone(), ) .await @@ -663,7 +664,7 @@ pub async fn command_runner( transaction_service.clone(), config.fee_per_gram, args.amount, - args.destination.into(), + args.destination, args.message, ) .await @@ -681,7 +682,7 @@ pub async fn command_runner( config.fee_per_gram, args.amount, UtxoSelectionCriteria::default(), - args.destination.into(), + args.destination, args.message, ) .await @@ -699,7 +700,7 @@ pub async fn command_runner( config.fee_per_gram, args.amount, UtxoSelectionCriteria::default(), - args.destination.into(), + args.destination, args.message, ) .await @@ -724,7 +725,7 @@ pub async fn command_runner( args.start_amount, args.increase_amount, args.start_time.unwrap_or_else(Utc::now), - args.destination.into(), + args.destination, transaction_type, args.message, ) @@ -864,7 +865,7 @@ pub async fn command_runner( config.fee_per_gram, args.amount, UtxoSelectionCriteria::default(), - args.destination.into(), + args.destination, args.message, ) .await diff --git a/applications/tari_console_wallet/src/cli.rs b/applications/tari_console_wallet/src/cli.rs index 0b1efc2937..cc862a107e 100644 --- a/applications/tari_console_wallet/src/cli.rs +++ b/applications/tari_console_wallet/src/cli.rs @@ -30,6 +30,7 @@ use chrono::{DateTime, Utc}; use clap::{Args, Parser, Subcommand}; use tari_app_utilities::{common_cli_args::CommonCliArgs, utilities::UniPublicKey}; use tari_common::configuration::{ConfigOverrideProvider, Network}; +use tari_common_types::tari_address::TariAddress; use tari_comms::multiaddr::Multiaddr; use tari_core::transactions::{tari_amount, tari_amount::MicroTari}; use tari_utilities::{ @@ -142,7 +143,7 @@ pub struct DiscoverPeerArgs { #[derive(Debug, Args, Clone)] pub struct SendTariArgs { pub amount: MicroTari, - pub destination: UniPublicKey, + pub destination: TariAddress, #[clap(short, long, default_value = "")] pub message: String, } @@ -156,7 +157,7 @@ pub struct BurnTariArgs { #[derive(Debug, Args, Clone)] pub struct MakeItRainArgs { - pub destination: UniPublicKey, + pub destination: TariAddress, #[clap(short, long, alias="amount", default_value_t = tari_amount::T)] pub start_amount: MicroTari, #[clap(short, long, alias = "tps", default_value_t = 25)] diff --git a/applications/tari_console_wallet/src/grpc/mod.rs b/applications/tari_console_wallet/src/grpc/mod.rs index 3579da1500..b346cebfe4 100644 --- a/applications/tari_console_wallet/src/grpc/mod.rs +++ b/applications/tari_console_wallet/src/grpc/mod.rs @@ -4,7 +4,6 @@ mod wallet_grpc_server; use tari_app_grpc::tari_rpc::TransactionEvent; -use tari_utilities::hex::Hex; use tari_wallet::transaction_service::storage::models::{ CompletedTransaction, InboundTransaction, @@ -24,8 +23,8 @@ pub fn convert_to_transaction_event(event: String, source: TransactionWrapper) - TransactionWrapper::Completed(completed) => TransactionEvent { event, tx_id: completed.tx_id.to_string(), - source_pk: completed.source_public_key.to_hex().into_bytes(), - dest_pk: completed.destination_public_key.to_hex().into_bytes(), + source_address: completed.source_address.to_bytes().to_vec(), + dest_address: completed.destination_address.to_bytes().to_vec(), status: completed.status.to_string(), direction: completed.direction.to_string(), amount: completed.amount.as_u64(), @@ -35,8 +34,8 @@ pub fn convert_to_transaction_event(event: String, source: TransactionWrapper) - TransactionWrapper::Outbound(outbound) => TransactionEvent { event, tx_id: outbound.tx_id.to_string(), - source_pk: vec![], - dest_pk: outbound.destination_public_key.to_hex().into_bytes(), + source_address: vec![], + dest_address: outbound.destination_address.to_bytes().to_vec(), status: outbound.status.to_string(), direction: "outbound".to_string(), amount: outbound.amount.as_u64(), @@ -46,8 +45,8 @@ pub fn convert_to_transaction_event(event: String, source: TransactionWrapper) - TransactionWrapper::Inbound(inbound) => TransactionEvent { event, tx_id: inbound.tx_id.to_string(), - source_pk: inbound.source_public_key.to_hex().into_bytes(), - dest_pk: vec![], + source_address: inbound.source_address.to_bytes().to_vec(), + dest_address: vec![], status: inbound.status.to_string(), direction: "inbound".to_string(), amount: inbound.amount.as_u64(), diff --git a/applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs b/applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs index 80c3b91ddb..c382113f2b 100644 --- a/applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs +++ b/applications/tari_console_wallet/src/grpc/wallet_grpc_server.rs @@ -81,6 +81,7 @@ use tari_app_grpc::{ }, }; use tari_common_types::{ + tari_address::TariAddress, transaction::TxId, types::{BlockHash, PublicKey, Signature}, }; @@ -297,7 +298,7 @@ impl wallet_server::Wallet for WalletGrpcServer { .into_inner() .recipient .ok_or_else(|| Status::internal("Request is malformed".to_string()))?; - let address = CommsPublicKey::from_hex(&message.address) + let address = TariAddress::from_hex(&message.address) .map_err(|_| Status::internal("Destination address is malformed".to_string()))?; let mut transaction_service = self.get_transaction_service(); @@ -458,11 +459,11 @@ impl wallet_server::Wallet for WalletGrpcServer { .into_iter() .enumerate() .map(|(idx, dest)| -> Result<_, String> { - let pk = CommsPublicKey::from_hex(&dest.address) + let address = TariAddress::from_hex(&dest.address) .map_err(|_| format!("Destination address at index {} is malformed", idx))?; Ok(( dest.address, - pk, + address, dest.amount, dest.fee_per_gram, dest.message, @@ -473,15 +474,15 @@ impl wallet_server::Wallet for WalletGrpcServer { .map_err(Status::invalid_argument)?; let mut transfers = Vec::new(); - for (address, pk, amount, fee_per_gram, message, payment_type) in recipients { + for (hex_address, address, amount, fee_per_gram, message, payment_type) in recipients { let mut transaction_service = self.get_transaction_service(); transfers.push(async move { ( - address, + hex_address, if payment_type == PaymentType::StandardMimblewimble as i32 { transaction_service .send_transaction( - pk, + address, amount.into(), UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -492,7 +493,7 @@ impl wallet_server::Wallet for WalletGrpcServer { } else if payment_type == PaymentType::OneSided as i32 { transaction_service .send_one_sided_transaction( - pk, + address, amount.into(), UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -503,7 +504,7 @@ impl wallet_server::Wallet for WalletGrpcServer { } else { transaction_service .send_one_sided_to_stealth_address_transaction( - pk, + address, amount.into(), UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -606,10 +607,11 @@ impl wallet_server::Wallet for WalletGrpcServer { .map_err(|err| Status::unknown(err.to_string()))?; let wallet_pk = self.wallet.comms.node_identity_ref().public_key(); - + let wallet_network = self.wallet.network.as_network(); + let wallet_address = TariAddress::new(wallet_pk.clone(), wallet_network); let transactions = transactions .map(|(tx_id, tx)| match tx { - Some(tx) => convert_wallet_transaction_into_transaction_info(tx, wallet_pk), + Some(tx) => convert_wallet_transaction_into_transaction_info(tx, &wallet_address), None => TransactionInfo::not_found(tx_id), }) .collect(); @@ -716,8 +718,8 @@ impl wallet_server::Wallet for WalletGrpcServer { let response = GetCompletedTransactionsResponse { transaction: Some(TransactionInfo { tx_id: txn.tx_id.into(), - source_pk: txn.source_public_key.to_vec(), - dest_pk: txn.destination_public_key.to_vec(), + source_address: txn.source_address.to_bytes().to_vec(), + dest_address: txn.destination_address.to_bytes().to_vec(), status: TransactionStatus::from(txn.status) as i32, amount: txn.amount.into(), is_cancelled: txn.cancelled.is_some(), @@ -792,7 +794,7 @@ impl wallet_server::Wallet for WalletGrpcServer { wallet .import_unblinded_output_as_non_rewindable( o.clone(), - &CommsPublicKey::default(), + TariAddress::default(), "Imported via gRPC".to_string(), ) .await @@ -1023,8 +1025,8 @@ fn simple_event(event: &str) -> TransactionEvent { TransactionEvent { event: event.to_string(), tx_id: String::default(), - source_pk: vec![], - dest_pk: vec![], + source_address: vec![], + dest_address: vec![], status: event.to_string(), direction: event.to_string(), amount: 0, @@ -1035,14 +1037,14 @@ fn simple_event(event: &str) -> TransactionEvent { fn convert_wallet_transaction_into_transaction_info( tx: models::WalletTransaction, - wallet_pk: &CommsPublicKey, + wallet_address: &TariAddress, ) -> TransactionInfo { use models::WalletTransaction::{Completed, PendingInbound, PendingOutbound}; match tx { PendingInbound(tx) => TransactionInfo { tx_id: tx.tx_id.into(), - source_pk: tx.source_public_key.to_vec(), - dest_pk: wallet_pk.to_vec(), + source_address: tx.source_address.to_bytes().to_vec(), + dest_address: wallet_address.to_bytes().to_vec(), status: TransactionStatus::from(tx.status) as i32, amount: tx.amount.into(), is_cancelled: tx.cancelled, @@ -1054,8 +1056,8 @@ fn convert_wallet_transaction_into_transaction_info( }, PendingOutbound(tx) => TransactionInfo { tx_id: tx.tx_id.into(), - source_pk: wallet_pk.to_vec(), - dest_pk: tx.destination_public_key.to_vec(), + source_address: wallet_address.to_bytes().to_vec(), + dest_address: tx.destination_address.to_bytes().to_vec(), status: TransactionStatus::from(tx.status) as i32, amount: tx.amount.into(), is_cancelled: tx.cancelled, @@ -1067,8 +1069,8 @@ fn convert_wallet_transaction_into_transaction_info( }, Completed(tx) => TransactionInfo { tx_id: tx.tx_id.into(), - source_pk: tx.source_public_key.to_vec(), - dest_pk: tx.destination_public_key.to_vec(), + source_address: tx.source_address.to_bytes().to_vec(), + dest_address: tx.destination_address.to_bytes().to_vec(), status: TransactionStatus::from(tx.status) as i32, amount: tx.amount.into(), is_cancelled: tx.cancelled.is_some(), diff --git a/applications/tari_console_wallet/src/notifier/mod.rs b/applications/tari_console_wallet/src/notifier/mod.rs index cdd3c3dd00..1167309045 100644 --- a/applications/tari_console_wallet/src/notifier/mod.rs +++ b/applications/tari_console_wallet/src/notifier/mod.rs @@ -311,8 +311,8 @@ fn args_from_complete(tx: &CompletedTransaction, event: &str, confirmations: Opt amount, tx.tx_id.to_string(), tx.message.clone(), - tx.source_public_key.to_hex(), - tx.destination_public_key.to_hex(), + tx.source_address.to_hex(), + tx.destination_address.to_hex(), status, excess, public_nonce, @@ -332,7 +332,7 @@ fn args_from_outbound(tx: &OutboundTransaction, event: &str) -> Vec { amount, tx.tx_id.to_string(), tx.message.clone(), - tx.destination_public_key.to_hex(), + tx.destination_address.to_hex(), status, "outbound".to_string(), ] @@ -348,7 +348,7 @@ fn args_from_inbound(tx: &InboundTransaction, event: &str) -> Vec { amount, tx.tx_id.to_string(), tx.message.clone(), - tx.source_public_key.to_hex(), + tx.source_address.to_hex(), status, "inbound".to_string(), ] diff --git a/applications/tari_console_wallet/src/ui/app.rs b/applications/tari_console_wallet/src/ui/app.rs index 833fd14764..3dfaa003a9 100644 --- a/applications/tari_console_wallet/src/ui/app.rs +++ b/applications/tari_console_wallet/src/ui/app.rs @@ -20,9 +20,8 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use tari_common::configuration::Network; use tari_comms::peer_manager::Peer; -use tari_wallet::{WalletConfig, WalletSqlite}; +use tari_wallet::{util::wallet_identity::WalletIdentity, WalletConfig, WalletSqlite}; use tokio::runtime::Handle; use tui::{ backend::Backend, @@ -71,15 +70,14 @@ impl App { pub fn new( title: String, wallet: WalletSqlite, - network: Network, wallet_config: WalletConfig, base_node_selected: Peer, base_node_config: PeerConfig, notifier: Notifier, ) -> Self { + let wallet_id = WalletIdentity::new(wallet.comms.node_identity(), wallet.network.as_network()); let app_state = AppState::new( - wallet.comms.node_identity().as_ref(), - network, + &wallet_id, wallet, base_node_selected.clone(), base_node_config, diff --git a/applications/tari_console_wallet/src/ui/components/contacts_tab.rs b/applications/tari_console_wallet/src/ui/components/contacts_tab.rs index e7fdf0efe2..556653604f 100644 --- a/applications/tari_console_wallet/src/ui/components/contacts_tab.rs +++ b/applications/tari_console_wallet/src/ui/components/contacts_tab.rs @@ -27,7 +27,7 @@ pub struct ContactsTab { edit_contact_mode: ContactInputMode, show_edit_contact: bool, alias_field: String, - public_key_field: String, + address_field: String, error_message: Option, contacts_list_state: WindowedListState, confirmation_dialog: Option, @@ -39,7 +39,7 @@ impl ContactsTab { edit_contact_mode: ContactInputMode::None, show_edit_contact: false, alias_field: String::new(), - public_key_field: String::new(), + address_field: String::new(), error_message: None, contacts_list_state: WindowedListState::new(), confirmation_dialog: None, @@ -93,7 +93,7 @@ impl ContactsTab { let mut column4_items = Vec::new(); for c in windowed_view.iter() { column0_items.push(ListItem::new(Span::raw(c.alias.clone()))); - column1_items.push(ListItem::new(Span::raw(c.public_key.clone()))); + column1_items.push(ListItem::new(Span::raw(c.address.clone()))); column2_items.push(ListItem::new(Span::raw(display_compressed_string( c.emoji_id.clone(), 3, @@ -108,7 +108,7 @@ impl ContactsTab { .max_width(MAX_WIDTH) .add_column(Some("Alias"), Some(25), column0_items) .add_column(None, Some(1), Vec::new()) - .add_column(Some("Public Key"), Some(64), column1_items) + .add_column(Some("Tari Address"), Some(64), column1_items) .add_column(None, Some(1), Vec::new()) .add_column(Some("Emoji ID"), Some(14), column2_items) .add_column(None, Some(1), Vec::new()) @@ -143,7 +143,7 @@ impl ContactsTab { Span::raw(" field, "), Span::styled("K", Style::default().add_modifier(Modifier::BOLD)), Span::raw(" to edit "), - Span::styled("Public Key/Emoji ID", Style::default().add_modifier(Modifier::BOLD)), + Span::styled("Emoji ID", Style::default().add_modifier(Modifier::BOLD)), Span::raw(" field, "), Span::styled("Enter", Style::default().add_modifier(Modifier::BOLD)), Span::raw(" to save Contact."), @@ -159,13 +159,13 @@ impl ContactsTab { .block(Block::default().borders(Borders::ALL).title("A(l)ias:")); f.render_widget(alias_input, vert_chunks[1]); - let pubkey_input = Paragraph::new(self.public_key_field.as_ref()) + let tari_address_input = Paragraph::new(self.address_field.as_ref()) .style(match self.edit_contact_mode { ContactInputMode::PubkeyEmojiId => Style::default().fg(Color::Magenta), _ => Style::default(), }) - .block(Block::default().borders(Borders::ALL).title("Public (K)ey / Emoji Id:")); - f.render_widget(pubkey_input, vert_chunks[2]); + .block(Block::default().borders(Borders::ALL).title("Emoji Id:")); + f.render_widget(tari_address_input, vert_chunks[2]); match self.edit_contact_mode { ContactInputMode::None => (), @@ -177,7 +177,7 @@ impl ContactsTab { ), ContactInputMode::PubkeyEmojiId => f.set_cursor( // Put cursor past the end of the input text - vert_chunks[2].x + self.public_key_field.width() as u16 + 1, + vert_chunks[2].x + self.address_field.width() as u16 + 1, // Move one line down, from the border to the input line vert_chunks[2].y + 1, ), @@ -200,7 +200,7 @@ impl ContactsTab { .and_then(|i| app_state.get_contact(i)) .cloned() { - if let Err(_e) = Handle::current().block_on(app_state.delete_contact(c.public_key)) { + if let Err(_e) = Handle::current().block_on(app_state.delete_contact(c.address)) { self.error_message = Some("Could not delete selected contact\nPress Enter to continue.".to_string()); } @@ -237,18 +237,19 @@ impl ContactsTab { self.show_edit_contact = false; if let Err(_e) = Handle::current() - .block_on(app_state.upsert_contact(self.alias_field.clone(), self.public_key_field.clone())) + .block_on(app_state.upsert_contact(self.alias_field.clone(), self.address_field.clone())) { - self.error_message = - Some("Invalid Public key or Emoji ID provided\n Press Enter to continue.".to_string()); + self.error_message = Some( + "Invalid Tari address or Emoji ID provided\n Press Enter to continue.".to_string(), + ); } self.alias_field = "".to_string(); - self.public_key_field = "".to_string(); + self.address_field = "".to_string(); return KeyHandled::Handled; }, c => { - self.public_key_field.push(c); + self.address_field.push(c); return KeyHandled::Handled; }, }, @@ -329,7 +330,7 @@ impl Component for ContactsTab { .selected() .and_then(|i| app_state.get_contact(i)) { - self.public_key_field = c.public_key.clone(); + self.address_field = c.address.clone(); self.alias_field = c.alias.clone(); self.show_edit_contact = true; self.edit_contact_mode = ContactInputMode::Alias; @@ -338,7 +339,7 @@ impl Component for ContactsTab { _ => { self.show_edit_contact = false; self.edit_contact_mode = ContactInputMode::Alias; - self.public_key_field = "".to_string(); + self.address_field = "".to_string(); }, } } @@ -371,7 +372,7 @@ impl Component for ContactsTab { let _ = self.alias_field.pop(); }, ContactInputMode::PubkeyEmojiId => { - let _ = self.public_key_field.pop(); + let _ = self.address_field.pop(); }, ContactInputMode::None => {}, } diff --git a/applications/tari_console_wallet/src/ui/components/receive_tab.rs b/applications/tari_console_wallet/src/ui/components/receive_tab.rs index 8ec9af7dcd..388b98f516 100644 --- a/applications/tari_console_wallet/src/ui/components/receive_tab.rs +++ b/applications/tari_console_wallet/src/ui/components/receive_tab.rs @@ -57,20 +57,20 @@ impl ReceiveTab { .title(Span::styled("Connection Details", Style::default().fg(Color::White))); f.render_widget(block, chunks[0]); - const ITEM_01: &str = "Public Key: "; + const ITEM_01: &str = "Tari Address: "; const ITEM_02: &str = "Node ID: "; - const ITEM_03: &str = "Public Address: "; + const ITEM_03: &str = "Network Address: "; const ITEM_04: &str = "Emoji ID: "; - // Public Key - let public_key_text = Spans::from(vec![ + // Tari address + let tari_address_text = Spans::from(vec![ Span::styled(ITEM_01, Style::default().fg(Color::Magenta)), Span::styled( - app_state.get_identity().public_key.clone(), + app_state.get_identity().tari_address.clone(), Style::default().fg(Color::White), ), ]); - let paragraph = Paragraph::new(public_key_text).block(Block::default()); + let paragraph = Paragraph::new(tari_address_text).block(Block::default()); f.render_widget(paragraph, details_chunks[0]); // NodeId @@ -85,14 +85,14 @@ impl ReceiveTab { f.render_widget(paragraph, details_chunks[1]); // Public Address - let public_ddress_text = Spans::from(vec![ + let public_address_text = Spans::from(vec![ Span::styled(ITEM_03, Style::default().fg(Color::Magenta)), Span::styled( - app_state.get_identity().public_address.clone(), + app_state.get_identity().network_address.clone(), Style::default().fg(Color::White), ), ]); - let paragraph = Paragraph::new(public_ddress_text).block(Block::default()); + let paragraph = Paragraph::new(public_address_text).block(Block::default()); f.render_widget(paragraph, details_chunks[2]); // Emoji ID diff --git a/applications/tari_console_wallet/src/ui/components/send_tab.rs b/applications/tari_console_wallet/src/ui/components/send_tab.rs index cffad8bd69..f4fec78a35 100644 --- a/applications/tari_console_wallet/src/ui/components/send_tab.rs +++ b/applications/tari_console_wallet/src/ui/components/send_tab.rs @@ -123,7 +123,7 @@ impl SendTab { .block( Block::default() .borders(Borders::ALL) - .title("(T)o (Public Key or Emoji ID) :"), + .title("(T)o (Tari Address or Emoji ID) :"), ); f.render_widget(to_input, vert_chunks[1]); @@ -402,7 +402,7 @@ impl SendTab { .and_then(|i| app_state.get_contact(i)) .cloned() { - self.to_field = c.public_key; + self.to_field = c.address; self.send_input_mode = SendInputMode::Amount; self.show_contacts = false; } @@ -577,7 +577,8 @@ impl Component for SendTab { 'm' => self.send_input_mode = SendInputMode::Message, 's' | 'o' | 'x' => { if self.to_field.is_empty() { - self.error_message = Some("Destination Public Key/Emoji ID\nPress Enter to continue.".to_string()); + self.error_message = + Some("Destination Tari Address/Emoji ID\nPress Enter to continue.".to_string()); return; } if self.amount_field.is_empty() && self.selected_unique_id.is_none() { diff --git a/applications/tari_console_wallet/src/ui/components/transactions_tab.rs b/applications/tari_console_wallet/src/ui/components/transactions_tab.rs index ab15aee417..44b09a2ab9 100644 --- a/applications/tari_console_wallet/src/ui/components/transactions_tab.rs +++ b/applications/tari_console_wallet/src/ui/components/transactions_tab.rs @@ -106,7 +106,7 @@ impl TransactionsTab { .to_owned(); if t.direction == TransactionDirection::Outbound { column0_items.push(ListItem::new(Span::styled( - app_state.get_alias(&t.destination_public_key), + app_state.get_alias(&t.destination_address), Style::default().fg(text_color), ))); let amount_style = if t.cancelled.is_some() { @@ -118,7 +118,7 @@ impl TransactionsTab { column1_items.push(ListItem::new(Span::styled(amount, amount_style))); } else { column0_items.push(ListItem::new(Span::styled( - app_state.get_alias(&t.source_public_key), + app_state.get_alias(&t.source_address), Style::default().fg(text_color), ))); let amount_style = if t.cancelled.is_some() { @@ -200,7 +200,7 @@ impl TransactionsTab { let text_color = text_colors.get(&cancelled).unwrap_or(&Color::Reset).to_owned(); if t.direction == TransactionDirection::Outbound { column0_items.push(ListItem::new(Span::styled( - app_state.get_alias(&t.destination_public_key), + app_state.get_alias(&t.destination_address), Style::default().fg(text_color), ))); let amount_style = if t.cancelled.is_some() { @@ -212,7 +212,7 @@ impl TransactionsTab { column1_items.push(ListItem::new(Span::styled(amount, amount_style))); } else { column0_items.push(ListItem::new(Span::styled( - app_state.get_alias(&t.source_public_key), + app_state.get_alias(&t.source_address), Style::default().fg(text_color), ))); let color = match (t.cancelled.is_some(), chain_height) { @@ -328,16 +328,13 @@ impl TransactionsTab { if tx.status == TransactionStatus::Pending && tx.direction == TransactionDirection::Outbound { Span::raw("") } else { - Span::styled(format!("{}", tx.source_public_key), Style::default().fg(Color::White)) + Span::styled(format!("{}", tx.source_address), Style::default().fg(Color::White)) }; let destination_public_key = if tx.status == TransactionStatus::Pending && tx.direction == TransactionDirection::Inbound { Span::raw("") } else { - Span::styled( - format!("{}", tx.destination_public_key), - Style::default().fg(Color::White), - ) + Span::styled(format!("{}", tx.destination_address), Style::default().fg(Color::White)) }; let direction = Span::styled(format!("{}", tx.direction), Style::default().fg(Color::White)); let amount = tx.amount.to_string(); diff --git a/applications/tari_console_wallet/src/ui/state/app_state.rs b/applications/tari_console_wallet/src/ui/state/app_state.rs index 0301553c6a..ab3e7c75cc 100644 --- a/applications/tari_console_wallet/src/ui/state/app_state.rs +++ b/applications/tari_console_wallet/src/ui/state/app_state.rs @@ -32,7 +32,7 @@ use log::*; use qrcode::{render::unicode, QrCode}; use tari_common::configuration::Network; use tari_common_types::{ - emoji::EmojiId, + tari_address::TariAddress, transaction::{TransactionDirection, TransactionStatus, TxId}, types::PublicKey, }; @@ -40,17 +40,14 @@ use tari_comms::{ connectivity::ConnectivityEventRx, multiaddr::Multiaddr, peer_manager::{NodeId, Peer, PeerFeatures, PeerFlags}, - types::CommsPublicKey, - NodeIdentity, }; use tari_core::transactions::{ tari_amount::{uT, MicroTari}, transaction_components::OutputFeatures, weight::TransactionWeight, }; -use tari_crypto::ristretto::RistrettoPublicKey; use tari_shutdown::ShutdownSignal; -use tari_utilities::hex::Hex; +use tari_utilities::hex::{from_hex, Hex}; use tari_wallet::{ base_node_service::{handle::BaseNodeEventReceiver, service::BaseNodeState}, connectivity_service::{OnlineStatus, WalletConnectivityHandle, WalletConnectivityInterface}, @@ -60,6 +57,7 @@ use tari_wallet::{ handle::TransactionEventReceiver, storage::models::{CompletedTransaction, TxCancellationReason}, }, + util::wallet_identity::WalletIdentity, WalletConfig, WalletSqlite, }; @@ -100,8 +98,7 @@ pub struct AppState { impl AppState { pub fn new( - node_identity: &NodeIdentity, - network: Network, + wallet_identity: &WalletIdentity, wallet: WalletSqlite, base_node_selected: Peer, base_node_config: PeerConfig, @@ -109,7 +106,7 @@ impl AppState { ) -> Self { let wallet_connectivity = wallet.wallet_connectivity.clone(); let output_manager_service = wallet.output_manager_service.clone(); - let inner = AppStateInner::new(node_identity, network, wallet, base_node_selected, base_node_config); + let inner = AppStateInner::new(wallet_identity, wallet, base_node_selected, base_node_config); let cached_data = inner.data.clone(); let inner = Arc::new(RwLock::new(inner)); @@ -212,17 +209,16 @@ impl AppState { } } - pub async fn upsert_contact(&mut self, alias: String, public_key_or_emoji_id: String) -> Result<(), UiError> { + pub async fn upsert_contact(&mut self, alias: String, tari_emoji: String) -> Result<(), UiError> { let mut inner = self.inner.write().await; - let public_key = match CommsPublicKey::from_hex(public_key_or_emoji_id.as_str()) { - Ok(pk) => pk, - Err(_) => EmojiId::from_emoji_string(public_key_or_emoji_id.as_str()) - .map_err(|_| UiError::PublicKeyParseError)? - .to_public_key(), + let address = match TariAddress::from_emoji_string(&tari_emoji) { + Ok(address) => address, + Err(_) => TariAddress::from_bytes(&from_hex(&tari_emoji).map_err(|_| UiError::PublicKeyParseError)?) + .map_err(|_| UiError::PublicKeyParseError)?, }; - let contact = Contact::new(alias, public_key, None, None); + let contact = Contact::new(alias, address, None, None); inner.wallet.contacts_service.upsert_contact(contact).await?; inner.refresh_contacts_state().await?; @@ -232,30 +228,29 @@ impl AppState { } // Return alias or pub key if the contact is not in the list. - pub fn get_alias(&self, pub_key: &RistrettoPublicKey) -> String { - let pub_key_hex = format!("{}", pub_key); + pub fn get_alias(&self, address: &TariAddress) -> String { + let address_hex = address.to_hex(); match self .cached_data .contacts .iter() - .find(|&contact| contact.public_key.eq(&pub_key_hex)) + .find(|&contact| contact.address.eq(&address_hex)) { Some(contact) => contact.alias.clone(), - None => pub_key_hex, + None => address_hex, } } - pub async fn delete_contact(&mut self, public_key: String) -> Result<(), UiError> { + pub async fn delete_contact(&mut self, tari_emoji: String) -> Result<(), UiError> { let mut inner = self.inner.write().await; - let public_key = match CommsPublicKey::from_hex(public_key.as_str()) { - Ok(pk) => pk, - Err(_) => EmojiId::from_emoji_string(public_key.as_str()) - .map_err(|_| UiError::PublicKeyParseError)? - .to_public_key(), + let address = match TariAddress::from_emoji_string(&tari_emoji) { + Ok(address) => address, + Err(_) => TariAddress::from_bytes(&from_hex(&tari_emoji).map_err(|_| UiError::PublicKeyParseError)?) + .map_err(|_| UiError::PublicKeyParseError)?, }; - inner.wallet.contacts_service.remove_contact(public_key).await?; + inner.wallet.contacts_service.remove_contact(address).await?; inner.refresh_contacts_state().await?; drop(inner); @@ -265,7 +260,7 @@ impl AppState { pub async fn send_transaction( &mut self, - public_key: String, + address: String, amount: u64, selection_criteria: UtxoSelectionCriteria, fee_per_gram: u64, @@ -273,11 +268,10 @@ impl AppState { result_tx: watch::Sender, ) -> Result<(), UiError> { let inner = self.inner.write().await; - let public_key = match CommsPublicKey::from_hex(public_key.as_str()) { - Ok(pk) => pk, - Err(_) => EmojiId::from_emoji_string(public_key.as_str()) - .map_err(|_| UiError::PublicKeyParseError)? - .to_public_key(), + let address = match TariAddress::from_emoji_string(&address) { + Ok(address) => address, + Err(_) => TariAddress::from_bytes(&from_hex(&address).map_err(|_| UiError::PublicKeyParseError)?) + .map_err(|_| UiError::PublicKeyParseError)?, }; let output_features = OutputFeatures { ..Default::default() }; @@ -285,7 +279,7 @@ impl AppState { let fee_per_gram = fee_per_gram * uT; let tx_service_handle = inner.wallet.transaction_service.clone(); tokio::spawn(send_transaction_task( - public_key, + address, MicroTari::from(amount), selection_criteria, output_features, @@ -300,7 +294,7 @@ impl AppState { pub async fn send_one_sided_transaction( &mut self, - public_key: String, + address: String, amount: u64, selection_criteria: UtxoSelectionCriteria, fee_per_gram: u64, @@ -308,19 +302,17 @@ impl AppState { result_tx: watch::Sender, ) -> Result<(), UiError> { let inner = self.inner.write().await; - let public_key = match CommsPublicKey::from_hex(public_key.as_str()) { - Ok(pk) => pk, - Err(_) => EmojiId::from_emoji_string(public_key.as_str()) - .map_err(|_| UiError::PublicKeyParseError)? - .to_public_key(), + let address = match TariAddress::from_emoji_string(&address) { + Ok(address) => address, + Err(_) => TariAddress::from_bytes(&from_hex(&address).map_err(|_| UiError::PublicKeyParseError)?) + .map_err(|_| UiError::PublicKeyParseError)?, }; - let output_features = OutputFeatures { ..Default::default() }; let fee_per_gram = fee_per_gram * uT; let tx_service_handle = inner.wallet.transaction_service.clone(); tokio::spawn(send_one_sided_transaction_task( - public_key, + address, MicroTari::from(amount), selection_criteria, output_features, @@ -335,7 +327,7 @@ impl AppState { pub async fn send_one_sided_to_stealth_address_transaction( &mut self, - dest_pubkey: String, + address: String, amount: u64, selection_criteria: UtxoSelectionCriteria, fee_per_gram: u64, @@ -343,11 +335,10 @@ impl AppState { result_tx: watch::Sender, ) -> Result<(), UiError> { let inner = self.inner.write().await; - let dest_pubkey = match CommsPublicKey::from_hex(dest_pubkey.as_str()) { - Ok(pk) => pk, - Err(_) => EmojiId::from_emoji_string(dest_pubkey.as_str()) - .map_err(|_| UiError::PublicKeyParseError)? - .to_public_key(), + let address = match TariAddress::from_emoji_string(&address) { + Ok(address) => address, + Err(_) => TariAddress::from_bytes(&from_hex(&address).map_err(|_| UiError::PublicKeyParseError)?) + .map_err(|_| UiError::PublicKeyParseError)?, }; let output_features = OutputFeatures { ..Default::default() }; @@ -355,7 +346,7 @@ impl AppState { let fee_per_gram = fee_per_gram * uT; let tx_service_handle = inner.wallet.transaction_service.clone(); tokio::spawn(send_one_sided_to_stealth_address_transaction( - dest_pubkey, + address, MicroTari::from(amount), selection_criteria, output_features, @@ -577,13 +568,12 @@ pub struct AppStateInner { impl AppStateInner { pub fn new( - node_identity: &NodeIdentity, - network: Network, + wallet_identity: &WalletIdentity, wallet: WalletSqlite, base_node_selected: Peer, base_node_config: PeerConfig, ) -> Self { - let data = AppStateData::new(node_identity, network, base_node_selected, base_node_config); + let data = AppStateData::new(wallet_identity, base_node_selected, base_node_config); AppStateInner { updated: false, @@ -1005,8 +995,8 @@ impl AppStateInner { #[derive(Clone)] pub struct CompletedTransactionInfo { pub tx_id: TxId, - pub source_public_key: CommsPublicKey, - pub destination_public_key: CommsPublicKey, + pub source_address: TariAddress, + pub destination_address: TariAddress, pub amount: MicroTari, pub fee: MicroTari, pub excess_signature: String, @@ -1037,8 +1027,8 @@ impl CompletedTransactionInfo { Self { tx_id: tx.tx_id, - source_public_key: tx.source_public_key.clone(), - destination_public_key: tx.destination_public_key.clone(), + source_address: tx.source_address.clone(), + destination_address: tx.destination_address.clone(), amount: tx.amount, fee: tx.fee, excess_signature, @@ -1089,14 +1079,9 @@ pub struct EventListItem { } impl AppStateData { - pub fn new( - node_identity: &NodeIdentity, - network: Network, - base_node_selected: Peer, - base_node_config: PeerConfig, - ) -> Self { - let eid = EmojiId::from_public_key(node_identity.public_key()).to_emoji_string(); - let qr_link = format!("tari://{}/pubkey/{}", network, &node_identity.public_key().to_hex()); + pub fn new(wallet_identity: &WalletIdentity, base_node_selected: Peer, base_node_config: PeerConfig) -> Self { + let eid = wallet_identity.address.to_emoji_string(); + let qr_link = format!("tari_address://{}", wallet_identity.address.to_hex()); let code = QrCode::new(qr_link).unwrap(); let image = code .render::() @@ -1108,11 +1093,11 @@ impl AppStateData { .fold("".to_string(), |acc, l| format!("{}{}\n", acc, l)); let identity = MyIdentity { - public_key: node_identity.public_key().to_string(), - public_address: node_identity.public_address().to_string(), + tari_address: wallet_identity.address.to_hex(), + network_address: wallet_identity.node_identity.public_address().to_string(), emoji_id: eid, qr_code: image, - node_id: node_identity.node_id().to_string(), + node_id: wallet_identity.node_identity.node_id().to_string(), }; let base_node_previous = base_node_selected.clone(); @@ -1159,8 +1144,8 @@ impl AppStateData { #[derive(Clone)] pub struct MyIdentity { - pub public_key: String, - pub public_address: String, + pub tari_address: String, + pub network_address: String, pub emoji_id: String, pub qr_code: String, pub node_id: String, diff --git a/applications/tari_console_wallet/src/ui/state/tasks.rs b/applications/tari_console_wallet/src/ui/state/tasks.rs index be18a312f9..db4151b857 100644 --- a/applications/tari_console_wallet/src/ui/state/tasks.rs +++ b/applications/tari_console_wallet/src/ui/state/tasks.rs @@ -20,7 +20,7 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use tari_comms::types::CommsPublicKey; +use tari_common_types::tari_address::TariAddress; use tari_core::transactions::{tari_amount::MicroTari, transaction_components::OutputFeatures}; use tari_wallet::{ output_manager_service::UtxoSelectionCriteria, @@ -33,7 +33,7 @@ use crate::ui::{state::UiTransactionSendStatus, UiError}; const LOG_TARGET: &str = "wallet::console_wallet::tasks "; pub async fn send_transaction_task( - public_key: CommsPublicKey, + address: TariAddress, amount: MicroTari, selection_criteria: UtxoSelectionCriteria, output_features: OutputFeatures, @@ -47,7 +47,7 @@ pub async fn send_transaction_task( let mut send_status = TransactionSendStatus::default(); match transaction_service_handle .send_transaction( - public_key, + address, amount, selection_criteria, output_features, @@ -109,7 +109,7 @@ pub async fn send_transaction_task( } pub async fn send_one_sided_transaction_task( - public_key: CommsPublicKey, + address: TariAddress, amount: MicroTari, selection_criteria: UtxoSelectionCriteria, output_features: OutputFeatures, @@ -122,7 +122,7 @@ pub async fn send_one_sided_transaction_task( let mut event_stream = transaction_service_handle.get_event_stream(); match transaction_service_handle .send_one_sided_transaction( - public_key, + address, amount, selection_criteria, output_features, @@ -163,7 +163,7 @@ pub async fn send_one_sided_transaction_task( } pub async fn send_one_sided_to_stealth_address_transaction( - dest_pubkey: CommsPublicKey, + address: TariAddress, amount: MicroTari, selection_criteria: UtxoSelectionCriteria, output_features: OutputFeatures, @@ -176,7 +176,7 @@ pub async fn send_one_sided_to_stealth_address_transaction( let mut event_stream = transaction_service_handle.get_event_stream(); match transaction_service_handle .send_one_sided_to_stealth_address_transaction( - dest_pubkey, + address, amount, selection_criteria, output_features, diff --git a/applications/tari_console_wallet/src/ui/ui_contact.rs b/applications/tari_console_wallet/src/ui/ui_contact.rs index d55d1eb6e4..585be0bcde 100644 --- a/applications/tari_console_wallet/src/ui/ui_contact.rs +++ b/applications/tari_console_wallet/src/ui/ui_contact.rs @@ -2,13 +2,12 @@ // SPDX-License-Identifier: BSD-3-Clause use chrono::{DateTime, Local}; -use tari_common_types::emoji::EmojiId; use tari_wallet::contacts_service::storage::database::Contact; #[derive(Debug, Clone)] pub struct UiContact { pub alias: String, - pub public_key: String, + pub address: String, pub emoji_id: String, pub last_seen: String, pub online_status: String, @@ -25,8 +24,8 @@ impl From for UiContact { fn from(c: Contact) -> Self { Self { alias: c.alias, - public_key: c.public_key.to_string(), - emoji_id: EmojiId::from_public_key(&c.public_key).to_emoji_string(), + address: c.address.to_hex(), + emoji_id: c.address.to_emoji_string(), last_seen: match c.last_seen { Some(val) => DateTime::::from_utc(val, Local::now().offset().to_owned()) .format("%m-%dT%H:%M") diff --git a/applications/tari_console_wallet/src/wallet_modes.rs b/applications/tari_console_wallet/src/wallet_modes.rs index a95f5c4888..ac0efa707f 100644 --- a/applications/tari_console_wallet/src/wallet_modes.rs +++ b/applications/tari_console_wallet/src/wallet_modes.rs @@ -296,7 +296,6 @@ pub fn tui_mode( let app = App::>::new( "Tari Console Wallet".into(), wallet, - config.network, config.clone(), base_node_selected, base_node_config.clone(), @@ -412,6 +411,7 @@ async fn run_grpc( #[cfg(test)] mod test { + use crate::{cli::CliCommands, wallet_modes::parse_command_file}; #[test] @@ -425,7 +425,7 @@ mod test { discover-peer f6b2ca781342a3ebe30ee1643655c96f1d7c14f4d49f077695395de98ae73665 - send-tari --message Our_secret! 125T 5c4f2a4b3f3f84e047333218a84fd24f581a9d7e4f23b78e3714e9d174427d61 + send-tari --message Our_secret! 125T 5c4f2a4b3f3f84e047333218a84fd24f581a9d7e4f23b78e3714e9d174427d615e burn-tari --message Ups_these_funds_will_be_burned! 100T @@ -433,7 +433,7 @@ mod test { make-it-rain --duration 100 --transactions-per-second 10 --start-amount 0.009200T --increase-amount 0T \ --start-time now --message Stressing_it_a_bit...!_(from_Feeling-a-bit-Generous) \ - 5c4f2a4b3f3f84e047333218a84fd24f581a9d7e4f23b78e3714e9d174427d61 + 5c4f2a4b3f3f84e047333218a84fd24f581a9d7e4f23b78e3714e9d174427d615e # End of script file " diff --git a/base_layer/common_types/Cargo.toml b/base_layer/common_types/Cargo.toml index 336d9d4757..48fa9857e2 100644 --- a/base_layer/common_types/Cargo.toml +++ b/base_layer/common_types/Cargo.toml @@ -9,6 +9,7 @@ edition = "2018" [dependencies] tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.15.7" } tari_utilities = { git = "https://github.com/tari-project/tari_utilities.git", tag="v0.4.7" } +tari_common = { version = "^0.39", path = "../../common" } base64 = "0.13.0" digest = "0.9.0" diff --git a/base_layer/common_types/src/emoji.rs b/base_layer/common_types/src/emoji.rs index 2642bf8c41..489bb3f259 100644 --- a/base_layer/common_types/src/emoji.rs +++ b/base_layer/common_types/src/emoji.rs @@ -75,7 +75,7 @@ const INTERNAL_SIZE: usize = 32; // number of bytes used for the internal repres const CHECKSUM_SIZE: usize = 1; // number of bytes in the checksum // The emoji table, mapping byte values to emoji characters -const EMOJI: [char; DICT_SIZE] = [ +pub const EMOJI: [char; DICT_SIZE] = [ '🌀', '🌂', '🌈', '🌊', '🌋', '🌍', '🌙', '🌝', '🌞', '🌟', '🌠', '🌰', '🌴', '🌵', '🌷', '🌸', '🌹', '🌻', '🌽', '🍀', '🍁', '🍄', '🍅', '🍆', '🍇', '🍈', '🍉', '🍊', '🍋', '🍌', '🍍', '🍎', '🍐', '🍑', '🍒', '🍓', '🍔', '🍕', '🍗', '🍚', '🍞', '🍟', '🍠', '🍣', '🍦', '🍩', '🍪', '🍫', '🍬', '🍭', '🍯', '🍰', '🍳', '🍴', '🍵', '🍶', '🍷', @@ -94,7 +94,7 @@ const EMOJI: [char; DICT_SIZE] = [ // The reverse table, mapping emoji to characters to byte values lazy_static! { - static ref REVERSE_EMOJI: HashMap = { + pub static ref REVERSE_EMOJI: HashMap = { let mut m = HashMap::with_capacity(DICT_SIZE); EMOJI.iter().enumerate().for_each(|(i, c)| { m.insert(*c, i as u8); diff --git a/base_layer/common_types/src/lib.rs b/base_layer/common_types/src/lib.rs index df1e3012cc..c4cad69f91 100644 --- a/base_layer/common_types/src/lib.rs +++ b/base_layer/common_types/src/lib.rs @@ -24,6 +24,7 @@ pub mod chain_metadata; pub mod dammsum; pub mod emoji; pub mod grpc_authentication; +pub mod tari_address; pub mod transaction; mod tx_id; pub mod types; diff --git a/base_layer/common_types/src/tari_address.rs b/base_layer/common_types/src/tari_address.rs new file mode 100644 index 0000000000..2e9f95caf1 --- /dev/null +++ b/base_layer/common_types/src/tari_address.rs @@ -0,0 +1,352 @@ +// Copyright 2020. The Tari Project +// +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +// following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +// disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +// following disclaimer in the documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +// products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use std::{ + convert::TryFrom, + fmt::{Display, Error, Formatter}, + str::FromStr, +}; + +use serde::{Deserialize, Serialize}; +use tari_common::configuration::Network; +use tari_crypto::tari_utilities::ByteArray; +use tari_utilities::hex::{from_hex, Hex}; +use thiserror::Error; + +use crate::{ + dammsum::{compute_checksum, validate_checksum}, + emoji::{EMOJI, REVERSE_EMOJI}, + types::PublicKey, +}; + +const INTERNAL_SIZE: usize = 33; // number of bytes used for the internal representation + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)] +pub struct TariAddress { + network: Network, + public_key: PublicKey, +} + +#[derive(Debug, Error, PartialEq)] +pub enum TariAddressError { + #[error("Invalid size")] + InvalidSize, + #[error("Invalid network or checksum")] + InvalidNetworkOrChecksum, + #[error("Invalid emoji character")] + InvalidEmoji, + #[error("Cannot recover public key")] + CannotRecoverPublicKey, +} + +impl TariAddress { + /// Creates a new Tari Address from the provided public key and network while using the current version + pub fn new(public_key: PublicKey, network: Network) -> Self { + TariAddress { network, public_key } + } + + /// helper function to convert emojis to u8 + fn emoji_to_bytes(emoji: &str) -> Result, TariAddressError> { + // The string must be the correct size, including the checksum + if emoji.chars().count() != INTERNAL_SIZE { + return Err(TariAddressError::InvalidSize); + } + + // Convert the emoji string to a byte array + let mut bytes = Vec::::with_capacity(INTERNAL_SIZE); + for c in emoji.chars() { + if let Some(i) = REVERSE_EMOJI.get(&c) { + bytes.push(*i); + } else { + return Err(TariAddressError::InvalidEmoji); + } + } + Ok(bytes) + } + + /// Construct an TariAddress from an emoji string with checksum and network + pub fn from_emoji_string_with_network(emoji: &str, network: Network) -> Result { + let bytes = TariAddress::emoji_to_bytes(emoji)?; + + TariAddress::from_bytes_with_network(&bytes, network) + } + + /// Construct an TariAddress from an emoji string with checksum trying to calculate the network + pub fn from_emoji_string(emoji: &str) -> Result { + let bytes = TariAddress::emoji_to_bytes(emoji)?; + + TariAddress::from_bytes(&bytes) + } + + /// Construct an Tari Address from a public key + pub fn from_public_key(public_key: &PublicKey, network: Network) -> Self { + Self { + network, + public_key: public_key.clone(), + } + } + + /// Gets the network from the Tari Address + pub fn network(&self) -> Network { + self.network + } + + /// Convert Tari Address to an emoji string with checksum + pub fn to_emoji_string(&self) -> String { + // Convert the public key to bytes and compute the checksum + let bytes = self.to_bytes(); + bytes.iter().map(|b| EMOJI[*b as usize]).collect::() + } + + /// Return the public key of an Tari Address + pub fn public_key(&self) -> &PublicKey { + &self.public_key + } + + /// Construct Tari Address from bytes with network + pub fn from_bytes_with_network(bytes: &[u8], network: Network) -> Result + where Self: Sized { + if bytes.len() != INTERNAL_SIZE { + return Err(TariAddressError::InvalidSize); + } + let mut fixed_data = bytes.to_vec(); + fixed_data[32] ^= network.as_byte(); + // Assert the checksum is valid + if validate_checksum(&fixed_data).is_err() { + return Err(TariAddressError::InvalidNetworkOrChecksum); + } + let key = PublicKey::from_bytes(&bytes[0..32]).map_err(|_| TariAddressError::CannotRecoverPublicKey)?; + Ok(TariAddress { + public_key: key, + network, + }) + } + + /// Construct Tari Address from bytes and try to calculate the network + pub fn from_bytes(bytes: &[u8]) -> Result + where Self: Sized { + if bytes.len() != INTERNAL_SIZE { + return Err(TariAddressError::InvalidSize); + } + let checksum = compute_checksum(&bytes[0..32].to_vec()); + // if the network is a valid network number, we can assume that the checksum as valid + let network = + Network::try_from(checksum ^ bytes[32]).map_err(|_| TariAddressError::InvalidNetworkOrChecksum)?; + let key = PublicKey::from_bytes(&bytes[0..32]).map_err(|_| TariAddressError::CannotRecoverPublicKey)?; + Ok(TariAddress { + public_key: key, + network, + }) + } + + /// Convert Tari Address to bytes + pub fn to_bytes(&self) -> [u8; INTERNAL_SIZE] { + let mut buf = [0u8; INTERNAL_SIZE]; + buf[0..32].copy_from_slice(self.public_key.as_bytes()); + let checksum = compute_checksum(&buf[0..32].to_vec()); + buf[32] = self.network.as_byte() ^ checksum; + buf + } + + /// Construct Tari Address from hex with network + pub fn from_hex_with_network(hex_str: &str, network: Network) -> Result { + let buf = from_hex(hex_str).map_err(|_| TariAddressError::CannotRecoverPublicKey)?; + TariAddress::from_bytes_with_network(buf.as_slice(), network) + } + + /// Construct Tari Address from hex and try to calculate the network + pub fn from_hex(hex_str: &str) -> Result { + let buf = from_hex(hex_str).map_err(|_| TariAddressError::CannotRecoverPublicKey)?; + TariAddress::from_bytes(buf.as_slice()) + } + + /// Convert Tari Address to bytes + pub fn to_hex(&self) -> String { + let buf = self.to_bytes(); + buf.to_hex() + } +} + +impl FromStr for TariAddress { + type Err = TariAddressError; + + fn from_str(key: &str) -> Result { + if let Ok(address) = TariAddress::from_emoji_string(&key.trim().replace('|', "")) { + Ok(address) + } else if let Ok(address) = TariAddress::from_hex(key) { + Ok(address) + } else { + Err(TariAddressError::CannotRecoverPublicKey) + } + } +} + +impl Display for TariAddress { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + fmt.write_str(&self.to_emoji_string()) + } +} + +#[cfg(test)] +mod test { + use tari_crypto::keys::{PublicKey, SecretKey}; + + use super::*; + use crate::types::PrivateKey; + + #[test] + /// Test valid tari address + fn valid_emoji_id() { + // Generate random public key + let mut rng = rand::thread_rng(); + let public_key = PublicKey::from_secret_key(&PrivateKey::random(&mut rng)); + + // Generate an emoji ID from the public key and ensure we recover it + let emoji_id_from_public_key = TariAddress::from_public_key(&public_key, Network::Esmeralda); + assert_eq!(emoji_id_from_public_key.public_key(), &public_key); + + // Check the size of the corresponding emoji string + let emoji_string = emoji_id_from_public_key.to_emoji_string(); + assert_eq!(emoji_string.chars().count(), INTERNAL_SIZE); + + // Generate an emoji ID from the emoji string and ensure we recover it + let emoji_id_from_emoji_string = TariAddress::from_emoji_string(&emoji_string).unwrap(); + assert_eq!(emoji_id_from_emoji_string.to_emoji_string(), emoji_string); + + // Return to the original public key for good measure + assert_eq!(emoji_id_from_emoji_string.public_key(), &public_key); + } + + #[test] + /// Test encoding for tari address + fn encoding() { + // Generate random public key + let mut rng = rand::thread_rng(); + let public_key = PublicKey::from_secret_key(&PrivateKey::random(&mut rng)); + + // Generate an emoji ID from the public key and ensure we recover it + let address = TariAddress::from_public_key(&public_key, Network::Esmeralda); + + let buff = address.to_bytes(); + let hex = address.to_hex(); + + let address_buff = TariAddress::from_bytes(&buff); + assert_eq!(address_buff, Ok(address.clone())); + + let address_buff = TariAddress::from_bytes_with_network(&buff, Network::Esmeralda); + assert_eq!(address_buff, Ok(address.clone())); + + let address_hex = TariAddress::from_hex(&hex); + assert_eq!(address_hex, Ok(address.clone())); + + let address_hex = TariAddress::from_hex_with_network(&hex, Network::Esmeralda); + assert_eq!(address_hex, Ok(address)); + } + + #[test] + /// Test invalid size + fn invalid_size() { + // This emoji string is too short to be a valid emoji ID + let emoji_string = "🌴🐩🔌📌🚑🌰🎓🌴🐊🐌💕💡🐜📉👛🍵👛🐽🎂🐻🌀🍓😿🐭🐼🏀🎪💔💸🍅🔋🎒"; + assert_eq!( + TariAddress::from_emoji_string(emoji_string), + Err(TariAddressError::InvalidSize) + ); + // This emoji string is too long to be a valid emoji ID + let emoji_string = "🌴🐩🔌📌🚑🌰🎓🌴🐊🐌💕💡🐜📉👛🍵👛🐽🎂🐻🌀🍓😿🐭🐼🏀🎪💔💸🍅🔋🎒🎒🎒🎒🎒"; + assert_eq!( + TariAddress::from_emoji_string(emoji_string), + Err(TariAddressError::InvalidSize) + ); + } + + #[test] + /// Test invalid emoji + fn invalid_emoji() { + // This emoji string contains an invalid emoji character + let emoji_string = "🌴🐩🔌📌🚑🌰🎓🌴🐊🐌💕💡🐜📉👛🍵👛🐽🎂🐻🌀🍓😿🐭🐼🏀🎪💔💸🍅🔋🎒🎅"; + assert_eq!( + TariAddress::from_emoji_string(emoji_string), + Err(TariAddressError::InvalidEmoji) + ); + } + + #[test] + /// Test invalid checksum + fn invalid_checksum() { + // This emoji string contains an invalid checksum + let emoji_string = "🌴🐩🔌📌🚑🌰🎓🌴🐊🐌💕💡🐜📉👛🍵👛🐽🎂🐻🌀🍓😿🐭🐼🏀🎪💔💸🍅🔋🎒🎒"; + assert_eq!( + TariAddress::from_emoji_string(emoji_string), + Err(TariAddressError::InvalidNetworkOrChecksum) + ); + } + + #[test] + /// Test invalid network + fn invalid_network() { + let mut rng = rand::thread_rng(); + let public_key = PublicKey::from_secret_key(&PrivateKey::random(&mut rng)); + + let emoji_id_from_public_key = TariAddress::from_public_key(&public_key, Network::Esmeralda); + + // let create byte string with bad network u8 + let mut buf = [0u8; INTERNAL_SIZE]; + buf[0..32].copy_from_slice(emoji_id_from_public_key.public_key.as_bytes()); + let checksum = compute_checksum(&buf[0..32].to_vec()); + // 0xb3 is a bad network + buf[32] = 0xb3 ^ checksum; + + let mut bytes = emoji_id_from_public_key.to_bytes(); + // make the network invalid + bytes[1] = 0xb3; + let emoji_string = bytes.iter().map(|b| EMOJI[*b as usize]).collect::(); + + // This emoji string contains an invalid checksum + assert_eq!( + TariAddress::from_emoji_string(&emoji_string), + Err(TariAddressError::InvalidNetworkOrChecksum) + ); + + // This emoji string contains an invalid checksum + assert_eq!( + TariAddress::from_emoji_string_with_network(&emoji_string, Network::Esmeralda), + Err(TariAddressError::InvalidNetworkOrChecksum) + ); + } + + #[test] + /// Test invalid public key + fn invalid_public_key() { + let mut bytes = [0; 33].to_vec(); + bytes[0] = 1; + let checksum = compute_checksum(&bytes[0..32].to_vec()); + bytes[32] = Network::Esmeralda.as_byte() ^ checksum; + let emoji_string = bytes.iter().map(|b| EMOJI[*b as usize]).collect::(); + + // This emoji string contains an invalid checksum + assert_eq!( + TariAddress::from_emoji_string(&emoji_string), + Err(TariAddressError::CannotRecoverPublicKey) + ); + } +} diff --git a/base_layer/wallet/migrations/2022-08-08-134037_initial/up.sql b/base_layer/wallet/migrations/2022-08-08-134037_initial/up.sql index e9897c669d..78412bca8b 100644 --- a/base_layer/wallet/migrations/2022-08-08-134037_initial/up.sql +++ b/base_layer/wallet/migrations/2022-08-08-134037_initial/up.sql @@ -5,8 +5,8 @@ CREATE TABLE client_key_values ( CREATE TABLE completed_transactions ( tx_id BIGINT PRIMARY KEY NOT NULL, - source_public_key BLOB NOT NULL, - destination_public_key BLOB NOT NULL, + source_address BLOB NOT NULL, + destination_address BLOB NOT NULL, amount BIGINT NOT NULL, fee BIGINT NOT NULL, transaction_protocol TEXT NOT NULL, @@ -27,7 +27,7 @@ CREATE TABLE completed_transactions ( ); CREATE TABLE contacts ( - public_key BLOB PRIMARY KEY NOT NULL UNIQUE, + address BLOB PRIMARY KEY NOT NULL UNIQUE, node_id BLOB NOT NULL UNIQUE, alias TEXT NOT NULL, last_seen DATETIME NULL, @@ -36,7 +36,7 @@ CREATE TABLE contacts ( CREATE TABLE inbound_transactions ( tx_id BIGINT PRIMARY KEY NOT NULL, - source_public_key BLOB NOT NULL, + source_address BLOB NOT NULL, amount BIGINT NOT NULL, receiver_protocol TEXT NOT NULL, message TEXT NOT NULL, @@ -54,14 +54,6 @@ CREATE TABLE key_manager_states ( timestamp DATETIME NOT NULL ); -CREATE TABLE key_manager_states_old ( - id INTEGER PRIMARY KEY NOT NULL, - seed BLOB NOT NULL, - branch_seed TEXT UNIQUE NOT NULL, - primary_key_index BLOB NOT NULL, - timestamp DATETIME NOT NULL -); - CREATE TABLE known_one_sided_payment_scripts ( script_hash BLOB PRIMARY KEY NOT NULL, private_key BLOB NOT NULL, @@ -72,7 +64,7 @@ CREATE TABLE known_one_sided_payment_scripts ( CREATE TABLE outbound_transactions ( tx_id BIGINT PRIMARY KEY NOT NULL, - destination_public_key BLOB NOT NULL, + destination_address BLOB NOT NULL, amount BIGINT NOT NULL, fee BIGINT NOT NULL, sender_protocol TEXT NOT NULL, @@ -110,14 +102,11 @@ CREATE TABLE outputs ( spent_in_tx_id BIGINT NULL, coinbase_block_height UNSIGNED BIGINT NULL, metadata BLOB NULL, - features_parent_public_key BLOB NULL, - features_unique_id BLOB NULL, features_json TEXT NOT NULL DEFAULT '{}', spending_priority UNSIGNED INTEGER NOT NULL DEFAULT 500, covenant BLOB NOT NULL, mined_timestamp DATETIME NULL, encrypted_value BLOB NOT NULL, - contract_id BLOB NULL, minimum_value_promise BIGINT NOT NULL, source INTEGER NOT NULL DEFAULT 0, CONSTRAINT unique_commitment UNIQUE (commitment) diff --git a/base_layer/wallet/src/contacts_service/handle.rs b/base_layer/wallet/src/contacts_service/handle.rs index 45c7fe8cfd..165a112d34 100644 --- a/base_layer/wallet/src/contacts_service/handle.rs +++ b/base_layer/wallet/src/contacts_service/handle.rs @@ -26,7 +26,8 @@ use std::{ }; use chrono::{DateTime, Local, NaiveDateTime}; -use tari_comms::{peer_manager::NodeId, types::CommsPublicKey}; +use tari_common_types::tari_address::TariAddress; +use tari_comms::peer_manager::NodeId; use tari_service_framework::reply_channel::SenderService; use tokio::sync::broadcast; use tower::Service; @@ -39,7 +40,7 @@ use crate::contacts_service::{ #[derive(Debug, Clone, PartialEq, Eq)] pub struct ContactsLivenessData { - public_key: CommsPublicKey, + address: TariAddress, node_id: NodeId, latency: Option, last_seen: Option, @@ -49,7 +50,7 @@ pub struct ContactsLivenessData { impl ContactsLivenessData { pub fn new( - public_key: CommsPublicKey, + address: TariAddress, node_id: NodeId, latency: Option, last_seen: Option, @@ -57,7 +58,7 @@ impl ContactsLivenessData { online_status: ContactOnlineStatus, ) -> Self { Self { - public_key, + address, node_id, latency, last_seen, @@ -66,8 +67,8 @@ impl ContactsLivenessData { } } - pub fn public_key(&self) -> &CommsPublicKey { - &self.public_key + pub fn address(&self) -> &TariAddress { + &self.address } pub fn node_id(&self) -> &NodeId { @@ -101,7 +102,7 @@ impl Display for ContactsLivenessData { f, "Liveness event '{}' for contact {} ({}) {}", self.message_type, - self.public_key, + self.address, self.node_id, if let Some(time) = self.last_seen { let local_time = DateTime::::from_utc(time, Local::now().offset().to_owned()) @@ -124,9 +125,9 @@ pub enum ContactsLivenessEvent { #[derive(Debug)] pub enum ContactsServiceRequest { - GetContact(CommsPublicKey), + GetContact(TariAddress), UpsertContact(Contact), - RemoveContact(CommsPublicKey), + RemoveContact(TariAddress), GetContacts, GetContactOnlineStatus(Contact), } @@ -161,10 +162,10 @@ impl ContactsServiceHandle { } } - pub async fn get_contact(&mut self, pub_key: CommsPublicKey) -> Result { + pub async fn get_contact(&mut self, address: TariAddress) -> Result { match self .request_response_service - .call(ContactsServiceRequest::GetContact(pub_key)) + .call(ContactsServiceRequest::GetContact(address)) .await?? { ContactsServiceResponse::Contact(c) => Ok(c), @@ -194,10 +195,10 @@ impl ContactsServiceHandle { } } - pub async fn remove_contact(&mut self, pub_key: CommsPublicKey) -> Result { + pub async fn remove_contact(&mut self, address: TariAddress) -> Result { match self .request_response_service - .call(ContactsServiceRequest::RemoveContact(pub_key)) + .call(ContactsServiceRequest::RemoveContact(address)) .await?? { ContactsServiceResponse::ContactRemoved(c) => Ok(c), diff --git a/base_layer/wallet/src/contacts_service/service.rs b/base_layer/wallet/src/contacts_service/service.rs index a6ac57fec7..af5a1248c1 100644 --- a/base_layer/wallet/src/contacts_service/service.rs +++ b/base_layer/wallet/src/contacts_service/service.rs @@ -206,7 +206,7 @@ where T: ContactsBackend + 'static self.liveness.check_add_monitored_peer(c.node_id).await?; info!( target: LOG_TARGET, - "Contact Saved: \nAlias: {}\nPubKey: {} ", c.alias, c.public_key + "Contact Saved: \nAlias: {}\nAddress: {} ", c.alias, c.address ); Ok(ContactsServiceResponse::ContactSaved) }, @@ -217,7 +217,7 @@ where T: ContactsBackend + 'static .await?; info!( target: LOG_TARGET, - "Contact Removed: \nAlias: {}\nPubKey: {} ", result.alias, result.public_key + "Contact Removed: \nAlias: {}\nAddress: {} ", result.alias, result.address ); Ok(ContactsServiceResponse::ContactRemoved(result)) }, @@ -284,7 +284,7 @@ where T: ContactsBackend + 'static continue; } let data = ContactsLivenessData::new( - contact.public_key.clone(), + contact.address.clone(), contact.node_id.clone(), contact.latency, contact.last_seen, diff --git a/base_layer/wallet/src/contacts_service/storage/database.rs b/base_layer/wallet/src/contacts_service/storage/database.rs index 425f59a464..3811e7e08f 100644 --- a/base_layer/wallet/src/contacts_service/storage/database.rs +++ b/base_layer/wallet/src/contacts_service/storage/database.rs @@ -27,7 +27,8 @@ use std::{ use chrono::NaiveDateTime; use log::*; -use tari_comms::{peer_manager::NodeId, types::CommsPublicKey}; +use tari_common_types::tari_address::TariAddress; +use tari_comms::peer_manager::NodeId; use crate::contacts_service::error::ContactsServiceStorageError; @@ -36,23 +37,18 @@ const LOG_TARGET: &str = "wallet::contacts_service::database"; #[derive(Debug, Clone, PartialEq, Eq)] pub struct Contact { pub alias: String, - pub public_key: CommsPublicKey, + pub address: TariAddress, pub node_id: NodeId, pub last_seen: Option, pub latency: Option, } impl Contact { - pub fn new( - alias: String, - public_key: CommsPublicKey, - last_seen: Option, - latency: Option, - ) -> Self { + pub fn new(alias: String, address: TariAddress, last_seen: Option, latency: Option) -> Self { Self { alias, - public_key: public_key.clone(), - node_id: NodeId::from_key(&public_key), + node_id: NodeId::from_key(address.public_key()), + address, last_seen, latency, } @@ -69,7 +65,7 @@ pub trait ContactsBackend: Send + Sync + Clone { #[derive(Debug, Clone, PartialEq, Eq)] pub enum DbKey { - Contact(CommsPublicKey), + Contact(TariAddress), ContactId(NodeId), Contacts, } @@ -77,12 +73,12 @@ pub enum DbKey { pub enum DbValue { Contact(Box), Contacts(Vec), - PublicKey(Box), + TariAddress(Box), } #[allow(clippy::large_enum_variant)] pub enum DbKeyValuePair { - Contact(CommsPublicKey, Contact), + Contact(TariAddress, Contact), LastSeen(NodeId, NaiveDateTime, Option), } @@ -118,9 +114,9 @@ where T: ContactsBackend + 'static Self { db: Arc::new(db) } } - pub fn get_contact(&self, pub_key: CommsPublicKey) -> Result { + pub fn get_contact(&self, address: TariAddress) -> Result { let db_clone = self.db.clone(); - fetch!(db_clone, pub_key, Contact) + fetch!(db_clone, address, Contact) } pub fn get_contacts(&self) -> Result, ContactsServiceStorageError> { @@ -138,7 +134,7 @@ where T: ContactsBackend + 'static pub fn upsert_contact(&self, contact: Contact) -> Result<(), ContactsServiceStorageError> { self.db.write(WriteOperation::Upsert(Box::new(DbKeyValuePair::Contact( - contact.public_key.clone(), + contact.address.clone(), contact, ))))?; Ok(()) @@ -149,7 +145,7 @@ where T: ContactsBackend + 'static node_id: &NodeId, last_seen: NaiveDateTime, latency: Option, - ) -> Result { + ) -> Result { let result = self .db .write(WriteOperation::UpdateLastSeen(Box::new(DbKeyValuePair::LastSeen( @@ -159,21 +155,21 @@ where T: ContactsBackend + 'static ))))? .ok_or_else(|| ContactsServiceStorageError::ValueNotFound(DbKey::ContactId(node_id.clone())))?; match result { - DbValue::PublicKey(k) => Ok(*k), + DbValue::TariAddress(k) => Ok(*k), _ => Err(ContactsServiceStorageError::UnexpectedResult( "Incorrect response from backend.".to_string(), )), } } - pub fn remove_contact(&self, pub_key: CommsPublicKey) -> Result { + pub fn remove_contact(&self, address: TariAddress) -> Result { let result = self .db - .write(WriteOperation::Remove(DbKey::Contact(pub_key.clone())))? - .ok_or_else(|| ContactsServiceStorageError::ValueNotFound(DbKey::Contact(pub_key.clone())))?; + .write(WriteOperation::Remove(DbKey::Contact(address.clone())))? + .ok_or_else(|| ContactsServiceStorageError::ValueNotFound(DbKey::Contact(address.clone())))?; match result { DbValue::Contact(c) => Ok(*c), - DbValue::Contacts(_) | DbValue::PublicKey(_) => Err(ContactsServiceStorageError::UnexpectedResult( + DbValue::Contacts(_) | DbValue::TariAddress(_) => Err(ContactsServiceStorageError::UnexpectedResult( "Incorrect response from backend.".to_string(), )), } @@ -201,7 +197,7 @@ impl Display for DbValue { match self { DbValue::Contact(_) => f.write_str("Contact"), DbValue::Contacts(_) => f.write_str("Contacts"), - DbValue::PublicKey(_) => f.write_str("PublicKey"), + DbValue::TariAddress(_) => f.write_str("Address"), } } } diff --git a/base_layer/wallet/src/contacts_service/storage/sqlite_db.rs b/base_layer/wallet/src/contacts_service/storage/sqlite_db.rs index a599c6cc02..4efd8e778e 100644 --- a/base_layer/wallet/src/contacts_service/storage/sqlite_db.rs +++ b/base_layer/wallet/src/contacts_service/storage/sqlite_db.rs @@ -24,7 +24,7 @@ use std::convert::TryFrom; use chrono::NaiveDateTime; use diesel::{prelude::*, result::Error as DieselError, SqliteConnection}; -use tari_common_types::types::PublicKey; +use tari_common_types::tari_address::TariAddress; use tari_comms::peer_manager::NodeId; use tari_utilities::ByteArray; @@ -54,7 +54,7 @@ impl ContactsBackend for ContactsServiceSqliteDatabase { let conn = self.database_connection.get_pooled_connection()?; let result = match key { - DbKey::Contact(pk) => match ContactSql::find_by_public_key(&pk.to_vec(), &conn) { + DbKey::Contact(address) => match ContactSql::find_by_address(&address.to_bytes(), &conn) { Ok(c) => Some(DbValue::Contact(Box::new(Contact::try_from(c)?))), Err(ContactsServiceStorageError::DieselError(DieselError::NotFound)) => None, Err(e) => return Err(e), @@ -81,7 +81,7 @@ impl ContactsBackend for ContactsServiceSqliteDatabase { match op { WriteOperation::Upsert(kvp) => match *kvp { DbKeyValuePair::Contact(k, c) => { - if ContactSql::find_by_public_key_and_update(&conn, &k.to_vec(), UpdateContact { + if ContactSql::find_by_address_and_update(&conn, &k.to_bytes(), UpdateContact { alias: Some(c.clone().alias), last_seen: None, latency: None, @@ -100,15 +100,15 @@ impl ContactsBackend for ContactsServiceSqliteDatabase { last_seen: Some(Some(date_time)), latency: Some(latency), })?; - return Ok(Some(DbValue::PublicKey(Box::new( - PublicKey::from_vec(&contact.public_key) + return Ok(Some(DbValue::TariAddress(Box::new( + TariAddress::from_bytes(&contact.address) .map_err(|_| ContactsServiceStorageError::ConversionError)?, )))); }, DbKeyValuePair::Contact(..) => return Err(ContactsServiceStorageError::OperationNotSupported), }, WriteOperation::Remove(k) => match k { - DbKey::Contact(k) => match ContactSql::find_by_public_key_and_delete(&conn, &k.to_vec()) { + DbKey::Contact(k) => match ContactSql::find_by_address_and_delete(&conn, &k.to_bytes()) { Ok(c) => { return Ok(Some(DbValue::Contact(Box::new(Contact::try_from(c)?)))); }, @@ -134,7 +134,7 @@ impl ContactsBackend for ContactsServiceSqliteDatabase { #[derive(Clone, Debug, Queryable, Insertable, PartialEq, Eq)] #[table_name = "contacts"] struct ContactSql { - public_key: Vec, + address: Vec, node_id: Vec, alias: String, last_seen: Option, @@ -155,13 +155,10 @@ impl ContactSql { Ok(contacts::table.load::(conn)?) } - /// Find a particular Contact by their public key, if it exists - pub fn find_by_public_key( - public_key: &[u8], - conn: &SqliteConnection, - ) -> Result { + /// Find a particular Contact by their address, if it exists + pub fn find_by_address(address: &[u8], conn: &SqliteConnection) -> Result { Ok(contacts::table - .filter(contacts::public_key.eq(public_key)) + .filter(contacts::address.eq(address)) .first::(conn)?) } @@ -172,28 +169,28 @@ impl ContactSql { .first::(conn)?) } - /// Find a particular Contact by their public key, and update it if it exists, returning the affected record - pub fn find_by_public_key_and_update( + /// Find a particular Contact by their address, and update it if it exists, returning the affected record + pub fn find_by_address_and_update( conn: &SqliteConnection, - public_key: &[u8], + address: &[u8], updated_contact: UpdateContact, ) -> Result { // Note: `get_result` not implemented for SQLite - diesel::update(contacts::table.filter(contacts::public_key.eq(public_key))) + diesel::update(contacts::table.filter(contacts::address.eq(address))) .set(updated_contact) .execute(conn) .num_rows_affected_or_not_found(1)?; - ContactSql::find_by_public_key(public_key, conn) + ContactSql::find_by_address(address, conn) } - /// Find a particular Contact by their public key, and delete it if it exists, returning the affected record - pub fn find_by_public_key_and_delete( + /// Find a particular Contact by their address, and delete it if it exists, returning the affected record + pub fn find_by_address_and_delete( conn: &SqliteConnection, - public_key: &[u8], + address: &[u8], ) -> Result { // Note: `get_result` not implemented for SQLite - let contact = ContactSql::find_by_public_key(public_key, conn)?; - if diesel::delete(contacts::table.filter(contacts::public_key.eq(public_key))).execute(conn)? == 0 { + let contact = ContactSql::find_by_address(address, conn)?; + if diesel::delete(contacts::table.filter(contacts::address.eq(address))).execute(conn)? == 0 { return Err(ContactsServiceStorageError::ValuesNotFound); } Ok(contact) @@ -233,12 +230,11 @@ impl TryFrom for Contact { #[allow(clippy::cast_sign_loss)] fn try_from(o: ContactSql) -> Result { - let public_key = - PublicKey::from_vec(&o.public_key).map_err(|_| ContactsServiceStorageError::ConversionError)?; + let address = TariAddress::from_bytes(&o.address).map_err(|_| ContactsServiceStorageError::ConversionError)?; Ok(Self { - public_key: public_key.clone(), // Public key must always be the master data source for node ID here - node_id: NodeId::from_key(&public_key), + node_id: NodeId::from_key(address.public_key()), + address, alias: o.alias, last_seen: o.last_seen, latency: o.latency.map(|val| val as u32), @@ -251,9 +247,9 @@ impl TryFrom for Contact { impl From for ContactSql { fn from(o: Contact) -> Self { Self { - public_key: o.public_key.to_vec(), // Public key must always be the master data source for node ID here - node_id: NodeId::from_key(&o.public_key).to_vec(), + node_id: NodeId::from_key(o.address.public_key()).to_vec(), + address: o.address.to_bytes().to_vec(), alias: o.alias, last_seen: o.last_seen, latency: o.latency.map(|val| val as i32), @@ -275,11 +271,12 @@ mod test { use diesel::{Connection, SqliteConnection}; use rand::rngs::OsRng; - use tari_common_types::types::{PrivateKey, PublicKey}; - use tari_crypto::{ - keys::{PublicKey as PublicKeyTrait, SecretKey as SecretKeyTrait}, - tari_utilities::ByteArray, + use tari_common::configuration::Network; + use tari_common_types::{ + tari_address::TariAddress, + types::{PrivateKey, PublicKey}, }; + use tari_crypto::keys::{PublicKey as PublicKeyTrait, SecretKey as SecretKeyTrait}; use tari_test_utils::{paths::with_temp_dir, random::string}; use crate::contacts_service::storage::{ @@ -306,7 +303,8 @@ mod test { let mut contacts = Vec::new(); for i in 0..names.len() { let pub_key = PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)); - contacts.push(Contact::new(names[i].clone(), pub_key, None, None)); + let address = TariAddress::new(pub_key, Network::default()); + contacts.push(Contact::new(names[i].clone(), address, None, None)); ContactSql::from(contacts[i].clone()).commit(&conn).unwrap(); } @@ -318,11 +316,11 @@ mod test { assert_eq!( contacts[1], - Contact::try_from(ContactSql::find_by_public_key(&contacts[1].public_key.to_vec(), &conn).unwrap()) + Contact::try_from(ContactSql::find_by_address(&contacts[1].address.to_bytes(), &conn).unwrap()) .unwrap() ); - ContactSql::find_by_public_key_and_delete(&conn, &contacts[0].public_key.clone().to_vec()).unwrap(); + ContactSql::find_by_address_and_delete(&conn, &contacts[0].address.clone().to_bytes()).unwrap(); let retrieved_contacts = ContactSql::index(&conn).unwrap(); assert_eq!(retrieved_contacts.len(), 2); @@ -331,15 +329,14 @@ mod test { .iter() .any(|v| v == &ContactSql::from(contacts[0].clone()))); - let _c = - ContactSql::find_by_public_key_and_update(&conn, &contacts[1].public_key.to_vec(), UpdateContact { - alias: Some("Fred".to_string()), - last_seen: None, - latency: None, - }) - .unwrap(); + let _c = ContactSql::find_by_address_and_update(&conn, &contacts[1].address.to_bytes(), UpdateContact { + alias: Some("Fred".to_string()), + last_seen: None, + latency: None, + }) + .unwrap(); - let c_updated = ContactSql::find_by_public_key(&contacts[1].public_key.to_vec(), &conn).unwrap(); + let c_updated = ContactSql::find_by_address(&contacts[1].address.to_bytes(), &conn).unwrap(); assert_eq!(c_updated.alias, "Fred".to_string()); }); } diff --git a/base_layer/wallet/src/schema.rs b/base_layer/wallet/src/schema.rs index 06fd45f00e..943b64dcd3 100644 --- a/base_layer/wallet/src/schema.rs +++ b/base_layer/wallet/src/schema.rs @@ -1,37 +1,15 @@ -// Copyright 2020. The Tari Project -// -// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the -// following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following -// disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the -// following disclaimer in the documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote -// products derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE -// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -table! { +diesel::table! { client_key_values (key) { key -> Text, value -> Text, } } -table! { +diesel::table! { completed_transactions (tx_id) { tx_id -> BigInt, - source_public_key -> Binary, - destination_public_key -> Binary, + source_address -> Binary, + destination_address -> Binary, amount -> BigInt, fee -> BigInt, transaction_protocol -> Text, @@ -52,9 +30,9 @@ table! { } } -table! { - contacts (public_key) { - public_key -> Binary, +diesel::table! { + contacts (address) { + address -> Binary, node_id -> Binary, alias -> Text, last_seen -> Nullable, @@ -62,10 +40,10 @@ table! { } } -table! { +diesel::table! { inbound_transactions (tx_id) { tx_id -> BigInt, - source_public_key -> Binary, + source_address -> Binary, amount -> BigInt, receiver_protocol -> Text, message -> Text, @@ -77,7 +55,7 @@ table! { } } -table! { +diesel::table! { key_manager_states (id) { id -> Integer, branch_seed -> Text, @@ -86,17 +64,7 @@ table! { } } -table! { - key_manager_states_old (id) { - id -> Integer, - seed -> Binary, - branch_seed -> Text, - primary_key_index -> BigInt, - timestamp -> Timestamp, - } -} - -table! { +diesel::table! { known_one_sided_payment_scripts (script_hash) { script_hash -> Binary, private_key -> Binary, @@ -106,10 +74,10 @@ table! { } } -table! { +diesel::table! { outbound_transactions (tx_id) { tx_id -> BigInt, - destination_public_key -> Binary, + destination_address -> Binary, amount -> BigInt, fee -> BigInt, sender_protocol -> Text, @@ -122,7 +90,7 @@ table! { } } -table! { +diesel::table! { outputs (id) { id -> Integer, commitment -> Nullable, @@ -159,7 +127,7 @@ table! { } } -table! { +diesel::table! { scanned_blocks (header_hash) { header_hash -> Binary, height -> BigInt, @@ -169,20 +137,19 @@ table! { } } -table! { +diesel::table! { wallet_settings (key) { key -> Text, value -> Text, } } -allow_tables_to_appear_in_same_query!( +diesel::allow_tables_to_appear_in_same_query!( client_key_values, completed_transactions, contacts, inbound_transactions, key_manager_states, - key_manager_states_old, known_one_sided_payment_scripts, outbound_transactions, outputs, diff --git a/base_layer/wallet/src/transaction_service/error.rs b/base_layer/wallet/src/transaction_service/error.rs index 0d96676711..11c3ab67d8 100644 --- a/base_layer/wallet/src/transaction_service/error.rs +++ b/base_layer/wallet/src/transaction_service/error.rs @@ -24,6 +24,7 @@ use diesel::result::Error as DieselError; use futures::channel::oneshot::Canceled; use serde_json::Error as SerdeJsonError; use tari_common_types::{ + tari_address::TariAddressError, transaction::{TransactionConversionError, TransactionDirectionError, TxId}, types::FixedHashSizeError, }; @@ -52,6 +53,8 @@ use crate::{ pub enum TransactionServiceError { #[error("Transaction protocol is not in the correct state for this operation")] InvalidStateError, + #[error("Transaction is sending to a network different than ours")] + InvalidNetwork, #[error("One-sided transaction error: `{0}`")] OneSidedTransactionError(String), #[error("Transaction Protocol Error: `{0}`")] @@ -179,10 +182,10 @@ pub enum TransactionServiceError { #[derive(Debug, Error)] pub enum TransactionKeyError { - #[error("Invalid source Publickey")] - Source(ByteArrayError), - #[error("Invalid destination PublicKey")] - Destination(ByteArrayError), + #[error("Invalid source address")] + Source(TariAddressError), + #[error("Invalid destination address")] + Destination(TariAddressError), #[error("Invalid transaction signature nonce")] SignatureNonce(ByteArrayError), #[error("Invalid transaction signature key")] @@ -233,6 +236,8 @@ pub enum TransactionStorageError { TransactionNotMined(TxId), #[error("Conversion error: `{0}`")] ByteArrayError(#[from] ByteArrayError), + #[error("Tari address error: `{0}`")] + TariAddressError(#[from] TariAddressError), #[error("Not a coinbase transaction so cannot be abandoned")] NotCoinbase, } diff --git a/base_layer/wallet/src/transaction_service/handle.rs b/base_layer/wallet/src/transaction_service/handle.rs index 92a11c17bb..81d190b241 100644 --- a/base_layer/wallet/src/transaction_service/handle.rs +++ b/base_layer/wallet/src/transaction_service/handle.rs @@ -30,6 +30,7 @@ use std::{ use chacha20poly1305::XChaCha20Poly1305; use chrono::NaiveDateTime; use tari_common_types::{ + tari_address::TariAddress, transaction::{ImportStatus, TxId}, types::{PublicKey, Signature}, }; @@ -43,7 +44,6 @@ use tari_core::{ }, }; use tari_service_framework::reply_channel::SenderService; -use tari_utilities::hex::Hex; use tokio::sync::broadcast; use tower::Service; @@ -75,7 +75,7 @@ pub enum TransactionServiceRequest { GetCompletedTransaction(TxId), GetAnyTransaction(TxId), SendTransaction { - dest_pubkey: CommsPublicKey, + destination: TariAddress, amount: MicroTari, selection_criteria: UtxoSelectionCriteria, output_features: Box, @@ -96,7 +96,7 @@ pub enum TransactionServiceRequest { message: String, }, SendOneSidedTransaction { - dest_pubkey: CommsPublicKey, + destination: TariAddress, amount: MicroTari, selection_criteria: UtxoSelectionCriteria, output_features: Box, @@ -104,18 +104,18 @@ pub enum TransactionServiceRequest { message: String, }, SendOneSidedToStealthAddressTransaction { - dest_pubkey: CommsPublicKey, + destination: TariAddress, amount: MicroTari, selection_criteria: UtxoSelectionCriteria, output_features: Box, fee_per_gram: MicroTari, message: String, }, - SendShaAtomicSwapTransaction(CommsPublicKey, MicroTari, UtxoSelectionCriteria, MicroTari, String), + SendShaAtomicSwapTransaction(TariAddress, MicroTari, UtxoSelectionCriteria, MicroTari, String), CancelTransaction(TxId), ImportUtxoWithStatus { amount: MicroTari, - source_public_key: CommsPublicKey, + source_address: TariAddress, message: String, maturity: Option, import_status: ImportStatus, @@ -152,17 +152,11 @@ impl fmt::Display for TransactionServiceRequest { Self::GetCancelledCompletedTransactions => write!(f, "GetCancelledCompletedTransactions"), Self::GetCompletedTransaction(t) => write!(f, "GetCompletedTransaction({})", t), Self::SendTransaction { - dest_pubkey, + destination, amount, message, .. - } => write!( - f, - "SendTransaction (to {}, {}, {})", - dest_pubkey.to_hex(), - amount, - message - ), + } => write!(f, "SendTransaction (to {}, {}, {})", destination, amount, message), Self::BurnTari { amount, message, .. } => write!(f, "Burning Tari ({}, {})", amount, message), Self::RegisterValidatorNode { validator_node_public_key, @@ -170,28 +164,24 @@ impl fmt::Display for TransactionServiceRequest { .. } => write!(f, "Registering VN ({}, {})", validator_node_public_key, message), Self::SendOneSidedTransaction { - dest_pubkey, + destination, amount, message, .. } => write!( f, "SendOneSidedTransaction (to {}, {}, {})", - dest_pubkey.to_hex(), - amount, - message + destination, amount, message ), Self::SendOneSidedToStealthAddressTransaction { - dest_pubkey, + destination, amount, message, .. } => write!( f, "SendOneSidedToStealthAddressTransaction (to {}, {}, {})", - dest_pubkey.to_hex(), - amount, - message + destination, amount, message ), Self::SendShaAtomicSwapTransaction(k, _, v, _, msg) => { write!(f, "SendShaAtomicSwapTransaction (to {}, {}, {})", k, v, msg) @@ -199,7 +189,7 @@ impl fmt::Display for TransactionServiceRequest { Self::CancelTransaction(t) => write!(f, "CancelTransaction ({})", t), Self::ImportUtxoWithStatus { amount, - source_public_key, + source_address, message, maturity, import_status, @@ -209,7 +199,7 @@ impl fmt::Display for TransactionServiceRequest { } => write!( f, "ImportUtxo (from {}, {}, {} with maturity {} and {:?} and {:?} and {:?} and {:?})", - source_public_key, + source_address, amount, message, maturity.unwrap_or(0), @@ -447,7 +437,7 @@ impl TransactionServiceHandle { pub async fn send_transaction( &mut self, - dest_pubkey: CommsPublicKey, + destination: TariAddress, amount: MicroTari, selection_criteria: UtxoSelectionCriteria, output_features: OutputFeatures, @@ -457,7 +447,7 @@ impl TransactionServiceHandle { match self .handle .call(TransactionServiceRequest::SendTransaction { - dest_pubkey, + destination, amount, selection_criteria, output_features: Box::new(output_features), @@ -497,7 +487,7 @@ impl TransactionServiceHandle { pub async fn send_one_sided_transaction( &mut self, - dest_pubkey: CommsPublicKey, + destination: TariAddress, amount: MicroTari, selection_criteria: UtxoSelectionCriteria, output_features: OutputFeatures, @@ -507,7 +497,7 @@ impl TransactionServiceHandle { match self .handle .call(TransactionServiceRequest::SendOneSidedTransaction { - dest_pubkey, + destination, amount, selection_criteria, output_features: Box::new(output_features), @@ -546,7 +536,7 @@ impl TransactionServiceHandle { pub async fn send_one_sided_to_stealth_address_transaction( &mut self, - dest_pubkey: CommsPublicKey, + destination: TariAddress, amount: MicroTari, selection_criteria: UtxoSelectionCriteria, output_features: OutputFeatures, @@ -556,7 +546,7 @@ impl TransactionServiceHandle { match self .handle .call(TransactionServiceRequest::SendOneSidedToStealthAddressTransaction { - dest_pubkey, + destination, amount, selection_criteria, output_features: Box::new(output_features), @@ -690,7 +680,7 @@ impl TransactionServiceHandle { pub async fn import_utxo_with_status( &mut self, amount: MicroTari, - source_public_key: CommsPublicKey, + source_address: TariAddress, message: String, maturity: Option, import_status: ImportStatus, @@ -702,7 +692,7 @@ impl TransactionServiceHandle { .handle .call(TransactionServiceRequest::ImportUtxoWithStatus { amount, - source_public_key, + source_address, message, maturity, import_status, @@ -861,7 +851,7 @@ impl TransactionServiceHandle { pub async fn send_sha_atomic_swap_transaction( &mut self, - dest_pubkey: CommsPublicKey, + destination: TariAddress, amount: MicroTari, selection_criteria: UtxoSelectionCriteria, fee_per_gram: MicroTari, @@ -870,7 +860,7 @@ impl TransactionServiceHandle { match self .handle .call(TransactionServiceRequest::SendShaAtomicSwapTransaction( - dest_pubkey, + destination, amount, selection_criteria, fee_per_gram, diff --git a/base_layer/wallet/src/transaction_service/mod.rs b/base_layer/wallet/src/transaction_service/mod.rs index 0f14c7dd0b..e6be0fb21c 100644 --- a/base_layer/wallet/src/transaction_service/mod.rs +++ b/base_layer/wallet/src/transaction_service/mod.rs @@ -24,7 +24,6 @@ use std::sync::Arc; use futures::{Stream, StreamExt}; use log::*; -use tari_comms::peer_manager::NodeIdentity; use tari_comms_dht::Dht; use tari_core::{ proto::base_node as base_node_proto, @@ -56,6 +55,7 @@ use crate::{ service::TransactionService, storage::database::{TransactionBackend, TransactionDatabase}, }, + util::wallet_identity::WalletIdentity, }; pub mod config; @@ -78,7 +78,7 @@ where config: TransactionServiceConfig, subscription_factory: Arc, tx_backend: Option, - node_identity: Arc, + wallet_identity: WalletIdentity, factories: CryptoFactories, wallet_database: Option>, } @@ -92,7 +92,7 @@ where config: TransactionServiceConfig, subscription_factory: Arc, backend: T, - node_identity: Arc, + wallet_identity: WalletIdentity, factories: CryptoFactories, wallet_database: WalletDatabase, ) -> Self { @@ -100,7 +100,7 @@ where config, subscription_factory, tx_backend: Some(backend), - node_identity, + wallet_identity, factories, wallet_database: Some(wallet_database), } @@ -204,7 +204,7 @@ where .take() .expect("Cannot start Transaction Service without providing a wallet database"); - let node_identity = self.node_identity.clone(); + let wallet_identity = self.wallet_identity.clone(); let factories = self.factories.clone(); let config = self.config.clone(); @@ -228,7 +228,7 @@ where outbound_message_service, connectivity, publisher, - node_identity, + wallet_identity, factories, handles.get_shutdown_signal(), base_node_service_handle, diff --git a/base_layer/wallet/src/transaction_service/protocols/transaction_receive_protocol.rs b/base_layer/wallet/src/transaction_service/protocols/transaction_receive_protocol.rs index ff1d55ef7f..5cd19767c1 100644 --- a/base_layer/wallet/src/transaction_service/protocols/transaction_receive_protocol.rs +++ b/base_layer/wallet/src/transaction_service/protocols/transaction_receive_protocol.rs @@ -26,10 +26,10 @@ use chrono::Utc; use futures::future::FutureExt; use log::*; use tari_common_types::{ + tari_address::TariAddress, transaction::{TransactionDirection, TransactionStatus, TxId}, types::HashOutput, }; -use tari_comms::types::CommsPublicKey; use tari_core::transactions::{ transaction_components::Transaction, transaction_protocol::{recipient::RecipientState, sender::TransactionSenderMessage}, @@ -64,11 +64,11 @@ pub enum TransactionReceiveProtocolStage { pub struct TransactionReceiveProtocol { id: TxId, - source_pubkey: CommsPublicKey, + source_address: TariAddress, sender_message: TransactionSenderMessage, stage: TransactionReceiveProtocolStage, resources: TransactionServiceResources, - transaction_finalize_receiver: Option>, + transaction_finalize_receiver: Option>, cancellation_receiver: Option>, prev_header: Option, height: Option, @@ -81,18 +81,18 @@ where { pub fn new( id: TxId, - source_pubkey: CommsPublicKey, + source_address: TariAddress, sender_message: TransactionSenderMessage, stage: TransactionReceiveProtocolStage, resources: TransactionServiceResources, - transaction_finalize_receiver: mpsc::Receiver<(CommsPublicKey, TxId, Transaction)>, + transaction_finalize_receiver: mpsc::Receiver<(TariAddress, TxId, Transaction)>, cancellation_receiver: oneshot::Receiver<()>, prev_header: Option, height: Option, ) -> Self { Self { id, - source_pubkey, + source_address, sender_message, stage, resources, @@ -155,7 +155,7 @@ where let inbound_transaction = InboundTransaction::new( data.tx_id, - self.source_pubkey.clone(), + self.source_address.clone(), amount, rtp, TransactionStatus::Pending, @@ -185,14 +185,14 @@ where if send_result { info!( target: LOG_TARGET, - "Transaction with TX_ID = {} received from {}. Reply Sent", data.tx_id, self.source_pubkey, + "Transaction with TX_ID = {} received from {}. Reply Sent", data.tx_id, self.source_address, ); } else { error!( target: LOG_TARGET, "Transaction with TX_ID = {} received from {}. Reply could not be sent!", data.tx_id, - self.source_pubkey, + self.source_address, ); } @@ -304,9 +304,9 @@ where loop { let resend_timeout = sleep(self.resources.config.transaction_resend_period).fuse(); tokio::select! { - Some((spk, tx_id, tx)) = receiver.recv() => { + Some((address, tx_id, tx)) = receiver.recv() => { incoming_finalized_transaction = Some(tx); - if inbound_tx.source_public_key != spk { + if inbound_tx.source_address != address { warn!( target: LOG_TARGET, "Finalized Transaction did not come from the expected Public Key" @@ -360,7 +360,7 @@ where target: LOG_TARGET, "Finalized Transaction with TX_ID = {} received from {}", self.id, - self.source_pubkey.clone() + self.source_address.clone() ); finalized_transaction @@ -435,8 +435,8 @@ where let completed_transaction = CompletedTransaction::new( self.id, - self.source_pubkey.clone(), - self.resources.node_identity.public_key().clone(), + self.source_address.clone(), + self.resources.wallet_identity.address.clone(), inbound_tx.amount, finalized_transaction.body.get_total_fee(), finalized_transaction.clone(), @@ -458,7 +458,7 @@ where target: LOG_TARGET, "Inbound Transaction with TX_ID = {} from {} moved to Completed Transactions", self.id, - self.source_pubkey.clone() + self.source_address.clone() ); let _size = self diff --git a/base_layer/wallet/src/transaction_service/protocols/transaction_send_protocol.rs b/base_layer/wallet/src/transaction_service/protocols/transaction_send_protocol.rs index 7d498b139e..2442f3fc62 100644 --- a/base_layer/wallet/src/transaction_service/protocols/transaction_send_protocol.rs +++ b/base_layer/wallet/src/transaction_service/protocols/transaction_send_protocol.rs @@ -26,6 +26,7 @@ use chrono::Utc; use futures::FutureExt; use log::*; use tari_common_types::{ + tari_address::TariAddress, transaction::{TransactionDirection, TransactionStatus, TxId}, types::HashOutput, }; @@ -87,7 +88,7 @@ pub enum TransactionSendProtocolStage { pub struct TransactionSendProtocol { id: TxId, - dest_pubkey: CommsPublicKey, + dest_address: TariAddress, amount: MicroTari, fee_per_gram: MicroTari, message: String, @@ -112,7 +113,7 @@ where resources: TransactionServiceResources, transaction_reply_receiver: Receiver<(CommsPublicKey, RecipientSignedMessage)>, cancellation_receiver: oneshot::Receiver<()>, - dest_pubkey: CommsPublicKey, + dest_address: TariAddress, amount: MicroTari, fee_per_gram: MicroTari, message: String, @@ -130,7 +131,7 @@ where resources, transaction_reply_receiver: Some(transaction_reply_receiver), cancellation_receiver: Some(cancellation_receiver), - dest_pubkey, + dest_address, amount, fee_per_gram, message, @@ -324,7 +325,7 @@ where .map_err(|e| TransactionServiceProtocolError::new(self.id, TransactionServiceError::from(e)))?; let outbound_tx = OutboundTransaction::new( tx_id, - self.dest_pubkey.clone(), + self.dest_address.clone(), self.amount, fee, sender_protocol.clone(), @@ -468,7 +469,7 @@ where let rr_tx_id = rr.tx_id; reply = Some(rr); - if outbound_tx.destination_public_key != spk { + if outbound_tx.destination_address.public_key() != &spk { warn!( target: LOG_TARGET, "Transaction Reply did not come from the expected Public Key" @@ -483,7 +484,7 @@ where if result.is_ok() { info!(target: LOG_TARGET, "Cancelling Transaction Send Protocol (TxId: {})", self.id); let _ = send_transaction_cancelled_message( - self.id,self.dest_pubkey.clone(), + self.id,self.dest_address.public_key().clone(), self.resources.outbound_message_service.clone(), ) .await.map_err(|e| { warn!( @@ -570,8 +571,8 @@ where let completed_transaction = CompletedTransaction::new( tx_id, - self.resources.node_identity.public_key().clone(), - outbound_tx.destination_public_key.clone(), + self.resources.wallet_identity.address.clone(), + outbound_tx.destination_address, outbound_tx.amount, outbound_tx.fee, tx.clone(), @@ -596,7 +597,7 @@ where send_finalized_transaction_message( tx_id, tx.clone(), - self.dest_pubkey.clone(), + self.dest_address.public_key().clone(), self.resources.outbound_message_service.clone(), self.resources.config.direct_send_timeout, self.resources.config.transaction_routing_mechanism, @@ -670,14 +671,14 @@ where info!( target: LOG_TARGET, - "Attempting to Send Transaction (TxId: {}) to recipient with Public Key: {}", self.id, self.dest_pubkey, + "Attempting to Send Transaction (TxId: {}) to recipient with address: {}", self.id, self.dest_address, ); match self .resources .outbound_message_service .send_direct( - self.dest_pubkey.clone(), + self.dest_address.public_key().clone(), OutboundDomainMessage::new(&TariMessageType::SenderPartialTransaction, proto_message.clone()), "transaction send".to_string(), ) @@ -688,7 +689,7 @@ where if wait_on_dial( send_states, self.id, - self.dest_pubkey.clone(), + self.dest_address.public_key().clone(), "Transaction", self.resources.config.direct_send_timeout, ) @@ -703,10 +704,10 @@ where // minutes after wallet shutdown. info!( target: LOG_TARGET, - "Direct Send result was {}. Sending SAF for TxId: {} to recipient with Public Key: {}", + "Direct Send result was {}. Sending SAF for TxId: {} to recipient with Address: {}", direct_send_result, self.id, - self.dest_pubkey, + self.dest_address, ); match self.send_transaction_store_and_forward(msg.clone()).await { Ok(res) => { @@ -752,7 +753,7 @@ where target: LOG_TARGET, "Sending SAF for TxId {} failed; we will still wait for discovery of {} to complete ({:?})", self.id, - self.dest_pubkey, + self.dest_address, e ), } @@ -761,12 +762,12 @@ where Ok(SendMessageResponse::Queued(send_states)) => { debug!( target: LOG_TARGET, - "Discovery of {} completed for TxID: {}", self.dest_pubkey, self.id + "Discovery of {} completed for TxID: {}", self.dest_address, self.id ); direct_send_result = wait_on_dial( send_states, self.id, - self.dest_pubkey.clone(), + self.dest_address.public_key().clone(), "Transaction", self.resources.config.direct_send_timeout, ) @@ -820,8 +821,8 @@ where .resources .outbound_message_service .closest_broadcast( - self.dest_pubkey.clone(), - OutboundEncryption::encrypt_for(self.dest_pubkey.clone()), + self.dest_address.public_key().clone(), + OutboundEncryption::encrypt_for(self.dest_address.public_key().clone()), vec![], OutboundDomainMessage::new(&TariMessageType::SenderPartialTransaction, proto_message), ) @@ -884,7 +885,7 @@ where ); let _ = send_transaction_cancelled_message( self.id, - self.dest_pubkey.clone(), + self.dest_address.public_key().clone(), self.resources.outbound_message_service.clone(), ) .await diff --git a/base_layer/wallet/src/transaction_service/service.rs b/base_layer/wallet/src/transaction_service/service.rs index 1681a35f50..5b55a6a353 100644 --- a/base_layer/wallet/src/transaction_service/service.rs +++ b/base_layer/wallet/src/transaction_service/service.rs @@ -34,13 +34,11 @@ use log::*; use rand::rngs::OsRng; use sha2::Sha256; use tari_common_types::{ + tari_address::TariAddress, transaction::{ImportStatus, TransactionDirection, TransactionStatus, TxId}, types::{PrivateKey, PublicKey, Signature}, }; -use tari_comms::{ - peer_manager::NodeIdentity, - types::{CommsDHKE, CommsPublicKey}, -}; +use tari_comms::types::{CommsDHKE, CommsPublicKey}; use tari_comms_dht::outbound::OutboundMessageRequester; use tari_core::{ covenants::Covenant, @@ -119,7 +117,7 @@ use crate::{ utc::utc_duration_since, }, types::WalletHasher, - util::watch::Watch, + util::{wallet_identity::WalletIdentity, watch::Watch}, utxo_scanner_service::RECOVERY_KEY, OperationId, WalletOutputEncryptionKeysDomainHasher, @@ -164,12 +162,11 @@ pub struct TransactionService< reply_channel::Receiver>, >, event_publisher: TransactionEventSender, - node_identity: Arc, resources: TransactionServiceResources, pending_transaction_reply_senders: HashMap>, base_node_response_senders: HashMap)>, send_transaction_cancellation_senders: HashMap>, - finalized_transaction_senders: HashMap>, + finalized_transaction_senders: HashMap>, receiver_transaction_cancellation_senders: HashMap>, active_transaction_broadcast_protocols: HashSet, timeout_update_watch: Watch, @@ -226,7 +223,7 @@ where outbound_message_service: OutboundMessageRequester, connectivity: TWalletConnectivity, event_publisher: TransactionEventSender, - node_identity: Arc, + wallet_identity: WalletIdentity, factories: CryptoFactories, shutdown_signal: ShutdownSignal, base_node_service: BaseNodeServiceHandle, @@ -239,7 +236,7 @@ where outbound_message_service, connectivity, event_publisher: event_publisher.clone(), - node_identity: node_identity.clone(), + wallet_identity, factories, config: config.clone(), @@ -263,7 +260,6 @@ where transaction_cancelled_stream: Some(transaction_cancelled_stream), request_stream: Some(request_stream), event_publisher, - node_identity, resources, pending_transaction_reply_senders: HashMap::new(), base_node_response_senders: HashMap::new(), @@ -395,7 +391,7 @@ where } Err(e) => { warn!(target: LOG_TARGET, "Failed to handle incoming Transaction message: {} for NodeID: {}, Trace: {}", - e, self.node_identity.node_id().short_str(), msg.dht_header.message_tag); + e, self.resources.wallet_identity.node_identity.node_id().short_str(), msg.dht_header.message_tag); let _size = self.event_publisher.send(Arc::new(TransactionEvent::Error(format!("Error handling \ Transaction Sender message: {:?}", e).to_string()))); } @@ -419,12 +415,12 @@ where Err(TransactionServiceError::TransactionDoesNotExistError) => { trace!(target: LOG_TARGET, "Unable to handle incoming Transaction Reply message from NodeId: \ {} due to Transaction not existing. This usually means the message was a repeated message \ - from Store and Forward, Trace: {}", self.node_identity.node_id().short_str(), + from Store and Forward, Trace: {}", self.resources.wallet_identity.node_identity.node_id().short_str(), msg.dht_header.message_tag); }, Err(e) => { warn!(target: LOG_TARGET, "Failed to handle incoming Transaction Reply message: {} \ - for NodeId: {}, Trace: {}", e, self.node_identity.node_id().short_str(), + for NodeId: {}, Trace: {}", e, self.resources.wallet_identity.node_identity.node_id().short_str(), msg.dht_header.message_tag); let _size = self.event_publisher.send(Arc::new(TransactionEvent::Error("Error handling \ Transaction Recipient Reply message".to_string()))); @@ -456,12 +452,12 @@ where Err(TransactionServiceError::TransactionDoesNotExistError) => { trace!(target: LOG_TARGET, "Unable to handle incoming Finalized Transaction message from NodeId: \ {} due to Transaction not existing. This usually means the message was a repeated message \ - from Store and Forward, Trace: {}", self.node_identity.node_id().short_str(), + from Store and Forward, Trace: {}", self.resources.wallet_identity.node_identity.node_id().short_str(), msg.dht_header.message_tag); }, Err(e) => { warn!(target: LOG_TARGET, "Failed to handle incoming Transaction Finalized message: {} \ - for NodeID: {}, Trace: {}", e , self.node_identity.node_id().short_str(), + for NodeID: {}, Trace: {}", e , self.resources.wallet_identity.node_identity.node_id().short_str(), msg.dht_header.message_tag.as_value()); let _size = self.event_publisher.send(Arc::new(TransactionEvent::Error("Error handling Transaction \ Finalized message".to_string(),))); @@ -482,7 +478,7 @@ where trace!(target: LOG_TARGET, "Handling Base Node Response, Trace: {}", msg.dht_header.message_tag); let _result = self.handle_base_node_response(inner_msg).await.map_err(|e| { warn!(target: LOG_TARGET, "Error handling base node service response from {}: {:?} for \ - NodeID: {}, Trace: {}", origin_public_key, e, self.node_identity.node_id().short_str(), + NodeID: {}, Trace: {}", origin_public_key, e, self.resources.wallet_identity.node_identity.node_id().short_str(), msg.dht_header.message_tag.as_value()); e }); @@ -578,7 +574,7 @@ where trace!(target: LOG_TARGET, "Handling Service Request: {}", request); let response = match request { TransactionServiceRequest::SendTransaction { - dest_pubkey, + destination, amount, selection_criteria, output_features, @@ -587,7 +583,7 @@ where } => { let rp = reply_channel.take().expect("Cannot be missing"); self.send_transaction( - dest_pubkey, + destination, amount, selection_criteria, *output_features, @@ -602,7 +598,7 @@ where return Ok(()); }, TransactionServiceRequest::SendOneSidedTransaction { - dest_pubkey, + destination, amount, selection_criteria, output_features, @@ -610,7 +606,7 @@ where message, } => self .send_one_sided_transaction( - dest_pubkey, + destination, amount, selection_criteria, *output_features, @@ -621,7 +617,7 @@ where .await .map(TransactionServiceResponse::TransactionSent), TransactionServiceRequest::SendOneSidedToStealthAddressTransaction { - dest_pubkey, + destination, amount, selection_criteria, output_features, @@ -629,7 +625,7 @@ where message, } => self .send_one_sided_to_stealth_address_transaction( - dest_pubkey, + destination, amount, selection_criteria, *output_features, @@ -676,14 +672,14 @@ where return Ok(()); }, TransactionServiceRequest::SendShaAtomicSwapTransaction( - dest_pubkey, + destination, amount, selection_criteria, fee_per_gram, message, ) => Ok(TransactionServiceResponse::ShaAtomicSwapTransactionSent( self.send_sha_atomic_swap_transaction( - dest_pubkey, + destination, amount, selection_criteria, fee_per_gram, @@ -727,7 +723,7 @@ where )), TransactionServiceRequest::ImportUtxoWithStatus { amount, - source_public_key, + source_address, message, maturity, import_status, @@ -737,7 +733,7 @@ where } => self .add_utxo_import_transaction_with_status( amount, - source_public_key, + source_address, message, maturity, import_status, @@ -913,7 +909,7 @@ where /// 'fee_per_gram': The amount of fee per transaction gram to be included in transaction pub async fn send_transaction( &mut self, - dest_pubkey: CommsPublicKey, + destination: TariAddress, amount: MicroTari, selection_criteria: UtxoSelectionCriteria, output_features: OutputFeatures, @@ -929,9 +925,12 @@ where reply_channel: oneshot::Sender>, ) -> Result<(), TransactionServiceError> { let tx_id = TxId::new_random(); - + if destination.network() != self.resources.wallet_identity.network { + return Err(TransactionServiceError::InvalidNetwork); + } + let dest_pubkey = destination.public_key(); // If we're paying ourselves, let's complete and submit the transaction immediately - if self.node_identity.public_key() == &dest_pubkey { + if self.resources.wallet_identity.address.public_key() == dest_pubkey { debug!( target: LOG_TARGET, "Received transaction with spend-to-self transaction" @@ -959,8 +958,8 @@ where transaction_broadcast_join_handles, CompletedTransaction::new( tx_id, - self.node_identity.public_key().clone(), - self.node_identity.public_key().clone(), + self.resources.wallet_identity.address.clone(), + self.resources.wallet_identity.address.clone(), amount, fee, transaction, @@ -995,7 +994,7 @@ where self.resources.clone(), tx_reply_receiver, cancellation_receiver, - dest_pubkey, + destination, amount, fee_per_gram, message, @@ -1020,7 +1019,7 @@ where #[allow(clippy::too_many_lines)] pub async fn send_sha_atomic_swap_transaction( &mut self, - dest_pubkey: CommsPublicKey, + destination: TariAddress, amount: MicroTari, selection_criteria: UtxoSelectionCriteria, fee_per_gram: MicroTari, @@ -1029,6 +1028,7 @@ where JoinHandle>>, >, ) -> Result, TransactionServiceError> { + let dest_pubkey = destination.public_key(); let tx_id = TxId::new_random(); // this can be anything, so lets generate a random private key let pre_image = PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)); @@ -1042,7 +1042,7 @@ where HashSha256 PushHash(Box::new(hash)) Equal IfThen PushPubKey(Box::new(dest_pubkey.clone())) Else - CheckHeightVerify(height) PushPubKey(Box::new(self.node_identity.public_key().clone())) + CheckHeightVerify(height) PushPubKey(Box::new(self.resources.wallet_identity.node_identity.public_key().clone())) EndIf ); @@ -1088,7 +1088,7 @@ where .get_recipient_sender_offset_private_key(0) .map_err(|e| TransactionServiceProtocolError::new(tx_id, e.into()))?; - let shared_secret = CommsDHKE::new(&sender_offset_private_key, &dest_pubkey); + let shared_secret = CommsDHKE::new(&sender_offset_private_key, destination.public_key()); let spending_key = shared_secret_to_output_spending_key(&shared_secret) .map_err(|e| TransactionServiceProtocolError::new(tx_id, e.into()))?; @@ -1123,8 +1123,10 @@ where spending_key, output.features.clone(), script, - inputs!(PublicKey::from_secret_key(self.node_identity.secret_key())), - self.node_identity.secret_key().clone(), + inputs!(PublicKey::from_secret_key( + self.resources.wallet_identity.node_identity.secret_key() + )), + self.resources.wallet_identity.node_identity.secret_key().clone(), output.sender_offset_public_key.clone(), output.metadata_signature.clone(), height, @@ -1180,8 +1182,8 @@ where transaction_broadcast_join_handles, CompletedTransaction::new( tx_id, - self.resources.node_identity.public_key().clone(), - dest_pubkey.clone(), + self.resources.wallet_identity.address.clone(), + destination, amount, fee, tx.clone(), @@ -1200,7 +1202,7 @@ where async fn send_one_sided_or_stealth( &mut self, - dest_pubkey: CommsPublicKey, + dest_address: TariAddress, amount: MicroTari, selection_criteria: UtxoSelectionCriteria, output_features: OutputFeatures, @@ -1248,7 +1250,7 @@ where let sender_offset_private_key = stp .get_recipient_sender_offset_private_key(0) .map_err(|e| TransactionServiceProtocolError::new(tx_id, e.into()))?; - let shared_secret = CommsDHKE::new(&sender_offset_private_key, &dest_pubkey); + let shared_secret = CommsDHKE::new(&sender_offset_private_key, dest_address.public_key()); let spending_key = shared_secret_to_output_spending_key(&shared_secret) .map_err(|e| TransactionServiceProtocolError::new(tx_id, e.into()))?; @@ -1309,8 +1311,8 @@ where transaction_broadcast_join_handles, CompletedTransaction::new( tx_id, - self.resources.node_identity.public_key().clone(), - dest_pubkey.clone(), + self.resources.wallet_identity.address.clone(), + dest_address, amount, fee, tx.clone(), @@ -1334,7 +1336,7 @@ where /// 'fee_per_gram': The amount of fee per transaction gram to be included in transaction pub async fn send_one_sided_transaction( &mut self, - dest_pubkey: CommsPublicKey, + destination: TariAddress, amount: MicroTari, selection_criteria: UtxoSelectionCriteria, output_features: OutputFeatures, @@ -1344,14 +1346,18 @@ where JoinHandle>>, >, ) -> Result { - if self.node_identity.public_key() == &dest_pubkey { + if destination.network() != self.resources.wallet_identity.network { + return Err(TransactionServiceError::InvalidNetwork); + } + if self.resources.wallet_identity.node_identity.public_key() == destination.public_key() { warn!(target: LOG_TARGET, "One-sided spend-to-self transactions not supported"); return Err(TransactionServiceError::OneSidedTransactionError( "One-sided spend-to-self transactions not supported".to_string(), )); } + let dest_pubkey = destination.public_key().clone(); self.send_one_sided_or_stealth( - dest_pubkey.clone(), + destination, amount, selection_criteria, output_features, @@ -1457,8 +1463,8 @@ where transaction_broadcast_join_handles, CompletedTransaction::new( tx_id, - self.resources.node_identity.public_key().clone(), - CommsPublicKey::default(), + self.resources.wallet_identity.address.clone(), + TariAddress::default(), amount, fee, tx.clone(), @@ -1495,7 +1501,7 @@ where let tx_meta = TransactionMetadata::new_with_features(0.into(), 3, KernelFeatures::create_validator_node_registration()); self.send_transaction( - self.node_identity.public_key().clone(), + self.resources.wallet_identity.address.clone(), MicroTari::from(1), selection_criteria, output_features, @@ -1516,7 +1522,7 @@ where /// 'fee_per_gram': The amount of fee per transaction gram to be included in transaction pub async fn send_one_sided_to_stealth_address_transaction( &mut self, - dest_pubkey: CommsPublicKey, + destination: TariAddress, amount: MicroTari, selection_criteria: UtxoSelectionCriteria, output_features: OutputFeatures, @@ -1526,7 +1532,10 @@ where JoinHandle>>, >, ) -> Result { - if self.node_identity.public_key() == &dest_pubkey { + if destination.network() != self.resources.wallet_identity.network { + return Err(TransactionServiceError::InvalidNetwork); + } + if self.resources.wallet_identity.node_identity.public_key() == destination.public_key() { warn!(target: LOG_TARGET, "One-sided spend-to-self transactions not supported"); return Err(TransactionServiceError::OneSidedTransactionError( "One-sided-to-stealth-address spend-to-self transactions not supported".to_string(), @@ -1535,15 +1544,16 @@ where let (nonce_private_key, nonce_public_key) = PublicKey::random_keypair(&mut OsRng); + let dest_pubkey = destination.public_key().clone(); let c = WalletHasher::new_with_label("stealth_address") .chain((dest_pubkey.clone() * nonce_private_key).as_bytes()) .finalize(); let script_spending_key = - PublicKey::from_secret_key(&PrivateKey::from_bytes(c.as_ref()).unwrap()) + dest_pubkey.clone(); + PublicKey::from_secret_key(&PrivateKey::from_bytes(c.as_ref()).unwrap()) + dest_pubkey; self.send_one_sided_or_stealth( - dest_pubkey, + destination, amount, selection_criteria, output_features, @@ -1598,7 +1608,7 @@ where if let Ok(ctx) = completed_tx { // Check that it is from the same person - if ctx.destination_public_key != source_pubkey { + if ctx.destination_address.public_key() != &source_pubkey { return Err(TransactionServiceError::InvalidSourcePublicKey); } if !check_cooldown(ctx.last_send_timestamp) { @@ -1645,7 +1655,7 @@ where if let Ok(otx) = cancelled_outbound_tx { // Check that it is from the same person - if otx.destination_public_key != source_pubkey { + if otx.destination_address.public_key() != &source_pubkey { return Err(TransactionServiceError::InvalidSourcePublicKey); } if !check_cooldown(otx.last_send_timestamp) { @@ -1800,7 +1810,7 @@ where // Check that an inbound transaction exists to be cancelled and that the Source Public key for that transaction // is the same as the cancellation message if let Ok(inbound_tx) = self.db.get_pending_inbound_transaction(tx_id) { - if inbound_tx.source_public_key == source_pubkey { + if inbound_tx.source_address.public_key() == &source_pubkey { self.cancel_pending_transaction(tx_id).await?; } else { trace!( @@ -1860,7 +1870,7 @@ where self.resources.clone(), tx_reply_receiver, cancellation_receiver, - tx.destination_public_key, + tx.destination_address, tx.amount, tx.fee, tx.message, @@ -1913,7 +1923,7 @@ where if let Ok(Some(any_tx)) = self.db.get_any_cancelled_transaction(data.tx_id) { let tx = CompletedTransaction::from(any_tx); - if tx.source_public_key != source_pubkey { + if tx.source_address.public_key() != &source_pubkey { return Err(TransactionServiceError::InvalidSourcePublicKey); } trace!( @@ -1933,7 +1943,7 @@ where // Check if this transaction has already been received. if let Ok(inbound_tx) = self.db.get_pending_inbound_transaction(data.tx_id) { // Check that it is from the same person - if inbound_tx.source_public_key != source_pubkey { + if inbound_tx.source_address.public_key() != &source_pubkey { return Err(TransactionServiceError::InvalidSourcePublicKey); } // Check if the last reply is beyond the resend cooldown @@ -1990,10 +2000,11 @@ where .insert(data.tx_id, tx_finalized_sender); self.receiver_transaction_cancellation_senders .insert(data.tx_id, cancellation_sender); - + // we are making the assumption that because we received this transaction, its on the same network as us. + let source_address = TariAddress::new(source_pubkey, self.resources.wallet_identity.network); let protocol = TransactionReceiveProtocol::new( data.tx_id, - source_pubkey, + source_address, sender_message, TransactionReceiveProtocolStage::Initial, self.resources.clone(), @@ -2038,12 +2049,14 @@ where ) })?; + // assuming since we talked to the node, it has the same identity than + let source_address = TariAddress::new(source_pubkey, self.resources.wallet_identity.network); let sender = match self.finalized_transaction_senders.get_mut(&tx_id) { None => { // First check if perhaps we know about this inbound transaction but it was cancelled match self.db.get_cancelled_pending_inbound_transaction(tx_id) { Ok(t) => { - if t.source_public_key != source_pubkey { + if t.source_address != source_address { debug!( target: LOG_TARGET, "Received Finalized Transaction for a cancelled pending Inbound Transaction (TxId: \ @@ -2062,8 +2075,7 @@ where self.output_manager_service .reinstate_cancelled_inbound_transaction_outputs(tx_id) .await?; - - self.restart_receive_transaction_protocol(tx_id, source_pubkey.clone(), join_handles); + self.restart_receive_transaction_protocol(tx_id, source_address.clone(), join_handles); match self.finalized_transaction_senders.get_mut(&tx_id) { None => return Err(TransactionServiceError::TransactionDoesNotExistError), Some(s) => s, @@ -2076,7 +2088,7 @@ where }; sender - .send((source_pubkey, tx_id, transaction)) + .send((source_address, tx_id, transaction)) .await .map_err(|_| TransactionServiceError::ProtocolChannelError)?; @@ -2154,7 +2166,7 @@ where ) -> Result<(), TransactionServiceError> { let inbound_txs = self.db.get_pending_inbound_transaction_sender_info()?; for txn in inbound_txs { - self.restart_receive_transaction_protocol(txn.tx_id, txn.source_public_key, join_handles); + self.restart_receive_transaction_protocol(txn.tx_id, txn.source_address, join_handles); } Ok(()) @@ -2163,7 +2175,7 @@ where fn restart_receive_transaction_protocol( &mut self, tx_id: TxId, - source_public_key: CommsPublicKey, + source_address: TariAddress, join_handles: &mut FuturesUnordered>>>, ) { if !self.pending_transaction_reply_senders.contains_key(&tx_id) { @@ -2178,7 +2190,7 @@ where .insert(tx_id, cancellation_sender); let protocol = TransactionReceiveProtocol::new( tx_id, - source_public_key, + source_address, TransactionSenderMessage::None, TransactionReceiveProtocolStage::WaitForFinalize, self.resources.clone(), @@ -2489,7 +2501,7 @@ where pub fn add_utxo_import_transaction_with_status( &mut self, value: MicroTari, - source_public_key: CommsPublicKey, + source_address: TariAddress, message: String, maturity: Option, import_status: ImportStatus, @@ -2501,8 +2513,8 @@ where self.db.add_utxo_import_transaction_with_status( tx_id, value, - source_public_key, - self.node_identity.public_key().clone(), + source_address, + self.resources.wallet_identity.address.clone(), message, maturity, import_status.clone(), @@ -2574,8 +2586,8 @@ where transaction_broadcast_join_handles, CompletedTransaction::new( tx_id, - self.node_identity.public_key().clone(), - self.node_identity.public_key().clone(), + self.resources.wallet_identity.address.clone(), + self.resources.wallet_identity.address.clone(), amount, fee, tx, @@ -2627,8 +2639,8 @@ where tx_id, CompletedTransaction::new( tx_id, - self.node_identity.public_key().clone(), - self.node_identity.public_key().clone(), + self.resources.wallet_identity.address.clone(), + self.resources.wallet_identity.address.clone(), amount, MicroTari::from(0), tx.clone(), @@ -2689,7 +2701,7 @@ pub struct TransactionServiceResources { pub outbound_message_service: OutboundMessageRequester, pub connectivity: TWalletConnectivity, pub event_publisher: TransactionEventSender, - pub node_identity: Arc, + pub wallet_identity: WalletIdentity, pub factories: CryptoFactories, pub config: TransactionServiceConfig, pub shutdown_signal: ShutdownSignal, diff --git a/base_layer/wallet/src/transaction_service/storage/database.rs b/base_layer/wallet/src/transaction_service/storage/database.rs index 8a7eec4100..6416f60daf 100644 --- a/base_layer/wallet/src/transaction_service/storage/database.rs +++ b/base_layer/wallet/src/transaction_service/storage/database.rs @@ -32,10 +32,10 @@ use chacha20poly1305::XChaCha20Poly1305; use chrono::{NaiveDateTime, Utc}; use log::*; use tari_common_types::{ + tari_address::TariAddress, transaction::{ImportStatus, TransactionDirection, TransactionStatus, TxId}, types::{BlindingFactor, BlockHash}, }; -use tari_comms::types::CommsPublicKey; use tari_core::transactions::{tari_amount::MicroTari, transaction_components::Transaction}; use crate::transaction_service::{ @@ -110,10 +110,10 @@ pub trait TransactionBackend: Send + Sync + Clone { cancelled: bool, ) -> Result<(), TransactionStorageError>; /// Search all pending transaction for the provided tx_id and if it exists return the public key of the counterparty - fn get_pending_transaction_counterparty_pub_key_by_tx_id( + fn get_pending_transaction_counterparty_address_by_tx_id( &self, tx_id: TxId, - ) -> Result; + ) -> Result; /// Mark a pending transaction direct send attempt as a success fn mark_direct_send_success(&self, tx_id: TxId) -> Result<(), TransactionStorageError>; /// Cancel coinbase transactions at a specific block height @@ -544,12 +544,12 @@ where T: TransactionBackend + 'static Ok(t) } - pub fn get_pending_transaction_counterparty_pub_key_by_tx_id( + pub fn get_pending_transaction_counterparty_address_by_tx_id( &mut self, tx_id: TxId, - ) -> Result { - let pub_key = self.db.get_pending_transaction_counterparty_pub_key_by_tx_id(tx_id)?; - Ok(pub_key) + ) -> Result { + let address = self.db.get_pending_transaction_counterparty_address_by_tx_id(tx_id)?; + Ok(address) } pub fn get_completed_transactions(&self) -> Result, TransactionStorageError> { @@ -651,8 +651,8 @@ where T: TransactionBackend + 'static &self, tx_id: TxId, amount: MicroTari, - source_public_key: CommsPublicKey, - comms_public_key: CommsPublicKey, + source_address: TariAddress, + comms_address: TariAddress, message: String, maturity: Option, import_status: ImportStatus, @@ -661,8 +661,8 @@ where T: TransactionBackend + 'static ) -> Result<(), TransactionStorageError> { let transaction = CompletedTransaction::new( tx_id, - source_public_key, - comms_public_key, + source_address, + comms_address, amount, MicroTari::from(0), Transaction::new( diff --git a/base_layer/wallet/src/transaction_service/storage/models.rs b/base_layer/wallet/src/transaction_service/storage/models.rs index fa85f834e4..15631de2a2 100644 --- a/base_layer/wallet/src/transaction_service/storage/models.rs +++ b/base_layer/wallet/src/transaction_service/storage/models.rs @@ -28,10 +28,10 @@ use std::{ use chrono::NaiveDateTime; use serde::{Deserialize, Serialize}; use tari_common_types::{ + tari_address::TariAddress, transaction::{TransactionConversionError, TransactionDirection, TransactionStatus, TxId}, types::{BlockHash, PrivateKey, Signature}, }; -use tari_comms::types::CommsPublicKey; use tari_core::transactions::{ tari_amount::MicroTari, transaction_components::Transaction, @@ -42,7 +42,7 @@ use tari_core::transactions::{ #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct InboundTransaction { pub tx_id: TxId, - pub source_public_key: CommsPublicKey, + pub source_address: TariAddress, pub amount: MicroTari, pub receiver_protocol: ReceiverTransactionProtocol, pub status: TransactionStatus, @@ -57,7 +57,7 @@ pub struct InboundTransaction { impl InboundTransaction { pub fn new( tx_id: TxId, - source_public_key: CommsPublicKey, + source_address: TariAddress, amount: MicroTari, receiver_protocol: ReceiverTransactionProtocol, status: TransactionStatus, @@ -66,7 +66,7 @@ impl InboundTransaction { ) -> Self { Self { tx_id, - source_public_key, + source_address, amount, receiver_protocol, status, @@ -83,7 +83,7 @@ impl InboundTransaction { #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct OutboundTransaction { pub tx_id: TxId, - pub destination_public_key: CommsPublicKey, + pub destination_address: TariAddress, pub amount: MicroTari, pub fee: MicroTari, pub sender_protocol: SenderTransactionProtocol, @@ -99,7 +99,7 @@ pub struct OutboundTransaction { impl OutboundTransaction { pub fn new( tx_id: TxId, - destination_public_key: CommsPublicKey, + destination_address: TariAddress, amount: MicroTari, fee: MicroTari, sender_protocol: SenderTransactionProtocol, @@ -110,7 +110,7 @@ impl OutboundTransaction { ) -> Self { Self { tx_id, - destination_public_key, + destination_address, amount, fee, sender_protocol, @@ -128,8 +128,8 @@ impl OutboundTransaction { #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] pub struct CompletedTransaction { pub tx_id: TxId, - pub source_public_key: CommsPublicKey, - pub destination_public_key: CommsPublicKey, + pub source_address: TariAddress, + pub destination_address: TariAddress, pub amount: MicroTari, pub fee: MicroTari, pub transaction: Transaction, @@ -151,8 +151,8 @@ pub struct CompletedTransaction { impl CompletedTransaction { pub fn new( tx_id: TxId, - source_public_key: CommsPublicKey, - destination_public_key: CommsPublicKey, + source_address: TariAddress, + destination_address: TariAddress, amount: MicroTari, fee: MicroTari, transaction: Transaction, @@ -171,8 +171,8 @@ impl CompletedTransaction { }; Self { tx_id, - source_public_key, - destination_public_key, + source_address, + destination_address, amount, fee, transaction, @@ -205,7 +205,7 @@ impl From for InboundTransaction { fn from(ct: CompletedTransaction) -> Self { Self { tx_id: ct.tx_id, - source_public_key: ct.source_public_key, + source_address: ct.source_address, amount: ct.amount, receiver_protocol: ReceiverTransactionProtocol::new_placeholder(), status: ct.status, @@ -223,7 +223,7 @@ impl From for OutboundTransaction { fn from(ct: CompletedTransaction) -> Self { Self { tx_id: ct.tx_id, - destination_public_key: ct.destination_public_key, + destination_address: ct.destination_address, amount: ct.amount, fee: ct.fee, sender_protocol: SenderTransactionProtocol::new_placeholder(), @@ -255,8 +255,8 @@ impl From for CompletedTransaction { }; Self { tx_id: tx.tx_id, - source_public_key: Default::default(), - destination_public_key: tx.destination_public_key, + source_address: Default::default(), + destination_address: tx.destination_address, amount: tx.amount, fee: tx.fee, status: tx.status, @@ -285,8 +285,8 @@ impl From for CompletedTransaction { fn from(tx: InboundTransaction) -> Self { Self { tx_id: tx.tx_id, - source_public_key: tx.source_public_key, - destination_public_key: Default::default(), + source_address: tx.source_address, + destination_address: Default::default(), amount: tx.amount, fee: MicroTari::from(0), status: tx.status, diff --git a/base_layer/wallet/src/transaction_service/storage/sqlite_db.rs b/base_layer/wallet/src/transaction_service/storage/sqlite_db.rs index 7d244ca817..c85fe879e6 100644 --- a/base_layer/wallet/src/transaction_service/storage/sqlite_db.rs +++ b/base_layer/wallet/src/transaction_service/storage/sqlite_db.rs @@ -32,6 +32,7 @@ use chrono::{NaiveDateTime, Utc}; use diesel::{prelude::*, result::Error as DieselError, SqliteConnection}; use log::*; use tari_common_types::{ + tari_address::TariAddress, transaction::{ TransactionConversionError, TransactionDirection, @@ -41,7 +42,6 @@ use tari_common_types::{ }, types::{BlockHash, PrivateKey, PublicKey, Signature}, }; -use tari_comms::types::CommsPublicKey; use tari_core::transactions::tari_amount::MicroTari; use tari_utilities::{ hex::{from_hex, Hex}, @@ -492,10 +492,10 @@ impl TransactionBackend for TransactionServiceSqliteDatabase { Ok(result) } - fn get_pending_transaction_counterparty_pub_key_by_tx_id( + fn get_pending_transaction_counterparty_address_by_tx_id( &self, tx_id: TxId, - ) -> Result { + ) -> Result { let start = Instant::now(); let conn = self.database_connection.get_pooled_connection()?; let acquire_lock = start.elapsed(); @@ -513,7 +513,7 @@ impl TransactionBackend for TransactionServiceSqliteDatabase { start.elapsed().as_millis() ); } - return Ok(outbound_tx.destination_public_key); + return Ok(outbound_tx.destination_address); } if let Ok(mut inbound_tx_sql) = InboundTransactionSql::find_by_cancelled(tx_id, false, &conn) { self.decrypt_if_necessary(&mut inbound_tx_sql)?; @@ -528,7 +528,7 @@ impl TransactionBackend for TransactionServiceSqliteDatabase { start.elapsed().as_millis() ); } - return Ok(inbound_tx.source_public_key); + return Ok(inbound_tx.source_address); } Err(TransactionStorageError::ValuesNotFound) @@ -1310,7 +1310,7 @@ impl TransactionBackend for TransactionServiceSqliteDatabase { #[derive(Debug, PartialEq)] pub struct InboundTransactionSenderInfo { pub(crate) tx_id: TxId, - pub(crate) source_public_key: CommsPublicKey, + pub(crate) source_address: TariAddress, } impl TryFrom for InboundTransactionSenderInfo { @@ -1319,8 +1319,8 @@ impl TryFrom for InboundTransactionSenderInfo { fn try_from(i: InboundTransactionSenderInfoSql) -> Result { Ok(Self { tx_id: TxId::from(i.tx_id as u64), - source_public_key: CommsPublicKey::from_bytes(&*i.source_public_key) - .map_err(TransactionStorageError::ByteArrayError)?, + source_address: TariAddress::from_bytes(&*i.source_address) + .map_err(TransactionStorageError::TariAddressError)?, }) } } @@ -1328,7 +1328,7 @@ impl TryFrom for InboundTransactionSenderInfo { #[derive(Clone, Queryable)] pub struct InboundTransactionSenderInfoSql { pub tx_id: i64, - pub source_public_key: Vec, + pub source_address: Vec, } impl InboundTransactionSenderInfoSql { @@ -1336,7 +1336,7 @@ impl InboundTransactionSenderInfoSql { conn: &SqliteConnection, ) -> Result, TransactionStorageError> { let query_result = inbound_transactions::table - .select((inbound_transactions::tx_id, inbound_transactions::source_public_key)) + .select((inbound_transactions::tx_id, inbound_transactions::source_address)) .filter(inbound_transactions::cancelled.eq(i32::from(false))) .load::(conn)?; Ok(query_result) @@ -1347,7 +1347,7 @@ impl InboundTransactionSenderInfoSql { #[table_name = "inbound_transactions"] struct InboundTransactionSql { tx_id: i64, - source_public_key: Vec, + source_address: Vec, amount: i64, receiver_protocol: String, message: String, @@ -1565,7 +1565,7 @@ impl TryFrom for InboundTransactionSql { fn try_from(i: InboundTransaction) -> Result { Ok(Self { tx_id: i.tx_id.as_u64() as i64, - source_public_key: i.source_public_key.to_vec(), + source_address: i.source_address.to_bytes().to_vec(), amount: u64::from(i.amount) as i64, receiver_protocol: serde_json::to_string(&i.receiver_protocol)?, message: i.message, @@ -1584,7 +1584,7 @@ impl TryFrom for InboundTransaction { fn try_from(i: InboundTransactionSql) -> Result { Ok(Self { tx_id: (i.tx_id as u64).into(), - source_public_key: PublicKey::from_vec(&i.source_public_key).map_err(TransactionKeyError::Source)?, + source_address: TariAddress::from_bytes(&i.source_address).map_err(TransactionKeyError::Source)?, amount: MicroTari::from(i.amount as u64), receiver_protocol: serde_json::from_str(&i.receiver_protocol.clone())?, status: TransactionStatus::Pending, @@ -1613,7 +1613,7 @@ pub struct UpdateInboundTransactionSql { #[table_name = "outbound_transactions"] struct OutboundTransactionSql { tx_id: i64, - destination_public_key: Vec, + destination_address: Vec, amount: i64, fee: i64, sender_protocol: String, @@ -1816,7 +1816,7 @@ impl TryFrom for OutboundTransactionSql { fn try_from(o: OutboundTransaction) -> Result { Ok(Self { tx_id: o.tx_id.as_u64() as i64, - destination_public_key: o.destination_public_key.to_vec(), + destination_address: o.destination_address.to_bytes().to_vec(), amount: u64::from(o.amount) as i64, fee: u64::from(o.fee) as i64, sender_protocol: serde_json::to_string(&o.sender_protocol)?, @@ -1836,7 +1836,7 @@ impl TryFrom for OutboundTransaction { fn try_from(o: OutboundTransactionSql) -> Result { Ok(Self { tx_id: (o.tx_id as u64).into(), - destination_public_key: PublicKey::from_vec(&o.destination_public_key) + destination_address: TariAddress::from_bytes(&o.destination_address) .map_err(TransactionKeyError::Destination)?, amount: MicroTari::from(o.amount as u64), fee: MicroTari::from(o.fee as u64), @@ -1867,8 +1867,8 @@ pub struct UpdateOutboundTransactionSql { #[table_name = "completed_transactions"] struct CompletedTransactionSql { tx_id: i64, - source_public_key: Vec, - destination_public_key: Vec, + source_address: Vec, + destination_address: Vec, amount: i64, fee: i64, transaction_protocol: String, @@ -2216,8 +2216,8 @@ impl TryFrom for CompletedTransactionSql { fn try_from(c: CompletedTransaction) -> Result { Ok(Self { tx_id: c.tx_id.as_u64() as i64, - source_public_key: c.source_public_key.to_vec(), - destination_public_key: c.destination_public_key.to_vec(), + source_address: c.source_address.to_bytes().to_vec(), + destination_address: c.destination_address.to_bytes().to_vec(), amount: u64::from(c.amount) as i64, fee: u64::from(c.fee) as i64, transaction_protocol: serde_json::to_string(&c.transaction)?, @@ -2271,8 +2271,8 @@ impl TryFrom for CompletedTransaction { }; Ok(Self { tx_id: (c.tx_id as u64).into(), - source_public_key: PublicKey::from_vec(&c.source_public_key).map_err(TransactionKeyError::Source)?, - destination_public_key: PublicKey::from_vec(&c.destination_public_key) + source_address: TariAddress::from_bytes(&c.source_address).map_err(TransactionKeyError::Source)?, + destination_address: TariAddress::from_bytes(&c.destination_address) .map_err(TransactionKeyError::Destination)?, amount: MicroTari::from(c.amount as u64), fee: MicroTari::from(c.fee as u64), @@ -2397,8 +2397,10 @@ mod test { use chrono::Utc; use diesel::{Connection, SqliteConnection}; use rand::{rngs::OsRng, RngCore}; + use tari_common::configuration::Network; use tari_common_sqlite::sqlite_connection_pool::SqliteConnectionPool; use tari_common_types::{ + tari_address::TariAddress, transaction::{TransactionDirection, TransactionStatus, TxId}, types::{PrivateKey, PublicKey, Signature}, }; @@ -2490,9 +2492,13 @@ mod test { let mut stp = builder.build(&factories, None, u64::MAX).unwrap(); + let address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let outbound_tx1 = OutboundTransaction { tx_id: 1u64.into(), - destination_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + destination_address: address, amount, fee: stp.get_fee_amount().unwrap(), sender_protocol: stp.clone(), @@ -2504,10 +2510,13 @@ mod test { send_count: 0, last_send_timestamp: None, }; - + let address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let outbound_tx2 = OutboundTransactionSql::try_from(OutboundTransaction { tx_id: 2u64.into(), - destination_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + destination_address: address, amount, fee: stp.get_fee_amount().unwrap(), sender_protocol: stp.clone(), @@ -2545,10 +2554,13 @@ mod test { PrivateKey::random(&mut OsRng), &factories, ); - + let address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let inbound_tx1 = InboundTransaction { tx_id: 2u64.into(), - source_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + source_address: address, amount, receiver_protocol: rtp.clone(), status: TransactionStatus::Pending, @@ -2559,9 +2571,13 @@ mod test { send_count: 0, last_send_timestamp: None, }; + let address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let inbound_tx2 = InboundTransaction { tx_id: 3u64.into(), - source_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + source_address: address, amount, receiver_protocol: rtp, status: TransactionStatus::Pending, @@ -2600,11 +2616,18 @@ mod test { PrivateKey::random(&mut OsRng), PrivateKey::random(&mut OsRng), ); - + let source_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); + let destination_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let completed_tx1 = CompletedTransaction { tx_id: 2u64.into(), - source_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), - destination_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + source_address, + destination_address, amount, fee: MicroTari::from(100), transaction: tx.clone(), @@ -2622,10 +2645,18 @@ mod test { mined_in_block: None, mined_timestamp: None, }; + let source_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); + let destination_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let completed_tx2 = CompletedTransaction { tx_id: 3u64.into(), - source_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), - destination_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + source_address, + destination_address, amount, fee: MicroTari::from(100), transaction: tx.clone(), @@ -2748,10 +2779,18 @@ mod test { assert!(CompletedTransactionSql::find_by_cancelled(completed_tx1.tx_id, false, &conn).is_err()); assert!(CompletedTransactionSql::find_by_cancelled(completed_tx1.tx_id, true, &conn).is_ok()); + let source_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); + let destination_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let coinbase_tx1 = CompletedTransaction { tx_id: 101u64.into(), - source_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), - destination_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + source_address, + destination_address, amount, fee: MicroTari::from(100), transaction: tx.clone(), @@ -2770,10 +2809,18 @@ mod test { mined_timestamp: None, }; + let source_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); + let destination_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let coinbase_tx2 = CompletedTransaction { tx_id: 102u64.into(), - source_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), - destination_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + source_address, + destination_address, amount, fee: MicroTari::from(100), transaction: tx.clone(), @@ -2792,10 +2839,18 @@ mod test { mined_timestamp: None, }; + let source_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); + let destination_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let coinbase_tx3 = CompletedTransaction { tx_id: 103u64.into(), - source_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), - destination_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + source_address, + destination_address, amount, fee: MicroTari::from(100), transaction: tx.clone(), @@ -2836,6 +2891,7 @@ mod test { } #[test] + #[allow(clippy::too_many_lines)] fn test_encryption_crud() { let db_name = format!("{}.sqlite3", string(8).as_str()); let temp_dir = tempdir().unwrap(); @@ -2854,9 +2910,13 @@ mod test { let key_ga = Key::from_slice(&key); let cipher = XChaCha20Poly1305::new(key_ga); + let source_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let inbound_tx = InboundTransaction { tx_id: 1u64.into(), - source_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + source_address, amount: MicroTari::from(100), receiver_protocol: ReceiverTransactionProtocol::new_placeholder(), status: TransactionStatus::Pending, @@ -2876,9 +2936,13 @@ mod test { let decrypted_inbound_tx = InboundTransaction::try_from(db_inbound_tx).unwrap(); assert_eq!(inbound_tx, decrypted_inbound_tx); + let destination_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let outbound_tx = OutboundTransaction { tx_id: 2u64.into(), - destination_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + destination_address, amount: MicroTari::from(100), fee: MicroTari::from(10), sender_protocol: SenderTransactionProtocol::new_placeholder(), @@ -2900,10 +2964,18 @@ mod test { let decrypted_outbound_tx = OutboundTransaction::try_from(db_outbound_tx).unwrap(); assert_eq!(outbound_tx, decrypted_outbound_tx); + let source_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); + let destination_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let completed_tx = CompletedTransaction { tx_id: 3u64.into(), - source_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), - destination_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + source_address, + destination_address, amount: MicroTari::from(100), fee: MicroTari::from(100), transaction: Transaction::new( @@ -2939,6 +3011,7 @@ mod test { } #[test] + #[allow(clippy::too_many_lines)] fn test_apply_remove_encryption() { let db_name = format!("{}.sqlite3", string(8).as_str()); let temp_dir = tempdir().unwrap(); @@ -2958,9 +3031,13 @@ mod test { embedded_migrations::run_with_output(&conn, &mut std::io::stdout()).expect("Migration failed"); + let source_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let inbound_tx = InboundTransaction { tx_id: 1u64.into(), - source_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + source_address, amount: MicroTari::from(100), receiver_protocol: ReceiverTransactionProtocol::new_placeholder(), status: TransactionStatus::Pending, @@ -2974,9 +3051,13 @@ mod test { let inbound_tx_sql = InboundTransactionSql::try_from(inbound_tx).unwrap(); inbound_tx_sql.commit(&conn).unwrap(); + let destination_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let outbound_tx = OutboundTransaction { tx_id: 2u64.into(), - destination_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + destination_address, amount: MicroTari::from(100), fee: MicroTari::from(10), sender_protocol: SenderTransactionProtocol::new_placeholder(), @@ -2991,10 +3072,18 @@ mod test { let outbound_tx_sql = OutboundTransactionSql::try_from(outbound_tx).unwrap(); outbound_tx_sql.commit(&conn).unwrap(); + let source_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); + let destination_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let completed_tx = CompletedTransaction { tx_id: 3u64.into(), - source_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), - destination_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + source_address, + destination_address, amount: MicroTari::from(100), fee: MicroTari::from(100), transaction: Transaction::new( @@ -3119,10 +3208,18 @@ mod test { 10 => (None, TransactionStatus::MinedConfirmed, None), _ => (None, TransactionStatus::Completed, Some(i)), }; + let source_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); + let destination_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let completed_tx = CompletedTransaction { tx_id: TxId::from(i), - source_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), - destination_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + source_address, + destination_address, amount: MicroTari::from(100), fee: MicroTari::from(100), transaction: Transaction::new( @@ -3156,7 +3253,7 @@ mod test { if cancelled.is_none() { info_list_reference.push(InboundTransactionSenderInfo { tx_id: inbound_tx.tx_id, - source_public_key: inbound_tx.source_public_key, + source_address: inbound_tx.source_address, }) } } diff --git a/base_layer/wallet/src/transaction_service/tasks/send_transaction_reply.rs b/base_layer/wallet/src/transaction_service/tasks/send_transaction_reply.rs index 9c81ba5255..259b9e366f 100644 --- a/base_layer/wallet/src/transaction_service/tasks/send_transaction_reply.rs +++ b/base_layer/wallet/src/transaction_service/tasks/send_transaction_reply.rs @@ -65,7 +65,7 @@ pub async fn send_transaction_reply( TransactionRoutingMechanism::StoreAndForwardOnly => { send_transaction_reply_store_and_forward( inbound_transaction.tx_id, - inbound_transaction.source_public_key, + inbound_transaction.source_address.public_key().clone(), proto_message.clone(), &mut outbound_message_service, ) @@ -93,7 +93,7 @@ pub async fn send_transaction_reply_direct( let proto_message: proto::RecipientSignedMessage = recipient_reply.into(); match outbound_message_service .send_direct( - inbound_transaction.source_public_key.clone(), + inbound_transaction.source_address.public_key().clone(), OutboundDomainMessage::new(&TariMessageType::ReceiverPartialTransactionReply, proto_message.clone()), "wallet transaction reply".to_string(), ) @@ -104,7 +104,7 @@ pub async fn send_transaction_reply_direct( if wait_on_dial( send_states, tx_id, - inbound_transaction.source_public_key.clone(), + inbound_transaction.source_address.public_key().clone(), "Transaction Reply", direct_send_timeout, ) @@ -115,15 +115,15 @@ pub async fn send_transaction_reply_direct( // Send a Store and Forward (SAF) regardless. info!( target: LOG_TARGET, - "Direct Send reply result was {}. Sending SAF for TxId: {} to recipient with Public Key: {}", + "Direct Send reply result was {}. Sending SAF for TxId: {} to recipient with address: {}", direct_send_result, tx_id, - inbound_transaction.source_public_key, + inbound_transaction.source_address, ); if transaction_routing_mechanism == TransactionRoutingMechanism::DirectAndStoreAndForward { store_and_forward_send_result = send_transaction_reply_store_and_forward( tx_id, - inbound_transaction.source_public_key, + inbound_transaction.source_address.public_key().clone(), proto_message.clone(), &mut outbound_message_service, ) @@ -138,7 +138,7 @@ pub async fn send_transaction_reply_direct( if transaction_routing_mechanism == TransactionRoutingMechanism::DirectAndStoreAndForward { store_and_forward_send_result = send_transaction_reply_store_and_forward( tx_id, - inbound_transaction.source_public_key.clone(), + inbound_transaction.source_address.public_key().clone(), proto_message.clone(), &mut outbound_message_service, ) @@ -149,7 +149,7 @@ pub async fn send_transaction_reply_direct( if transaction_routing_mechanism == TransactionRoutingMechanism::DirectAndStoreAndForward { store_and_forward_send_result = send_transaction_reply_store_and_forward( tx_id, - inbound_transaction.source_public_key.clone(), + inbound_transaction.source_address.public_key().clone(), proto_message.clone(), &mut outbound_message_service, ) @@ -160,12 +160,12 @@ pub async fn send_transaction_reply_direct( Ok(SendMessageResponse::Queued(send_states)) => { debug!( target: LOG_TARGET, - "Discovery of {} completed for TxID: {}", inbound_transaction.source_public_key, tx_id + "Discovery of {} completed for TxID: {}", inbound_transaction.source_address, tx_id ); direct_send_result = wait_on_dial( send_states, tx_id, - inbound_transaction.source_public_key.clone(), + inbound_transaction.source_address.public_key().clone(), "Transaction Reply", direct_send_timeout, ) diff --git a/base_layer/wallet/src/util/mod.rs b/base_layer/wallet/src/util/mod.rs index adc24249d0..b4f0ab0d64 100644 --- a/base_layer/wallet/src/util/mod.rs +++ b/base_layer/wallet/src/util/mod.rs @@ -22,4 +22,5 @@ pub mod diesel_ext; pub mod encryption; +pub mod wallet_identity; pub mod watch; diff --git a/base_layer/wallet/src/util/wallet_identity.rs b/base_layer/wallet/src/util/wallet_identity.rs new file mode 100644 index 0000000000..3f6b030ca4 --- /dev/null +++ b/base_layer/wallet/src/util/wallet_identity.rs @@ -0,0 +1,54 @@ +// Copyright 2022, The Tari Project +// +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +// following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +// disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +// following disclaimer in the documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +// products derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +use std::{fmt, fmt::Display, sync::Arc}; + +use tari_common::configuration::Network; +use tari_common_types::tari_address::TariAddress; +use tari_comms::peer_manager::NodeIdentity; + +#[derive(Clone, Debug)] +pub struct WalletIdentity { + pub node_identity: Arc, + pub network: Network, + pub address: TariAddress, +} + +impl WalletIdentity { + pub fn new(node_identity: Arc, network: Network) -> Self { + let address = TariAddress::new(node_identity.public_key().clone(), network); + WalletIdentity { + node_identity, + network, + address, + } + } +} + +impl Display for WalletIdentity { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + writeln!(f, "{}", self.node_identity)?; + writeln!(f, "Network: {:?}", self.network)?; + + Ok(()) + } +} diff --git a/base_layer/wallet/src/utxo_scanner_service/initializer.rs b/base_layer/wallet/src/utxo_scanner_service/initializer.rs index d53cfaa5a3..14df2190aa 100644 --- a/base_layer/wallet/src/utxo_scanner_service/initializer.rs +++ b/base_layer/wallet/src/utxo_scanner_service/initializer.rs @@ -20,11 +20,9 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use std::sync::Arc; - use futures::future; use log::*; -use tari_comms::{connectivity::ConnectivityRequester, NodeIdentity}; +use tari_comms::connectivity::ConnectivityRequester; use tari_core::transactions::CryptoFactories; use tari_service_framework::{async_trait, ServiceInitializationError, ServiceInitializer, ServiceInitializerContext}; use tokio::sync::broadcast; @@ -35,7 +33,7 @@ use crate::{ output_manager_service::handle::OutputManagerHandle, storage::database::{WalletBackend, WalletDatabase}, transaction_service::handle::TransactionServiceHandle, - util::watch::Watch, + util::{wallet_identity::WalletIdentity, watch::Watch}, utxo_scanner_service::{ handle::UtxoScannerHandle, service::UtxoScannerService, @@ -48,17 +46,17 @@ const LOG_TARGET: &str = "wallet::utxo_scanner_service::initializer"; pub struct UtxoScannerServiceInitializer { backend: Option>, factories: CryptoFactories, - node_identity: Arc, + wallet_identity: WalletIdentity, } impl UtxoScannerServiceInitializer where T: WalletBackend + 'static { - pub fn new(backend: WalletDatabase, factories: CryptoFactories, node_identity: Arc) -> Self { + pub fn new(backend: WalletDatabase, factories: CryptoFactories, wallet_identity: WalletIdentity) -> Self { Self { backend: Some(backend), factories, - node_identity, + wallet_identity, } } } @@ -88,7 +86,7 @@ where T: WalletBackend + 'static .take() .expect("Cannot start Utxo scanner service without setting a storage backend"); let factories = self.factories.clone(); - let node_identity = self.node_identity.clone(); + let wallet_identity = self.wallet_identity.clone(); context.spawn_when_ready(move |handles| async move { let transaction_service = handles.expect_handle::(); @@ -107,7 +105,7 @@ where T: WalletBackend + 'static wallet_connectivity.clone(), output_manager_service, transaction_service, - node_identity, + wallet_identity, factories, handles.get_shutdown_signal(), event_sender, diff --git a/base_layer/wallet/src/utxo_scanner_service/service.rs b/base_layer/wallet/src/utxo_scanner_service/service.rs index 29a5f6dbe9..a119855e74 100644 --- a/base_layer/wallet/src/utxo_scanner_service/service.rs +++ b/base_layer/wallet/src/utxo_scanner_service/service.rs @@ -20,13 +20,11 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use std::sync::Arc; - use chrono::NaiveDateTime; use futures::FutureExt; use log::*; use tari_common_types::types::HashOutput; -use tari_comms::{connectivity::ConnectivityRequester, peer_manager::Peer, types::CommsPublicKey, NodeIdentity}; +use tari_comms::{connectivity::ConnectivityRequester, peer_manager::Peer, types::CommsPublicKey}; use tari_core::transactions::{tari_amount::MicroTari, CryptoFactories}; use tari_shutdown::{Shutdown, ShutdownSignal}; use tokio::{ @@ -41,6 +39,7 @@ use crate::{ output_manager_service::handle::OutputManagerHandle, storage::database::{WalletBackend, WalletDatabase}, transaction_service::handle::TransactionServiceHandle, + util::wallet_identity::WalletIdentity, utxo_scanner_service::{ handle::UtxoScannerEvent, utxo_scanner_task::UtxoScannerTask, @@ -198,7 +197,7 @@ pub struct UtxoScannerResources { pub current_base_node_watcher: watch::Receiver>, pub output_manager_service: OutputManagerHandle, pub transaction_service: TransactionServiceHandle, - pub node_identity: Arc, + pub wallet_identity: WalletIdentity, pub factories: CryptoFactories, pub recovery_message: String, pub one_sided_payment_message: String, diff --git a/base_layer/wallet/src/utxo_scanner_service/utxo_scanner_task.rs b/base_layer/wallet/src/utxo_scanner_service/utxo_scanner_task.rs index 3366b311d2..2aed07f271 100644 --- a/base_layer/wallet/src/utxo_scanner_service/utxo_scanner_task.rs +++ b/base_layer/wallet/src/utxo_scanner_service/utxo_scanner_task.rs @@ -29,6 +29,7 @@ use chrono::{NaiveDateTime, Utc}; use futures::StreamExt; use log::*; use tari_common_types::{ + tari_address::TariAddress, transaction::{ImportStatus, TxId}, types::HashOutput, }; @@ -579,22 +580,19 @@ where ) -> Result<(u64, MicroTari), UtxoScannerError> { let mut num_recovered = 0u64; let mut total_amount = MicroTari::from(0); - let default_key = CommsPublicKey::default(); - let self_key = self.resources.node_identity.public_key().clone(); - for (uo, message, import_status, tx_id) in utxos { - let source_public_key = if uo.features.is_coinbase() { + let source_address = if uo.features.is_coinbase() { // its a coinbase, so we know we mined it and it comes from us. - &self_key + self.resources.wallet_identity.address.clone() } else { // Because we do not know the source public key we are making it the default key of zeroes to make it // clear this value is a placeholder. - &default_key + TariAddress::default() }; match self .import_unblinded_utxo_to_transaction_service( uo.clone(), - source_public_key, + source_address, message, import_status, tx_id, @@ -652,7 +650,7 @@ where pub async fn import_unblinded_utxo_to_transaction_service( &mut self, unblinded_output: UnblindedOutput, - source_public_key: &CommsPublicKey, + source_address: TariAddress, message: String, import_status: ImportStatus, tx_id: TxId, @@ -664,7 +662,7 @@ where .transaction_service .import_utxo_with_status( unblinded_output.value, - source_public_key.clone(), + source_address, message, Some(unblinded_output.features.maturity), import_status.clone(), diff --git a/base_layer/wallet/src/utxo_scanner_service/uxto_scanner_service_builder.rs b/base_layer/wallet/src/utxo_scanner_service/uxto_scanner_service_builder.rs index ac80c30ae3..4a6ccd8970 100644 --- a/base_layer/wallet/src/utxo_scanner_service/uxto_scanner_service_builder.rs +++ b/base_layer/wallet/src/utxo_scanner_service/uxto_scanner_service_builder.rs @@ -20,9 +20,7 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -use std::sync::Arc; - -use tari_comms::{connectivity::ConnectivityRequester, types::CommsPublicKey, NodeIdentity}; +use tari_comms::{connectivity::ConnectivityRequester, types::CommsPublicKey}; use tari_core::transactions::CryptoFactories; use tari_shutdown::ShutdownSignal; use tokio::sync::{broadcast, watch}; @@ -36,6 +34,7 @@ use crate::{ sqlite_db::wallet::WalletSqliteDatabase, }, transaction_service::handle::TransactionServiceHandle, + util::wallet_identity::WalletIdentity, utxo_scanner_service::{ handle::UtxoScannerEvent, service::{UtxoScannerResources, UtxoScannerService}, @@ -109,6 +108,7 @@ impl UtxoScannerServiceBuilder { wallet: &WalletSqlite, shutdown_signal: ShutdownSignal, ) -> UtxoScannerService { + let wallet_identity = WalletIdentity::new(wallet.comms.node_identity(), wallet.network.as_network()); let resources = UtxoScannerResources { db: wallet.db.clone(), comms_connectivity: wallet.comms.connectivity(), @@ -116,7 +116,7 @@ impl UtxoScannerServiceBuilder { current_base_node_watcher: wallet.wallet_connectivity.get_current_base_node_watcher(), output_manager_service: wallet.output_manager_service.clone(), transaction_service: wallet.transaction_service.clone(), - node_identity: wallet.comms.node_identity(), + wallet_identity, factories: wallet.factories.clone(), recovery_message: self.recovery_message.clone(), one_sided_payment_message: self.one_sided_message.clone(), @@ -144,7 +144,7 @@ impl UtxoScannerServiceBuilder { wallet_connectivity: TWalletConnectivity, output_manager_service: OutputManagerHandle, transaction_service: TransactionServiceHandle, - node_identity: Arc, + wallet_identity: WalletIdentity, factories: CryptoFactories, shutdown_signal: ShutdownSignal, event_sender: broadcast::Sender, @@ -159,7 +159,7 @@ impl UtxoScannerServiceBuilder { wallet_connectivity, output_manager_service, transaction_service, - node_identity, + wallet_identity, factories, recovery_message: self.recovery_message.clone(), one_sided_payment_message: self.one_sided_message.clone(), diff --git a/base_layer/wallet/src/wallet.rs b/base_layer/wallet/src/wallet.rs index c042fd332b..4aae59c6d1 100644 --- a/base_layer/wallet/src/wallet.rs +++ b/base_layer/wallet/src/wallet.rs @@ -25,6 +25,7 @@ use std::{cmp, marker::PhantomData, sync::Arc}; use log::*; use tari_common::configuration::bootstrap::ApplicationType; use tari_common_types::{ + tari_address::TariAddress, transaction::{ImportStatus, TxId}, types::{ComSignature, Commitment, PrivateKey, PublicKey}, }; @@ -93,6 +94,7 @@ use crate::{ TransactionServiceInitializer, }, types::KeyDigest, + util::wallet_identity::WalletIdentity, utxo_scanner_service::{handle::UtxoScannerHandle, initializer::UtxoScannerServiceInitializer, RECOVERY_KEY}, }; @@ -166,6 +168,7 @@ where config.buffer_size, config.buffer_rate_limit ); + let wallet_identity = WalletIdentity::new(node_identity.clone(), config.network); let stack = StackBuilder::new(shutdown_signal) .add_initializer(P2pInitializer::new( config.p2p.clone(), @@ -186,7 +189,7 @@ where config.transaction_service_config, peer_message_subscription_factory.clone(), transaction_backend, - node_identity.clone(), + wallet_identity.clone(), factories.clone(), wallet_database.clone(), )) @@ -212,7 +215,7 @@ where .add_initializer(UtxoScannerServiceInitializer::new( wallet_database.clone(), factories.clone(), - node_identity.clone(), + wallet_identity, )); // Check if we have update config. FFI wallets don't do this, the update on mobile is done differently. @@ -404,7 +407,7 @@ where spending_key: &PrivateKey, script: TariScript, input_data: ExecutionStack, - source_public_key: &CommsPublicKey, + source_address: TariAddress, features: OutputFeatures, message: String, metadata_signature: ComSignature, @@ -434,7 +437,7 @@ where .transaction_service .import_utxo_with_status( amount, - source_public_key.clone(), + source_address, message, Some(features.maturity), ImportStatus::Imported, @@ -470,14 +473,14 @@ where pub async fn import_unblinded_output_as_non_rewindable( &mut self, unblinded_output: UnblindedOutput, - source_public_key: &CommsPublicKey, + source_address: TariAddress, message: String, ) -> Result { let tx_id = self .transaction_service .import_utxo_with_status( unblinded_output.value, - source_public_key.clone(), + source_address, message, Some(unblinded_output.features.maturity), ImportStatus::Imported, diff --git a/base_layer/wallet/tests/contacts_service.rs b/base_layer/wallet/tests/contacts_service.rs index a37dba5e1c..8c2916ebb0 100644 --- a/base_layer/wallet/tests/contacts_service.rs +++ b/base_layer/wallet/tests/contacts_service.rs @@ -42,6 +42,7 @@ use tokio::{runtime::Runtime, sync::broadcast::error::TryRecvError}; pub mod support; use support::data::get_temp_sqlite_database_connection; use tari_common::configuration::{Network, StringList}; +use tari_common_types::tari_address::TariAddress; use tari_comms::{peer_manager::PeerFeatures, NodeIdentity}; use tari_comms_dht::{store_forward::SafConfig, DhtConfig}; use tari_p2p::{ @@ -141,8 +142,9 @@ pub fn test_contacts_service() { let mut contacts = Vec::new(); for i in 0..5 { let (_secret_key, public_key) = PublicKey::random_keypair(&mut OsRng); + let address = TariAddress::new(public_key, Network::default()); - contacts.push(Contact::new(random::string(8), public_key, None, None)); + contacts.push(Contact::new(random::string(8), address, None, None)); runtime .block_on(contacts_service.upsert_contact(contacts[i].clone())) @@ -153,31 +155,32 @@ pub fn test_contacts_service() { assert_eq!(contacts, got_contacts); let contact = runtime - .block_on(contacts_service.get_contact(contacts[0].public_key.clone())) + .block_on(contacts_service.get_contact(contacts[0].address.clone())) .unwrap(); assert_eq!(contact, contacts[0]); let (_secret_key, public_key) = PublicKey::random_keypair(&mut OsRng); + let address = TariAddress::new(public_key, Network::default()); - let contact = runtime.block_on(contacts_service.get_contact(public_key.clone())); + let contact = runtime.block_on(contacts_service.get_contact(address.clone())); match contact { Ok(_) => panic!("There should be an error here"), Err(ContactsServiceError::ContactsServiceStorageError(ContactsServiceStorageError::ValueNotFound(val))) => { - assert_eq!(val, DbKey::Contact(public_key.clone())) + assert_eq!(val, DbKey::Contact(address.clone())) }, _ => panic!("There should be a specific error here"), } - let result = runtime.block_on(contacts_service.remove_contact(public_key.clone())); + let result = runtime.block_on(contacts_service.remove_contact(address.clone())); match result { Ok(_) => panic!("There should be an error here"), Err(ContactsServiceError::ContactsServiceStorageError(ContactsServiceStorageError::ValueNotFound(val))) => { - assert_eq!(val, DbKey::Contact(public_key)) + assert_eq!(val, DbKey::Contact(address)) }, _ => panic!("There should be a specific error here"), } let _contact = runtime - .block_on(contacts_service.remove_contact(contacts[0].public_key.clone())) + .block_on(contacts_service.remove_contact(contacts[0].address.clone())) .unwrap(); contacts.remove(0); let got_contacts = runtime.block_on(contacts_service.get_contacts()).unwrap(); @@ -191,7 +194,7 @@ pub fn test_contacts_service() { .block_on(contacts_service.upsert_contact(updated_contact.clone())) .unwrap(); let new_contact = runtime - .block_on(contacts_service.get_contact(updated_contact.public_key)) + .block_on(contacts_service.get_contact(updated_contact.address)) .unwrap(); assert_eq!(new_contact.alias, updated_contact.alias); diff --git a/base_layer/wallet/tests/transaction_service_tests/service.rs b/base_layer/wallet/tests/transaction_service_tests/service.rs index 0227ac7053..b1234c7791 100644 --- a/base_layer/wallet/tests/transaction_service_tests/service.rs +++ b/base_layer/wallet/tests/transaction_service_tests/service.rs @@ -38,6 +38,7 @@ use prost::Message; use rand::rngs::OsRng; use tari_common_types::{ chain_metadata::ChainMetadata, + tari_address::TariAddress, transaction::{ImportStatus, TransactionDirection, TransactionStatus, TxId}, types::{FixedHash, PrivateKey, PublicKey, Signature}, }; @@ -139,6 +140,7 @@ use tari_wallet::{ }, TransactionServiceInitializer, }, + util::wallet_identity::WalletIdentity, }; use tempfile::tempdir; use tokio::{ @@ -170,7 +172,7 @@ async fn setup_transaction_service>( let (publisher, subscription_factory) = pubsub_connector(100, 20); let subscription_factory = Arc::new(subscription_factory); let (comms, dht) = setup_comms_services( - node_identity, + node_identity.clone(), peers, publisher, database_path.as_ref().to_str().unwrap().to_owned(), @@ -187,6 +189,7 @@ async fn setup_transaction_service>( let ts_backend = TransactionServiceSqliteDatabase::new(db_connection.clone(), None); let oms_backend = OutputManagerSqliteDatabase::new(db_connection.clone(), None); let kms_backend = KeyManagerSqliteDatabase::new(db_connection, None).unwrap(); + let wallet_identity = WalletIdentity::new(node_identity, Network::LocalNet); let cipher = CipherSeed::new(); let handles = StackBuilder::new(shutdown_signal) @@ -199,7 +202,7 @@ async fn setup_transaction_service>( OutputManagerServiceConfig::default(), oms_backend, factories.clone(), - Network::Weatherwax.into(), + Network::LocalNet.into(), comms.node_identity(), )) .add_initializer(TransactionServiceInitializer::new( @@ -212,7 +215,7 @@ async fn setup_transaction_service>( }, subscription_factory, ts_backend, - comms.node_identity(), + wallet_identity, factories, db.clone(), )) @@ -286,21 +289,21 @@ async fn setup_transaction_service_no_comms( let server = BaseNodeWalletRpcServer::new(service); let protocol_name = server.as_protocol_name(); - let base_node_identity = build_node_identity(PeerFeatures::COMMUNICATION_NODE); + let node_identity = build_node_identity(PeerFeatures::COMMUNICATION_NODE); - let mut mock_rpc_server = MockRpcServer::new(server, base_node_identity.clone()); + let mut mock_rpc_server = MockRpcServer::new(server, node_identity.clone()); mock_rpc_server.serve(); let mut wallet_connectivity_service_mock = create_wallet_connectivity_mock(); let mut rpc_server_connection = mock_rpc_server - .create_connection(base_node_identity.to_peer(), protocol_name.into()) + .create_connection(node_identity.to_peer(), protocol_name.into()) .await; wallet_connectivity_service_mock .set_base_node_wallet_rpc_client(connect_rpc_client(&mut rpc_server_connection).await); - wallet_connectivity_service_mock.set_base_node(base_node_identity.to_peer()); + wallet_connectivity_service_mock.set_base_node(node_identity.to_peer()); wallet_connectivity_service_mock.base_node_changed().await; let constants = ConsensusConstantsBuilder::new(Network::Weatherwax).build(); @@ -332,7 +335,7 @@ async fn setup_transaction_service_no_comms( shutdown.to_signal(), base_node_service_handle.clone(), wallet_connectivity_service_mock.clone(), - base_node_identity.clone(), + node_identity.clone(), key_manager, ) .await @@ -354,7 +357,7 @@ async fn setup_transaction_service_no_comms( max_tx_query_batch_size: 2, ..Default::default() }); - + let wallet_identity = WalletIdentity::new(node_identity.clone(), Network::LocalNet); let ts_service = TransactionService::new( test_config, ts_db, @@ -369,7 +372,7 @@ async fn setup_transaction_service_no_comms( outbound_message_requester, wallet_connectivity_service_mock.clone(), event_publisher, - base_node_identity.clone(), + wallet_identity, factories, shutdown.to_signal(), base_node_service_handle, @@ -387,7 +390,7 @@ async fn setup_transaction_service_no_comms( transaction_cancelled_message_channel, _shutdown: shutdown, _mock_rpc_server: mock_rpc_server, - base_node_identity, + base_node_identity: node_identity, base_node_rpc_mock_state, wallet_connectivity_service_mock, _rpc_server_connection: rpc_server_connection, @@ -516,10 +519,10 @@ async fn manage_single_transaction() { let value = MicroTari::from(1000); let (_utxo, uo1) = make_input(&mut OsRng, MicroTari(2500), &factories.commitment).await; - + let bob_address = TariAddress::new(bob_node_identity.public_key().clone(), Network::LocalNet); assert!(alice_ts .send_transaction( - bob_node_identity.public_key().clone(), + bob_address.clone(), value, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -533,7 +536,7 @@ async fn manage_single_transaction() { let message = "TAKE MAH MONEYS!".to_string(); alice_ts .send_transaction( - bob_node_identity.public_key().clone(), + bob_address, value, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -636,9 +639,10 @@ async fn single_transaction_to_self() { alice_oms.add_rewindable_output(uo1, None, None).await.unwrap(); let message = "TAKE MAH _OWN_ MONEYS!".to_string(); let value = 10000.into(); + let alice_address = TariAddress::new(alice_node_identity.public_key().clone(), Network::LocalNet); let tx_id = alice_ts .send_transaction( - alice_node_identity.public_key().clone(), + alice_address, value, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -718,9 +722,10 @@ async fn send_one_sided_transaction_to_other() { let message = "SEE IF YOU CAN CATCH THIS ONE..... SIDED TX!".to_string(); let value = 10000.into(); let mut alice_ts_clone = alice_ts.clone(); + let bob_address = TariAddress::new(bob_node_identity.public_key().clone(), Network::LocalNet); let tx_id = alice_ts_clone .send_one_sided_transaction( - bob_node_identity.public_key().clone(), + bob_address, value, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -842,9 +847,10 @@ async fn recover_one_sided_transaction() { let message = "".to_string(); let value = 10000.into(); let mut alice_ts_clone = alice_ts.clone(); + let bob_address = TariAddress::new(bob_node_identity.public_key().clone(), Network::LocalNet); let tx_id = alice_ts_clone .send_one_sided_transaction( - bob_node_identity.public_key().clone(), + bob_address, value, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -935,9 +941,10 @@ async fn test_htlc_send_and_claim() { let value = 10000.into(); let mut alice_ts_clone = alice_ts.clone(); let bob_pubkey = bob_ts_interface.base_node_identity.public_key().clone(); + let bob_address = TariAddress::new(bob_pubkey.clone(), Network::LocalNet); let (tx_id, pre_image, output) = alice_ts_clone .send_sha_atomic_swap_transaction( - bob_pubkey, + bob_address, value, UtxoSelectionCriteria::default(), 20.into(), @@ -1045,9 +1052,10 @@ async fn send_one_sided_transaction_to_self() { let message = "SEE IF YOU CAN CATCH THIS ONE..... SIDED TX!".to_string(); let value = 1000.into(); let mut alice_ts_clone = alice_ts; + let alice_address = TariAddress::new(alice_node_identity.public_key().clone(), Network::LocalNet); match alice_ts_clone .send_one_sided_transaction( - alice_node_identity.public_key().clone(), + alice_address, value, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -1183,9 +1191,10 @@ async fn manage_multiple_transactions() { let value_b_to_a_1 = MicroTari::from(11000); let value_a_to_c_1 = MicroTari::from(14000); log::trace!("Sending A to B 1"); + let bob_address = TariAddress::new(bob_node_identity.public_key().clone(), Network::LocalNet); let tx_id_a_to_b_1 = alice_ts .send_transaction( - bob_node_identity.public_key().clone(), + bob_address.clone(), value_a_to_b_1, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -1196,9 +1205,10 @@ async fn manage_multiple_transactions() { .unwrap(); log::trace!("A to B 1 TxID: {}", tx_id_a_to_b_1); log::trace!("Sending A to C 1"); + let carol_address = TariAddress::new(carol_node_identity.public_key().clone(), Network::LocalNet); let tx_id_a_to_c_1 = alice_ts .send_transaction( - carol_node_identity.public_key().clone(), + carol_address, value_a_to_c_1, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -1211,9 +1221,10 @@ async fn manage_multiple_transactions() { assert_eq!(alice_completed_tx.len(), 0); log::trace!("A to C 1 TxID: {}", tx_id_a_to_c_1); + let alice_address = TariAddress::new(alice_node_identity.public_key().clone(), Network::LocalNet); bob_ts .send_transaction( - alice_node_identity.public_key().clone(), + alice_address, value_b_to_a_1, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -1224,7 +1235,7 @@ async fn manage_multiple_transactions() { .unwrap(); alice_ts .send_transaction( - bob_node_identity.public_key().clone(), + bob_address, value_a_to_b_2, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -1348,10 +1359,11 @@ async fn test_accepting_unknown_tx_id_and_malformed_reply() { .await .unwrap(); + let bob_address = TariAddress::new(bob_node_identity.public_key().clone(), Network::LocalNet); alice_ts_interface .transaction_service_handle .send_transaction( - bob_node_identity.public_key().clone(), + bob_address, MicroTari::from(5000), UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -1732,10 +1744,10 @@ async fn discovery_async_return_test() { let initial_balance = alice_oms.get_balance().await.unwrap(); let value_a_to_c_1 = MicroTari::from(14000); - + let bob_address = TariAddress::new(bob_node_identity.public_key().clone(), Network::LocalNet); let tx_id = alice_ts .send_transaction( - bob_node_identity.public_key().clone(), + bob_address, value_a_to_c_1, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -1770,9 +1782,10 @@ async fn discovery_async_return_test() { assert_eq!(found_txid, tx_id); assert!(!is_direct_send); + let carol_address = TariAddress::new(carol_node_identity.public_key().clone(), Network::LocalNet); let tx_id2 = alice_ts .send_transaction( - carol_node_identity.public_key().clone(), + carol_address, value_a_to_c_1, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -1848,10 +1861,18 @@ async fn test_power_mode_updates() { PrivateKey::random(&mut OsRng), PrivateKey::random(&mut OsRng), ); + let source_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); + let destination_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let completed_tx1 = CompletedTransaction { tx_id: 1u64.into(), - source_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), - destination_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + source_address, + destination_address, amount: 5000 * uT, fee: MicroTari::from(100), transaction: tx.clone(), @@ -1870,10 +1891,18 @@ async fn test_power_mode_updates() { mined_timestamp: None, }; + let source_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); + let destination_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let completed_tx2 = CompletedTransaction { tx_id: 2u64.into(), - source_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), - destination_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + source_address, + destination_address, amount: 6000 * uT, fee: MicroTari::from(200), transaction: tx.clone(), @@ -2038,11 +2067,11 @@ async fn test_transaction_cancellation() { .unwrap(); let amount_sent = 100000 * uT; - + let bob_address = TariAddress::new(bob_node_identity.public_key().clone(), Network::LocalNet); let tx_id = alice_ts_interface .transaction_service_handle .send_transaction( - bob_node_identity.public_key().clone(), + bob_address, amount_sent, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -2360,11 +2389,11 @@ async fn test_direct_vs_saf_send_of_tx_reply_and_finalize() { .unwrap(); let amount_sent = 100000 * uT; - + let bob_address = TariAddress::new(bob_node_identity.public_key().clone(), Network::LocalNet); let tx_id = alice_ts_interface .transaction_service_handle .send_transaction( - bob_node_identity.public_key().clone(), + bob_address, amount_sent, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -2546,10 +2575,11 @@ async fn test_direct_vs_saf_send_of_tx_reply_and_finalize() { let amount_sent = 20000 * uT; + let bob_address = TariAddress::new(bob_node_identity.public_key().clone(), Network::LocalNet); let _tx_id2 = alice_ts_interface .transaction_service_handle .send_transaction( - bob_node_identity.public_key().clone(), + bob_address, amount_sent, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -2679,10 +2709,11 @@ async fn test_tx_direct_send_behaviour() { }) .await; + let bob_address = TariAddress::new(bob_node_identity.public_key().clone(), Network::LocalNet); let _tx_id = alice_ts_interface .transaction_service_handle .send_transaction( - bob_node_identity.public_key().clone(), + bob_address.clone(), amount_sent, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -2726,7 +2757,7 @@ async fn test_tx_direct_send_behaviour() { let _tx_id = alice_ts_interface .transaction_service_handle .send_transaction( - bob_node_identity.public_key().clone(), + bob_address.clone(), amount_sent, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -2775,7 +2806,7 @@ async fn test_tx_direct_send_behaviour() { let _tx_id = alice_ts_interface .transaction_service_handle .send_transaction( - bob_node_identity.public_key().clone(), + bob_address.clone(), amount_sent, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -2824,7 +2855,7 @@ async fn test_tx_direct_send_behaviour() { let _tx_id = alice_ts_interface .transaction_service_handle .send_transaction( - bob_node_identity.public_key().clone(), + bob_address, amount_sent, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -2942,9 +2973,10 @@ async fn test_restarting_transaction_protocols() { }; let tx = bob_stp.get_transaction().unwrap().clone(); + let bob_address = TariAddress::new(bob_identity.public_key().clone(), Network::LocalNet); let inbound_tx = InboundTransaction { tx_id, - source_public_key: bob_identity.public_key().clone(), + source_address: bob_address, amount: msg.amount, receiver_protocol, status: TransactionStatus::Pending, @@ -2963,9 +2995,10 @@ async fn test_restarting_transaction_protocols() { ))) .unwrap(); + let alice_address = TariAddress::new(alice_identity.public_key().clone(), Network::LocalNet); let outbound_tx = OutboundTransaction { tx_id, - destination_public_key: alice_identity.public_key().clone(), + destination_address: alice_address, amount: msg.amount, fee, sender_protocol: bob_pre_finalize, @@ -4045,10 +4078,11 @@ async fn test_transaction_resending() { let amount_sent = 100000 * uT; + let bob_address = TariAddress::new(bob_node_identity.public_key().clone(), Network::LocalNet); let tx_id = alice_ts_interface .transaction_service_handle .send_transaction( - bob_node_identity.public_key().clone(), + bob_address, amount_sent, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -4261,9 +4295,13 @@ async fn test_resend_on_startup() { let tx_sender_msg = TransactionSenderMessage::Single(Box::new(stp_msg)); let tx_id = stp.get_tx_id().unwrap(); + let address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let mut outbound_tx = OutboundTransaction { tx_id, - destination_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + destination_address: address, amount, fee: stp.get_fee_amount().unwrap(), sender_protocol: stp, @@ -4387,10 +4425,13 @@ async fn test_resend_on_startup() { PrivateKey::random(&mut OsRng), &factories, ); - + let address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let mut inbound_tx = InboundTransaction { tx_id, - source_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + source_address: address, amount, receiver_protocol: rtp, status: TransactionStatus::Pending, @@ -4532,11 +4573,11 @@ async fn test_replying_to_cancelled_tx() { .unwrap(); let amount_sent = 100000 * uT; - + let bob_address = TariAddress::new(bob_node_identity.public_key().clone(), Network::LocalNet); let tx_id = alice_ts_interface .transaction_service_handle .send_transaction( - bob_node_identity.public_key().clone(), + bob_address, amount_sent, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -4656,10 +4697,11 @@ async fn test_transaction_timeout_cancellation() { let amount_sent = 10000 * uT; + let bob_address = TariAddress::new(bob_node_identity.public_key().clone(), Network::LocalNet); let tx_id = alice_ts_interface .transaction_service_handle .send_transaction( - bob_node_identity.public_key().clone(), + bob_address, amount_sent, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -4740,9 +4782,13 @@ async fn test_transaction_timeout_cancellation() { let tx_sender_msg = TransactionSenderMessage::Single(Box::new(stp_msg)); let tx_id = stp.get_tx_id().unwrap(); + let address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let outbound_tx = OutboundTransaction { tx_id, - destination_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + destination_address: address, amount, fee: stp.get_fee_amount().unwrap(), sender_protocol: stp, @@ -4910,11 +4956,12 @@ async fn transaction_service_tx_broadcast() { let amount_sent1 = 100000 * uT; + let bob_address = TariAddress::new(bob_node_identity.public_key().clone(), Network::LocalNet); // Send Tx1 let tx_id1 = alice_ts_interface .transaction_service_handle .send_transaction( - bob_node_identity.public_key().clone(), + bob_address.clone(), amount_sent1, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -4975,7 +5022,7 @@ async fn transaction_service_tx_broadcast() { let tx_id2 = alice_ts_interface .transaction_service_handle .send_transaction( - bob_node_identity.public_key().clone(), + bob_address, amount_sent2, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -5240,11 +5287,18 @@ async fn broadcast_all_completed_transactions_on_startup() { PrivateKey::random(&mut OsRng), PrivateKey::random(&mut OsRng), ); - + let source_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); + let destination_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let completed_tx1 = CompletedTransaction { tx_id: 1u64.into(), - source_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), - destination_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + source_address, + destination_address, amount: 5000 * uT, fee: MicroTari::from(20), transaction: tx.clone(), @@ -5356,12 +5410,15 @@ async fn test_update_faux_tx_on_oms_validation() { let (connection, _temp_dir) = make_wallet_database_connection(None); let mut alice_ts_interface = setup_transaction_service_no_comms(factories.clone(), connection, None).await; - + let alice_address = TariAddress::new( + alice_ts_interface.base_node_identity.public_key().clone(), + Network::LocalNet, + ); let tx_id_1 = alice_ts_interface .transaction_service_handle .import_utxo_with_status( MicroTari::from(10000), - alice_ts_interface.base_node_identity.public_key().clone(), + alice_address.clone(), "blah".to_string(), None, ImportStatus::Imported, @@ -5375,7 +5432,7 @@ async fn test_update_faux_tx_on_oms_validation() { .transaction_service_handle .import_utxo_with_status( MicroTari::from(20000), - alice_ts_interface.base_node_identity.public_key().clone(), + alice_address.clone(), "one-sided 1".to_string(), None, ImportStatus::FauxUnconfirmed, @@ -5390,7 +5447,7 @@ async fn test_update_faux_tx_on_oms_validation() { .transaction_service_handle .import_utxo_with_status( MicroTari::from(30000), - alice_ts_interface.base_node_identity.public_key().clone(), + alice_address, "one-sided 2".to_string(), None, ImportStatus::FauxConfirmed, diff --git a/base_layer/wallet/tests/transaction_service_tests/storage.rs b/base_layer/wallet/tests/transaction_service_tests/storage.rs index 1cc9272fdb..a8feb5e8b6 100644 --- a/base_layer/wallet/tests/transaction_service_tests/storage.rs +++ b/base_layer/wallet/tests/transaction_service_tests/storage.rs @@ -25,7 +25,9 @@ use std::mem::size_of; use chacha20poly1305::{aead::NewAead, Key, XChaCha20Poly1305}; use chrono::{NaiveDateTime, Utc}; use rand::{rngs::OsRng, RngCore}; +use tari_common::configuration::Network; use tari_common_types::{ + tari_address::TariAddress, transaction::{TransactionDirection, TransactionStatus, TxId}, types::{FixedHash, PrivateKey, PublicKey, Signature}, }; @@ -107,9 +109,13 @@ pub fn test_db_backend(backend: T) { for i in 0..messages.len() { let tx_id = TxId::from(i + 10); + let address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); outbound_txs.push(OutboundTransaction { tx_id, - destination_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + destination_address: address, amount: amounts[i], fee: stp.clone().get_fee_amount().unwrap(), sender_protocol: stp.clone(), @@ -162,10 +168,14 @@ pub fn test_db_backend(backend: T) { let mut inbound_txs = Vec::new(); for i in 0..messages.len() { + let address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let tx_id = TxId::from(i); inbound_txs.push(InboundTransaction { tx_id, - source_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + source_address: address, amount: amounts[i], receiver_protocol: rtp.clone(), status: TransactionStatus::Pending, @@ -203,19 +213,19 @@ pub fn test_db_backend(backend: T) { panic!("Should have found inbound tx"); } - let inbound_pub_key = db - .get_pending_transaction_counterparty_pub_key_by_tx_id(inbound_txs[0].tx_id) + let inbound_address = db + .get_pending_transaction_counterparty_address_by_tx_id(inbound_txs[0].tx_id) .unwrap(); - assert_eq!(inbound_pub_key, inbound_txs[0].source_public_key); + assert_eq!(inbound_address, inbound_txs[0].source_address); assert!(db - .get_pending_transaction_counterparty_pub_key_by_tx_id(100u64.into()) + .get_pending_transaction_counterparty_address_by_tx_id(100u64.into()) .is_err()); - let outbound_pub_key = db - .get_pending_transaction_counterparty_pub_key_by_tx_id(outbound_txs[0].tx_id) + let outbound_address = db + .get_pending_transaction_counterparty_address_by_tx_id(outbound_txs[0].tx_id) .unwrap(); - assert_eq!(outbound_pub_key, outbound_txs[0].destination_public_key); + assert_eq!(outbound_address, outbound_txs[0].destination_address); let mut completed_txs = Vec::new(); let tx = Transaction::new( @@ -227,10 +237,18 @@ pub fn test_db_backend(backend: T) { ); for i in 0..messages.len() { + let source_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); + let dest_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); completed_txs.push(CompletedTransaction { tx_id: outbound_txs[i].tx_id, - source_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), - destination_public_key: PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + source_address, + destination_address: dest_address, amount: outbound_txs[i].amount, fee: MicroTari::from(200), transaction: tx.clone(), @@ -330,12 +348,15 @@ pub fn test_db_backend(backend: T) { } else { panic!("Should have found cancelled completed tx"); } - + let address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); db.add_pending_inbound_transaction( 999u64.into(), InboundTransaction::new( 999u64.into(), - PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + address, 22 * uT, rtp, TransactionStatus::Pending, @@ -378,12 +399,15 @@ pub fn test_db_backend(backend: T) { let mut cancelled_txs = db.get_cancelled_pending_inbound_transactions().unwrap(); assert_eq!(cancelled_txs.len(), 1); assert!(cancelled_txs.remove(&999u64.into()).is_some()); - + let address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); db.add_pending_outbound_transaction( 998u64.into(), OutboundTransaction::new( 998u64.into(), - PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + address, 22 * uT, stp.get_fee_amount().unwrap(), stp, @@ -484,8 +508,8 @@ async fn import_tx_and_read_it_from_db() { let transaction = CompletedTransaction::new( TxId::from(1u64), - PublicKey::default(), - PublicKey::default(), + TariAddress::default(), + TariAddress::default(), MicroTari::from(100000), MicroTari::from(0), Transaction::new( @@ -513,8 +537,8 @@ async fn import_tx_and_read_it_from_db() { let transaction = CompletedTransaction::new( TxId::from(2u64), - PublicKey::default(), - PublicKey::default(), + TariAddress::default(), + TariAddress::default(), MicroTari::from(100000), MicroTari::from(0), Transaction::new( @@ -542,8 +566,8 @@ async fn import_tx_and_read_it_from_db() { let transaction = CompletedTransaction::new( TxId::from(3u64), - PublicKey::default(), - PublicKey::default(), + TariAddress::default(), + TariAddress::default(), MicroTari::from(100000), MicroTari::from(0), Transaction::new( diff --git a/base_layer/wallet/tests/transaction_service_tests/transaction_protocols.rs b/base_layer/wallet/tests/transaction_service_tests/transaction_protocols.rs index eb4c040aad..5670ba8426 100644 --- a/base_layer/wallet/tests/transaction_service_tests/transaction_protocols.rs +++ b/base_layer/wallet/tests/transaction_service_tests/transaction_protocols.rs @@ -25,12 +25,15 @@ use std::{collections::HashMap, sync::Arc, time::Duration}; use chrono::Utc; use futures::StreamExt; use rand::rngs::OsRng; -use tari_common_types::transaction::{TransactionDirection, TransactionStatus, TxId}; +use tari_common::configuration::Network; +use tari_common_types::{ + tari_address::TariAddress, + transaction::{TransactionDirection, TransactionStatus, TxId}, +}; use tari_comms::{ peer_manager::PeerFeatures, protocol::rpc::{mock::MockRpcServer, NamedProtocolService}, test_utils::node_identity::build_node_identity, - types::CommsPublicKey, NodeIdentity, }; use tari_comms_dht::outbound::mock::{create_outbound_service_mock, OutboundServiceMockState}; @@ -80,7 +83,7 @@ use tari_wallet::{ sqlite_db::TransactionServiceSqliteDatabase, }, }, - util::watch::Watch, + util::{wallet_identity::WalletIdentity, watch::Watch}, }; use tempfile::{tempdir, TempDir}; use tokio::{sync::broadcast, task, time::sleep}; @@ -142,14 +145,14 @@ pub async fn setup() -> ( broadcast::channel(200); let shutdown = Shutdown::new(); - + let wallet_identity = WalletIdentity::new(client_node_identity, Network::LocalNet); let resources = TransactionServiceResources { db, output_manager_service: output_manager_service_handle, outbound_message_service: outbound_message_requester, connectivity: wallet_connectivity.clone(), event_publisher: ts_event_publisher, - node_identity: client_node_identity, + wallet_identity, factories: CryptoFactories::default(), config: TransactionServiceConfig { broadcast_monitoring_timeout: Duration::from_secs(3), @@ -185,8 +188,8 @@ pub async fn add_transaction_to_database( let tx1 = (*txs1[0]).clone(); let completed_tx1 = CompletedTransaction::new( tx_id, - CommsPublicKey::default(), - CommsPublicKey::default(), + TariAddress::default(), + TariAddress::default(), amount, 200 * uT, tx1, diff --git a/base_layer/wallet/tests/utxo_scanner.rs b/base_layer/wallet/tests/utxo_scanner.rs index bb245d0502..3ce9eea8b1 100644 --- a/base_layer/wallet/tests/utxo_scanner.rs +++ b/base_layer/wallet/tests/utxo_scanner.rs @@ -74,11 +74,12 @@ use support::{ transaction_service_mock::make_transaction_service_mock, utils::make_input, }; -use tari_comms::types::CommsPublicKey; +use tari_common::configuration::Network; +use tari_common_types::tari_address::TariAddress; use tari_wallet::{ output_manager_service::storage::OutputSource, transaction_service::handle::TransactionServiceRequest, - util::watch::Watch, + util::{wallet_identity::WalletIdentity, watch::Watch}, utxo_scanner_service::handle::UtxoScannerHandle, }; @@ -146,6 +147,7 @@ async fn setup( task::spawn(oms_mock.run()); let node_identity = build_node_identity(PeerFeatures::COMMUNICATION_NODE); + let wallet_identity = WalletIdentity::new(node_identity, Network::default()); let (event_sender, _) = broadcast::channel(200); let temp_dir = tempdir().unwrap(); @@ -194,7 +196,7 @@ async fn setup( wallet_connectivity_mock, oms_handle, ts_handle, - node_identity, + wallet_identity, factories, shutdown.to_signal(), event_sender, @@ -445,7 +447,7 @@ async fn test_utxo_scanner_recovery_with_restart() { for req in requests { if let TransactionServiceRequest::ImportUtxoWithStatus { amount: _, - source_public_key, + source_address, message, maturity: _, import_status: _, @@ -455,7 +457,7 @@ async fn test_utxo_scanner_recovery_with_restart() { } = req { assert_eq!(message, "Output found on blockchain during Wallet Recovery".to_string()); - assert_eq!(source_public_key, CommsPublicKey::default()); + assert_eq!(source_address, TariAddress::default()); } } @@ -512,7 +514,7 @@ async fn test_utxo_scanner_recovery_with_restart() { for req in requests { if let TransactionServiceRequest::ImportUtxoWithStatus { amount: _, - source_public_key: _, + source_address: _, message, maturity: _, import_status: _, @@ -884,7 +886,7 @@ async fn test_utxo_scanner_one_sided_payments() { for req in requests { if let TransactionServiceRequest::ImportUtxoWithStatus { amount: _, - source_public_key: _, + source_address: _, message, maturity: _, import_status: _, @@ -972,7 +974,7 @@ async fn test_utxo_scanner_one_sided_payments() { for req in requests { if let TransactionServiceRequest::ImportUtxoWithStatus { amount: _, - source_public_key: _, + source_address: _, message, maturity: _, import_status: _, diff --git a/base_layer/wallet/tests/wallet.rs b/base_layer/wallet/tests/wallet.rs index 077f63ae2b..0832e20e2f 100644 --- a/base_layer/wallet/tests/wallet.rs +++ b/base_layer/wallet/tests/wallet.rs @@ -27,6 +27,7 @@ use support::{comms_and_services::get_next_memory_address, utils::make_input}; use tari_common::configuration::StringList; use tari_common_types::{ chain_metadata::ChainMetadata, + tari_address::TariAddress, transaction::TransactionStatus, types::{FixedHash, PrivateKey, PublicKey}, }; @@ -210,6 +211,8 @@ async fn test_wallet() { let base_node_identity = NodeIdentity::random(&mut OsRng, get_next_memory_address(), PeerFeatures::COMMUNICATION_NODE); + // create wallet creates a local wallet + let network = Network::LocalNet; let mut alice_wallet = create_wallet( alice_db_tempdir.path(), "alice_db", @@ -233,6 +236,7 @@ async fn test_wallet() { .await .unwrap(); let bob_identity = (*bob_wallet.comms.node_identity()).clone(); + let bob_address = TariAddress::new(bob_identity.public_key().clone(), network); alice_wallet .comms @@ -272,7 +276,7 @@ async fn test_wallet() { alice_wallet .transaction_service .send_transaction( - bob_identity.public_key().clone(), + bob_address.clone(), value, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -301,8 +305,9 @@ async fn test_wallet() { let mut contacts = Vec::new(); for i in 0..2 { let (_secret_key, public_key) = PublicKey::random_keypair(&mut OsRng); + let address = TariAddress::new(public_key, Network::LocalNet); - contacts.push(Contact::new(random::string(8), public_key, None, None)); + contacts.push(Contact::new(random::string(8), address, None, None)); alice_wallet .contacts_service @@ -496,6 +501,8 @@ async fn test_store_and_forward_send_tx() { let alice_db_tempdir = tempdir().unwrap(); let carol_db_tempdir = tempdir().unwrap(); let base_node_tempdir = tempdir().unwrap(); + // create wallet uses local net + let network = Network::LocalNet; let mut alice_wallet = create_wallet( alice_db_tempdir.path(), @@ -537,6 +544,7 @@ async fn test_store_and_forward_send_tx() { .unwrap(); let carol_identity = carol_wallet.comms.node_identity(); + let carol_address = TariAddress::new(carol_identity.public_key().clone(), network); let mut carol_event_stream = carol_wallet.transaction_service.get_event_stream(); alice_wallet @@ -562,7 +570,7 @@ async fn test_store_and_forward_send_tx() { alice_wallet .transaction_service .send_transaction( - carol_identity.public_key().clone(), + carol_address.clone(), value, UtxoSelectionCriteria::default(), OutputFeatures::default(), @@ -620,6 +628,7 @@ async fn test_store_and_forward_send_tx() { #[allow(clippy::too_many_lines)] #[tokio::test] async fn test_import_utxo() { + let network = Network::Weatherwax; let factories = CryptoFactories::default(); let shutdown = Shutdown::new(); let alice_identity = Arc::new(NodeIdentity::random( @@ -627,7 +636,7 @@ async fn test_import_utxo() { "/ip4/127.0.0.1/tcp/24521".parse().unwrap(), PeerFeatures::COMMUNICATION_NODE, )); - let base_node_identity = Arc::new(NodeIdentity::random( + let node_identity = Arc::new(NodeIdentity::random( &mut OsRng, "/ip4/127.0.0.1/tcp/24522".parse().unwrap(), PeerFeatures::COMMUNICATION_NODE, @@ -658,7 +667,7 @@ async fn test_import_utxo() { }; let config = WalletConfig { p2p: comms_config, - network: Network::Weatherwax, + network, ..Default::default() }; @@ -691,14 +700,14 @@ async fn test_import_utxo() { let utxo = create_unblinded_output(script.clone(), temp_features, &p, 20000 * uT); let output = utxo.as_transaction_output(&factories).unwrap(); let expected_output_hash = output.hash(); - + let node_address = TariAddress::new(node_identity.public_key().clone(), network); let tx_id = alice_wallet .import_external_utxo_as_non_rewindable( utxo.value, &utxo.spending_key, script.clone(), input.clone(), - base_node_identity.public_key(), + node_address, utxo.features.clone(), "Testing".to_string(), utxo.metadata_signature.clone(), @@ -797,7 +806,8 @@ async fn test_contacts_service_liveness() { let factories = CryptoFactories::default(); let alice_db_tempdir = tempdir().unwrap(); let bob_db_tempdir = tempdir().unwrap(); - + // network used by create wallet is local net + let network = Network::LocalNet; let mut alice_wallet = create_wallet( alice_db_tempdir.path(), "alice_db", @@ -809,6 +819,7 @@ async fn test_contacts_service_liveness() { .await .unwrap(); let alice_identity = alice_wallet.comms.node_identity(); + let alice_address = TariAddress::new(alice_identity.public_key().clone(), network); let mut bob_wallet = create_wallet( bob_db_tempdir.path(), @@ -821,6 +832,7 @@ async fn test_contacts_service_liveness() { .await .unwrap(); let bob_identity = (*bob_wallet.comms.node_identity()).clone(); + let bob_address = TariAddress::new(bob_identity.public_key().clone(), network); alice_wallet .comms @@ -828,7 +840,7 @@ async fn test_contacts_service_liveness() { .add_peer(bob_identity.to_peer()) .await .unwrap(); - let contact_bob = Contact::new(random::string(8), bob_identity.public_key().clone(), None, None); + let contact_bob = Contact::new(random::string(8), bob_address.clone(), None, None); alice_wallet.contacts_service.upsert_contact(contact_bob).await.unwrap(); bob_wallet @@ -837,7 +849,7 @@ async fn test_contacts_service_liveness() { .add_peer(alice_identity.to_peer()) .await .unwrap(); - let contact_alice = Contact::new(random::string(8), alice_identity.public_key().clone(), None, None); + let contact_alice = Contact::new(random::string(8), alice_address.clone(), None, None); bob_wallet.contacts_service.upsert_contact(contact_alice).await.unwrap(); alice_wallet @@ -856,7 +868,7 @@ async fn test_contacts_service_liveness() { tokio::select! { event = liveness_event_stream_alice.recv() => { if let ContactsLivenessEvent::StatusUpdated(data) = &*event.unwrap() { - if data.public_key() == bob_identity.public_key(){ + if data.address() == &bob_address{ assert_eq!(data.node_id(), bob_identity.node_id()); match data.message_type() { ContactMessageType::Ping => { @@ -890,7 +902,7 @@ async fn test_contacts_service_liveness() { tokio::select! { event = liveness_event_stream_bob.recv() => { if let ContactsLivenessEvent::StatusUpdated(data) = &*event.unwrap() { - if data.public_key() == alice_identity.public_key(){ + if data.address() == &alice_address{ assert_eq!(data.node_id(), alice_identity.node_id()); if data.message_type() == ContactMessageType::Ping { ping_count += 1; diff --git a/base_layer/wallet_ffi/src/callback_handler.rs b/base_layer/wallet_ffi/src/callback_handler.rs index b720ec42f9..a28a85a864 100644 --- a/base_layer/wallet_ffi/src/callback_handler.rs +++ b/base_layer/wallet_ffi/src/callback_handler.rs @@ -38,8 +38,7 @@ use std::{ops::Deref, sync::Arc}; use log::*; -use tari_common_types::transaction::TxId; -use tari_comms::types::CommsPublicKey; +use tari_common_types::{tari_address::TariAddress, transaction::TxId}; use tari_comms_dht::event::{DhtEvent, DhtEventReceiver}; use tari_shutdown::ShutdownSignal; use tari_wallet::{ @@ -86,7 +85,7 @@ where TBackend: TransactionBackend + 'static output_manager_service: OutputManagerHandle, dht_event_stream: DhtEventReceiver, shutdown_signal: Option, - comms_public_key: CommsPublicKey, + comms_address: TariAddress, balance_cache: Balance, connectivity_status_watch: watch::Receiver, contacts_liveness_events: broadcast::Receiver>, @@ -103,7 +102,7 @@ where TBackend: TransactionBackend + 'static output_manager_service: OutputManagerHandle, dht_event_stream: DhtEventReceiver, shutdown_signal: ShutdownSignal, - comms_public_key: CommsPublicKey, + comms_address: TariAddress, connectivity_status_watch: watch::Receiver, contacts_liveness_events: broadcast::Receiver>, callback_received_transaction: unsafe extern "C" fn(*mut InboundTransaction), @@ -211,7 +210,7 @@ where TBackend: TransactionBackend + 'static output_manager_service, dht_event_stream, shutdown_signal: Some(shutdown_signal), - comms_public_key, + comms_address, balance_cache: Balance::zero(), connectivity_status_watch, contacts_liveness_events, @@ -443,7 +442,7 @@ where TBackend: TransactionBackend + 'static debug!( target: LOG_TARGET, "Calling Contacts Liveness Data Updated callback function for contact {}", - data.public_key(), + data.address(), ); let boxing = Box::into_raw(Box::new(data)); unsafe { @@ -468,11 +467,11 @@ where TBackend: TransactionBackend + 'static transaction = Some(tx); } else if let Ok(tx) = self.db.get_cancelled_pending_outbound_transaction(tx_id) { let mut outbound_tx = CompletedTransaction::from(tx); - outbound_tx.source_public_key = self.comms_public_key.clone(); + outbound_tx.source_address = self.comms_address.clone(); transaction = Some(outbound_tx); } else if let Ok(tx) = self.db.get_cancelled_pending_inbound_transaction(tx_id) { let mut inbound_tx = CompletedTransaction::from(tx); - inbound_tx.destination_public_key = self.comms_public_key.clone(); + inbound_tx.destination_address = self.comms_address.clone(); transaction = Some(inbound_tx); } else { }; diff --git a/base_layer/wallet_ffi/src/callback_handler_tests.rs b/base_layer/wallet_ffi/src/callback_handler_tests.rs index 666dcfd909..204058a282 100644 --- a/base_layer/wallet_ffi/src/callback_handler_tests.rs +++ b/base_layer/wallet_ffi/src/callback_handler_tests.rs @@ -11,7 +11,9 @@ mod test { use chrono::{NaiveDateTime, Utc}; use rand::rngs::OsRng; + use tari_common::configuration::Network; use tari_common_types::{ + tari_address::TariAddress, transaction::{TransactionDirection, TransactionStatus}, types::{BlindingFactor, PrivateKey, PublicKey}, }; @@ -250,9 +252,13 @@ mod test { let db = TransactionDatabase::new(TransactionServiceSqliteDatabase::new(connection, None)); let rtp = ReceiverTransactionProtocol::new_placeholder(); + let source_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let inbound_tx = InboundTransaction::new( 1u64.into(), - PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + source_address, 22 * uT, rtp, TransactionStatus::Pending, @@ -262,10 +268,18 @@ mod test { db.add_pending_inbound_transaction(1u64.into(), inbound_tx.clone()) .unwrap(); - let completed_tx = CompletedTransaction::new( - 2u64.into(), + let source_address = TariAddress::new( PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); + let destination_address = TariAddress::new( PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); + let completed_tx = CompletedTransaction::new( + 2u64.into(), + source_address, + destination_address, MicroTari::from(100), MicroTari::from(2000), Transaction::new( @@ -287,9 +301,13 @@ mod test { .unwrap(); let stp = SenderTransactionProtocol::new_placeholder(); + let destination_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let outbound_tx = OutboundTransaction::new( 3u64.into(), - PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + destination_address, 22 * uT, 23 * uT, stp, @@ -318,11 +336,18 @@ mod test { .unwrap(); db.reject_completed_transaction(5u64.into(), TxCancellationReason::Unknown) .unwrap(); - - let faux_unconfirmed_tx = CompletedTransaction::new( - 6u64.into(), + let source_address = TariAddress::new( PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); + let destination_address = TariAddress::new( PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); + let faux_unconfirmed_tx = CompletedTransaction::new( + 6u64.into(), + source_address, + destination_address, MicroTari::from(100), MicroTari::from(2000), Transaction::new( @@ -343,10 +368,18 @@ mod test { db.insert_completed_transaction(6u64.into(), faux_unconfirmed_tx.clone()) .unwrap(); - let faux_confirmed_tx = CompletedTransaction::new( - 7u64.into(), + let source_address = TariAddress::new( PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); + let destination_address = TariAddress::new( PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); + let faux_confirmed_tx = CompletedTransaction::new( + 7u64.into(), + source_address, + destination_address, MicroTari::from(100), MicroTari::from(2000), Transaction::new( @@ -394,6 +427,10 @@ mod test { let (connectivity_tx, connectivity_rx) = watch::channel(OnlineStatus::Offline); let (contacts_liveness_events_sender, _) = broadcast::channel(250); let contacts_liveness_events = contacts_liveness_events_sender.subscribe(); + let comms_address = TariAddress::new( + PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + Network::LocalNet, + ); let callback_handler = CallbackHandler::new( db, @@ -402,7 +439,7 @@ mod test { oms_handle, dht_event_receiver, shutdown_signal.to_signal(), - PublicKey::from_secret_key(&PrivateKey::random(&mut OsRng)), + comms_address, connectivity_rx, contacts_liveness_events, received_tx_callback, @@ -683,12 +720,12 @@ mod test { let contact = Contact::new( "My friend".to_string(), - faux_unconfirmed_tx.destination_public_key, + faux_unconfirmed_tx.destination_address, None, None, ); let data = ContactsLivenessData::new( - contact.public_key.clone(), + contact.address.clone(), contact.node_id.clone(), contact.latency, contact.last_seen, @@ -699,7 +736,7 @@ mod test { .send(Arc::new(ContactsLivenessEvent::StatusUpdated(Box::new(data)))) .unwrap(); let data = ContactsLivenessData::new( - contact.public_key.clone(), + contact.address.clone(), contact.node_id, Some(1234), Some(Utc::now().naive_utc()), diff --git a/base_layer/wallet_ffi/src/error.rs b/base_layer/wallet_ffi/src/error.rs index 29022018e7..491259ff4e 100644 --- a/base_layer/wallet_ffi/src/error.rs +++ b/base_layer/wallet_ffi/src/error.rs @@ -20,6 +20,7 @@ // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE // USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. use log::*; +use tari_common_types::tari_address::TariAddressError; use tari_comms::multiaddr; use tari_comms_dht::store_forward::StoreAndForwardError; use tari_crypto::{ @@ -391,6 +392,32 @@ impl From for LibWalletError { } } +/// This implementation maps the internal TariAddressError to a set of LibWalletErrors. +/// The mapping is explicitly managed here. +impl From for LibWalletError { + fn from(e: TariAddressError) -> Self { + error!(target: LOG_TARGET, "{}", format!("{:?}", e)); + match e { + TariAddressError::InvalidNetworkOrChecksum => Self { + code: 701, + message: format!("{:?}", e), + }, + TariAddressError::CannotRecoverPublicKey => Self { + code: 702, + message: format!("{:?}", e), + }, + TariAddressError::InvalidSize => Self { + code: 703, + message: format!("{:?}", e), + }, + TariAddressError::InvalidEmoji => Self { + code: 704, + message: format!("{:?}", e), + }, + } + } +} + impl From for LibWalletError { fn from(err: multiaddr::Error) -> Self { error!(target: LOG_TARGET, "{}", format!("{:?}", err)); diff --git a/base_layer/wallet_ffi/src/lib.rs b/base_layer/wallet_ffi/src/lib.rs index 7fee8198a1..507c1cb95e 100644 --- a/base_layer/wallet_ffi/src/lib.rs +++ b/base_layer/wallet_ffi/src/lib.rs @@ -87,7 +87,8 @@ use num_traits::FromPrimitive; use rand::rngs::OsRng; use tari_common::configuration::StringList; use tari_common_types::{ - emoji::{emoji_set, EmojiId, EmojiIdError}, + emoji::emoji_set, + tari_address::{TariAddress, TariAddressError}, transaction::{TransactionDirection, TransactionStatus, TxId}, types::{Commitment, PublicKey}, }; @@ -178,6 +179,7 @@ const LOG_TARGET: &str = "wallet_ffi"; pub type TariTransportConfig = tari_p2p::TransportConfig; pub type TariPublicKey = tari_common_types::types::PublicKey; +pub type TariWalletAddress = tari_common_types::tari_address::TariAddress; pub type TariNodeId = tari_comms::peer_manager::NodeId; pub type TariPrivateKey = tari_common_types::types::PrivateKey; pub type TariOutputFeatures = tari_core::transactions::transaction_components::OutputFeatures; @@ -1008,49 +1010,228 @@ pub unsafe extern "C" fn public_key_from_hex(key: *const c_char, error_out: *mut } } -/// Creates a char array from a TariPublicKey in emoji format +/// -------------------------------------------------------------------------------------------- /// + +/// -------------------------------- Tari Address ---------------------------------------------- /// + +/// Creates a TariWalletAddress from a ByteVector /// /// ## Arguments -/// `pk` - The pointer to a TariPublicKey +/// `bytes` - The pointer to a ByteVector +/// `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions +/// as an out parameter. +/// +/// ## Returns +/// `TariWalletAddress` - Returns a public key. Note that it will be ptr::null_mut() if bytes is null or +/// if there was an error with the contents of bytes +/// +/// # Safety +/// The ```public_key_destroy``` function must be called when finished with a TariWalletAddress to prevent a memory leak +#[no_mangle] +pub unsafe extern "C" fn tari_address_create(bytes: *mut ByteVector, error_out: *mut c_int) -> *mut TariWalletAddress { + let mut error = 0; + ptr::swap(error_out, &mut error as *mut c_int); + if bytes.is_null() { + error = LibWalletError::from(InterfaceError::NullError("bytes".to_string())).code; + ptr::swap(error_out, &mut error as *mut c_int); + return ptr::null_mut(); + } + let v = (*bytes).0.clone(); + let address = TariWalletAddress::from_bytes(&v); + match address { + Ok(address) => Box::into_raw(Box::new(address)), + Err(e) => { + error = LibWalletError::from(e).code; + ptr::swap(error_out, &mut error as *mut c_int); + ptr::null_mut() + }, + } +} + +/// Frees memory for a TariWalletAddress +/// +/// ## Arguments +/// `pk` - The pointer to a TariWalletAddress +/// +/// ## Returns +/// `()` - Does not return a value, equivalent to void in C +/// +/// # Safety +/// None +#[no_mangle] +pub unsafe extern "C" fn tari_address_destroy(address: *mut TariWalletAddress) { + if !address.is_null() { + Box::from_raw(address); + } +} + +/// Gets a ByteVector from a TariWalletAddress +/// +/// ## Arguments +/// `address` - The pointer to a TariWalletAddress +/// `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions +/// as an out parameter. +/// +/// ## Returns +/// `*mut ByteVector` - Returns a pointer to a ByteVector. Note that it returns ptr::null_mut() if address is null +/// +/// # Safety +/// The ```byte_vector_destroy``` function must be called when finished with the ByteVector to prevent a memory leak. +#[no_mangle] +pub unsafe extern "C" fn tari_address_get_bytes( + address: *mut TariWalletAddress, + error_out: *mut c_int, +) -> *mut ByteVector { + let mut error = 0; + ptr::swap(error_out, &mut error as *mut c_int); + let mut bytes = ByteVector(Vec::new()); + if address.is_null() { + error = LibWalletError::from(InterfaceError::NullError("address".to_string())).code; + ptr::swap(error_out, &mut error as *mut c_int); + return ptr::null_mut(); + } else { + bytes.0 = (*address).to_bytes().to_vec(); + } + Box::into_raw(Box::new(bytes)) +} + +/// Creates a TariWalletAddress from a TariPrivateKey +/// +/// ## Arguments +/// `secret_key` - The pointer to a TariPrivateKey +/// `network` - an u8 indicating the network +/// `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions +/// as an out parameter. +/// +/// ## Returns +/// `*mut TariWalletAddress` - Returns a pointer to a TariWalletAddress +/// +/// # Safety +/// The ```private_key_destroy``` method must be called when finished with a private key to prevent a memory leak +#[no_mangle] +pub unsafe extern "C" fn tari_address_from_private_key( + secret_key: *mut TariPrivateKey, + network: c_uint, + error_out: *mut c_int, +) -> *mut TariWalletAddress { + let mut error = 0; + ptr::swap(error_out, &mut error as *mut c_int); + if secret_key.is_null() { + error = LibWalletError::from(InterfaceError::NullError("secret_key".to_string())).code; + ptr::swap(error_out, &mut error as *mut c_int); + return ptr::null_mut(); + } + let key = PublicKey::from_secret_key(&(*secret_key)); + let network = match (network as u8).try_into() { + Ok(network) => network, + Err(_) => { + error = LibWalletError::from(InterfaceError::InvalidArgument("network".to_string())).code; + ptr::swap(error_out, &mut error as *mut c_int); + return ptr::null_mut(); + }, + }; + let address = TariWalletAddress::new(key, network); + Box::into_raw(Box::new(address)) +} + +/// Creates a TariWalletAddress from a char array +/// +/// ## Arguments +/// `address` - The pointer to a char array which is hex encoded +/// `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions +/// as an out parameter. +/// +/// ## Returns +/// `*mut TariWalletAddress` - Returns a pointer to a TariWalletAddress. Note that it returns ptr::null_mut() +/// if key is null or if there was an error creating the TariWalletAddress from key +/// +/// # Safety +/// The ```public_key_destroy``` method must be called when finished with a TariWalletAddress to prevent a memory leak +#[no_mangle] +pub unsafe extern "C" fn tari_address_from_hex( + address: *const c_char, + error_out: *mut c_int, +) -> *mut TariWalletAddress { + let mut error = 0; + ptr::swap(error_out, &mut error as *mut c_int); + let key_str; + if address.is_null() { + error = LibWalletError::from(InterfaceError::NullError("key".to_string())).code; + ptr::swap(error_out, &mut error as *mut c_int); + return ptr::null_mut(); + } else { + match CStr::from_ptr(address).to_str() { + Ok(v) => { + key_str = v.to_owned(); + }, + _ => { + error = LibWalletError::from(InterfaceError::PointerError("key".to_string())).code; + ptr::swap(error_out, &mut error as *mut c_int); + return ptr::null_mut(); + }, + } + } + + let address = TariWalletAddress::from_hex(key_str.as_str()); + match address { + Ok(address) => Box::into_raw(Box::new(address)), + Err(e) => { + error!(target: LOG_TARGET, "Error creating a Tari Address from Hex: {:?}", e); + error = LibWalletError::from(e).code; + ptr::swap(error_out, &mut error as *mut c_int); + ptr::null_mut() + }, + } +} + +/// Creates a char array from a TariWalletAddress in emoji format +/// +/// ## Arguments +/// `address` - The pointer to a TariWalletAddress /// `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions /// as an out parameter. /// /// ## Returns /// `*mut c_char` - Returns a pointer to a char array. Note that it returns empty -/// if emoji is null or if there was an error creating the emoji string from TariPublicKey +/// if emoji is null or if there was an error creating the emoji string from TariWalletAddress /// /// # Safety /// The ```string_destroy``` method must be called when finished with a string from rust to prevent a memory leak #[no_mangle] -pub unsafe extern "C" fn public_key_to_emoji_id(pk: *mut TariPublicKey, error_out: *mut c_int) -> *mut c_char { +pub unsafe extern "C" fn tari_address_to_emoji_id( + address: *mut TariWalletAddress, + error_out: *mut c_int, +) -> *mut c_char { let mut error = 0; let mut result = CString::new("").expect("Blank CString will not fail."); ptr::swap(error_out, &mut error as *mut c_int); - if pk.is_null() { - error = LibWalletError::from(InterfaceError::NullError("key".to_string())).code; + if address.is_null() { + error = LibWalletError::from(InterfaceError::NullError("address".to_string())).code; ptr::swap(error_out, &mut error as *mut c_int); return CString::into_raw(result); } - - let emoji_id = EmojiId::from_public_key(&(*pk)); - result = CString::new(emoji_id.to_emoji_string().as_str()).expect("Emoji will not fail."); + let emoji_string = address.as_ref().expect("Address should not be empty").to_emoji_string(); + result = CString::new(emoji_string).expect("Emoji will not fail."); CString::into_raw(result) } -/// Creates a TariPublicKey from a char array in emoji format +/// Creates a TariWalletAddress from a char array in emoji format /// /// ## Arguments -/// `const *c_char` - The pointer to a TariPublicKey +/// `const *c_char` - The pointer to a TariWalletAddress /// `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions /// as an out parameter. /// /// ## Returns -/// `*mut c_char` - Returns a pointer to a TariPublicKey. Note that it returns null on error. +/// `*mut c_char` - Returns a pointer to a TariWalletAddress. Note that it returns null on error. /// /// # Safety -/// The ```public_key_destroy``` method must be called when finished with a TariPublicKey to prevent a memory leak +/// The ```public_key_destroy``` method must be called when finished with a TariWalletAddress to prevent a memory leak #[no_mangle] -pub unsafe extern "C" fn emoji_id_to_public_key(emoji: *const c_char, error_out: *mut c_int) -> *mut TariPublicKey { +pub unsafe extern "C" fn emoji_id_to_tari_address( + emoji: *const c_char, + error_out: *mut c_int, +) -> *mut TariWalletAddress { let mut error = 0; ptr::swap(error_out, &mut error as *mut c_int); if emoji.is_null() { @@ -1061,10 +1242,10 @@ pub unsafe extern "C" fn emoji_id_to_public_key(emoji: *const c_char, error_out: match CStr::from_ptr(emoji) .to_str() - .map_err(|_| EmojiIdError::InvalidEmoji) - .and_then(EmojiId::from_emoji_string) + .map_err(|_| TariAddressError::InvalidEmoji) + .and_then(TariAddress::from_emoji_string) { - Ok(emoji_id) => Box::into_raw(Box::new(emoji_id.to_public_key())), + Ok(address) => Box::into_raw(Box::new(address)), Err(_) => { error = LibWalletError::from(InterfaceError::InvalidEmojiId).code; ptr::swap(error_out, &mut error as *mut c_int); @@ -1085,7 +1266,7 @@ pub unsafe extern "C" fn emoji_id_to_public_key(emoji: *const c_char, error_out: /// as an out parameter. /// /// ## Returns -/// `*mut TariPrivateKey` - Returns a pointer to a TariPublicKey. Note that it returns ptr::null_mut() +/// `*mut TariPrivateKey` - Returns a pointer to a TariPrivateKey. Note that it returns ptr::null_mut() /// if bytes is null or if there was an error creating the TariPrivateKey from bytes /// /// # Safety @@ -1180,7 +1361,7 @@ pub unsafe extern "C" fn private_key_generate() -> *mut TariPrivateKey { /// as an out parameter. /// /// ## Returns -/// `*mut TariPrivateKey` - Returns a pointer to a TariPublicKey. Note that it returns ptr::null_mut() +/// `*mut TariPrivateKey` - Returns a pointer to a TariPrivateKey. Note that it returns ptr::null_mut() /// if key is null or if there was an error creating the TariPrivateKey from key /// /// # Safety @@ -1875,7 +2056,7 @@ pub unsafe extern "C" fn seed_words_destroy(seed_words: *mut TariSeedWords) { /// /// ## Arguments /// `alias` - The pointer to a char array -/// `public_key` - The pointer to a TariPublicKey +/// `address` - The pointer to a TariWalletAddress /// `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions /// as an out parameter. /// @@ -1888,7 +2069,7 @@ pub unsafe extern "C" fn seed_words_destroy(seed_words: *mut TariSeedWords) { #[no_mangle] pub unsafe extern "C" fn contact_create( alias: *const c_char, - public_key: *mut TariPublicKey, + address: *mut TariWalletAddress, error_out: *mut c_int, ) -> *mut TariContact { let mut error = 0; @@ -1911,13 +2092,13 @@ pub unsafe extern "C" fn contact_create( } } - if public_key.is_null() { - error = LibWalletError::from(InterfaceError::NullError("public_key".to_string())).code; + if address.is_null() { + error = LibWalletError::from(InterfaceError::NullError("address".to_string())).code; ptr::swap(error_out, &mut error as *mut c_int); return ptr::null_mut(); } - let contact = Contact::new(alias_string, (*public_key).clone(), None, None); + let contact = Contact::new(alias_string, (*address).clone(), None, None); Box::into_raw(Box::new(contact)) } @@ -1954,7 +2135,7 @@ pub unsafe extern "C" fn contact_get_alias(contact: *mut TariContact, error_out: CString::into_raw(a) } -/// Gets the TariPublicKey of the TariContact +/// Gets the TariWalletAddress of the TariContact /// /// ## Arguments /// `contact` - The pointer to a TariContact @@ -1962,16 +2143,16 @@ pub unsafe extern "C" fn contact_get_alias(contact: *mut TariContact, error_out: /// as an out parameter. /// /// ## Returns -/// `*mut TariPublicKey` - Returns a pointer to a TariPublicKey. Note that it returns +/// `*mut TariWalletAddress` - Returns a pointer to a TariWalletAddress. Note that it returns /// ptr::null_mut() if contact is null /// /// # Safety -/// The ```public_key_destroy``` method must be called when finished with a TariPublicKey to prevent a memory leak +/// The ```tari_address_destroy``` method must be called when finished with a TariWalletAddress to prevent a memory leak #[no_mangle] -pub unsafe extern "C" fn contact_get_public_key( +pub unsafe extern "C" fn contact_get_tari_address( contact: *mut TariContact, error_out: *mut c_int, -) -> *mut TariPublicKey { +) -> *mut TariWalletAddress { let mut error = 0; ptr::swap(error_out, &mut error as *mut c_int); if contact.is_null() { @@ -1979,7 +2160,7 @@ pub unsafe extern "C" fn contact_get_public_key( ptr::swap(error_out, &mut error as *mut c_int); return ptr::null_mut(); } - Box::into_raw(Box::new((*contact).public_key.clone())) + Box::into_raw(Box::new((*contact).address.clone())) } /// Frees memory for a TariContact @@ -2094,7 +2275,7 @@ pub unsafe extern "C" fn contacts_destroy(contacts: *mut TariContacts) { /// as an out parameter. /// /// ## Returns -/// `*mut TariPublicKey` - Returns a pointer to a TariPublicKey. Note that it returns ptr::null_mut() if +/// `*mut TariWalletAddress` - Returns a pointer to a TariWalletAddress. Note that it returns ptr::null_mut() if /// liveness_data is null. /// /// # Safety @@ -2104,7 +2285,7 @@ pub unsafe extern "C" fn contacts_destroy(contacts: *mut TariContacts) { pub unsafe extern "C" fn liveness_data_get_public_key( liveness_data: *mut TariContactsLivenessData, error_out: *mut c_int, -) -> *mut TariPublicKey { +) -> *mut TariWalletAddress { let mut error = 0; ptr::swap(error_out, &mut error as *mut c_int); if liveness_data.is_null() { @@ -2112,7 +2293,7 @@ pub unsafe extern "C" fn liveness_data_get_public_key( ptr::swap(error_out, &mut error as *mut c_int); return ptr::null_mut(); } - Box::into_raw(Box::new((*liveness_data).public_key().clone())) + Box::into_raw(Box::new((*liveness_data).address().clone())) } /// Gets the latency in milli-seconds (ms) from a TariContactsLivenessData @@ -2585,7 +2766,7 @@ pub unsafe extern "C" fn completed_transaction_get_transaction_id( (*transaction).tx_id.as_u64() as c_ulonglong } -/// Gets the destination TariPublicKey of a TariCompletedTransaction +/// Gets the destination TariWalletAddress of a TariCompletedTransaction /// /// ## Arguments /// `transaction` - The pointer to a TariCompletedTransaction @@ -2593,16 +2774,16 @@ pub unsafe extern "C" fn completed_transaction_get_transaction_id( /// as an out parameter. /// /// ## Returns -/// `*mut TariPublicKey` - Returns the destination TariPublicKey, note that it will be +/// `*mut TariWalletAddress` - Returns the destination TariWalletAddress, note that it will be /// ptr::null_mut() if transaction is null /// /// # Safety -/// The ```public_key_destroy``` method must be called when finished with a TariPublicKey to prevent a memory leak +/// The ```public_key_destroy``` method must be called when finished with a TariWalletAddress to prevent a memory leak #[no_mangle] pub unsafe extern "C" fn completed_transaction_get_destination_public_key( transaction: *mut TariCompletedTransaction, error_out: *mut c_int, -) -> *mut TariPublicKey { +) -> *mut TariWalletAddress { let mut error = 0; ptr::swap(error_out, &mut error as *mut c_int); if transaction.is_null() { @@ -2610,8 +2791,8 @@ pub unsafe extern "C" fn completed_transaction_get_destination_public_key( ptr::swap(error_out, &mut error as *mut c_int); return ptr::null_mut(); } - let m = (*transaction).destination_public_key.clone(); - Box::into_raw(Box::new(m)) + let address = (*transaction).destination_address.clone(); + Box::into_raw(Box::new(address)) } /// Gets the TariTransactionKernel of a TariCompletedTransaction @@ -2668,7 +2849,7 @@ pub unsafe extern "C" fn completed_transaction_get_transaction_kernel( Box::into_raw(Box::new(x)) } -/// Gets the source TariPublicKey of a TariCompletedTransaction +/// Gets the source TariWalletAddress of a TariCompletedTransaction /// /// ## Arguments /// `transaction` - The pointer to a TariCompletedTransaction @@ -2676,16 +2857,16 @@ pub unsafe extern "C" fn completed_transaction_get_transaction_kernel( /// as an out parameter. /// /// ## Returns -/// `*mut TariPublicKey` - Returns the source TariPublicKey, note that it will be +/// `*mut TariWalletAddress` - Returns the source TariWalletAddress, note that it will be /// ptr::null_mut() if transaction is null /// /// # Safety -/// The ```public_key_destroy``` method must be called when finished with a TariPublicKey to prevent a memory leak +/// The ```tari_address_destroy``` method must be called when finished with a TariWalletAddress to prevent a memory leak #[no_mangle] pub unsafe extern "C" fn completed_transaction_get_source_public_key( transaction: *mut TariCompletedTransaction, error_out: *mut c_int, -) -> *mut TariPublicKey { +) -> *mut TariWalletAddress { let mut error = 0; ptr::swap(error_out, &mut error as *mut c_int); if transaction.is_null() { @@ -2693,7 +2874,7 @@ pub unsafe extern "C" fn completed_transaction_get_source_public_key( ptr::swap(error_out, &mut error as *mut c_int); return ptr::null_mut(); } - let m = (*transaction).source_public_key.clone(); + let m = (*transaction).source_address.clone(); Box::into_raw(Box::new(m)) } @@ -3007,7 +3188,7 @@ pub unsafe extern "C" fn pending_outbound_transaction_get_transaction_id( (*transaction).tx_id.as_u64() as c_ulonglong } -/// Gets the destination TariPublicKey of a TariPendingOutboundTransaction +/// Gets the destination TariWalletAddress of a TariPendingOutboundTransaction /// /// ## Arguments /// `transaction` - The pointer to a TariPendingOutboundTransaction @@ -3015,16 +3196,16 @@ pub unsafe extern "C" fn pending_outbound_transaction_get_transaction_id( /// as an out parameter. /// /// ## Returns -/// `*mut TariPublicKey` - Returns the destination TariPublicKey, note that it will be +/// `*mut TariWalletAddress` - Returns the destination TariWalletAddress, note that it will be /// ptr::null_mut() if transaction is null /// /// # Safety -/// The ```public_key_destroy``` method must be called when finished with a TariPublicKey to prevent a memory leak +/// The ```public_key_destroy``` method must be called when finished with a TariWalletAddress to prevent a memory leak #[no_mangle] pub unsafe extern "C" fn pending_outbound_transaction_get_destination_public_key( transaction: *mut TariPendingOutboundTransaction, error_out: *mut c_int, -) -> *mut TariPublicKey { +) -> *mut TariWalletAddress { let mut error = 0; ptr::swap(error_out, &mut error as *mut c_int); if transaction.is_null() { @@ -3032,7 +3213,7 @@ pub unsafe extern "C" fn pending_outbound_transaction_get_destination_public_key ptr::swap(error_out, &mut error as *mut c_int); return ptr::null_mut(); } - let m = (*transaction).destination_public_key.clone(); + let m = (*transaction).destination_address.clone(); Box::into_raw(Box::new(m)) } @@ -3241,7 +3422,7 @@ pub unsafe extern "C" fn pending_inbound_transaction_get_transaction_id( (*transaction).tx_id.as_u64() as c_ulonglong } -/// Gets the source TariPublicKey of a TariPendingInboundTransaction +/// Gets the source TariWalletAddress of a TariPendingInboundTransaction /// /// ## Arguments /// `transaction` - The pointer to a TariPendingInboundTransaction @@ -3249,16 +3430,16 @@ pub unsafe extern "C" fn pending_inbound_transaction_get_transaction_id( /// as an out parameter. /// /// ## Returns -/// `*mut TariPublicKey` - Returns a pointer to the source TariPublicKey, note that it will be +/// `*mut TariWalletAddress` - Returns a pointer to the source TariWalletAddress, note that it will be /// ptr::null_mut() if transaction is null /// /// # Safety -/// The ```public_key_destroy``` method must be called when finished with a TariPublicKey to prevent a memory leak +/// The ```public_key_destroy``` method must be called when finished with a TariWalletAddress to prevent a memory leak #[no_mangle] pub unsafe extern "C" fn pending_inbound_transaction_get_source_public_key( transaction: *mut TariPendingInboundTransaction, error_out: *mut c_int, -) -> *mut TariPublicKey { +) -> *mut TariWalletAddress { let mut error = 0; ptr::swap(error_out, &mut error as *mut c_int); if transaction.is_null() { @@ -3266,7 +3447,7 @@ pub unsafe extern "C" fn pending_inbound_transaction_get_source_public_key( ptr::swap(error_out, &mut error as *mut c_int); return ptr::null_mut(); } - let m = (*transaction).source_public_key.clone(); + let m = (*transaction).source_address.clone(); Box::into_raw(Box::new(m)) } @@ -4399,6 +4580,7 @@ pub unsafe extern "C" fn wallet_create( warn!(target: LOG_TARGET, "Could not save tor identity to db: {:?}", e); } } + let wallet_address = TariAddress::new(w.comms.node_identity().public_key().clone(), w.network.as_network()); // Start Callback Handler let callback_handler = CallbackHandler::new( TransactionDatabase::new(transaction_backend), @@ -4407,7 +4589,7 @@ pub unsafe extern "C" fn wallet_create( w.output_manager_service.clone(), w.dht_service.subscribe_dht_events(), w.comms.shutdown_signal(), - w.comms.node_identity().public_key().clone(), + wallet_address, w.wallet_connectivity.get_connectivity_status_watch(), w.contacts_service.get_contacts_liveness_event_stream(), callback_received_transaction, @@ -5102,7 +5284,7 @@ pub unsafe extern "C" fn wallet_remove_contact( (*wallet) .wallet .contacts_service - .remove_contact((*contact).public_key.clone()), + .remove_contact((*contact).address.clone()), ) { Ok(_) => true, Err(e) => { @@ -5239,7 +5421,7 @@ pub unsafe extern "C" fn balance_destroy(balance: *mut TariBalance) { /// /// ## Arguments /// `wallet` - The TariWallet pointer -/// `dest_public_key` - The TariPublicKey pointer of the peer +/// `destination` - The TariWalletAddress pointer of the peer /// `amount` - The amount /// `commitments` - A `TariVector` of "strings", tagged as `TariTypeTag::String`, containing commitment's hex values /// (see `Commitment::to_hex()`) @@ -5256,7 +5438,7 @@ pub unsafe extern "C" fn balance_destroy(balance: *mut TariBalance) { #[no_mangle] pub unsafe extern "C" fn wallet_send_transaction( wallet: *mut TariWallet, - dest_public_key: *mut TariPublicKey, + destination: *mut TariWalletAddress, amount: c_ulonglong, commitments: *mut TariVector, fee_per_gram: c_ulonglong, @@ -5272,7 +5454,7 @@ pub unsafe extern "C" fn wallet_send_transaction( return 0; } - if dest_public_key.is_null() { + if destination.is_null() { error = LibWalletError::from(InterfaceError::NullError("dest_public_key".to_string())).code; ptr::swap(error_out, &mut error as *mut c_int); return 0; @@ -5322,7 +5504,7 @@ pub unsafe extern "C" fn wallet_send_transaction( .wallet .transaction_service .send_one_sided_to_stealth_address_transaction( - (*dest_public_key).clone(), + (*destination).clone(), MicroTari::from(amount), selection_criteria, OutputFeatures::default(), @@ -5341,7 +5523,7 @@ pub unsafe extern "C" fn wallet_send_transaction( match (*wallet) .runtime .block_on((*wallet).wallet.transaction_service.send_transaction( - (*dest_public_key).clone(), + (*destination).clone(), MicroTari::from(amount), selection_criteria, OutputFeatures::default(), @@ -5803,14 +5985,18 @@ pub unsafe extern "C" fn wallet_get_cancelled_transactions( for tx in completed_transactions.values() { completed.push(tx.clone()); } + let wallet_address = TariAddress::new( + (*wallet).wallet.comms.node_identity().public_key().clone(), + (*wallet).wallet.network.as_network(), + ); for tx in inbound_transactions.values() { let mut inbound_tx = CompletedTransaction::from(tx.clone()); - inbound_tx.destination_public_key = (*wallet).wallet.comms.node_identity().public_key().clone(); + inbound_tx.destination_address = wallet_address.clone(); completed.push(inbound_tx); } for tx in outbound_transactions.values() { let mut outbound_tx = CompletedTransaction::from(tx.clone()); - outbound_tx.source_public_key = (*wallet).wallet.comms.node_identity().public_key().clone(); + outbound_tx.source_address = wallet_address.clone(); completed.push(outbound_tx); } @@ -6081,10 +6267,11 @@ pub unsafe extern "C" fn wallet_get_cancelled_transaction_by_id( return ptr::null_mut(); }, }; - + let network = (*wallet).wallet.network.as_network(); + let address = TariWalletAddress::new((*wallet).wallet.comms.node_identity().public_key().clone(), network); if let Some(tx) = outbound_transactions.remove(&transaction_id) { let mut outbound_tx = CompletedTransaction::from(tx); - outbound_tx.source_public_key = (*wallet).wallet.comms.node_identity().public_key().clone(); + outbound_tx.source_address = address; transaction = Some(outbound_tx); } else { let mut inbound_transactions = match (*wallet).runtime.block_on( @@ -6102,7 +6289,7 @@ pub unsafe extern "C" fn wallet_get_cancelled_transaction_by_id( }; if let Some(tx) = inbound_transactions.remove(&transaction_id) { let mut inbound_tx = CompletedTransaction::from(tx); - inbound_tx.destination_public_key = (*wallet).wallet.comms.node_identity().public_key().clone(); + inbound_tx.destination_address = address; transaction = Some(inbound_tx); } } @@ -6124,7 +6311,7 @@ pub unsafe extern "C" fn wallet_get_cancelled_transaction_by_id( ptr::null_mut() } -/// Get the TariPublicKey from a TariWallet +/// Get the TariWalletAddress from a TariWallet /// /// ## Arguments /// `wallet` - The TariWallet pointer @@ -6132,13 +6319,16 @@ pub unsafe extern "C" fn wallet_get_cancelled_transaction_by_id( /// as an out parameter. /// /// ## Returns -/// `*mut TariPublicKey` - returns the public key, note that ptr::null_mut() is returned +/// `*mut TariWalletAddress` - returns the address, note that ptr::null_mut() is returned /// if wc is null /// /// # Safety -/// The ```public_key_destroy``` method must be called when finished with a TariPublicKey to prevent a memory leak +/// The ```tari_address_destroy``` method must be called when finished with a TariWalletAddress to prevent a memory leak #[no_mangle] -pub unsafe extern "C" fn wallet_get_public_key(wallet: *mut TariWallet, error_out: *mut c_int) -> *mut TariPublicKey { +pub unsafe extern "C" fn wallet_get_tari_address( + wallet: *mut TariWallet, + error_out: *mut c_int, +) -> *mut TariWalletAddress { let mut error = 0; ptr::swap(error_out, &mut error as *mut c_int); if wallet.is_null() { @@ -6146,8 +6336,10 @@ pub unsafe extern "C" fn wallet_get_public_key(wallet: *mut TariWallet, error_ou ptr::swap(error_out, &mut error as *mut c_int); return ptr::null_mut(); } + let network = (*wallet).wallet.network.as_network(); let pk = (*wallet).wallet.comms.node_identity().public_key().clone(); - Box::into_raw(Box::new(pk)) + let address = TariWalletAddress::new(pk, network); + Box::into_raw(Box::new(address)) } /// Import an external UTXO into the wallet as a non-rewindable (i.e. non-recoverable) output. This will add a spendable @@ -6157,7 +6349,7 @@ pub unsafe extern "C" fn wallet_get_public_key(wallet: *mut TariWallet, error_ou /// `wallet` - The TariWallet pointer /// `amount` - The value of the UTXO in MicroTari /// `spending_key` - The private spending key -/// `source_public_key` - The public key of the source of the transaction +/// `source_address` - The tari address of the source of the transaction /// `features` - Options for an output's structure or use /// `metadata_signature` - UTXO signature with the script offset private key, k_O /// `sender_offset_public_key` - Tari script offset pubkey, K_O @@ -6181,7 +6373,7 @@ pub unsafe extern "C" fn wallet_import_external_utxo_as_non_rewindable( wallet: *mut TariWallet, amount: c_ulonglong, spending_key: *mut TariPrivateKey, - source_public_key: *mut TariPublicKey, + source_address: *mut TariWalletAddress, features: *mut TariOutputFeatures, metadata_signature: *mut TariCommitmentSignature, sender_offset_public_key: *mut TariPublicKey, @@ -6206,10 +6398,10 @@ pub unsafe extern "C" fn wallet_import_external_utxo_as_non_rewindable( return 0; } - let source_public_key = if source_public_key.is_null() { - TariPublicKey::default() + let source_address = if source_address.is_null() { + TariWalletAddress::default() } else { - (*source_public_key).clone() + (*source_address).clone() }; if metadata_signature.is_null() { @@ -6284,7 +6476,7 @@ pub unsafe extern "C" fn wallet_import_external_utxo_as_non_rewindable( &(*spending_key).clone(), script!(Nop), inputs!(public_script_key), - &source_public_key, + source_address, features, message_string, (*metadata_signature).clone(), @@ -8027,27 +8219,36 @@ mod test { let private_key = private_key_generate(); let public_key = public_key_from_private_key(private_key, error_ptr); assert_eq!(error, 0); + let address = tari_address_from_private_key(private_key, 0x26, error_ptr); + assert_eq!(error, 0); let private_bytes = private_key_get_bytes(private_key, error_ptr); assert_eq!(error, 0); let public_bytes = public_key_get_bytes(public_key, error_ptr); assert_eq!(error, 0); + let address_bytes = tari_address_get_bytes(address, error_ptr); + assert_eq!(error, 0); let private_key_length = byte_vector_get_length(private_bytes, error_ptr); assert_eq!(error, 0); let public_key_length = byte_vector_get_length(public_bytes, error_ptr); assert_eq!(error, 0); + let tari_address_length = byte_vector_get_length(address_bytes, error_ptr); + assert_eq!(error, 0); assert_eq!(private_key_length, 32); assert_eq!(public_key_length, 32); + assert_eq!(tari_address_length, 33); assert_ne!((*private_bytes), (*public_bytes)); - let emoji = public_key_to_emoji_id(public_key, error_ptr) as *mut c_char; + let emoji = tari_address_to_emoji_id(address, error_ptr) as *mut c_char; let emoji_str = CStr::from_ptr(emoji).to_str().unwrap(); - assert!(EmojiId::from_emoji_string(emoji_str).is_ok()); - let pk_emoji = emoji_id_to_public_key(emoji, error_ptr); - assert_eq!((*public_key), (*pk_emoji)); + assert!(TariAddress::from_emoji_string(emoji_str).is_ok()); + let address_emoji = emoji_id_to_tari_address(emoji, error_ptr); + assert_eq!((*address), (*address_emoji)); private_key_destroy(private_key); public_key_destroy(public_key); - public_key_destroy(pk_emoji); + tari_address_destroy(address_emoji); + tari_address_destroy(address); byte_vector_destroy(public_bytes); byte_vector_destroy(private_bytes); + byte_vector_destroy(address_bytes); } } @@ -8261,20 +8462,20 @@ mod test { let mut error = 0; let error_ptr = &mut error as *mut c_int; let test_contact_private_key = private_key_generate(); - let test_contact_public_key = public_key_from_private_key(test_contact_private_key, error_ptr); + let test_address = tari_address_from_private_key(test_contact_private_key, 0x10, error_ptr); let test_str = "Test Contact"; let test_contact_str = CString::new(test_str).unwrap(); let test_contact_alias: *const c_char = CString::into_raw(test_contact_str) as *const c_char; - let test_contact = contact_create(test_contact_alias, test_contact_public_key, error_ptr); + let test_contact = contact_create(test_contact_alias, test_address, error_ptr); let alias = contact_get_alias(test_contact, error_ptr); let alias_string = CString::from_raw(alias).to_str().unwrap().to_owned(); assert_eq!(alias_string, test_str); - let contact_key = contact_get_public_key(test_contact, error_ptr); - let contact_key_bytes = public_key_get_bytes(contact_key, error_ptr); + let contact_address = contact_get_tari_address(test_contact, error_ptr); + let contact_key_bytes = tari_address_get_bytes(contact_address, error_ptr); let contact_bytes_len = byte_vector_get_length(contact_key_bytes, error_ptr); - assert_eq!(contact_bytes_len, 32); + assert_eq!(contact_bytes_len, 33); contact_destroy(test_contact); - public_key_destroy(test_contact_public_key); + tari_address_destroy(test_address); private_key_destroy(test_contact_private_key); string_destroy(test_contact_alias as *mut c_char); byte_vector_destroy(contact_key_bytes); @@ -8287,11 +8488,11 @@ mod test { let mut error = 0; let error_ptr = &mut error as *mut c_int; let test_contact_private_key = private_key_generate(); - let test_contact_public_key = public_key_from_private_key(test_contact_private_key, error_ptr); + let test_contact_address = tari_address_from_private_key(test_contact_private_key, 0x00, error_ptr); let test_str = "Test Contact"; let test_contact_str = CString::new(test_str).unwrap(); let test_contact_alias: *const c_char = CString::into_raw(test_contact_str) as *const c_char; - let mut _test_contact = contact_create(ptr::null_mut(), test_contact_public_key, error_ptr); + let mut _test_contact = contact_create(ptr::null_mut(), test_contact_address, error_ptr); assert_eq!( error, LibWalletError::from(InterfaceError::NullError("alias_ptr".to_string())).code @@ -8306,7 +8507,7 @@ mod test { error, LibWalletError::from(InterfaceError::NullError("contact_ptr".to_string())).code ); - let _contact_key = contact_get_public_key(ptr::null_mut(), error_ptr); + let _contact_address = contact_get_tari_address(ptr::null_mut(), error_ptr); assert_eq!( error, LibWalletError::from(InterfaceError::NullError("contact_ptr".to_string())).code @@ -8323,7 +8524,7 @@ mod test { ); assert_eq!(contact_bytes_len, 0); contact_destroy(_test_contact); - public_key_destroy(test_contact_public_key); + tari_address_destroy(test_contact_address); private_key_destroy(test_contact_private_key); string_destroy(test_contact_alias as *mut c_char); byte_vector_destroy(contact_key_bytes); @@ -8994,7 +9195,7 @@ mod test { let amount = utxo_1.value.as_u64(); let spending_key_ptr = Box::into_raw(Box::new(utxo_1.spending_key)); let features_ptr = Box::into_raw(Box::new(utxo_1.features.clone())); - let source_public_key_ptr = Box::into_raw(Box::new(TariPublicKey::default())); + let source_address_ptr = Box::into_raw(Box::new(TariWalletAddress::default())); let metadata_signature_ptr = Box::into_raw(Box::new(utxo_1.metadata_signature)); let sender_offset_public_key_ptr = Box::into_raw(Box::new(utxo_1.sender_offset_public_key)); let script_private_key_ptr = Box::into_raw(Box::new(utxo_1.script_private_key)); @@ -9007,7 +9208,7 @@ mod test { wallet_ptr, amount, spending_key_ptr, - source_public_key_ptr, + source_address_ptr, features_ptr, metadata_signature_ptr, sender_offset_public_key_ptr, @@ -9028,7 +9229,7 @@ mod test { let _sender_offset_public_key = Box::from_raw(sender_offset_public_key_ptr); let _metadata_signature = Box::from_raw(metadata_signature_ptr); let _features = Box::from_raw(features_ptr); - let _source_public_key = Box::from_raw(source_public_key_ptr); + let _source_address = Box::from_raw(source_address_ptr); let _spending_key = Box::from_raw(spending_key_ptr); let _base_node_peer_public_key = Box::from_raw(base_node_peer_public_key_ptr); @@ -9148,7 +9349,7 @@ mod test { let seed_words = wallet_get_seed_words(wallet, error_ptr); assert_eq!(error, 0); - let public_key = wallet_get_public_key(wallet, error_ptr); + let public_address = wallet_get_tari_address(wallet, error_ptr); assert_eq!(error, 0); // use seed words to create recovery wallet @@ -9203,11 +9404,11 @@ mod test { let recovered_seed_words = wallet_get_seed_words(recovered_wallet, error_ptr); assert_eq!(error, 0); - let recovered_public_key = wallet_get_public_key(recovered_wallet, error_ptr); + let recovered_address = wallet_get_tari_address(recovered_wallet, error_ptr); assert_eq!(error, 0); assert_eq!(*seed_words, *recovered_seed_words); - assert_eq!(*public_key, *recovered_public_key); + assert_eq!(*public_address, *recovered_address); // TODO: Clean up memory leaks please } } diff --git a/base_layer/wallet_ffi/wallet.h b/base_layer/wallet_ffi/wallet.h index bb422edb05..83ee5fb7b8 100644 --- a/base_layer/wallet_ffi/wallet.h +++ b/base_layer/wallet_ffi/wallet.h @@ -146,6 +146,8 @@ struct RistrettoPublicKey; */ struct RistrettoSecretKey; +struct TariAddress; + struct TariCompletedTransactions; struct TariContacts; @@ -204,6 +206,8 @@ typedef struct RistrettoSecretKey PrivateKey; typedef PrivateKey TariPrivateKey; +typedef struct TariAddress TariWalletAddress; + /** * # A Commitment signature implementation on Ristretto * @@ -655,39 +659,127 @@ TariPublicKey *public_key_from_hex(const char *key, int *error_out); /** - * Creates a char array from a TariPublicKey in emoji format + * -------------------------------------------------------------------------------------------- /// + * -------------------------------- Tari Address ---------------------------------------------- /// + * Creates a TariWalletAddress from a ByteVector * * ## Arguments - * `pk` - The pointer to a TariPublicKey + * `bytes` - The pointer to a ByteVector + * `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions + * as an out parameter. + * + * ## Returns + * `TariWalletAddress` - Returns a public key. Note that it will be ptr::null_mut() if bytes is null or + * if there was an error with the contents of bytes + * + * # Safety + * The ```public_key_destroy``` function must be called when finished with a TariWalletAddress to prevent a memory leak + */ +TariWalletAddress *tari_address_create(struct ByteVector *bytes, + int *error_out); + +/** + * Frees memory for a TariWalletAddress + * + * ## Arguments + * `pk` - The pointer to a TariWalletAddress + * + * ## Returns + * `()` - Does not return a value, equivalent to void in C + * + * # Safety + * None + */ +void tari_address_destroy(TariWalletAddress *address); + +/** + * Gets a ByteVector from a TariWalletAddress + * + * ## Arguments + * `address` - The pointer to a TariWalletAddress + * `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions + * as an out parameter. + * + * ## Returns + * `*mut ByteVector` - Returns a pointer to a ByteVector. Note that it returns ptr::null_mut() if address is null + * + * # Safety + * The ```byte_vector_destroy``` function must be called when finished with the ByteVector to prevent a memory leak. + */ +struct ByteVector *tari_address_get_bytes(TariWalletAddress *address, + int *error_out); + +/** + * Creates a TariWalletAddress from a TariPrivateKey + * + * ## Arguments + * `secret_key` - The pointer to a TariPrivateKey + * `network` - an u8 indicating the network + * `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions + * as an out parameter. + * + * ## Returns + * `*mut TariWalletAddress` - Returns a pointer to a TariWalletAddress + * + * # Safety + * The ```private_key_destroy``` method must be called when finished with a private key to prevent a memory leak + */ +TariWalletAddress *tari_address_from_private_key(TariPrivateKey *secret_key, + unsigned int network, + int *error_out); + +/** + * Creates a TariWalletAddress from a char array + * + * ## Arguments + * `address` - The pointer to a char array which is hex encoded + * `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions + * as an out parameter. + * + * ## Returns + * `*mut TariWalletAddress` - Returns a pointer to a TariWalletAddress. Note that it returns ptr::null_mut() + * if key is null or if there was an error creating the TariWalletAddress from key + * + * # Safety + * The ```public_key_destroy``` method must be called when finished with a TariWalletAddress to prevent a memory leak + */ +TariWalletAddress *tari_address_from_hex(const char *address, + int *error_out); + +/** + * Creates a char array from a TariWalletAddress in emoji format + * + * ## Arguments + * `address` - The pointer to a TariWalletAddress * `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions * as an out parameter. * * ## Returns * `*mut c_char` - Returns a pointer to a char array. Note that it returns empty - * if emoji is null or if there was an error creating the emoji string from TariPublicKey + * if emoji is null or if there was an error creating the emoji string from TariWalletAddress * * # Safety * The ```string_destroy``` method must be called when finished with a string from rust to prevent a memory leak */ -char *public_key_to_emoji_id(TariPublicKey *pk, - int *error_out); +char *tari_address_to_emoji_id(TariWalletAddress *address, + int *error_out); /** - * Creates a TariPublicKey from a char array in emoji format + * Creates a TariWalletAddress from a char array in emoji format * * ## Arguments - * `const *c_char` - The pointer to a TariPublicKey + * `const *c_char` - The pointer to a TariWalletAddress * `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions * as an out parameter. * * ## Returns - * `*mut c_char` - Returns a pointer to a TariPublicKey. Note that it returns null on error. + * `*mut c_char` - Returns a pointer to a TariWalletAddress. Note that it returns null on error. * * # Safety - * The ```public_key_destroy``` method must be called when finished with a TariPublicKey to prevent a memory leak + * The ```public_key_destroy``` method must be called when finished with a TariWalletAddress to prevent a memory leak */ -TariPublicKey *emoji_id_to_public_key(const char *emoji, - int *error_out); +TariWalletAddress *emoji_id_to_tari_address(const char *emoji, + int *error_out); /** * -------------------------------------------------------------------------------------------- /// @@ -700,7 +792,7 @@ TariPublicKey *emoji_id_to_public_key(const char *emoji, * as an out parameter. * * ## Returns - * `*mut TariPrivateKey` - Returns a pointer to a TariPublicKey. Note that it returns ptr::null_mut() + * `*mut TariPrivateKey` - Returns a pointer to a TariPrivateKey. Note that it returns ptr::null_mut() * if bytes is null or if there was an error creating the TariPrivateKey from bytes * * # Safety @@ -764,7 +856,7 @@ TariPrivateKey *private_key_generate(void); * as an out parameter. * * ## Returns - * `*mut TariPrivateKey` - Returns a pointer to a TariPublicKey. Note that it returns ptr::null_mut() + * `*mut TariPrivateKey` - Returns a pointer to a TariPrivateKey. Note that it returns ptr::null_mut() * if key is null or if there was an error creating the TariPrivateKey from key * * # Safety @@ -1056,7 +1148,7 @@ void seed_words_destroy(struct TariSeedWords *seed_words); * * ## Arguments * `alias` - The pointer to a char array - * `public_key` - The pointer to a TariPublicKey + * `address` - The pointer to a TariWalletAddress * `error_out` - Pointer to an int which will be modified to an error code should one occur, may not be null. Functions * as an out parameter. * @@ -1068,7 +1160,7 @@ void seed_words_destroy(struct TariSeedWords *seed_words); * The ```contact_destroy``` method must be called when finished with a TariContact */ TariContact *contact_create(const char *alias, - TariPublicKey *public_key, + TariWalletAddress *address, int *error_out); /** @@ -1090,7 +1182,7 @@ char *contact_get_alias(TariContact *contact, int *error_out); /** - * Gets the TariPublicKey of the TariContact + * Gets the TariWalletAddress of the TariContact * * ## Arguments * `contact` - The pointer to a TariContact @@ -1098,14 +1190,14 @@ char *contact_get_alias(TariContact *contact, * as an out parameter. * * ## Returns - * `*mut TariPublicKey` - Returns a pointer to a TariPublicKey. Note that it returns + * `*mut TariWalletAddress` - Returns a pointer to a TariWalletAddress. Note that it returns * ptr::null_mut() if contact is null * * # Safety - * The ```public_key_destroy``` method must be called when finished with a TariPublicKey to prevent a memory leak + * The ```tari_address_destroy``` method must be called when finished with a TariWalletAddress to prevent a memory leak */ -TariPublicKey *contact_get_public_key(TariContact *contact, - int *error_out); +TariWalletAddress *contact_get_tari_address(TariContact *contact, + int *error_out); /** * Frees memory for a TariContact @@ -1185,15 +1277,15 @@ void contacts_destroy(struct TariContacts *contacts); * as an out parameter. * * ## Returns - * `*mut TariPublicKey` - Returns a pointer to a TariPublicKey. Note that it returns ptr::null_mut() if + * `*mut TariWalletAddress` - Returns a pointer to a TariWalletAddress. Note that it returns ptr::null_mut() if * liveness_data is null. * * # Safety * The ```liveness_data_destroy``` method must be called when finished with a TariContactsLivenessData to prevent a * memory leak */ -TariPublicKey *liveness_data_get_public_key(TariContactsLivenessData *liveness_data, - int *error_out); +TariWalletAddress *liveness_data_get_public_key(TariContactsLivenessData *liveness_data, + int *error_out); /** * Gets the latency in milli-seconds (ms) from a TariContactsLivenessData @@ -1481,7 +1573,7 @@ unsigned long long completed_transaction_get_transaction_id(TariCompletedTransac int *error_out); /** - * Gets the destination TariPublicKey of a TariCompletedTransaction + * Gets the destination TariWalletAddress of a TariCompletedTransaction * * ## Arguments * `transaction` - The pointer to a TariCompletedTransaction @@ -1489,14 +1581,14 @@ unsigned long long completed_transaction_get_transaction_id(TariCompletedTransac * as an out parameter. * * ## Returns - * `*mut TariPublicKey` - Returns the destination TariPublicKey, note that it will be + * `*mut TariWalletAddress` - Returns the destination TariWalletAddress, note that it will be * ptr::null_mut() if transaction is null * * # Safety - * The ```public_key_destroy``` method must be called when finished with a TariPublicKey to prevent a memory leak + * The ```public_key_destroy``` method must be called when finished with a TariWalletAddress to prevent a memory leak */ -TariPublicKey *completed_transaction_get_destination_public_key(TariCompletedTransaction *transaction, - int *error_out); +TariWalletAddress *completed_transaction_get_destination_public_key(TariCompletedTransaction *transaction, + int *error_out); /** * Gets the TariTransactionKernel of a TariCompletedTransaction @@ -1519,7 +1611,7 @@ TariTransactionKernel *completed_transaction_get_transaction_kernel(TariComplete int *error_out); /** - * Gets the source TariPublicKey of a TariCompletedTransaction + * Gets the source TariWalletAddress of a TariCompletedTransaction * * ## Arguments * `transaction` - The pointer to a TariCompletedTransaction @@ -1527,14 +1619,14 @@ TariTransactionKernel *completed_transaction_get_transaction_kernel(TariComplete * as an out parameter. * * ## Returns - * `*mut TariPublicKey` - Returns the source TariPublicKey, note that it will be + * `*mut TariWalletAddress` - Returns the source TariWalletAddress, note that it will be * ptr::null_mut() if transaction is null * * # Safety - * The ```public_key_destroy``` method must be called when finished with a TariPublicKey to prevent a memory leak + * The ```tari_address_destroy``` method must be called when finished with a TariWalletAddress to prevent a memory leak */ -TariPublicKey *completed_transaction_get_source_public_key(TariCompletedTransaction *transaction, - int *error_out); +TariWalletAddress *completed_transaction_get_source_public_key(TariCompletedTransaction *transaction, + int *error_out); /** * Gets the status of a TariCompletedTransaction @@ -1727,7 +1819,7 @@ unsigned long long pending_outbound_transaction_get_transaction_id(TariPendingOu int *error_out); /** - * Gets the destination TariPublicKey of a TariPendingOutboundTransaction + * Gets the destination TariWalletAddress of a TariPendingOutboundTransaction * * ## Arguments * `transaction` - The pointer to a TariPendingOutboundTransaction @@ -1735,14 +1827,14 @@ unsigned long long pending_outbound_transaction_get_transaction_id(TariPendingOu * as an out parameter. * * ## Returns - * `*mut TariPublicKey` - Returns the destination TariPublicKey, note that it will be + * `*mut TariWalletAddress` - Returns the destination TariWalletAddress, note that it will be * ptr::null_mut() if transaction is null * * # Safety - * The ```public_key_destroy``` method must be called when finished with a TariPublicKey to prevent a memory leak + * The ```public_key_destroy``` method must be called when finished with a TariWalletAddress to prevent a memory leak */ -TariPublicKey *pending_outbound_transaction_get_destination_public_key(TariPendingOutboundTransaction *transaction, - int *error_out); +TariWalletAddress *pending_outbound_transaction_get_destination_public_key(TariPendingOutboundTransaction *transaction, + int *error_out); /** * Gets the amount of a TariPendingOutboundTransaction @@ -1874,7 +1966,7 @@ unsigned long long pending_inbound_transaction_get_transaction_id(TariPendingInb int *error_out); /** - * Gets the source TariPublicKey of a TariPendingInboundTransaction + * Gets the source TariWalletAddress of a TariPendingInboundTransaction * * ## Arguments * `transaction` - The pointer to a TariPendingInboundTransaction @@ -1882,14 +1974,14 @@ unsigned long long pending_inbound_transaction_get_transaction_id(TariPendingInb * as an out parameter. * * ## Returns - * `*mut TariPublicKey` - Returns a pointer to the source TariPublicKey, note that it will be + * `*mut TariWalletAddress` - Returns a pointer to the source TariWalletAddress, note that it will be * ptr::null_mut() if transaction is null * * # Safety - * The ```public_key_destroy``` method must be called when finished with a TariPublicKey to prevent a memory leak + * The ```public_key_destroy``` method must be called when finished with a TariWalletAddress to prevent a memory leak */ -TariPublicKey *pending_inbound_transaction_get_source_public_key(TariPendingInboundTransaction *transaction, - int *error_out); +TariWalletAddress *pending_inbound_transaction_get_source_public_key(TariPendingInboundTransaction *transaction, + int *error_out); /** * Gets the amount of a TariPendingInboundTransaction @@ -2633,7 +2725,7 @@ void balance_destroy(TariBalance *balance); * * ## Arguments * `wallet` - The TariWallet pointer - * `dest_public_key` - The TariPublicKey pointer of the peer + * `destination` - The TariWalletAddress pointer of the peer * `amount` - The amount * `commitments` - A `TariVector` of "strings", tagged as `TariTypeTag::String`, containing commitment's hex values * (see `Commitment::to_hex()`) @@ -2649,7 +2741,7 @@ void balance_destroy(TariBalance *balance); * None */ unsigned long long wallet_send_transaction(struct TariWallet *wallet, - TariPublicKey *dest_public_key, + TariWalletAddress *destination, unsigned long long amount, struct TariVector *commitments, unsigned long long fee_per_gram, @@ -2906,7 +2998,7 @@ TariCompletedTransaction *wallet_get_cancelled_transaction_by_id(struct TariWall int *error_out); /** - * Get the TariPublicKey from a TariWallet + * Get the TariWalletAddress from a TariWallet * * ## Arguments * `wallet` - The TariWallet pointer @@ -2914,14 +3006,14 @@ TariCompletedTransaction *wallet_get_cancelled_transaction_by_id(struct TariWall * as an out parameter. * * ## Returns - * `*mut TariPublicKey` - returns the public key, note that ptr::null_mut() is returned + * `*mut TariWalletAddress` - returns the address, note that ptr::null_mut() is returned * if wc is null * * # Safety - * The ```public_key_destroy``` method must be called when finished with a TariPublicKey to prevent a memory leak + * The ```tari_address_destroy``` method must be called when finished with a TariWalletAddress to prevent a memory leak */ -TariPublicKey *wallet_get_public_key(struct TariWallet *wallet, - int *error_out); +TariWalletAddress *wallet_get_tari_address(struct TariWallet *wallet, + int *error_out); /** * Import an external UTXO into the wallet as a non-rewindable (i.e. non-recoverable) output. This will add a spendable @@ -2931,7 +3023,7 @@ TariPublicKey *wallet_get_public_key(struct TariWallet *wallet, * `wallet` - The TariWallet pointer * `amount` - The value of the UTXO in MicroTari * `spending_key` - The private spending key - * `source_public_key` - The public key of the source of the transaction + * `source_address` - The tari address of the source of the transaction * `features` - Options for an output's structure or use * `metadata_signature` - UTXO signature with the script offset private key, k_O * `sender_offset_public_key` - Tari script offset pubkey, K_O @@ -2953,7 +3045,7 @@ TariPublicKey *wallet_get_public_key(struct TariWallet *wallet, unsigned long long wallet_import_external_utxo_as_non_rewindable(struct TariWallet *wallet, unsigned long long amount, TariPrivateKey *spending_key, - TariPublicKey *source_public_key, + TariWalletAddress *source_address, TariOutputFeatures *features, TariCommitmentSignature *metadata_signature, TariPublicKey *sender_offset_public_key, diff --git a/common/src/configuration/network.rs b/common/src/configuration/network.rs index 056bd42820..b587dc440a 100644 --- a/common/src/configuration/network.rs +++ b/common/src/configuration/network.rs @@ -113,6 +113,28 @@ impl From for String { } } +impl TryFrom for Network { + type Error = ConfigurationError; + + fn try_from(v: u8) -> Result { + match v { + x if x == Network::MainNet as u8 => Ok(Network::MainNet), + x if x == Network::LocalNet as u8 => Ok(Network::LocalNet), + x if x == Network::Ridcully as u8 => Ok(Network::Ridcully), + x if x == Network::Stibbons as u8 => Ok(Network::Stibbons), + x if x == Network::Weatherwax as u8 => Ok(Network::Weatherwax), + x if x == Network::Igor as u8 => Ok(Network::Igor), + x if x == Network::Dibbler as u8 => Ok(Network::Dibbler), + x if x == Network::Esmeralda as u8 => Ok(Network::Esmeralda), + _ => Err(ConfigurationError::new( + "network", + Some(v.to_string()), + &format!("Invalid network option: {}", v), + )), + } + } +} + impl Display for Network { fn fmt(&self, f: &mut Formatter) -> fmt::Result { f.write_str(self.as_key_str()) @@ -178,4 +200,16 @@ mod test { let err_network = Network::from_str("invalid network"); assert!(err_network.is_err()); } + + #[test] + fn network_from_byte() { + assert_eq!(Network::try_from(0x00).unwrap(), Network::MainNet); + assert_eq!(Network::try_from(0x10).unwrap(), Network::LocalNet); + assert_eq!(Network::try_from(0x21).unwrap(), Network::Ridcully); + assert_eq!(Network::try_from(0x22).unwrap(), Network::Stibbons); + assert_eq!(Network::try_from(0xa3).unwrap(), Network::Weatherwax); + assert_eq!(Network::try_from(0x24).unwrap(), Network::Igor); + assert_eq!(Network::try_from(0x25).unwrap(), Network::Dibbler); + assert_eq!(Network::try_from(0x26).unwrap(), Network::Esmeralda); + } }