Skip to content

Commit

Permalink
Change protocols to bytes
Browse files Browse the repository at this point in the history
Changed the sender and receiver protocol sin the wallet database to use bytes instead of a hex string, as the underlying data type is encrypted bytes. This issue was highlighted due to the to_hex function in tari_utilities not being able to convert large transactions into hex strings (returned **String to large**) for saving in the wallet database.
  • Loading branch information
hansieodendaal committed Nov 13, 2023
1 parent 55bbdf2 commit 361f0ea
Show file tree
Hide file tree
Showing 6 changed files with 252 additions and 58 deletions.
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

0 comments on commit 361f0ea

Please sign in to comment.