Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: sender and receiver protocols use bytes (not hex string) in wallet database #5950

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-- This file should undo anything in `up.sql`
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
-- Any old 'inbound_transactions' will not be valid due to the change in 'receiver_protocol' to 'BLOB', so we drop and
-- recreate the table.

DROP TABLE inbound_transactions;
CREATE TABLE inbound_transactions
(
tx_id BIGINT PRIMARY KEY NOT NULL,
source_address BLOB NOT NULL,
amount BIGINT NOT NULL,
receiver_protocol BLOB NOT NULL,
message TEXT NOT NULL,
timestamp DATETIME NOT NULL,
cancelled INTEGER NOT NULL,
direct_send_success INTEGER DEFAULT 0 NOT NULL,
send_count INTEGER DEFAULT 0 NOT NULL,
last_send_timestamp DATETIME NULL
);

-- Any old 'outbound_transactions' will not be valid due to the change in 'sender_protocol' to 'BLOB', so we drop and
-- recreate the table.

DROP TABLE outbound_transactions;
CREATE TABLE outbound_transactions
(
tx_id BIGINT PRIMARY KEY NOT NULL,
destination_address BLOB NOT NULL,
amount BIGINT NOT NULL,
fee BIGINT NOT NULL,
sender_protocol BLOB NOT NULL,
message TEXT NOT NULL,
timestamp DATETIME NOT NULL,
cancelled INTEGER DEFAULT 0 NOT NULL,
direct_send_success INTEGER DEFAULT 0 NOT NULL,
send_count INTEGER DEFAULT 0 NOT NULL,
last_send_timestamp DATETIME NULL
);
26 changes: 14 additions & 12 deletions base_layer/wallet/src/schema.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
table! {
// @generated automatically by Diesel CLI.

diesel::table! {
burnt_proofs (id) {
id -> Integer,
reciprocal_claim_public_key -> Text,
Expand All @@ -7,14 +9,14 @@ table! {
}
}

table! {
diesel::table! {
client_key_values (key) {
key -> Text,
value -> Text,
}
}

table! {
diesel::table! {
completed_transactions (tx_id) {
tx_id -> BigInt,
source_address -> Binary,
Expand All @@ -39,12 +41,12 @@ table! {
}
}

table! {
diesel::table! {
inbound_transactions (tx_id) {
tx_id -> BigInt,
source_address -> Binary,
amount -> BigInt,
receiver_protocol -> Text,
receiver_protocol -> Binary,
message -> Text,
timestamp -> Timestamp,
cancelled -> Integer,
Expand All @@ -54,7 +56,7 @@ table! {
}
}

table! {
diesel::table! {
known_one_sided_payment_scripts (script_hash) {
script_hash -> Binary,
private_key -> Text,
Expand All @@ -64,13 +66,13 @@ table! {
}
}

table! {
diesel::table! {
outbound_transactions (tx_id) {
tx_id -> BigInt,
destination_address -> Binary,
amount -> BigInt,
fee -> BigInt,
sender_protocol -> Text,
sender_protocol -> Binary,
message -> Text,
timestamp -> Timestamp,
cancelled -> Integer,
Expand All @@ -80,7 +82,7 @@ table! {
}
}

table! {
diesel::table! {
outputs (id) {
id -> Integer,
commitment -> Binary,
Expand Down Expand Up @@ -120,7 +122,7 @@ table! {
}
}

table! {
diesel::table! {
scanned_blocks (header_hash) {
header_hash -> Binary,
height -> BigInt,
Expand All @@ -130,14 +132,14 @@ 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!(
burnt_proofs,
client_key_values,
completed_transactions,
Expand Down
2 changes: 2 additions & 0 deletions base_layer/wallet/src/transaction_service/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,8 @@ pub enum TransactionStorageError {
UnexpectedResult(String),
#[error("Bincode error: `{0}`")]
BincodeSerialize(String),
#[error("Bincode error: `{0}`")]
BincodeDeserialize(String),
#[error("This write operation is not supported for provided DbKey")]
OperationNotSupported,
#[error("Could not find all values specified for batch operation")]
Expand Down
69 changes: 23 additions & 46 deletions base_layer/wallet/src/transaction_service/storage/sqlite_db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
use std::{
collections::HashMap,
convert::{TryFrom, TryInto},
str::from_utf8,
sync::{Arc, RwLock},
};

Expand All @@ -45,11 +44,7 @@ use tari_common_types::{
types::{BlockHash, PrivateKey, PublicKey, Signature},
};
use tari_core::transactions::tari_amount::MicroMinotari;
use tari_utilities::{
hex::{from_hex, Hex},
ByteArray,
Hidden,
};
use tari_utilities::{ByteArray, Hidden};
use thiserror::Error;
use tokio::time::Instant;
use zeroize::Zeroize;
Expand Down Expand Up @@ -1166,7 +1161,7 @@ struct InboundTransactionSql {
tx_id: i64,
source_address: Vec<u8>,
amount: i64,
receiver_protocol: String,
receiver_protocol: Vec<u8>,
message: String,
timestamp: NaiveDateTime,
cancelled: i32,
Expand Down Expand Up @@ -1345,11 +1340,13 @@ impl InboundTransactionSql {
}

fn try_from(i: InboundTransaction, cipher: &XChaCha20Poly1305) -> Result<Self, TransactionStorageError> {
let receiver_protocol_bytes = bincode::serialize(&i.receiver_protocol)
.map_err(|e| TransactionStorageError::BincodeSerialize(e.to_string()))?;
let i = Self {
tx_id: i.tx_id.as_u64() as i64,
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)?,
receiver_protocol: receiver_protocol_bytes.to_vec(),
message: i.message,
timestamp: i.timestamp,
cancelled: i32::from(i.cancelled),
Expand All @@ -1376,26 +1373,15 @@ impl Encryptable<XChaCha20Poly1305> for InboundTransactionSql {
self.receiver_protocol = encrypt_bytes_integral_nonce(
cipher,
self.domain("receiver_protocol"),
Hidden::hide(self.receiver_protocol.as_bytes().to_vec()),
)?
.to_hex();
Hidden::hide(self.receiver_protocol),
)?;

Ok(self)
}

fn decrypt(mut self, cipher: &XChaCha20Poly1305) -> Result<Self, String> {
let mut decrypted_protocol = decrypt_bytes_integral_nonce(
cipher,
self.domain("receiver_protocol"),
&from_hex(self.receiver_protocol.as_str()).map_err(|e| e.to_string())?,
)?;

self.receiver_protocol = from_utf8(decrypted_protocol.as_slice())
.map_err(|e| e.to_string())?
.to_string();

// zeroize sensitive data
decrypted_protocol.zeroize();
self.receiver_protocol =
decrypt_bytes_integral_nonce(cipher, self.domain("receiver_protocol"), &self.receiver_protocol)?;

Ok(self)
}
Expand All @@ -1408,7 +1394,8 @@ impl InboundTransaction {
tx_id: (i.tx_id as u64).into(),
source_address: TariAddress::from_bytes(&i.source_address).map_err(TransactionKeyError::Source)?,
amount: MicroMinotari::from(i.amount as u64),
receiver_protocol: serde_json::from_str(&i.receiver_protocol.clone())?,
receiver_protocol: bincode::deserialize(&i.receiver_protocol)
.map_err(|e| TransactionStorageError::BincodeDeserialize(e.to_string()))?,
status: TransactionStatus::Pending,
message: i.message,
timestamp: i.timestamp,
Expand All @@ -1425,7 +1412,7 @@ impl InboundTransaction {
pub struct UpdateInboundTransactionSql {
cancelled: Option<i32>,
direct_send_success: Option<i32>,
receiver_protocol: Option<String>,
receiver_protocol: Option<Vec<u8>>,
send_count: Option<i32>,
last_send_timestamp: Option<Option<NaiveDateTime>>,
}
Expand All @@ -1438,7 +1425,7 @@ struct OutboundTransactionSql {
destination_address: Vec<u8>,
amount: i64,
fee: i64,
sender_protocol: String,
sender_protocol: Vec<u8>,
message: String,
timestamp: NaiveDateTime,
cancelled: i32,
Expand Down Expand Up @@ -1601,12 +1588,14 @@ impl OutboundTransactionSql {
}

fn try_from(o: OutboundTransaction, cipher: &XChaCha20Poly1305) -> Result<Self, TransactionStorageError> {
let sender_protocol_bytes = bincode::serialize(&o.sender_protocol)
.map_err(|e| TransactionStorageError::BincodeSerialize(e.to_string()))?;
let outbound_tx = Self {
tx_id: o.tx_id.as_u64() as i64,
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)?,
sender_protocol: sender_protocol_bytes.to_vec(),
message: o.message,
timestamp: o.timestamp,
cancelled: i32::from(o.cancelled),
Expand Down Expand Up @@ -1634,42 +1623,30 @@ impl Encryptable<XChaCha20Poly1305> for OutboundTransactionSql {
self.sender_protocol = encrypt_bytes_integral_nonce(
cipher,
self.domain("sender_protocol"),
Hidden::hide(self.sender_protocol.as_bytes().to_vec()),
)?
.to_hex();
Hidden::hide(self.sender_protocol),
)?;

Ok(self)
}

fn decrypt(mut self, cipher: &XChaCha20Poly1305) -> Result<Self, String> {
let mut decrypted_protocol = decrypt_bytes_integral_nonce(
cipher,
self.domain("sender_protocol"),
&from_hex(self.sender_protocol.as_str()).map_err(|e| e.to_string())?,
)?;

self.sender_protocol = from_utf8(decrypted_protocol.as_slice())
.map_err(|e| e.to_string())?
.to_string();

// zeroize sensitive data
decrypted_protocol.zeroize();

self.sender_protocol =
decrypt_bytes_integral_nonce(cipher, self.domain("sender_protocol"), &self.sender_protocol)?;
Ok(self)
}
}

impl OutboundTransaction {
fn try_from(o: OutboundTransactionSql, cipher: &XChaCha20Poly1305) -> Result<Self, TransactionStorageError> {
let mut o = o.decrypt(cipher).map_err(TransactionStorageError::AeadError)?;

let outbound_tx = Self {
tx_id: (o.tx_id as u64).into(),
destination_address: TariAddress::from_bytes(&o.destination_address)
.map_err(TransactionKeyError::Destination)?,
amount: MicroMinotari::from(o.amount as u64),
fee: MicroMinotari::from(o.fee as u64),
sender_protocol: serde_json::from_str(&o.sender_protocol.clone())?,
sender_protocol: bincode::deserialize(&o.sender_protocol)
.map_err(|e| TransactionStorageError::BincodeDeserialize(e.to_string()))?,
status: TransactionStatus::Pending,
message: o.message,
timestamp: o.timestamp,
Expand All @@ -1691,7 +1668,7 @@ impl OutboundTransaction {
pub struct UpdateOutboundTransactionSql {
cancelled: Option<i32>,
direct_send_success: Option<i32>,
sender_protocol: Option<String>,
sender_protocol: Option<Vec<u8>>,
send_count: Option<i32>,
last_send_timestamp: Option<Option<NaiveDateTime>>,
}
Expand Down
Loading
Loading