Skip to content

Commit

Permalink
refactor(torii): abstract out how to format felts to avoid bugs
Browse files Browse the repository at this point in the history
commit-id:d618e874
  • Loading branch information
lambda-0x committed Sep 19, 2024
1 parent fc56768 commit a97288c
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 51 deletions.
4 changes: 2 additions & 2 deletions crates/torii/core/src/processors/store_set_record.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use tracing::info;

use super::EventProcessor;
use crate::processors::{ENTITY_ID_INDEX, MODEL_INDEX, NUM_KEYS_INDEX};
use crate::sql::utils::felts_sql_string;
use crate::sql::utils::felts_to_sql_string;
use crate::sql::Sql;

pub(crate) const LOG_TARGET: &str = "torii_core::processors::store_set_record";
Expand Down Expand Up @@ -61,7 +61,7 @@ where
let keys_end: usize =
keys_start + event.data[NUM_KEYS_INDEX].to_usize().context("invalid usize")?;
let keys = event.data[keys_start..keys_end].to_vec();
let keys_str = felts_sql_string(&keys);
let keys_str = felts_to_sql_string(&keys);

// keys_end is already the length of the values array.

Expand Down
69 changes: 35 additions & 34 deletions crates/torii/core/src/sql/erc.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
use std::ops::{Add, Sub};

use anyhow::Result;
use cainome::cairo_serde::ByteArray;
use cainome::cairo_serde::CairoSerde;
use starknet::core::types::{BlockId, BlockTag, FunctionCall, U256};
use cainome::cairo_serde::{ByteArray, CairoSerde};
use starknet::core::types::{BlockId, BlockTag, Felt, FunctionCall, U256};
use starknet::core::utils::{get_selector_from_name, parse_cairo_short_string};
use starknet::{core::types::Felt, providers::Provider};
use std::ops::{Add, Sub};
use starknet::providers::Provider;

use super::query_queue::{Argument, QueryQueue, QueryType};
use super::utils::{sql_string_to_u256, u256_to_sql_string};
use super::{Sql, FELT_DELIMITER};
use crate::sql::utils::{felt_and_u256_to_sql_string, felt_to_sql_string, felts_to_sql_string};
use crate::utils::utc_dt_string_from_timestamp;

use super::Sql;

impl Sql {
pub async fn handle_erc20_transfer<P: Provider + Sync>(
&mut self,
contract_address: Felt,
from: Felt,
to: Felt,
from_address: Felt,
to_address: Felt,
amount: U256,
provider: &P,
block_timestamp: u64,
) -> Result<()> {
// unique token identifier in DB
let token_id = format!("{:#x}", contract_address);
let token_id = felt_to_sql_string(&contract_address);

let token_exists: bool =
sqlx::query_scalar("SELECT EXISTS(SELECT 1 FROM tokens WHERE id = ?)")
Expand All @@ -43,8 +43,8 @@ impl Sql {

register_erc_transfer_event(
contract_address,
from,
to,
from_address,
to_address,
amount,
&token_id,
block_timestamp,
Expand All @@ -63,9 +63,9 @@ impl Sql {
"SELECT account_address, balance FROM balances WHERE contract_address = ? AND \
account_address IN (?, ?)",
)
.bind(format!("{:#x}", contract_address))
.bind(format!("{:#x}", from))
.bind(format!("{:#x}", to));
.bind(felt_to_sql_string(&contract_address))
.bind(felt_to_sql_string(&from_address))
.bind(felt_to_sql_string(&to_address));

// (address, balance)
let balances: Vec<(String, String)> = query.fetch_all(&self.pool).await?;
Expand All @@ -75,50 +75,51 @@ impl Sql {

let from_balance = balances
.iter()
.find(|(address, _)| address == &format!("{:#x}", from))
.find(|(address, _)| address == &felt_to_sql_string(&from_address))
.map(|(_, balance)| balance.clone())
.unwrap_or_else(|| format!("{:#64x}", crypto_bigint::U256::ZERO));
.unwrap_or_else(|| u256_to_sql_string(&U256::from(0u8)));

let to_balance = balances
.iter()
.find(|(address, _)| address == &format!("{:#x}", to))
.find(|(address, _)| address == &felt_to_sql_string(&to_address))
.map(|(_, balance)| balance.clone())
.unwrap_or_else(|| format!("{:#64x}", crypto_bigint::U256::ZERO));
.unwrap_or_else(|| u256_to_sql_string(&U256::from(0u8)));

let from_balance = sql_string_to_u256(&from_balance);
let to_balance = sql_string_to_u256(&to_balance);

let new_from_balance =
if from != Felt::ZERO { from_balance.sub(amount) } else { from_balance };
let new_to_balance = if to != Felt::ZERO { to_balance.add(amount) } else { to_balance };
if from_address != Felt::ZERO { from_balance.sub(amount) } else { from_balance };
let new_to_balance =
if to_address != Felt::ZERO { to_balance.add(amount) } else { to_balance };

let update_query = "
INSERT INTO balances (id, balance, account_address, contract_address, token_id)
VALUES (?, ?, ?, ?, ?)
ON CONFLICT (id)
DO UPDATE SET balance = excluded.balance";

if from != Felt::ZERO {
if from_address != Felt::ZERO {
self.query_queue.enqueue(
update_query,
vec![
Argument::String(format!("{:#x}:{:#x}", from, contract_address)),
Argument::String(felts_to_sql_string(&[from_address, contract_address])),
Argument::String(u256_to_sql_string(&new_from_balance)),
Argument::FieldElement(from),
Argument::FieldElement(from_address),
Argument::FieldElement(contract_address),
Argument::String(token_id.clone()),
],
QueryType::Other,
);
}

if to != Felt::ZERO {
if to_address != Felt::ZERO {
self.query_queue.enqueue(
update_query,
vec![
Argument::String(format!("{:#x}:{:#x}", to, contract_address)),
Argument::String(felts_to_sql_string(&[to_address, contract_address])),
Argument::String(u256_to_sql_string(&new_to_balance)),
Argument::FieldElement(to),
Argument::FieldElement(to_address),
Argument::FieldElement(contract_address),
Argument::String(token_id.clone()),
],
Expand All @@ -134,13 +135,13 @@ impl Sql {
pub async fn handle_erc721_transfer<P: Provider + Sync>(
&mut self,
contract_address: Felt,
from: Felt,
to: Felt,
from_address: Felt,
to_address: Felt,
token_id: U256,
provider: &P,
block_timestamp: u64,
) -> Result<()> {
let token_id = format!("{:#x}:{}", contract_address, u256_to_sql_string(&token_id));
let token_id = felt_and_u256_to_sql_string(&contract_address, &token_id);
let token_exists: bool =
sqlx::query_scalar("SELECT EXISTS(SELECT 1 FROM tokens WHERE id = ?)")
.bind(token_id.clone())
Expand All @@ -159,8 +160,8 @@ impl Sql {

register_erc_transfer_event(
contract_address,
from,
to,
from_address,
to_address,
U256::from(1u8),
&token_id,
block_timestamp,
Expand All @@ -175,7 +176,7 @@ impl Sql {
ON CONFLICT (id)
DO UPDATE SET balance = excluded.balance";

if from != Felt::ZERO {
if from_address != Felt::ZERO {
self.query_queue.enqueue(
update_query,
vec![
Expand All @@ -193,7 +194,7 @@ impl Sql {
);
}

if to != Felt::ZERO {
if to_address != Felt::ZERO {
self.query_queue.enqueue(
update_query,
vec![
Expand Down
18 changes: 9 additions & 9 deletions crates/torii/core/src/sql/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use sqlx::{Pool, Sqlite};
use starknet::core::types::{Event, Felt, InvokeTransaction, Transaction};
use starknet_crypto::poseidon_hash_many;
use tracing::{debug, warn};
use utils::felts_sql_string;
use utils::felts_to_sql_string;

use crate::cache::{Model, ModelCache};
use crate::types::{
Expand Down Expand Up @@ -420,7 +420,7 @@ impl Sql {
QueryType::Other,
);

let keys_str = felts_sql_string(&keys);
let keys_str = felts_to_sql_string(&keys);
let insert_entities = "INSERT INTO event_messages (id, keys, event_id, executed_at) \
VALUES (?, ?, ?, ?) ON CONFLICT(id) DO UPDATE SET \
updated_at=CURRENT_TIMESTAMP, executed_at=EXCLUDED.executed_at, \
Expand Down Expand Up @@ -561,15 +561,15 @@ impl Sql {
Transaction::Invoke(InvokeTransaction::V1(invoke_v1_transaction)) => (
Argument::FieldElement(invoke_v1_transaction.transaction_hash),
Argument::FieldElement(invoke_v1_transaction.sender_address),
Argument::String(felts_sql_string(&invoke_v1_transaction.calldata)),
Argument::String(felts_to_sql_string(&invoke_v1_transaction.calldata)),
Argument::FieldElement(invoke_v1_transaction.max_fee),
Argument::String(felts_sql_string(&invoke_v1_transaction.signature)),
Argument::String(felts_to_sql_string(&invoke_v1_transaction.signature)),
Argument::FieldElement(invoke_v1_transaction.nonce),
),
Transaction::L1Handler(l1_handler_transaction) => (
Argument::FieldElement(l1_handler_transaction.transaction_hash),
Argument::FieldElement(l1_handler_transaction.contract_address),
Argument::String(felts_sql_string(&l1_handler_transaction.calldata)),
Argument::String(felts_to_sql_string(&l1_handler_transaction.calldata)),
Argument::FieldElement(Felt::ZERO), // has no max_fee
Argument::String("".to_string()), // has no signature
Argument::FieldElement((l1_handler_transaction.nonce).into()),
Expand Down Expand Up @@ -604,8 +604,8 @@ impl Sql {
block_timestamp: u64,
) {
let id = Argument::String(event_id.to_string());
let keys = Argument::String(felts_sql_string(&event.keys));
let data = Argument::String(felts_sql_string(&event.data));
let keys = Argument::String(felts_to_sql_string(&event.keys));
let data = Argument::String(felts_to_sql_string(&event.data));
let hash = Argument::FieldElement(transaction_hash);
let executed_at = Argument::String(utc_dt_string_from_timestamp(block_timestamp));

Expand All @@ -618,8 +618,8 @@ impl Sql {

let emitted = EventEmitted {
id: event_id.to_string(),
keys: felts_sql_string(&event.keys),
data: felts_sql_string(&event.data),
keys: felts_to_sql_string(&event.keys),
data: felts_to_sql_string(&event.data),
transaction_hash: format!("{:#x}", transaction_hash),
created_at: Utc::now(),
executed_at: must_utc_datetime_from_timestamp(block_timestamp),
Expand Down
2 changes: 1 addition & 1 deletion crates/torii/core/src/sql/query_queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ impl QueryQueue {
Argument::Int(integer) => query.bind(integer),
Argument::Bool(bool) => query.bind(bool),
Argument::String(string) => query.bind(string),
Argument::FieldElement(felt) => query.bind(format!("{:#x}", felt)),
Argument::FieldElement(felt) => query.bind(felt_to_sql_string(felt)),
}
}

Expand Down
10 changes: 9 additions & 1 deletion crates/torii/core/src/sql/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,19 @@ use starknet_crypto::Felt;

use super::FELT_DELIMITER;

pub fn felts_sql_string(felts: &[Felt]) -> String {
pub fn felts_to_sql_string(felts: &[Felt]) -> String {
felts.iter().map(|k| format!("{:#x}", k)).collect::<Vec<String>>().join(FELT_DELIMITER)
+ FELT_DELIMITER
}

pub(crate) fn felt_to_sql_string(felt: &Felt) -> String {
format!("{:#x}", felt)
}

pub(crate) fn felt_and_u256_to_sql_string(felt: &Felt, u256: &U256) -> String {
format!("{}:{}", felt_to_sql_string(felt), u256_to_sql_string(u256))
}

pub(crate) fn u256_to_sql_string(u256: &U256) -> String {
format!("{:#064x}", u256)
}
Expand Down
7 changes: 4 additions & 3 deletions crates/torii/graphql/src/tests/subscription_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ mod tests {
use starknet::core::types::Event;
use starknet_crypto::{poseidon_hash_many, Felt};
use tokio::sync::mpsc;
use torii_core::sql::{felts_sql_string, Sql};
use torii_core::sql::utils::felts_to_sql_string;
use torii_core::sql::Sql;

use crate::tests::{model_fixtures, run_graphql_subscription};
use crate::utils;
Expand Down Expand Up @@ -105,7 +106,7 @@ mod tests {
],
});
let keys = keys_from_ty(&ty).unwrap();
let keys_str = felts_sql_string(&keys);
let keys_str = felts_to_sql_string(&keys);
let entity_id = poseidon_hash_many(&keys);
let model_id = model_id_from_ty(&ty);

Expand Down Expand Up @@ -223,7 +224,7 @@ mod tests {
});

let keys = keys_from_ty(&ty).unwrap();
let keys_str = felts_sql_string(&keys);
let keys_str = felts_to_sql_string(&keys);
let entity_id = poseidon_hash_many(&keys);
let model_id = model_id_from_ty(&ty);

Expand Down
2 changes: 1 addition & 1 deletion crates/torii/libp2p/src/server/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ impl<P: Provider + Sync> Relay<P> {
continue;
}
};
let keys_str = felts_sql_string(&keys);
let keys_str = felts_to_sql_string(&keys);
let entity_id = poseidon_hash_many(&keys);
let model_id = ty_model_id(&ty).unwrap();

Expand Down

0 comments on commit a97288c

Please sign in to comment.