1
1
use crate :: config:: { Config , PredicatesApi } ;
2
- use crate :: core:: protocol:: sequencing:: {
3
- update_storage_and_augment_bitcoin_block_with_inscription_reveal_data_tx,
4
- update_storage_and_augment_bitcoin_block_with_inscription_transfer_data_tx,
5
- } ;
2
+ use crate :: core:: pipeline:: processors:: inscription_indexing:: re_augment_block_with_ordinals_operations;
6
3
use crate :: core:: { self , get_inscriptions_revealed_in_block} ;
7
- use crate :: db:: {
8
- find_all_inscriptions_in_block, get_any_entry_in_ordinal_activities,
9
- open_readonly_hord_db_conn, InscriptionHeigthHint ,
10
- } ;
4
+ use crate :: db:: { get_any_entry_in_ordinal_activities, open_readonly_hord_db_conn} ;
11
5
use crate :: download:: download_ordinals_dataset_if_required;
12
6
use crate :: service:: {
13
7
open_readwrite_predicates_db_conn_or_panic, update_predicate_status, PredicateStatus ,
@@ -19,15 +13,15 @@ use chainhook_sdk::chainhooks::bitcoin::{
19
13
evaluate_bitcoin_chainhooks_on_chain_event, handle_bitcoin_hook_action,
20
14
BitcoinChainhookOccurrence , BitcoinTriggerChainhook ,
21
15
} ;
22
- use chainhook_sdk:: chainhooks:: types:: { BitcoinChainhookSpecification , BitcoinPredicateType } ;
16
+ use chainhook_sdk:: chainhooks:: types:: BitcoinChainhookSpecification ;
23
17
use chainhook_sdk:: indexer:: bitcoin:: {
24
18
build_http_client, download_and_parse_block_with_retry, retrieve_block_hash_with_retry,
25
19
} ;
26
20
use chainhook_sdk:: observer:: { gather_proofs, EventObserverConfig } ;
27
21
use chainhook_sdk:: types:: {
28
22
BitcoinBlockData , BitcoinChainEvent , BitcoinChainUpdatedWithBlocksData ,
29
23
} ;
30
- use chainhook_sdk:: utils:: { file_append, send_request, Context } ;
24
+ use chainhook_sdk:: utils:: { file_append, send_request, BlockHeights , Context } ;
31
25
use std:: collections:: HashMap ;
32
26
33
27
// TODO(lgalabru): Re-introduce support for blocks[] !!! gracefully handle hints for non consecutive blocks
@@ -49,72 +43,69 @@ pub async fn scan_bitcoin_chainstate_via_rpc_using_predicate(
49
43
return Err ( format ! ( "Bitcoin RPC error: {}" , message. to_string( ) ) ) ;
50
44
}
51
45
} ;
46
+ let mut floating_end_block = false ;
52
47
53
- let start_block = match predicate_spec. start_block {
54
- Some ( start_block) => start_block,
55
- None => {
56
- return Err (
57
- "Bitcoin chainhook specification must include a field start_block in replay mode"
58
- . into ( ) ,
59
- ) ;
60
- }
61
- } ;
62
-
63
- let ( mut end_block, floating_end_block) = match predicate_spec. end_block {
64
- Some ( end_block) => ( end_block, false ) ,
65
- None => match bitcoin_rpc. get_blockchain_info ( ) {
66
- Ok ( result) => ( result. blocks - 1 , true ) ,
67
- Err ( e) => {
68
- return Err ( format ! (
69
- "unable to retrieve Bitcoin chain tip ({})" ,
70
- e. to_string( )
71
- ) ) ;
48
+ let mut block_heights_to_scan = if let Some ( ref blocks) = predicate_spec. blocks {
49
+ BlockHeights :: Blocks ( blocks. clone ( ) ) . get_sorted_entries ( )
50
+ } else {
51
+ let start_block = match predicate_spec. start_block {
52
+ Some ( start_block) => start_block,
53
+ None => {
54
+ return Err (
55
+ "Bitcoin chainhook specification must include a field start_block in replay mode"
56
+ . into ( ) ,
57
+ ) ;
72
58
}
73
- } ,
59
+ } ;
60
+ let ( end_block, update_end_block) = match predicate_spec. end_block {
61
+ Some ( end_block) => ( end_block, false ) ,
62
+ None => match bitcoin_rpc. get_blockchain_info ( ) {
63
+ Ok ( result) => ( result. blocks - 1 , true ) ,
64
+ Err ( e) => {
65
+ return Err ( format ! (
66
+ "unable to retrieve Bitcoin chain tip ({})" ,
67
+ e. to_string( )
68
+ ) ) ;
69
+ }
70
+ } ,
71
+ } ;
72
+ floating_end_block = update_end_block;
73
+ BlockHeights :: BlockRange ( start_block, end_block) . get_sorted_entries ( )
74
74
} ;
75
75
76
76
// Are we dealing with an ordinals-based predicate?
77
77
// If so, we could use the ordinal storage to provide a set of hints.
78
- let mut inscriptions_db_conn = None ;
79
-
80
- if let BitcoinPredicateType :: OrdinalsProtocol ( _) = & predicate_spec. predicate {
81
- inscriptions_db_conn = Some ( open_readonly_hord_db_conn (
82
- & config. expected_cache_path ( ) ,
83
- ctx,
84
- ) ?) ;
85
- }
78
+ let inscriptions_db_conn = open_readonly_hord_db_conn ( & config. expected_cache_path ( ) , ctx) ?;
86
79
87
80
info ! (
88
81
ctx. expect_logger( ) ,
89
82
"Starting predicate evaluation on Bitcoin blocks" ,
90
83
) ;
91
-
92
- let mut blocks_scanned = 0 ;
93
84
let mut actions_triggered = 0 ;
94
- let occurrences_found = 0u64 ;
95
85
let mut err_count = 0 ;
96
86
97
87
let event_observer_config = config. get_event_observer_config ( ) ;
98
88
let bitcoin_config = event_observer_config. get_bitcoin_config ( ) ;
99
- let mut traversals = HashMap :: new ( ) ;
89
+ let number_of_blocks_to_scan = block_heights_to_scan. len ( ) as u64 ;
90
+ let mut number_of_blocks_scanned = 0 ;
91
+ let mut number_of_blocks_sent = 0u64 ;
100
92
let http_client = build_http_client ( ) ;
101
93
102
- let mut cursor = start_block. saturating_sub ( 1 ) ;
94
+ while let Some ( current_block_height) = block_heights_to_scan. pop_front ( ) {
95
+ number_of_blocks_scanned += 1 ;
103
96
104
- let mut inscription_height_hint = InscriptionHeigthHint :: new ( ) ;
105
-
106
- while cursor <= end_block {
107
- cursor += 1 ;
108
- blocks_scanned += 1 ;
109
-
110
- if let Some ( ref inscriptions_db_conn) = inscriptions_db_conn {
111
- if !get_any_entry_in_ordinal_activities ( & cursor, & inscriptions_db_conn, & ctx) {
112
- continue ;
113
- }
97
+ if !get_any_entry_in_ordinal_activities ( & current_block_height, & inscriptions_db_conn, & ctx)
98
+ {
99
+ continue ;
114
100
}
115
101
116
- let block_hash =
117
- retrieve_block_hash_with_retry ( & http_client, & cursor, & bitcoin_config, ctx) . await ?;
102
+ let block_hash = retrieve_block_hash_with_retry (
103
+ & http_client,
104
+ & current_block_height,
105
+ & bitcoin_config,
106
+ ctx,
107
+ )
108
+ . await ?;
118
109
let block_breakdown =
119
110
download_and_parse_block_with_retry ( & http_client, & block_hash, & bitcoin_config, ctx)
120
111
. await ?;
@@ -127,49 +118,26 @@ pub async fn scan_bitcoin_chainstate_via_rpc_using_predicate(
127
118
Err ( ( e, _) ) => {
128
119
warn ! (
129
120
ctx. expect_logger( ) ,
130
- "Unable to standardize block#{} {}: {}" , cursor , block_hash, e
121
+ "Unable to standardize block#{} {}: {}" , current_block_height , block_hash, e
131
122
) ;
132
123
continue ;
133
124
}
134
125
} ;
135
126
136
- if let Some ( ref mut inscriptions_db_conn) = inscriptions_db_conn {
137
- // Evaluating every single block is required for also keeping track of transfers.
138
- let local_traverals =
139
- find_all_inscriptions_in_block ( & cursor, & inscriptions_db_conn, & ctx) ;
140
- for ( key, traversal_result) in local_traverals. into_iter ( ) {
141
- traversals. insert ( key, traversal_result) ;
142
- }
143
-
144
- let transaction = inscriptions_db_conn. transaction ( ) . unwrap ( ) ;
145
- let empty_ctx = Context :: empty ( ) ;
146
- let _ = update_storage_and_augment_bitcoin_block_with_inscription_reveal_data_tx (
147
- & mut block,
148
- & transaction,
149
- & traversals,
150
- & mut inscription_height_hint,
151
- & empty_ctx,
152
- ) ?;
153
-
154
- let _ = update_storage_and_augment_bitcoin_block_with_inscription_transfer_data_tx (
155
- & mut block,
156
- & transaction,
157
- & empty_ctx,
158
- ) ?;
127
+ let empty_ctx = Context :: empty ( ) ;
128
+ re_augment_block_with_ordinals_operations ( & mut block, & inscriptions_db_conn, & empty_ctx) ;
159
129
160
- let inscriptions_revealed = get_inscriptions_revealed_in_block ( & block)
161
- . iter ( )
162
- . map ( |d| d. inscription_number . to_string ( ) )
163
- . collect :: < Vec < String > > ( ) ;
130
+ let inscriptions_revealed = get_inscriptions_revealed_in_block ( & block)
131
+ . iter ( )
132
+ . map ( |d| d. inscription_number . to_string ( ) )
133
+ . collect :: < Vec < String > > ( ) ;
164
134
165
- info ! (
166
- ctx. expect_logger( ) ,
167
- "Processing block #{} through {} predicate (inscriptions revealed: [{}])" ,
168
- cursor,
169
- predicate_spec. uuid,
170
- inscriptions_revealed. join( ", " )
171
- ) ;
172
- }
135
+ info ! (
136
+ ctx. expect_logger( ) ,
137
+ "Processing block #{current_block_height} through {} predicate (inscriptions revealed: [{}])" ,
138
+ predicate_spec. uuid,
139
+ inscriptions_revealed. join( ", " )
140
+ ) ;
173
141
174
142
match process_block_with_predicates (
175
143
block,
@@ -188,12 +156,12 @@ pub async fn scan_bitcoin_chainstate_via_rpc_using_predicate(
188
156
}
189
157
190
158
if let PredicatesApi :: On ( ref api_config) = config. http_api {
191
- if blocks_scanned % 50 == 0 {
159
+ if number_of_blocks_scanned % 50 == 0 {
192
160
let status = PredicateStatus :: Scanning ( ScanningData {
193
- start_block ,
194
- end_block ,
195
- cursor ,
196
- occurrences_found ,
161
+ number_of_blocks_to_scan ,
162
+ number_of_blocks_scanned ,
163
+ number_of_blocks_sent ,
164
+ current_block_height ,
197
165
} ) ;
198
166
let mut predicates_db_conn =
199
167
open_readwrite_predicates_db_conn_or_panic ( api_config, & ctx) ;
@@ -206,9 +174,13 @@ pub async fn scan_bitcoin_chainstate_via_rpc_using_predicate(
206
174
}
207
175
}
208
176
209
- if cursor == end_block && floating_end_block {
210
- end_block = match bitcoin_rpc. get_blockchain_info ( ) {
211
- Ok ( result) => result. blocks - 1 ,
177
+ if block_heights_to_scan. is_empty ( ) && floating_end_block {
178
+ match bitcoin_rpc. get_blockchain_info ( ) {
179
+ Ok ( result) => {
180
+ for entry in ( current_block_height + 1 ) ..result. blocks {
181
+ block_heights_to_scan. push_back ( entry) ;
182
+ }
183
+ }
212
184
Err ( _e) => {
213
185
continue ;
214
186
}
@@ -217,15 +189,15 @@ pub async fn scan_bitcoin_chainstate_via_rpc_using_predicate(
217
189
}
218
190
info ! (
219
191
ctx. expect_logger( ) ,
220
- "{blocks_scanned } blocks scanned, {actions_triggered} actions triggered"
192
+ "{number_of_blocks_scanned } blocks scanned, {actions_triggered} actions triggered"
221
193
) ;
222
194
223
195
if let PredicatesApi :: On ( ref api_config) = config. http_api {
224
196
let status = PredicateStatus :: Scanning ( ScanningData {
225
- start_block ,
226
- end_block ,
227
- cursor ,
228
- occurrences_found ,
197
+ number_of_blocks_to_scan ,
198
+ number_of_blocks_scanned ,
199
+ number_of_blocks_sent ,
200
+ current_block_height : 0 ,
229
201
} ) ;
230
202
let mut predicates_db_conn = open_readwrite_predicates_db_conn_or_panic ( api_config, & ctx) ;
231
203
update_predicate_status ( & predicate_spec. key ( ) , status, & mut predicates_db_conn, & ctx)
0 commit comments