2
2
self :: {
3
3
entry:: {
4
4
Entry , HeaderValue , InscriptionEntry , InscriptionEntryValue , InscriptionIdValue ,
5
- OutPointValue , RuneEntryValue , RuneIdValue , SatPointValue , SatRange , TxidValue ,
5
+ OutPointValue , RuneEntryValue , RuneIdValue , SatPointValue , SatRange , TxOutValue , TxidValue ,
6
6
} ,
7
7
event:: Event ,
8
8
lot:: Lot ,
@@ -48,11 +48,12 @@ mod updater;
48
48
#[ cfg( test) ]
49
49
pub ( crate ) mod testing;
50
50
51
- const SCHEMA_VERSION : u64 = 25 ;
51
+ const SCHEMA_VERSION : u64 = 26 ;
52
52
53
53
define_multimap_table ! { SATPOINT_TO_SEQUENCE_NUMBER , & SatPointValue , u32 }
54
54
define_multimap_table ! { SAT_TO_SEQUENCE_NUMBER , u64 , u32 }
55
55
define_multimap_table ! { SEQUENCE_NUMBER_TO_CHILDREN , u32 , u32 }
56
+ define_multimap_table ! { SCRIPT_PUBKEY_TO_OUTPOINT , & [ u8 ] , OutPointValue }
56
57
define_table ! { CONTENT_TYPE_TO_COUNT , Option <& [ u8 ] >, u64 }
57
58
define_table ! { HEIGHT_TO_BLOCK_HEADER , u32 , & HeaderValue }
58
59
define_table ! { HEIGHT_TO_LAST_SEQUENCE_NUMBER , u32 , u32 }
@@ -61,7 +62,7 @@ define_table! { INSCRIPTION_ID_TO_SEQUENCE_NUMBER, InscriptionIdValue, u32 }
61
62
define_table ! { INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER , i32 , u32 }
62
63
define_table ! { OUTPOINT_TO_RUNE_BALANCES , & OutPointValue , & [ u8 ] }
63
64
define_table ! { OUTPOINT_TO_SAT_RANGES , & OutPointValue , & [ u8 ] }
64
- define_table ! { OUTPOINT_TO_VALUE , & OutPointValue , u64 }
65
+ define_table ! { OUTPOINT_TO_TXOUT , & OutPointValue , TxOutValue }
65
66
define_table ! { RUNE_ID_TO_RUNE_ENTRY , RuneIdValue , RuneEntryValue }
66
67
define_table ! { RUNE_TO_RUNE_ID , u128 , RuneIdValue }
67
68
define_table ! { SAT_TO_SATPOINT , u64 , & SatPointValue }
@@ -90,6 +91,7 @@ pub(crate) enum Statistic {
90
91
IndexTransactions = 12 ,
91
92
IndexSpentSats = 13 ,
92
93
InitialSyncTime = 14 ,
94
+ IndexAddresses = 15 ,
93
95
}
94
96
95
97
impl Statistic {
@@ -189,12 +191,13 @@ pub struct Index {
189
191
genesis_block_coinbase_transaction : Transaction ,
190
192
genesis_block_coinbase_txid : Txid ,
191
193
height_limit : Option < u32 > ,
194
+ index_addresses : bool ,
192
195
index_runes : bool ,
193
196
index_sats : bool ,
194
197
index_spent_sats : bool ,
195
198
index_transactions : bool ,
196
- settings : Settings ,
197
199
path : PathBuf ,
200
+ settings : Settings ,
198
201
started : DateTime < Utc > ,
199
202
unrecoverably_reorged : AtomicBool ,
200
203
}
@@ -298,6 +301,7 @@ impl Index {
298
301
299
302
tx. open_multimap_table ( SATPOINT_TO_SEQUENCE_NUMBER ) ?;
300
303
tx. open_multimap_table ( SAT_TO_SEQUENCE_NUMBER ) ?;
304
+ tx. open_multimap_table ( SCRIPT_PUBKEY_TO_OUTPOINT ) ?;
301
305
tx. open_multimap_table ( SEQUENCE_NUMBER_TO_CHILDREN ) ?;
302
306
tx. open_table ( CONTENT_TYPE_TO_COUNT ) ?;
303
307
tx. open_table ( HEIGHT_TO_BLOCK_HEADER ) ?;
@@ -306,7 +310,7 @@ impl Index {
306
310
tx. open_table ( INSCRIPTION_ID_TO_SEQUENCE_NUMBER ) ?;
307
311
tx. open_table ( INSCRIPTION_NUMBER_TO_SEQUENCE_NUMBER ) ?;
308
312
tx. open_table ( OUTPOINT_TO_RUNE_BALANCES ) ?;
309
- tx. open_table ( OUTPOINT_TO_VALUE ) ?;
313
+ tx. open_table ( OUTPOINT_TO_TXOUT ) ?;
310
314
tx. open_table ( RUNE_ID_TO_RUNE_ENTRY ) ?;
311
315
tx. open_table ( RUNE_TO_RUNE_ID ) ?;
312
316
tx. open_table ( SAT_TO_SATPOINT ) ?;
@@ -324,6 +328,12 @@ impl Index {
324
328
outpoint_to_sat_ranges. insert ( & OutPoint :: null ( ) . store ( ) , [ ] . as_slice ( ) ) ?;
325
329
}
326
330
331
+ Self :: set_statistic (
332
+ & mut statistics,
333
+ Statistic :: IndexAddresses ,
334
+ u64:: from ( settings. index_addresses ( ) ) ,
335
+ ) ?;
336
+
327
337
Self :: set_statistic (
328
338
& mut statistics,
329
339
Statistic :: IndexRunes ,
@@ -402,6 +412,7 @@ impl Index {
402
412
Err ( error) => bail ! ( "failed to open index: {error}" ) ,
403
413
} ;
404
414
415
+ let index_addresses;
405
416
let index_runes;
406
417
let index_sats;
407
418
let index_spent_sats;
@@ -410,6 +421,7 @@ impl Index {
410
421
{
411
422
let tx = database. begin_read ( ) ?;
412
423
let statistics = tx. open_table ( STATISTIC_TO_COUNT ) ?;
424
+ index_addresses = Self :: is_statistic_set ( & statistics, Statistic :: IndexAddresses ) ?;
413
425
index_runes = Self :: is_statistic_set ( & statistics, Statistic :: IndexRunes ) ?;
414
426
index_sats = Self :: is_statistic_set ( & statistics, Statistic :: IndexSats ) ?;
415
427
index_spent_sats = Self :: is_statistic_set ( & statistics, Statistic :: IndexSpentSats ) ?;
@@ -428,6 +440,7 @@ impl Index {
428
440
first_inscription_height : settings. first_inscription_height ( ) ,
429
441
genesis_block_coinbase_transaction,
430
442
height_limit : settings. height_limit ( ) ,
443
+ index_addresses,
431
444
index_runes,
432
445
index_sats,
433
446
index_spent_sats,
@@ -449,12 +462,16 @@ impl Index {
449
462
self
450
463
. database
451
464
. begin_read ( ) ?
452
- . open_table ( OUTPOINT_TO_VALUE ) ?
465
+ . open_table ( OUTPOINT_TO_TXOUT ) ?
453
466
. get ( & output. store ( ) ) ?
454
467
. is_some ( ) ,
455
468
)
456
469
}
457
470
471
+ pub ( crate ) fn has_address_index ( & self ) -> bool {
472
+ self . index_addresses
473
+ }
474
+
458
475
pub ( crate ) fn has_rune_index ( & self ) -> bool {
459
476
self . index_runes
460
477
}
@@ -501,6 +518,7 @@ impl Index {
501
518
content_type_counts. sort_by_key ( |( _content_type, count) | Reverse ( * count) ) ;
502
519
503
520
Ok ( StatusHtml {
521
+ address_index : self . has_address_index ( ) ,
504
522
blessed_inscriptions,
505
523
chain : self . settings . chain ( ) ,
506
524
content_type_counts,
@@ -513,9 +531,9 @@ impl Index {
513
531
self . settings . chain ( ) . network ( ) ,
514
532
Height ( next_height) ,
515
533
) ,
516
- rune_index : statistic ( Statistic :: IndexRunes ) ? != 0 ,
534
+ rune_index : self . has_rune_index ( ) ,
517
535
runes : statistic ( Statistic :: Runes ) ?,
518
- sat_index : statistic ( Statistic :: IndexSats ) ? != 0 ,
536
+ sat_index : self . has_sat_index ( ) ,
519
537
started : self . started ,
520
538
transaction_index : statistic ( Statistic :: IndexTransactions ) ? != 0 ,
521
539
unrecoverably_reorged : self . unrecoverably_reorged . load ( atomic:: Ordering :: Relaxed ) ,
@@ -970,7 +988,7 @@ impl Index {
970
988
Ok ( ( ( id, balance) , len) )
971
989
}
972
990
973
- pub ( crate ) fn get_rune_balances_for_outpoint (
991
+ pub ( crate ) fn get_rune_balances_for_output (
974
992
& self ,
975
993
outpoint : OutPoint ,
976
994
) -> Result < BTreeMap < SpacedRune , Pile > > {
@@ -1502,7 +1520,7 @@ impl Index {
1502
1520
)
1503
1521
}
1504
1522
1505
- pub ( crate ) fn get_inscriptions_on_output (
1523
+ pub ( crate ) fn get_inscriptions_for_output (
1506
1524
& self ,
1507
1525
outpoint : OutPoint ,
1508
1526
) -> Result < Vec < InscriptionId > > {
@@ -1636,10 +1654,19 @@ impl Index {
1636
1654
Ok (
1637
1655
outpoint != OutPoint :: null ( )
1638
1656
&& outpoint != self . settings . chain ( ) . genesis_coinbase_outpoint ( )
1639
- && self
1640
- . client
1641
- . get_tx_out ( & outpoint. txid , outpoint. vout , Some ( true ) ) ?
1642
- . is_none ( ) ,
1657
+ && if self . settings . index_addresses ( ) {
1658
+ self
1659
+ . database
1660
+ . begin_read ( ) ?
1661
+ . open_table ( OUTPOINT_TO_TXOUT ) ?
1662
+ . get ( & outpoint. store ( ) ) ?
1663
+ . is_none ( )
1664
+ } else {
1665
+ self
1666
+ . client
1667
+ . get_tx_out ( & outpoint. txid , outpoint. vout , Some ( true ) ) ?
1668
+ . is_none ( )
1669
+ } ,
1643
1670
)
1644
1671
}
1645
1672
@@ -2186,6 +2213,20 @@ impl Index {
2186
2213
)
2187
2214
}
2188
2215
2216
+ pub ( crate ) fn get_address_info ( & self , address : & Address ) -> Result < Vec < OutPoint > > {
2217
+ self
2218
+ . database
2219
+ . begin_read ( ) ?
2220
+ . open_multimap_table ( SCRIPT_PUBKEY_TO_OUTPOINT ) ?
2221
+ . get ( address. script_pubkey ( ) . as_bytes ( ) ) ?
2222
+ . map ( |result| {
2223
+ result
2224
+ . map_err ( |err| anyhow ! ( err) )
2225
+ . map ( |value| OutPoint :: load ( value. value ( ) ) )
2226
+ } )
2227
+ . collect ( )
2228
+ }
2229
+
2189
2230
pub ( crate ) fn get_output_info ( & self , outpoint : OutPoint ) -> Result < Option < ( api:: Output , TxOut ) > > {
2190
2231
let sat_ranges = self . list ( outpoint) ?;
2191
2232
@@ -2213,16 +2254,16 @@ impl Index {
2213
2254
return Ok ( None ) ;
2214
2255
} ;
2215
2256
2216
- let Some ( output ) = tx. output . into_iter ( ) . nth ( outpoint. vout as usize ) else {
2257
+ let Some ( txout ) = tx. output . into_iter ( ) . nth ( outpoint. vout as usize ) else {
2217
2258
return Ok ( None ) ;
2218
2259
} ;
2219
2260
2220
- output
2261
+ txout
2221
2262
} ;
2222
2263
2223
- let inscriptions = self . get_inscriptions_on_output ( outpoint) ?;
2264
+ let inscriptions = self . get_inscriptions_for_output ( outpoint) ?;
2224
2265
2225
- let runes = self . get_rune_balances_for_outpoint ( outpoint) ?;
2266
+ let runes = self . get_rune_balances_for_output ( outpoint) ?;
2226
2267
2227
2268
let spent = self . is_output_spent ( outpoint) ?;
2228
2269
@@ -3372,7 +3413,7 @@ mod tests {
3372
3413
assert_eq ! (
3373
3414
context
3374
3415
. index
3375
- . get_inscriptions_on_output ( OutPoint { txid, vout: 0 } )
3416
+ . get_inscriptions_for_output ( OutPoint { txid, vout: 0 } )
3376
3417
. unwrap( ) ,
3377
3418
[ ]
3378
3419
) ;
@@ -3382,7 +3423,7 @@ mod tests {
3382
3423
assert_eq ! (
3383
3424
context
3384
3425
. index
3385
- . get_inscriptions_on_output ( OutPoint { txid, vout: 0 } )
3426
+ . get_inscriptions_for_output ( OutPoint { txid, vout: 0 } )
3386
3427
. unwrap( ) ,
3387
3428
[ inscription_id]
3388
3429
) ;
@@ -3397,15 +3438,15 @@ mod tests {
3397
3438
assert_eq ! (
3398
3439
context
3399
3440
. index
3400
- . get_inscriptions_on_output ( OutPoint { txid, vout: 0 } )
3441
+ . get_inscriptions_for_output ( OutPoint { txid, vout: 0 } )
3401
3442
. unwrap( ) ,
3402
3443
[ ]
3403
3444
) ;
3404
3445
3405
3446
assert_eq ! (
3406
3447
context
3407
3448
. index
3408
- . get_inscriptions_on_output ( OutPoint {
3449
+ . get_inscriptions_for_output ( OutPoint {
3409
3450
txid: send_id,
3410
3451
vout: 0 ,
3411
3452
} )
@@ -3435,7 +3476,7 @@ mod tests {
3435
3476
assert_eq ! (
3436
3477
context
3437
3478
. index
3438
- . get_inscriptions_on_output ( OutPoint {
3479
+ . get_inscriptions_for_output ( OutPoint {
3439
3480
txid: first,
3440
3481
vout: 0
3441
3482
} )
@@ -6268,6 +6309,79 @@ mod tests {
6268
6309
. unwrap( ) ) ;
6269
6310
}
6270
6311
6312
+ #[ test]
6313
+ fn output_addresses_are_updated ( ) {
6314
+ let context = Context :: builder ( )
6315
+ . arg ( "--index-addresses" )
6316
+ . arg ( "--index-sats" )
6317
+ . build ( ) ;
6318
+
6319
+ context. mine_blocks ( 2 ) ;
6320
+
6321
+ let txid = context. core . broadcast_tx ( TransactionTemplate {
6322
+ inputs : & [ ( 1 , 0 , 0 , Witness :: new ( ) ) , ( 2 , 0 , 0 , Witness :: new ( ) ) ] ,
6323
+ outputs : 2 ,
6324
+ ..Default :: default ( )
6325
+ } ) ;
6326
+
6327
+ context. mine_blocks ( 1 ) ;
6328
+
6329
+ let transaction = context. index . get_transaction ( txid) . unwrap ( ) . unwrap ( ) ;
6330
+
6331
+ let first_address = context
6332
+ . index
6333
+ . settings
6334
+ . chain ( )
6335
+ . address_from_script ( & transaction. output [ 0 ] . script_pubkey )
6336
+ . unwrap ( ) ;
6337
+
6338
+ let first_address_second_output = OutPoint {
6339
+ txid : transaction. txid ( ) ,
6340
+ vout : 1 ,
6341
+ } ;
6342
+
6343
+ assert_eq ! (
6344
+ context. index. get_address_info( & first_address) . unwrap( ) ,
6345
+ [
6346
+ OutPoint {
6347
+ txid: transaction. txid( ) ,
6348
+ vout: 0
6349
+ } ,
6350
+ first_address_second_output
6351
+ ]
6352
+ ) ;
6353
+
6354
+ let txid = context. core . broadcast_tx ( TransactionTemplate {
6355
+ inputs : & [ ( 3 , 1 , 0 , Witness :: new ( ) ) ] ,
6356
+ p2tr : true ,
6357
+ ..Default :: default ( )
6358
+ } ) ;
6359
+
6360
+ context. mine_blocks ( 1 ) ;
6361
+
6362
+ let transaction = context. index . get_transaction ( txid) . unwrap ( ) . unwrap ( ) ;
6363
+
6364
+ let second_address = context
6365
+ . index
6366
+ . settings
6367
+ . chain ( )
6368
+ . address_from_script ( & transaction. output [ 0 ] . script_pubkey )
6369
+ . unwrap ( ) ;
6370
+
6371
+ assert_eq ! (
6372
+ context. index. get_address_info( & first_address) . unwrap( ) ,
6373
+ [ first_address_second_output]
6374
+ ) ;
6375
+
6376
+ assert_eq ! (
6377
+ context. index. get_address_info( & second_address) . unwrap( ) ,
6378
+ [ OutPoint {
6379
+ txid: transaction. txid( ) ,
6380
+ vout: 0
6381
+ } ]
6382
+ ) ;
6383
+ }
6384
+
6271
6385
#[ test]
6272
6386
fn fee_spent_inscriptions_are_numbered_last_in_block ( ) {
6273
6387
for context in Context :: configurations ( ) {
0 commit comments