Skip to content

Commit 89deab4

Browse files
authored
rpc-index: deprecate and drop transaction info column (#25392)
## Description Deprecates and drops the transaction info column in the rpc_indexes. This also fixes a bug that was introduced in #24797 that could lead to the balance index being incorrect if a fullnode restored indexes with the 1.64 release. ## Test plan How did you test the new or updated feature? --- ## Release notes Check each box that your changes affect. If none of the boxes relate to your changes, release notes aren't required. For each box you select, include information after the relevant heading that describes the impact of your changes that a user might notice and any actions they must take to implement updates. - [ ] Protocol: - [ ] Nodes (Validators and Full nodes): - [x] gRPC: Fixes a bug that was introduced in #24797 that could lead to the balance index being incorrect if a fullnode restored indexes with the 1.64 release. - [ ] JSON-RPC: - [ ] GraphQL: - [ ] CLI: - [ ] Rust SDK: - [ ] Indexing Framework:
1 parent 72773a7 commit 89deab4

File tree

10 files changed

+168
-192
lines changed

10 files changed

+168
-192
lines changed

crates/sui-core/src/rpc_index.rs

Lines changed: 32 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,8 @@ struct IndexStoreTables {
330330
///
331331
/// Only contains entries for transactions which have yet to be pruned from the main database.
332332
#[default_options_override_fn = "default_table_options"]
333+
#[allow(unused)]
334+
#[deprecated]
333335
transactions: DBMap<TransactionDigest, TransactionInfo>,
334336

335337
/// An index of object ownership.
@@ -438,11 +440,12 @@ impl IndexStoreTables {
438440
events_table_options(index_options.events_compaction_filter),
439441
);
440442

441-
IndexStoreTables::open_tables_read_write(
443+
IndexStoreTables::open_tables_read_write_with_deprecation_option(
442444
path.into(),
443445
MetricConf::new("rpc-index"),
444446
None,
445447
Some(DBMapTableConfigMap::new(table_options)),
448+
true, // remove deprecated tables
446449
)
447450
}
448451

@@ -451,11 +454,12 @@ impl IndexStoreTables {
451454
options: typed_store::rocksdb::Options,
452455
table_options: Option<DBMapTableConfigMap>,
453456
) -> Self {
454-
IndexStoreTables::open_tables_read_write(
457+
IndexStoreTables::open_tables_read_write_with_deprecation_option(
455458
path.into(),
456459
MetricConf::new("rpc-index"),
457460
Some(options),
458461
table_options,
462+
true, // remove deprecated tables
459463
)
460464
}
461465

@@ -510,7 +514,7 @@ impl IndexStoreTables {
510514
});
511515

512516
if let Some(checkpoint_range) = checkpoint_range {
513-
self.index_existing_transactions(
517+
self.index_existing_checkpoints(
514518
authority_store,
515519
checkpoint_store,
516520
checkpoint_range,
@@ -558,7 +562,7 @@ impl IndexStoreTables {
558562
}
559563

560564
#[tracing::instrument(skip(self, authority_store, checkpoint_store, rpc_config))]
561-
fn index_existing_transactions(
565+
fn index_existing_checkpoints(
562566
&mut self,
563567
authority_store: &AuthorityStore,
564568
checkpoint_store: &CheckpointStore,
@@ -573,17 +577,19 @@ impl IndexStoreTables {
573577

574578
checkpoint_range.into_par_iter().try_for_each(|seq| {
575579
let load_events = rpc_config.authenticated_events_indexing();
576-
let checkpoint_data = sparse_checkpoint_data_for_backfill(
580+
let Some(checkpoint_data) = sparse_checkpoint_data_for_epoch_backfill(
577581
authority_store,
578582
checkpoint_store,
579583
seq,
580584
load_events,
581-
)?;
585+
)?
586+
else {
587+
return Ok(());
588+
};
582589

583-
let mut batch = self.transactions.batch();
590+
let mut batch = self.epochs.batch();
584591

585592
self.index_epoch(&checkpoint_data, &mut batch)?;
586-
self.index_transactions(&checkpoint_data, &mut batch, load_events)?;
587593

588594
batch
589595
.write_opt(bulk_ingestion_write_options())
@@ -601,15 +607,10 @@ impl IndexStoreTables {
601607
fn prune(
602608
&self,
603609
pruned_checkpoint_watermark: u64,
604-
checkpoint_contents_to_prune: &[CheckpointContents],
610+
_checkpoint_contents_to_prune: &[CheckpointContents],
605611
) -> Result<(), TypedStoreError> {
606-
let mut batch = self.transactions.batch();
607-
608-
let transactions_to_prune = checkpoint_contents_to_prune
609-
.iter()
610-
.flat_map(|contents| contents.iter().map(|digests| digests.transaction));
612+
let mut batch = self.watermark.batch();
611613

612-
batch.delete_batch(&self.transactions, transactions_to_prune)?;
613614
batch.insert_batch(
614615
&self.watermark,
615616
[(Watermark::Pruned, pruned_checkpoint_watermark)],
@@ -630,7 +631,7 @@ impl IndexStoreTables {
630631
"indexing checkpoint"
631632
);
632633

633-
let mut batch = self.transactions.batch();
634+
let mut batch = self.owner.batch();
634635

635636
self.index_epoch(checkpoint, &mut batch)?;
636637
self.index_transactions(
@@ -799,20 +800,18 @@ impl IndexStoreTables {
799800

800801
// iterate in reverse order, process accumulator settlements first
801802
for (tx_idx, tx) in checkpoint.transactions.iter().enumerate().rev() {
802-
let info = TransactionInfo::new(
803-
tx.transaction.transaction_data(),
803+
let balance_changes = sui_types::balance_change::derive_balance_changes(
804804
&tx.effects,
805805
&tx.input_objects,
806806
&tx.output_objects,
807-
cp,
808-
);
809-
810-
let balance_changes = info.balance_changes.iter().filter_map(|change| {
811-
if let TypeTag::Struct(coin_type) = &change.coin_type {
807+
)
808+
.into_iter()
809+
.filter_map(|change| {
810+
if let TypeTag::Struct(coin_type) = change.coin_type {
812811
Some((
813812
BalanceKey {
814813
owner: change.address,
815-
coin_type: coin_type.as_ref().to_owned(),
814+
coin_type: *coin_type,
816815
},
817816
BalanceIndexInfo {
818817
balance_delta: change.amount,
@@ -824,9 +823,6 @@ impl IndexStoreTables {
824823
});
825824
batch.partial_merge_batch(&self.balance, balance_changes)?;
826825

827-
let digest = tx.transaction.digest();
828-
batch.insert_batch(&self.transactions, [(digest, info)])?;
829-
830826
if index_events {
831827
if let Some(version) = self.extract_accumulator_version(tx) {
832828
current_accumulator_version = Some(version);
@@ -941,13 +937,6 @@ impl IndexStoreTables {
941937
self.epochs.get(&epoch)
942938
}
943939

944-
fn get_transaction_info(
945-
&self,
946-
digest: &TransactionDigest,
947-
) -> Result<Option<TransactionInfo>, TypedStoreError> {
948-
self.transactions.get(digest)
949-
}
950-
951940
fn event_iter(
952941
&self,
953942
stream_id: SuiAddress,
@@ -1460,13 +1449,6 @@ impl RpcIndexStore {
14601449
self.tables.get_epoch_info(epoch)
14611450
}
14621451

1463-
pub fn get_transaction_info(
1464-
&self,
1465-
digest: &TransactionDigest,
1466-
) -> Result<Option<TransactionInfo>, TypedStoreError> {
1467-
self.tables.get_transaction_info(digest)
1468-
}
1469-
14701452
pub fn owner_iter(
14711453
&self,
14721454
owner: SuiAddress,
@@ -1742,17 +1724,23 @@ impl LiveObjectIndexer for RpcLiveObjectIndexer<'_> {
17421724

17431725
// TODO figure out a way to dedup this logic. Today we'd need to do quite a bit of refactoring to
17441726
// make it possible.
1745-
fn sparse_checkpoint_data_for_backfill(
1727+
fn sparse_checkpoint_data_for_epoch_backfill(
17461728
authority_store: &AuthorityStore,
17471729
checkpoint_store: &CheckpointStore,
17481730
checkpoint: u64,
17491731
load_events: bool,
1750-
) -> Result<CheckpointData, StorageError> {
1732+
) -> Result<Option<CheckpointData>, StorageError> {
17511733
use sui_types::full_checkpoint_content::CheckpointTransaction;
17521734

17531735
let summary = checkpoint_store
17541736
.get_checkpoint_by_sequence_number(checkpoint)?
17551737
.ok_or_else(|| StorageError::missing(format!("missing checkpoint {checkpoint}")))?;
1738+
1739+
// Only load genesis and end of epoch checkpoints
1740+
if summary.end_of_epoch_data.is_none() && summary.sequence_number != 0 {
1741+
return Ok(None);
1742+
}
1743+
17561744
let contents = checkpoint_store
17571745
.get_checkpoint_contents(&summary.content_digest)?
17581746
.ok_or_else(|| StorageError::missing(format!("missing checkpoint {checkpoint}")))?;
@@ -1807,7 +1795,7 @@ fn sparse_checkpoint_data_for_backfill(
18071795
transactions: full_transactions,
18081796
};
18091797

1810-
Ok(checkpoint_data)
1798+
Ok(Some(checkpoint_data))
18111799
}
18121800

18131801
fn get_balance_and_type_if_coin(object: &Object) -> Result<Option<(StructTag, u64)>, StorageError> {

crates/sui-core/src/storage.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ use sui_types::storage::ObjectStore;
3434
use sui_types::storage::OwnedObjectInfo;
3535
use sui_types::storage::RpcIndexes;
3636
use sui_types::storage::RpcStateReader;
37-
use sui_types::storage::TransactionInfo;
3837
use sui_types::storage::WriteStore;
3938
use sui_types::storage::error::Error as StorageError;
4039
use sui_types::storage::error::Result;
@@ -594,15 +593,6 @@ impl RpcIndexes for RestReadStore {
594593
.map_err(StorageError::custom)
595594
}
596595

597-
fn get_transaction_info(
598-
&self,
599-
digest: &TransactionDigest,
600-
) -> sui_types::storage::error::Result<Option<TransactionInfo>> {
601-
self.index()?
602-
.get_transaction_info(digest)
603-
.map_err(StorageError::custom)
604-
}
605-
606596
fn owned_objects_iter(
607597
&self,
608598
owner: SuiAddress,

crates/sui-rpc-api/src/grpc/v2/ledger_service/get_checkpoint.rs

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use sui_rpc::proto::sui::rpc::v2::ObjectSet;
1919
use sui_rpc::proto::sui::rpc::v2::TransactionEvents;
2020
use sui_rpc::proto::sui::rpc::v2::get_checkpoint_request::CheckpointId;
2121
use sui_sdk_types::Digest;
22+
use sui_types::balance_change::derive_balance_changes_2;
2223

2324
pub const READ_MASK_DEFAULT: &str = "sequence_number,digest";
2425

@@ -121,21 +122,15 @@ pub fn get_checkpoint(
121122
.transactions
122123
.into_iter()
123124
.map(|t| {
124-
let balance_changes = submask
125-
.contains(ExecutedTransaction::BALANCE_CHANGES_FIELD)
126-
.then(|| {
127-
service
128-
.reader
129-
.get_transaction_info(&t.transaction.digest())
130-
.map(|info| {
131-
info.balance_changes
132-
.into_iter()
133-
.map(sui_rpc::proto::sui::rpc::v2::BalanceChange::from)
134-
.collect::<Vec<_>>()
135-
})
136-
})
137-
.flatten()
138-
.unwrap_or_default();
125+
let balance_changes =
126+
if submask.contains(ExecutedTransaction::BALANCE_CHANGES_FIELD) {
127+
derive_balance_changes_2(&t.effects, &checkpoint_data.object_set)
128+
.into_iter()
129+
.map(Into::into)
130+
.collect()
131+
} else {
132+
Vec::new()
133+
};
139134
let mut transaction = ExecutedTransaction::merge_from(&t, &submask);
140135
transaction.checkpoint = submask
141136
.contains(ExecutedTransaction::CHECKPOINT_FIELD)

0 commit comments

Comments
 (0)