@@ -1671,6 +1671,9 @@ impl BlockProcessor {
1671
1671
let mut total_txs_removed = 0 ;
1672
1672
let mut total_utxos_restored = 0 ;
1673
1673
let mut total_utxos_removed = 0 ;
1674
+ let mut total_spk_entries_cleaned = 0 ;
1675
+ let mut total_inputs_cleaned = 0 ;
1676
+ let mut total_outs_refs_cleaned = 0 ;
1674
1677
1675
1678
let block_spends_table = db
1676
1679
. open_table ( TABLE_BLOCK_SPENDS )
@@ -1696,6 +1699,26 @@ impl BlockProcessor {
1696
1699
. open_table ( TABLE_BLOCK_HEIGHTS )
1697
1700
. map_err ( |e| BlockProcError :: Custom ( format ! ( "Block heights table error: {}" , e) ) ) ?;
1698
1701
1702
+ // Open the SPKs table for script pubkey cleanup during rollback
1703
+ let mut spks_table = db
1704
+ . open_table ( TABLE_SPKS )
1705
+ . map_err ( |e| BlockProcError :: Custom ( format ! ( "SPKs table error: {}" , e) ) ) ?;
1706
+
1707
+ // Open the inputs table to clean up input references
1708
+ let mut inputs_table = db
1709
+ . open_table ( TABLE_INPUTS )
1710
+ . map_err ( |e| BlockProcError :: Custom ( format ! ( "Inputs table error: {}" , e) ) ) ?;
1711
+
1712
+ // Open the outs table to clean up spending relationships
1713
+ let mut outs_table = db
1714
+ . open_table ( TABLE_OUTS )
1715
+ . map_err ( |e| BlockProcError :: Custom ( format ! ( "Outs table error: {}" , e) ) ) ?;
1716
+
1717
+ // Open tx_blocks table to clean up transaction-block associations
1718
+ let mut tx_blocks_table = db
1719
+ . open_table ( TABLE_TX_BLOCKS )
1720
+ . map_err ( |e| BlockProcError :: Custom ( format ! ( "TX-Blocks table error: {}" , e) ) ) ?;
1721
+
1699
1722
// Iterate through blocks to roll back (should be in descending height order)
1700
1723
for & ( height, block_id) in blocks {
1701
1724
log:: info!(
@@ -1708,6 +1731,9 @@ impl BlockProcessor {
1708
1731
let mut block_utxos_restored = 0 ;
1709
1732
let mut block_utxos_removed = 0 ;
1710
1733
let mut block_txs_removed = 0 ;
1734
+ let mut block_spk_entries_cleaned = 0 ;
1735
+ let mut block_inputs_cleaned = 0 ;
1736
+ let mut block_outs_refs_cleaned = 0 ;
1711
1737
1712
1738
// 1. Restore UTXOs spent in this block
1713
1739
if let Some ( spends_record) = block_spends_table
@@ -1750,27 +1776,119 @@ impl BlockProcessor {
1750
1776
. map_err ( |e| BlockProcError :: Custom ( format ! ( "Tx lookup error: {}" , e) ) ) ?
1751
1777
{
1752
1778
let tx = tx_record. value ( ) ;
1753
- let num_outputs = tx. as_ref ( ) . outputs . len ( ) ;
1779
+ let outputs = tx. as_ref ( ) . outputs . as_slice ( ) ;
1780
+ let num_outputs = outputs. len ( ) ;
1754
1781
block_utxos_removed += num_outputs;
1755
1782
total_utxos_removed += num_outputs;
1756
1783
1757
- for vout in 0 ..num_outputs {
1758
- utxos_table. remove ( & ( txno, vout as u32 ) ) . map_err ( |e| {
1784
+ // Get the number of inputs for this transaction
1785
+ let inputs_count = tx. as_ref ( ) . inputs . len ( ) ;
1786
+
1787
+ for ( vout_idx, output) in outputs. iter ( ) . enumerate ( ) {
1788
+ // Remove UTXOs
1789
+ utxos_table. remove ( & ( txno, vout_idx as u32 ) ) . map_err ( |e| {
1759
1790
BlockProcError :: Custom ( format ! ( "UTXO removal error: {}" , e) )
1760
1791
} ) ?;
1761
1792
1762
1793
log:: debug!(
1763
1794
target: NAME ,
1764
1795
"Removed UTXO: txno={}, vout={}" ,
1765
1796
txno,
1766
- vout
1797
+ vout_idx
1798
+ ) ;
1799
+
1800
+ // 4. Clean up script pubkey index for this transaction output
1801
+ let script = & output. script_pubkey ;
1802
+ if !script. is_empty ( ) {
1803
+ let txnos = spks_table
1804
+ . get ( script. as_slice ( ) )
1805
+ . map_err ( |e| {
1806
+ BlockProcError :: Custom ( format ! ( "SPKs lookup error: {}" , e) )
1807
+ } ) ?
1808
+ . map ( |t| t. value ( ) . to_vec ( ) ) ;
1809
+
1810
+ if let Some ( mut txnos) = txnos {
1811
+ // Remove this transaction from the list
1812
+ if let Some ( pos) = txnos. iter ( ) . position ( |& t| t == txno) {
1813
+ txnos. remove ( pos) ;
1814
+ block_spk_entries_cleaned += 1 ;
1815
+
1816
+ // If the list is not empty, update it; otherwise, remove
1817
+ // the entry
1818
+ if !txnos. is_empty ( ) {
1819
+ spks_table. insert ( script. as_slice ( ) , txnos) . map_err (
1820
+ |e| {
1821
+ BlockProcError :: Custom ( format ! (
1822
+ "SPKs update error: {}" ,
1823
+ e
1824
+ ) )
1825
+ } ,
1826
+ ) ?;
1827
+ } else {
1828
+ spks_table. remove ( script. as_slice ( ) ) . map_err ( |e| {
1829
+ BlockProcError :: Custom ( format ! (
1830
+ "SPKs removal error: {}" ,
1831
+ e
1832
+ ) )
1833
+ } ) ?;
1834
+ }
1835
+
1836
+ log:: debug!(
1837
+ target: NAME ,
1838
+ "Cleaned up SPK index for txno={}, vout={}" ,
1839
+ txno,
1840
+ vout_idx
1841
+ ) ;
1842
+ }
1843
+ }
1844
+ }
1845
+ }
1846
+
1847
+ // 5. Clean up inputs table for this transaction
1848
+ for input_idx in 0 ..inputs_count {
1849
+ if inputs_table
1850
+ . remove ( & ( txno, input_idx as u32 ) )
1851
+ . map_err ( |e| {
1852
+ BlockProcError :: Custom ( format ! ( "Inputs removal error: {}" , e) )
1853
+ } ) ?
1854
+ . is_some ( )
1855
+ {
1856
+ block_inputs_cleaned += 1 ;
1857
+ log:: debug!(
1858
+ target: NAME ,
1859
+ "Removed input reference: txno={}, input_idx={}" ,
1860
+ txno,
1861
+ input_idx
1862
+ ) ;
1863
+ }
1864
+ }
1865
+ total_inputs_cleaned += block_inputs_cleaned;
1866
+
1867
+ // 6. Clean up this transaction from spending relationships
1868
+ if outs_table
1869
+ . remove ( txno)
1870
+ . map_err ( |e| {
1871
+ BlockProcError :: Custom ( format ! ( "Outs lookup error: {}" , e) )
1872
+ } ) ?
1873
+ . is_some ( )
1874
+ {
1875
+ block_outs_refs_cleaned += 1 ;
1876
+ log:: debug!(
1877
+ target: NAME ,
1878
+ "Removed spending relationship for txno={}" ,
1879
+ txno
1767
1880
) ;
1768
1881
}
1769
1882
}
1883
+
1884
+ // 7. Remove transaction-block association
1885
+ tx_blocks_table. remove ( txno) . map_err ( |e| {
1886
+ BlockProcError :: Custom ( format ! ( "TX-Blocks removal error: {}" , e) )
1887
+ } ) ?;
1770
1888
}
1771
1889
}
1772
1890
1773
- // 4 . Remove this block from the heights tables
1891
+ // 8 . Remove this block from the heights tables
1774
1892
heights_table
1775
1893
. remove ( height)
1776
1894
. map_err ( |e| BlockProcError :: Custom ( format ! ( "Heights removal error: {}" , e) ) ) ?;
@@ -1786,23 +1904,32 @@ impl BlockProcessor {
1786
1904
block_id
1787
1905
) ;
1788
1906
1907
+ total_spk_entries_cleaned += block_spk_entries_cleaned;
1908
+ total_outs_refs_cleaned += block_outs_refs_cleaned;
1909
+
1789
1910
log:: info!(
1790
1911
target: NAME ,
1791
- "Block rollback stats for height {}: removed {} transactions, restored {} UTXOs, removed {} UTXOs" ,
1912
+ "Block rollback stats for height {}: removed {} transactions, restored {} UTXOs, removed {} UTXOs, cleaned {} SPK entries, {} input refs, {} output refs " ,
1792
1913
height,
1793
1914
block_txs_removed,
1794
1915
block_utxos_restored,
1795
- block_utxos_removed
1916
+ block_utxos_removed,
1917
+ block_spk_entries_cleaned,
1918
+ block_inputs_cleaned,
1919
+ block_outs_refs_cleaned
1796
1920
) ;
1797
1921
}
1798
1922
1799
1923
log:: info!(
1800
1924
target: NAME ,
1801
- "Successfully rolled back {} blocks: removed {} transactions, restored {} UTXOs, removed {} UTXOs" ,
1925
+ "Successfully rolled back {} blocks: removed {} transactions, restored {} UTXOs, removed {} UTXOs, cleaned {} SPK entries, {} input refs, {} output refs " ,
1802
1926
blocks. len( ) ,
1803
1927
total_txs_removed,
1804
1928
total_utxos_restored,
1805
- total_utxos_removed
1929
+ total_utxos_removed,
1930
+ total_spk_entries_cleaned,
1931
+ total_inputs_cleaned,
1932
+ total_outs_refs_cleaned
1806
1933
) ;
1807
1934
1808
1935
Ok ( ( ) )
0 commit comments