From 624e732d5f7516dd7ee211a620e2ec418d85c3b3 Mon Sep 17 00:00:00 2001 From: Dawid Cichuta Date: Tue, 23 Apr 2024 14:03:37 +0200 Subject: [PATCH] Handle optional binaries with transaction request --- db/migrations/004_transactions_binaries.sql | 1 + src/db.rs | 18 +++++--- src/db/data.rs | 3 ++ src/serde_utils.rs | 1 + src/serde_utils/base64_binary.rs | 47 +++++++++++++++++++++ src/server/routes/transaction.rs | 3 ++ tests/send_too_many_txs.rs | 3 ++ 7 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 db/migrations/004_transactions_binaries.sql create mode 100644 src/serde_utils/base64_binary.rs diff --git a/db/migrations/004_transactions_binaries.sql b/db/migrations/004_transactions_binaries.sql new file mode 100644 index 0000000..45d6337 --- /dev/null +++ b/db/migrations/004_transactions_binaries.sql @@ -0,0 +1 @@ +ALTER TABLE transactions ADD COLUMN binaries BYTEA[] diff --git a/src/db.rs b/src/db.rs index ec2b221..cb14b88 100644 --- a/src/db.rs +++ b/src/db.rs @@ -263,6 +263,7 @@ impl Database { value: U256, gas_limit: U256, priority: TransactionPriority, + binaries: Option>>, relayer_id: &str, ) -> eyre::Result<()> { let mut tx = self.pool.begin().await?; @@ -288,8 +289,8 @@ impl Database { sqlx::query( r#" - INSERT INTO transactions (id, tx_to, data, value, gas_limit, priority, relayer_id, nonce) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8) + INSERT INTO transactions (id, tx_to, data, value, gas_limit, priority, relayer_id, nonce, binaries) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) "#, ) .bind(tx_id) @@ -300,6 +301,7 @@ impl Database { .bind(priority) .bind(relayer_id) .bind(nonce) + .bind(binaries.map(|b| b)) .execute(tx.as_mut()) .await?; @@ -312,7 +314,7 @@ impl Database { pub async fn get_unsent_txs(&self) -> eyre::Result> { Ok(sqlx::query_as( r#" - SELECT r.id as relayer_id, t.id, t.tx_to, t.data, t.value, t.gas_limit, t.priority, t.nonce, r.key_id, r.chain_id + SELECT r.id as relayer_id, t.id, t.tx_to, t.data, t.value, t.gas_limit, t.priority, t.nonce, t.binaries, r.key_id, r.chain_id FROM transactions t LEFT JOIN sent_transactions s ON (t.id = s.tx_id) INNER JOIN relayers r ON (t.relayer_id = r.id) @@ -763,7 +765,7 @@ impl Database { Ok(sqlx::query_as( r#" SELECT r.id as relayer_id, t.id, t.tx_to, t.data, t.value, t.gas_limit, t.nonce, - r.key_id, r.chain_id, + t.binaries, r.key_id, r.chain_id, s.initial_max_fee_per_gas, s.initial_max_priority_fee_per_gas, s.escalation_count FROM transactions t JOIN sent_transactions s ON t.id = s.tx_id @@ -847,7 +849,7 @@ impl Database { Ok(sqlx::query_as( r#" SELECT t.id as tx_id, t.tx_to as to, t.data, t.value, t.gas_limit, t.nonce, - h.tx_hash, s.status + t.binaries, h.tx_hash, s.status FROM transactions t LEFT JOIN sent_transactions s ON t.id = s.tx_id LEFT JOIN tx_hashes h ON s.valid_tx_hash = h.tx_hash @@ -873,7 +875,7 @@ impl Database { Ok(sqlx::query_as( r#" SELECT t.id as tx_id, t.tx_to as to, t.data, t.value, t.gas_limit, t.nonce, - h.tx_hash, s.status + t. binaries, h.tx_hash, s.status FROM transactions t LEFT JOIN sent_transactions s ON t.id = s.tx_id LEFT JOIN tx_hashes h ON s.valid_tx_hash = h.tx_hash @@ -1405,12 +1407,13 @@ mod tests { let value = U256::from(0); let gas_limit = U256::from(0); let priority = TransactionPriority::Regular; + let binaries = None; let tx = db.read_tx(tx_id).await?; assert!(tx.is_none(), "Tx has not been sent yet"); db.create_transaction( - tx_id, to, data, value, gas_limit, priority, relayer_id, + tx_id, to, data, value, gas_limit, priority, binaries, relayer_id, ) .await?; @@ -1423,6 +1426,7 @@ mod tests { assert_eq!(tx.gas_limit.0, gas_limit); assert_eq!(tx.nonce, 0); assert_eq!(tx.tx_hash, None); + assert_eq!(tx.binaries, None); let unsent_txs = db.read_txs(relayer_id, None).await?; assert_eq!(unsent_txs.len(), 1, "1 unsent tx"); diff --git a/src/db/data.rs b/src/db/data.rs index b9113be..50f1e94 100644 --- a/src/db/data.rs +++ b/src/db/data.rs @@ -19,6 +19,7 @@ pub struct UnsentTx { pub priority: TransactionPriority, #[sqlx(try_from = "i64")] pub nonce: u64, + pub binaries: Option>>, pub key_id: String, #[sqlx(try_from = "i64")] pub chain_id: u64, @@ -34,6 +35,7 @@ pub struct TxForEscalation { pub gas_limit: U256Wrapper, #[sqlx(try_from = "i64")] pub nonce: u64, + pub binaries: Option>>, pub key_id: String, #[sqlx(try_from = "i64")] pub chain_id: u64, @@ -52,6 +54,7 @@ pub struct ReadTxData { pub gas_limit: U256Wrapper, #[sqlx(try_from = "i64")] pub nonce: u64, + pub binaries: Option>>, // Sent tx data pub tx_hash: Option, diff --git a/src/serde_utils.rs b/src/serde_utils.rs index 7f1e57a..596953b 100644 --- a/src/serde_utils.rs +++ b/src/serde_utils.rs @@ -1 +1,2 @@ +pub mod base64_binary; pub mod decimal_u256; diff --git a/src/serde_utils/base64_binary.rs b/src/serde_utils/base64_binary.rs new file mode 100644 index 0000000..e4098b9 --- /dev/null +++ b/src/serde_utils/base64_binary.rs @@ -0,0 +1,47 @@ +use base64::engine::general_purpose; +use base64::Engine as _; +use serde::Deserialize; + +pub fn serialize( + binaries: &Option>>, + serializer: S, +) -> Result +where + S: serde::Serializer, +{ + match binaries { + Some(binaries) => { + let base64_vec: Vec = binaries + .iter() + .map(|binary| general_purpose::STANDARD.encode(binary)) + .collect(); + + serializer.serialize_some(&base64_vec) + } + None => serializer.serialize_none(), + } +} + +pub fn deserialize<'de, D>( + deserializer: D, +) -> Result>>, D::Error> +where + D: serde::Deserializer<'de>, +{ + let base64_strings: Option> = + Option::deserialize(deserializer)?; + + match base64_strings { + Some(base64_vec) => { + let decoded_vec: Vec> = base64_vec + .into_iter() + .map(|base64_str| { + general_purpose::STANDARD.decode(base64_str).unwrap() + }) + .collect(); + + Ok(Some(decoded_vec)) + } + None => Ok(None), + } +} diff --git a/src/server/routes/transaction.rs b/src/server/routes/transaction.rs index 45e16d5..020737a 100644 --- a/src/server/routes/transaction.rs +++ b/src/server/routes/transaction.rs @@ -25,6 +25,8 @@ pub struct SendTxRequest { pub priority: TransactionPriority, #[serde(default)] pub tx_id: Option, + #[serde(default, with = "crate::serde_utils::base64_binary")] + pub binaries: Option>>, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -116,6 +118,7 @@ pub async fn send_tx( req.value, req.gas_limit, req.priority, + req.binaries, api_token.relayer_id(), ) .await?; diff --git a/tests/send_too_many_txs.rs b/tests/send_too_many_txs.rs index 226cc43..727dc46 100644 --- a/tests/send_too_many_txs.rs +++ b/tests/send_too_many_txs.rs @@ -59,6 +59,7 @@ async fn send_too_many_txs() -> eyre::Result<()> { gas_limit: U256::from(21_000), priority: TransactionPriority::Regular, tx_id: None, + binaries: None, }, ) .await?; @@ -75,6 +76,7 @@ async fn send_too_many_txs() -> eyre::Result<()> { gas_limit: U256::from(21_000), priority: TransactionPriority::Regular, tx_id: None, + binaries: None, }, ) .await; @@ -102,6 +104,7 @@ async fn send_too_many_txs() -> eyre::Result<()> { gas_limit: U256::from(21_000), priority: TransactionPriority::Regular, tx_id: None, + binaries: None, }, ) .await?;