-
Notifications
You must be signed in to change notification settings - Fork 368
feat(ICRC-Rosetta): add ICRC-107 fee collector block handling #7697
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
base: master
Are you sure you want to change the base?
Changes from all commits
fc1e131
9e7c58d
8914b52
440545a
5ed8d30
b1a7a40
372c508
1bdf8a3
3dcf6a6
6a30c76
d010fbd
42072ed
0398011
cfbbc26
a5b886c
2fe87b4
5d5e118
8102274
3f83e5f
cbe5156
b5530ec
fd4dab5
08aba67
eba90cd
8125a18
a782c66
a201faf
5f2c5df
f28d46b
eeca831
c9a3a32
61d4e0b
975cdc9
50e90ae
bfb852e
17cb2b2
dc2eb00
3a858f5
26b1efc
a08a50f
de06078
6fa9607
f3c2280
fec306f
3c8283f
bf53fb8
8f8f140
b41b566
589bb91
32e1968
4c38fdb
3171dd6
015b692
74e8054
e551549
22272e5
27754a3
c45a302
2a865c1
3deef11
d9ac1b5
1dd9d73
681d089
774490c
21055eb
255084c
e457710
e3b5868
51d6341
90f6fdd
6a58bb9
ff5258a
b61ec33
ee9d541
d02ea5d
84c1536
04a9925
6837917
5d0e1b4
e0d7205
78e974a
a8f8a85
76cb1d3
b9aa459
19f0491
f817488
197b781
c7eda70
fb40fe2
75798c6
eba6fac
9b99d3e
ed6cbb7
843e630
78875e0
593bd3c
3c4bb10
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -91,6 +91,19 @@ pub fn create_tables(connection: &Connection) -> Result<()> { | |
| [], | ||
| )?; | ||
|
|
||
| // The rosetta_metadata table is meant to store values like the index | ||
| // of the highest processed block. This is different than the metadata | ||
| // table above which stores the ICRC1 token metadata. | ||
| connection.execute( | ||
| r#" | ||
| CREATE TABLE IF NOT EXISTS rosetta_metadata ( | ||
| key TEXT PRIMARY KEY, | ||
| value BLOB NOT NULL | ||
| ); | ||
| "#, | ||
| [], | ||
| )?; | ||
|
|
||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With the metadata table, updating ckBTC balances take ~4m. This is similar to having an index on |
||
| create_indexes(connection) | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -337,9 +337,9 @@ impl StorageClient { | |
|
|
||
| /// Retrieves the highest block index in the account balance table. | ||
| /// Returns None if the account balance table is empty. | ||
| pub fn get_highest_block_idx_in_account_balance_table(&self) -> Result<Option<u64>> { | ||
| pub fn get_highest_processed_block_idx(&self) -> Result<Option<u64>> { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This now returns the highest processed block idx using the |
||
| let open_connection = self.storage_connection.lock().unwrap(); | ||
| storage_operations::get_highest_block_idx_in_account_balance_table(&open_connection) | ||
| storage_operations::get_highest_processed_block_idx(&open_connection) | ||
| } | ||
|
|
||
| // Retrieves the account balance at a certain block height | ||
|
|
@@ -405,7 +405,8 @@ mod tests { | |
| use ic_icrc1::blocks::encoded_block_to_generic_block; | ||
| use ic_icrc1::blocks::generic_block_to_encoded_block; | ||
| use ic_icrc1_test_utils::{ | ||
| arb_amount, blocks_strategy, metadata_strategy, valid_blockchain_with_gaps_strategy, | ||
| arb_amount, blocks_strategy, metadata_strategy, valid_blockchain_strategy, | ||
| valid_blockchain_with_gaps_strategy, | ||
| }; | ||
| use ic_icrc1_tokens_u64::U64; | ||
| use ic_icrc1_tokens_u256::U256; | ||
|
|
@@ -432,7 +433,7 @@ mod tests { | |
|
|
||
| proptest! { | ||
| #[test] | ||
| fn test_read_and_write_blocks_u64(blockchain in prop::collection::vec(blocks_strategy::<U64>(arb_amount()),0..5)){ | ||
| fn test_read_and_write_blocks_u64(blockchain in valid_blockchain_strategy::<U64>(5)){ | ||
| let storage_client_memory = StorageClient::new_in_memory().unwrap(); | ||
| let mut rosetta_blocks = vec![]; | ||
| for (index,block) in blockchain.into_iter().enumerate(){ | ||
|
|
@@ -459,7 +460,7 @@ mod tests { | |
| } | ||
|
|
||
| #[test] | ||
| fn test_read_and_write_blocks_u256(blockchain in prop::collection::vec(blocks_strategy::<U256>(arb_amount()),0..5)){ | ||
| fn test_read_and_write_blocks_u256(blockchain in valid_blockchain_strategy::<U256>(5)){ | ||
| let storage_client_memory = StorageClient::new_in_memory().unwrap(); | ||
| let mut rosetta_blocks = vec![]; | ||
| for (index,block) in blockchain.into_iter().enumerate(){ | ||
|
|
@@ -508,10 +509,11 @@ mod tests { | |
|
|
||
| // Duplicate the last transaction generated | ||
| let duplicate_tx_block = RosettaBlock::from_generic_block(last_block.get_generic_block(), last_block.index + 1).unwrap(); | ||
| let count_before = storage_client_memory.get_transactions_by_hash(duplicate_tx_block.clone().get_transaction_hash()).unwrap().len(); | ||
| storage_client_memory.store_blocks([duplicate_tx_block.clone()].to_vec()).unwrap(); | ||
|
|
||
| // The hash of the duplicated transaction should still be the same --> There should be two transactions with the same transaction hash. | ||
| assert_eq!(storage_client_memory.get_transactions_by_hash(duplicate_tx_block.clone().get_transaction_hash()).unwrap().len(),2); | ||
| // The hash of the duplicated transaction should still be the same --> There should be one more transaction with the same transaction hash. | ||
| assert_eq!(storage_client_memory.get_transactions_by_hash(duplicate_tx_block.clone().get_transaction_hash()).unwrap().len(), count_before + 1); | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -14,6 +14,9 @@ use std::collections::{BTreeMap, HashMap}; | |||||||||||||||||||||||||||||
| use std::str::FromStr; | ||||||||||||||||||||||||||||||
| use tracing::{info, trace}; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| pub const METADATA_FEE_COL: &str = "fee_collector_107"; | ||||||||||||||||||||||||||||||
| pub const METADATA_BLOCK_IDX: &str = "highest_processed_block_index"; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| /// Gets the current value of a counter from the database. | ||||||||||||||||||||||||||||||
| /// Returns None if the counter doesn't exist. | ||||||||||||||||||||||||||||||
| pub fn get_counter_value( | ||||||||||||||||||||||||||||||
|
|
@@ -106,6 +109,20 @@ pub fn initialize_counter_if_missing( | |||||||||||||||||||||||||||||
| Ok(()) | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| pub fn get_107_fee_collector_or_legacy( | ||||||||||||||||||||||||||||||
| rosetta_block: &RosettaBlock, | ||||||||||||||||||||||||||||||
| connection: &Connection, | ||||||||||||||||||||||||||||||
| fee_collector_107: Option<Option<Account>>, | ||||||||||||||||||||||||||||||
| ) -> anyhow::Result<Option<Account>> { | ||||||||||||||||||||||||||||||
| // First check if we have a 107 fee collector | ||||||||||||||||||||||||||||||
| if let Some(fee_collector_107) = fee_collector_107 { | ||||||||||||||||||||||||||||||
| return Ok(fee_collector_107); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // There is no 107 fee collector, check legacy fee collector in the block | ||||||||||||||||||||||||||||||
| get_fee_collector_from_block(rosetta_block, connection) | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // Helper function to resolve the fee collector account from a block | ||||||||||||||||||||||||||||||
| pub fn get_fee_collector_from_block( | ||||||||||||||||||||||||||||||
| rosetta_block: &RosettaBlock, | ||||||||||||||||||||||||||||||
|
|
@@ -170,6 +187,27 @@ pub fn get_metadata(connection: &Connection) -> anyhow::Result<Vec<MetadataEntry | |||||||||||||||||||||||||||||
| Ok(result) | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| pub fn get_rosetta_metadata(connection: &Connection, key: &str) -> anyhow::Result<Option<Vec<u8>>> { | ||||||||||||||||||||||||||||||
| let mut stmt_metadata = connection.prepare_cached(&format!( | ||||||||||||||||||||||||||||||
| "SELECT value FROM rosetta_metadata WHERE key = '{key}'" | ||||||||||||||||||||||||||||||
| ))?; | ||||||||||||||||||||||||||||||
| let rows = stmt_metadata.query_map(params![], |row| row.get(0))?; | ||||||||||||||||||||||||||||||
| let mut result = vec![]; | ||||||||||||||||||||||||||||||
| for row in rows { | ||||||||||||||||||||||||||||||
| let entry: Vec<u8> = row?; | ||||||||||||||||||||||||||||||
| result.push(entry); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| if result.len() == 1 { | ||||||||||||||||||||||||||||||
| Ok(Some(result[0].clone())) | ||||||||||||||||||||||||||||||
| } else if result.is_empty() { | ||||||||||||||||||||||||||||||
| // Return None if no metadata entry found | ||||||||||||||||||||||||||||||
| Ok(None) | ||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||
| // If more than one metadata entry was found return an error | ||||||||||||||||||||||||||||||
| bail!(format!("Multiple metadata entries found for key: {key}")) | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
Comment on lines
+200
to
+208
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: The
Suggested change
|
||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| pub fn update_account_balances( | ||||||||||||||||||||||||||||||
| connection: &mut Connection, | ||||||||||||||||||||||||||||||
| flush_cache_and_shrink_memory: bool, | ||||||||||||||||||||||||||||||
|
|
@@ -250,7 +288,7 @@ pub fn update_account_balances( | |||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // The next block to be updated is the highest block index in the account balance table + 1 if the table is not empty and 0 otherwise | ||||||||||||||||||||||||||||||
| let next_block_to_be_updated = | ||||||||||||||||||||||||||||||
| get_highest_block_idx_in_account_balance_table(connection)?.map_or(0, |idx| idx + 1); | ||||||||||||||||||||||||||||||
| get_highest_processed_block_idx(connection)?.map_or(0, |idx| idx + 1); | ||||||||||||||||||||||||||||||
| let highest_block_idx = | ||||||||||||||||||||||||||||||
| get_block_with_highest_block_idx(connection)?.map_or(0, |block| block.index); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
|
@@ -266,9 +304,26 @@ pub fn update_account_balances( | |||||||||||||||||||||||||||||
| // This also makes the inserting of the account balances batchable and therefore faster | ||||||||||||||||||||||||||||||
| let mut account_balances_cache: HashMap<Account, BTreeMap<u64, Nat>> = HashMap::new(); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| let mut current_fee_collector_107 = match get_rosetta_metadata(connection, METADATA_FEE_COL)? { | ||||||||||||||||||||||||||||||
| Some(value) => { | ||||||||||||||||||||||||||||||
| let fc: Option<Account> = candid::decode_one(&value)?; | ||||||||||||||||||||||||||||||
| Some(fc) | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| None => None, | ||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||
|
Comment on lines
+307
to
+313
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: Not sure if this is more readable or not.
Suggested change
|
||||||||||||||||||||||||||||||
| let collector_before = current_fee_collector_107; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // As long as there are blocks to be fetched, keep on iterating over the blocks in the database with the given BATCH_SIZE interval | ||||||||||||||||||||||||||||||
| while !rosetta_blocks.is_empty() { | ||||||||||||||||||||||||||||||
| let mut last_block_index = batch_start_idx; | ||||||||||||||||||||||||||||||
| for rosetta_block in rosetta_blocks { | ||||||||||||||||||||||||||||||
| if rosetta_block.index < last_block_index { | ||||||||||||||||||||||||||||||
| bail!(format!( | ||||||||||||||||||||||||||||||
| "Processing blocks not in order, previous processed block: {last_block_index}, current block {}", | ||||||||||||||||||||||||||||||
| rosetta_block.index | ||||||||||||||||||||||||||||||
| )); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| last_block_index = rosetta_block.index; | ||||||||||||||||||||||||||||||
| match rosetta_block.get_transaction().operation { | ||||||||||||||||||||||||||||||
| crate::common::storage::types::IcrcOperation::Burn { | ||||||||||||||||||||||||||||||
| from, | ||||||||||||||||||||||||||||||
|
|
@@ -290,9 +345,11 @@ pub fn update_account_balances( | |||||||||||||||||||||||||||||
| connection, | ||||||||||||||||||||||||||||||
| &mut account_balances_cache, | ||||||||||||||||||||||||||||||
| )?; | ||||||||||||||||||||||||||||||
| if let Some(collector) = | ||||||||||||||||||||||||||||||
| get_fee_collector_from_block(&rosetta_block, connection)? | ||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||
| if let Some(collector) = get_107_fee_collector_or_legacy( | ||||||||||||||||||||||||||||||
| &rosetta_block, | ||||||||||||||||||||||||||||||
| connection, | ||||||||||||||||||||||||||||||
| current_fee_collector_107, | ||||||||||||||||||||||||||||||
| )? { | ||||||||||||||||||||||||||||||
| credit( | ||||||||||||||||||||||||||||||
| collector, | ||||||||||||||||||||||||||||||
| fee, | ||||||||||||||||||||||||||||||
|
|
@@ -317,9 +374,11 @@ pub fn update_account_balances( | |||||||||||||||||||||||||||||
| connection, | ||||||||||||||||||||||||||||||
| &mut account_balances_cache, | ||||||||||||||||||||||||||||||
| )?; | ||||||||||||||||||||||||||||||
| if let Some(collector) = | ||||||||||||||||||||||||||||||
| get_fee_collector_from_block(&rosetta_block, connection)? | ||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||
| if let Some(collector) = get_107_fee_collector_or_legacy( | ||||||||||||||||||||||||||||||
| &rosetta_block, | ||||||||||||||||||||||||||||||
| connection, | ||||||||||||||||||||||||||||||
| current_fee_collector_107, | ||||||||||||||||||||||||||||||
| )? { | ||||||||||||||||||||||||||||||
| credit( | ||||||||||||||||||||||||||||||
| collector, | ||||||||||||||||||||||||||||||
| fee, | ||||||||||||||||||||||||||||||
|
|
@@ -342,11 +401,21 @@ pub fn update_account_balances( | |||||||||||||||||||||||||||||
| .unwrap_or(Nat(BigUint::zero())); | ||||||||||||||||||||||||||||||
| debit( | ||||||||||||||||||||||||||||||
| from, | ||||||||||||||||||||||||||||||
| fee, | ||||||||||||||||||||||||||||||
| fee.clone(), | ||||||||||||||||||||||||||||||
| rosetta_block.index, | ||||||||||||||||||||||||||||||
| connection, | ||||||||||||||||||||||||||||||
| &mut account_balances_cache, | ||||||||||||||||||||||||||||||
| )?; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| if let Some(Some(collector)) = current_fee_collector_107 { | ||||||||||||||||||||||||||||||
| credit( | ||||||||||||||||||||||||||||||
| collector, | ||||||||||||||||||||||||||||||
| fee, | ||||||||||||||||||||||||||||||
| rosetta_block.index, | ||||||||||||||||||||||||||||||
| connection, | ||||||||||||||||||||||||||||||
| &mut account_balances_cache, | ||||||||||||||||||||||||||||||
| )?; | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| crate::common::storage::types::IcrcOperation::Transfer { | ||||||||||||||||||||||||||||||
| from, | ||||||||||||||||||||||||||||||
|
|
@@ -378,9 +447,11 @@ pub fn update_account_balances( | |||||||||||||||||||||||||||||
| &mut account_balances_cache, | ||||||||||||||||||||||||||||||
| )?; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| if let Some(collector) = | ||||||||||||||||||||||||||||||
| get_fee_collector_from_block(&rosetta_block, connection)? | ||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||
| if let Some(collector) = get_107_fee_collector_or_legacy( | ||||||||||||||||||||||||||||||
| &rosetta_block, | ||||||||||||||||||||||||||||||
| connection, | ||||||||||||||||||||||||||||||
| current_fee_collector_107, | ||||||||||||||||||||||||||||||
| )? { | ||||||||||||||||||||||||||||||
| credit( | ||||||||||||||||||||||||||||||
| collector, | ||||||||||||||||||||||||||||||
| fee, | ||||||||||||||||||||||||||||||
|
|
@@ -390,6 +461,12 @@ pub fn update_account_balances( | |||||||||||||||||||||||||||||
| )?; | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| crate::common::storage::types::IcrcOperation::FeeCollector { | ||||||||||||||||||||||||||||||
| fee_collector, | ||||||||||||||||||||||||||||||
| caller: _, | ||||||||||||||||||||||||||||||
| } => { | ||||||||||||||||||||||||||||||
| current_fee_collector_107 = Some(fee_collector); | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
|
@@ -407,6 +484,13 @@ pub fn update_account_balances( | |||||||||||||||||||||||||||||
| })?; | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| if collector_before != current_fee_collector_107 | ||||||||||||||||||||||||||||||
| && let Some(collector) = current_fee_collector_107 | ||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||
| insert_tx.prepare_cached("INSERT INTO rosetta_metadata (key, value) VALUES (?1, ?2) ON CONFLICT (key) DO UPDATE SET value = excluded.value;")?.execute(params![METADATA_FEE_COL, candid::encode_one(collector)?])?; | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| let last_block_index_bytes = last_block_index.to_le_bytes(); | ||||||||||||||||||||||||||||||
| insert_tx.prepare_cached("INSERT INTO rosetta_metadata (key, value) VALUES (?1, ?2) ON CONFLICT (key) DO UPDATE SET value = excluded.value;")?.execute(params![METADATA_BLOCK_IDX, last_block_index_bytes])?; | ||||||||||||||||||||||||||||||
| insert_tx.commit()?; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| if flush_cache_and_shrink_memory { | ||||||||||||||||||||||||||||||
|
|
@@ -416,7 +500,7 @@ pub fn update_account_balances( | |||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // Fetch the next batch of blocks | ||||||||||||||||||||||||||||||
| batch_start_idx = get_highest_block_idx_in_account_balance_table(connection)? | ||||||||||||||||||||||||||||||
| batch_start_idx = get_highest_processed_block_idx(connection)? | ||||||||||||||||||||||||||||||
| .context("No blocks in account balance table after inserting")? | ||||||||||||||||||||||||||||||
| + 1; | ||||||||||||||||||||||||||||||
| batch_end_idx = batch_start_idx + batch_size; | ||||||||||||||||||||||||||||||
|
|
@@ -514,6 +598,22 @@ pub fn store_blocks( | |||||||||||||||||||||||||||||
| fee, | ||||||||||||||||||||||||||||||
| expires_at, | ||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||
| crate::common::storage::types::IcrcOperation::FeeCollector { | ||||||||||||||||||||||||||||||
| fee_collector: _, | ||||||||||||||||||||||||||||||
| caller: _, | ||||||||||||||||||||||||||||||
| } => ( | ||||||||||||||||||||||||||||||
| "107feecol", | ||||||||||||||||||||||||||||||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this constant should be defined in the |
||||||||||||||||||||||||||||||
| None, | ||||||||||||||||||||||||||||||
| None, | ||||||||||||||||||||||||||||||
| None, | ||||||||||||||||||||||||||||||
| None, | ||||||||||||||||||||||||||||||
| None, | ||||||||||||||||||||||||||||||
| None, | ||||||||||||||||||||||||||||||
| Nat::from(0u64), | ||||||||||||||||||||||||||||||
| None, | ||||||||||||||||||||||||||||||
| None, | ||||||||||||||||||||||||||||||
| None, | ||||||||||||||||||||||||||||||
| ), | ||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| // SQLite doesn't support unsigned 64-bit integers. We need to convert the timestamps to signed | ||||||||||||||||||||||||||||||
|
|
@@ -666,16 +766,10 @@ pub fn get_blocks_by_transaction_hash( | |||||||||||||||||||||||||||||
| read_blocks(&mut stmt, params![hash.as_slice().to_vec()]) | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| pub fn get_highest_block_idx_in_account_balance_table( | ||||||||||||||||||||||||||||||
| connection: &Connection, | ||||||||||||||||||||||||||||||
| ) -> anyhow::Result<Option<u64>> { | ||||||||||||||||||||||||||||||
| match connection | ||||||||||||||||||||||||||||||
| .prepare_cached("SELECT block_idx FROM account_balances WHERE block_idx = (SELECT MAX(block_idx) FROM account_balances)")? | ||||||||||||||||||||||||||||||
| .query_map(params![], |row| row.get(0))? | ||||||||||||||||||||||||||||||
| .next() | ||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||
| pub fn get_highest_processed_block_idx(connection: &Connection) -> anyhow::Result<Option<u64>> { | ||||||||||||||||||||||||||||||
| match get_rosetta_metadata(connection, METADATA_BLOCK_IDX)? { | ||||||||||||||||||||||||||||||
| Some(value) => Ok(Some(u64::from_le_bytes(value.as_slice().try_into()?))), | ||||||||||||||||||||||||||||||
| None => Ok(None), | ||||||||||||||||||||||||||||||
| Some(res) => Ok(res?), | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
|
|
@@ -865,6 +959,10 @@ pub fn repair_fee_collector_balances( | |||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| info!("Starting balance reconciliation..."); | ||||||||||||||||||||||||||||||
| connection.execute("DELETE FROM account_balances", params![])?; | ||||||||||||||||||||||||||||||
| connection.execute( | ||||||||||||||||||||||||||||||
| &format!("DELETE FROM rosetta_metadata WHERE key = '{METADATA_BLOCK_IDX}' OR key = '{METADATA_FEE_COL}'"), | ||||||||||||||||||||||||||||||
| params![], | ||||||||||||||||||||||||||||||
| )?; | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
| if block_count > 0 { | ||||||||||||||||||||||||||||||
| info!("Reprocessing all blocks..."); | ||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would Rosetta behave if we:
rosetta_metadatatable, and thenAs long as there was no
107feecolblock in the ledger yet, I could imagine that everything will work? What about if one or more107feecolblocks were processed? Would the old Rosetta still start up with the new DB? Would it correctly e.g., determine the highest block (probably not if the latest block was a107feecolblock, but maybe otherwise yes?)? Is there any easy way to introduce a breaking database change, so that an old Rosetta version wouldn't start up when using a new DB? We discussed adding (in a separate ticket) a "schema version" entry to therosetta_metadatatable that we could check going forward, but for this upgrade that wouldn't work. Should we be looking at a major version bump when we create a release with theICRC-107support?