Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

This file was deleted.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

52 changes: 51 additions & 1 deletion substrate/frame/revive/rpc/src/receipt_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ impl<B: BlockInfoProvider> ReceiptProvider<B> {

query!(
r#"
INSERT INTO transaction_hashes (transaction_hash, block_hash, transaction_index)
INSERT OR REPLACE INTO transaction_hashes (transaction_hash, block_hash, transaction_index)
VALUES ($1, $2, $3)
"#,
transaction_hash,
Expand Down Expand Up @@ -765,6 +765,56 @@ mod tests {
return Ok(());
}

#[sqlx::test]
async fn test_reorg_same_transaction_hash(pool: SqlitePool) -> anyhow::Result<()> {
let provider = setup_sqlite_provider(pool).await;

// Build two blocks at the same height with the same transaction hash
let tx_hash = H256::from([42u8; 32]);

// Block A at height 1
let block_a = MockBlockInfo { hash: H256::from([1u8; 32]), number: 1 };
let ethereum_hash_a = H256::from([2u8; 32]);
let receipts_a = vec![(
TransactionSigned::default(),
ReceiptInfo {
transaction_hash: tx_hash,
transaction_index: U256::from(0),
..Default::default()
},
)];

provider.insert(&block_a, &receipts_a, &ethereum_hash_a).await?;

// Verify transaction points to block A
let (found_hash, _) = provider.find_transaction(&tx_hash).await.unwrap();
assert_eq!(found_hash, block_a.hash);

// Clear the in-memory map to simulate server restart
provider.block_number_to_hashes.lock().await.clear();

// Block B at same height 1 (re-org) with SAME transaction
let block_b = MockBlockInfo { hash: H256::from([3u8; 32]), number: 1 };
let ethereum_hash_b = H256::from([4u8; 32]);
let receipts_b = vec![(
TransactionSigned::default(),
ReceiptInfo {
transaction_hash: tx_hash, // Same tx hash!
transaction_index: U256::from(0),
..Default::default()
},
)];

// This should NOT fail with UNIQUE constraint violation
provider.insert(&block_b, &receipts_b, &ethereum_hash_b).await?;

// Transaction should now point to block B
let (found_hash, _) = provider.find_transaction(&tx_hash).await.unwrap();
assert_eq!(found_hash, block_b.hash);

Ok(())
}

#[sqlx::test]
async fn test_receipts_count_per_block(pool: SqlitePool) -> anyhow::Result<()> {
let provider = setup_sqlite_provider(pool).await;
Expand Down
Loading