1
1
// Copyright (c) Aptos Foundation
2
2
// SPDX-License-Identifier: Apache-2.0
3
3
4
+ use crate :: utils:: PrefixedStateValueIterator ;
4
5
use aptos_config:: config:: internal_indexer_db_config:: InternalIndexerDBConfig ;
5
6
use aptos_db_indexer_schemas:: {
6
7
metadata:: { MetadataKey , MetadataValue } ,
7
8
schema:: {
8
9
event_by_key:: EventByKeySchema , event_by_version:: EventByVersionSchema ,
9
- indexer_metadata:: InternalIndexerMetadataSchema ,
10
+ indexer_metadata:: InternalIndexerMetadataSchema , state_keys :: StateKeysSchema ,
10
11
transaction_by_account:: TransactionByAccountSchema ,
11
12
} ,
12
13
utils:: {
@@ -23,7 +24,12 @@ use aptos_types::{
23
24
contract_event:: { ContractEvent , EventWithVersion } ,
24
25
event:: EventKey ,
25
26
indexer:: indexer_db_reader:: Order ,
27
+ state_store:: {
28
+ state_key:: { prefix:: StateKeyPrefix , StateKey } ,
29
+ state_value:: StateValue ,
30
+ } ,
26
31
transaction:: { AccountTransactionsWithProof , Transaction , Version } ,
32
+ write_set:: { TransactionWrite , WriteSet } ,
27
33
} ;
28
34
use std:: {
29
35
cmp:: min,
@@ -120,31 +126,43 @@ impl DBIndexer {
120
126
self . config . enable_transaction
121
127
}
122
128
129
+ pub fn statekeys_enabled ( & self ) -> bool {
130
+ self . config . enable_statekeys
131
+ }
132
+
123
133
fn get_main_db_iter (
124
134
& self ,
125
135
start_version : Version ,
126
136
num_transactions : u64 ,
127
- ) -> Result < impl Iterator < Item = Result < ( Transaction , Vec < ContractEvent > ) > > + ' _ > {
137
+ ) -> Result < impl Iterator < Item = Result < ( Transaction , Vec < ContractEvent > , WriteSet ) > > + ' _ >
138
+ {
128
139
let txn_iter = self
129
140
. main_db_reader
130
141
. get_transaction_iterator ( start_version, num_transactions) ?;
131
142
let event_vec_iter = self
132
143
. main_db_reader
133
144
. get_events_iterator ( start_version, num_transactions) ?;
134
- let zipped = txn_iter
135
- . zip ( event_vec_iter)
136
- . map ( |( txn_res, event_vec_res) | {
145
+ let writeset_iter = self
146
+ . main_db_reader
147
+ . get_write_set_iterator ( start_version, num_transactions) ?;
148
+ let zipped = txn_iter. zip ( event_vec_iter) . zip ( writeset_iter) . map (
149
+ |( ( txn_res, event_vec_res) , writeset_res) | {
137
150
let txn = txn_res?;
138
151
let event_vec = event_vec_res?;
139
- Ok ( ( txn, event_vec) )
140
- } ) ;
152
+ let writeset = writeset_res?;
153
+ Ok ( ( txn, event_vec, writeset) )
154
+ } ,
155
+ ) ;
141
156
Ok ( zipped)
142
157
}
143
158
144
159
fn get_num_of_transactions ( & self , version : Version ) -> Result < u64 > {
145
160
let highest_version = self . main_db_reader . get_synced_version ( ) ?;
146
161
// we want to include the last transaction since the iterator interface will is right exclusive.
147
- let num_of_transaction = min ( self . config . batch_size as u64 , highest_version - version) + 1 ;
162
+ let num_of_transaction = min (
163
+ ( self . config . batch_size + 1 ) as u64 ,
164
+ highest_version - version + 1 ,
165
+ ) ;
148
166
Ok ( num_of_transaction)
149
167
}
150
168
@@ -155,34 +173,45 @@ impl DBIndexer {
155
173
let mut db_iter = self . get_main_db_iter ( version, num_transactions) ?;
156
174
let batch = SchemaBatch :: new ( ) ;
157
175
db_iter. try_for_each ( |res| {
158
- let ( txn, events) = res?;
176
+ let ( txn, events, writeset ) = res?;
159
177
if let Some ( txn) = txn. try_as_signed_user_txn ( ) {
160
178
if self . config . enable_transaction {
161
179
batch. put :: < TransactionByAccountSchema > (
162
180
& ( txn. sender ( ) , txn. sequence_number ( ) ) ,
163
181
& version,
164
182
) ?;
165
183
}
184
+ }
166
185
167
- if self . config . enable_event {
168
- events. iter ( ) . enumerate ( ) . for_each ( |( idx, event) | {
169
- if let ContractEvent :: V1 ( v1) = event {
170
- batch
171
- . put :: < EventByKeySchema > (
172
- & ( * v1. key ( ) , v1. sequence_number ( ) ) ,
173
- & ( version, idx as u64 ) ,
174
- )
175
- . expect ( "Failed to put events by key to a batch" ) ;
176
- batch
177
- . put :: < EventByVersionSchema > (
178
- & ( * v1. key ( ) , version, v1. sequence_number ( ) ) ,
179
- & ( idx as u64 ) ,
180
- )
181
- . expect ( "Failed to put events by version to a batch" ) ;
182
- }
183
- } ) ;
184
- }
186
+ if self . config . enable_event {
187
+ events. iter ( ) . enumerate ( ) . for_each ( |( idx, event) | {
188
+ if let ContractEvent :: V1 ( v1) = event {
189
+ batch
190
+ . put :: < EventByKeySchema > (
191
+ & ( * v1. key ( ) , v1. sequence_number ( ) ) ,
192
+ & ( version, idx as u64 ) ,
193
+ )
194
+ . expect ( "Failed to put events by key to a batch" ) ;
195
+ batch
196
+ . put :: < EventByVersionSchema > (
197
+ & ( * v1. key ( ) , version, v1. sequence_number ( ) ) ,
198
+ & ( idx as u64 ) ,
199
+ )
200
+ . expect ( "Failed to put events by version to a batch" ) ;
201
+ }
202
+ } ) ;
203
+ }
204
+
205
+ if self . config . enable_statekeys {
206
+ writeset. iter ( ) . for_each ( |( state_key, write_op) | {
207
+ if write_op. is_creation ( ) {
208
+ batch
209
+ . put :: < StateKeysSchema > ( state_key, & ( ) )
210
+ . expect ( "Failed to put state keys to a batch" ) ;
211
+ }
212
+ } ) ;
185
213
}
214
+
186
215
version += 1 ;
187
216
Ok :: < ( ) , AptosDbError > ( ( ) )
188
217
} ) ?;
@@ -270,6 +299,16 @@ impl DBIndexer {
270
299
Ok ( result)
271
300
}
272
301
302
+ #[ cfg( any( test, feature = "fuzzing" ) ) ]
303
+ pub fn get_state_keys ( & self , prefix : & StateKeyPrefix ) -> Result < Vec < StateKey > > {
304
+ let mut iter = self . db . iter :: < StateKeysSchema > ( ) ?;
305
+ iter. seek_to_first ( ) ;
306
+ Ok ( iter
307
+ . map ( |res| res. unwrap ( ) . 0 )
308
+ . filter ( |k| prefix. is_prefix ( k) . unwrap ( ) )
309
+ . collect ( ) )
310
+ }
311
+
273
312
#[ cfg( any( test, feature = "fuzzing" ) ) ]
274
313
pub fn get_event_by_key_iter (
275
314
& self ,
@@ -289,7 +328,7 @@ impl DBIndexer {
289
328
order : Order ,
290
329
limit : u64 ,
291
330
ledger_version : Version ,
292
- ) -> anyhow :: Result < Vec < EventWithVersion > > {
331
+ ) -> Result < Vec < EventWithVersion > > {
293
332
self . get_events_by_event_key ( event_key, start, order, limit, ledger_version)
294
333
}
295
334
@@ -300,7 +339,7 @@ impl DBIndexer {
300
339
order : Order ,
301
340
limit : u64 ,
302
341
ledger_version : Version ,
303
- ) -> anyhow :: Result < Vec < EventWithVersion > > {
342
+ ) -> Result < Vec < EventWithVersion > > {
304
343
error_if_too_many_requested ( limit, MAX_REQUEST_LIMIT ) ?;
305
344
let get_latest = order == Order :: Descending && start_seq_num == u64:: max_value ( ) ;
306
345
@@ -367,7 +406,7 @@ impl DBIndexer {
367
406
limit : u64 ,
368
407
include_events : bool ,
369
408
ledger_version : Version ,
370
- ) -> anyhow :: Result < AccountTransactionsWithProof > {
409
+ ) -> Result < AccountTransactionsWithProof > {
371
410
error_if_too_many_requested ( limit, MAX_REQUEST_LIMIT ) ?;
372
411
373
412
let txns_with_proofs = self
@@ -384,4 +423,19 @@ impl DBIndexer {
384
423
385
424
Ok ( AccountTransactionsWithProof :: new ( txns_with_proofs) )
386
425
}
426
+
427
+ pub fn get_prefixed_state_value_iterator (
428
+ & self ,
429
+ key_prefix : & StateKeyPrefix ,
430
+ cursor : Option < & StateKey > ,
431
+ version : Version ,
432
+ ) -> Result < impl Iterator < Item = anyhow:: Result < ( StateKey , StateValue ) > > + ' _ > {
433
+ PrefixedStateValueIterator :: new (
434
+ self . main_db_reader . clone ( ) ,
435
+ self . db . as_ref ( ) ,
436
+ key_prefix. clone ( ) ,
437
+ cursor. cloned ( ) ,
438
+ version,
439
+ )
440
+ }
387
441
}
0 commit comments