Skip to content
This repository was archived by the owner on Mar 14, 2025. It is now read-only.

Commit 7857b78

Browse files
authored
Merge pull request #25 from hirosystems/develop
release to beta
2 parents 03c7ebd + 68784da commit 7857b78

File tree

7 files changed

+501
-506
lines changed

7 files changed

+501
-506
lines changed

.github/workflows/ci.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,13 @@ jobs:
249249
fetch-depth: 0
250250
persist-credentials: false
251251

252+
- name: Checkout tag
253+
if: needs.semantic-release.outputs.new_release_version != ''
254+
uses: actions/checkout@v4
255+
with:
256+
persist-credentials: false
257+
ref: v${{ needs.semantic-release.outputs.new_release_version }}
258+
252259
- name: Set up Docker Buildx
253260
uses: docker/setup-buildx-action@v3
254261

api/src/pg/pg-store.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -144,12 +144,15 @@ export class PgStore extends BasePgStore {
144144
cte?: PgSqlQuery
145145
): Promise<DbPaginatedResult<DbItemWithRune<DbLedgerEntry>>> {
146146
const results = await this.sql<DbCountedQueryResult<DbItemWithRune<DbLedgerEntry>>[]>`
147-
${cte ? cte : this.sql``}
148-
SELECT l.*, r.name, r.spaced_name, r.divisibility, ${count} AS total
149-
FROM ledger AS l
150-
INNER JOIN runes AS r ON r.id = l.rune_id
151-
WHERE ${filter}
152-
ORDER BY l.block_height DESC, l.tx_index DESC, l.event_index DESC
147+
WITH ${cte ? cte : this.sql`none AS (SELECT NULL)`},
148+
results AS (
149+
SELECT l.*, r.name, r.spaced_name, r.divisibility, ${count} AS total
150+
FROM ledger AS l
151+
INNER JOIN runes AS r ON r.id = l.rune_id
152+
WHERE ${filter}
153+
)
154+
SELECT * FROM results
155+
ORDER BY block_height DESC, tx_index DESC, event_index DESC
153156
OFFSET ${offset} LIMIT ${limit}
154157
`;
155158
return {
@@ -164,7 +167,7 @@ export class PgStore extends BasePgStore {
164167
this.sql`COALESCE((SELECT total_operations FROM count), 0)`,
165168
offset,
166169
limit,
167-
this.sql`WITH count AS (
170+
this.sql`count AS (
168171
SELECT total_operations FROM supply_changes
169172
WHERE rune_id = (SELECT id FROM runes WHERE ${runeFilter(this.sql, runeId)})
170173
ORDER BY block_height DESC LIMIT 1
@@ -187,7 +190,7 @@ export class PgStore extends BasePgStore {
187190
this.sql`COALESCE((SELECT total_operations FROM count), 0)`,
188191
offset,
189192
limit,
190-
this.sql`WITH recent AS (
193+
this.sql`recent AS (
191194
SELECT DISTINCT ON (rune_id) total_operations
192195
FROM balance_changes
193196
WHERE address = ${address}

migrations/V1__runes.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ CREATE TABLE IF NOT EXISTS runes (
22
id TEXT NOT NULL PRIMARY KEY,
33
number BIGINT NOT NULL UNIQUE,
44
name TEXT NOT NULL UNIQUE,
5-
spaced_name TEXT NOT NULL,
5+
spaced_name TEXT NOT NULL UNIQUE,
66
block_hash TEXT NOT NULL,
77
block_height NUMERIC NOT NULL,
88
tx_index BIGINT NOT NULL,

src/db/cache/index_cache.rs

Lines changed: 64 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
use std::{collections::HashMap, num::NonZeroUsize, str::FromStr};
22

3-
use bitcoin::Network;
4-
use chainhook_sdk::{
5-
types::bitcoin::{TxIn, TxOut},
6-
utils::Context,
7-
};
3+
use bitcoin::{Network, ScriptBuf};
4+
use chainhook_sdk::{types::bitcoin::TxIn, utils::Context};
85
use lru::LruCache;
96
use ordinals::{Cenotaph, Edict, Etching, Rune, RuneId, Runestone};
107
use tokio_postgres::{Client, Transaction};
@@ -26,13 +23,14 @@ use crate::{
2623
use super::{
2724
db_cache::DbCache,
2825
transaction_cache::{InputRuneBalance, TransactionCache},
29-
utils::move_tx_output_cache_to_output_cache,
26+
transaction_location::TransactionLocation,
27+
utils::move_block_output_cache_to_output_cache,
3028
};
3129

3230
/// Holds rune data across multiple blocks for faster computations. Processes rune events as they happen during transactions and
3331
/// generates database rows for later insertion.
3432
pub struct IndexCache {
35-
network: Network,
33+
pub network: Network,
3634
/// Number to be assigned to the next rune etching.
3735
next_rune_number: u32,
3836
/// LRU cache for runes.
@@ -41,9 +39,9 @@ pub struct IndexCache {
4139
rune_total_mints_cache: LruCache<RuneId, u128>,
4240
/// LRU cache for outputs with rune balances.
4341
output_cache: LruCache<(String, u32), HashMap<RuneId, Vec<InputRuneBalance>>>,
44-
/// Same as above but only for the current transaction. We use a `HashMap` instead of an LRU cache to make sure we keep all
45-
/// outputs in memory while we index this transaction. Must be cleared every time a new transaction is processed.
46-
tx_output_cache: HashMap<(String, u32), HashMap<RuneId, Vec<InputRuneBalance>>>,
42+
/// Same as above but only for the current block. We use a `HashMap` instead of an LRU cache to make sure we keep all outputs
43+
/// in memory while we index this block. Must be cleared every time a new block is processed.
44+
block_output_cache: HashMap<(String, u32), HashMap<RuneId, Vec<InputRuneBalance>>>,
4745
/// Holds a single transaction's rune cache. Must be cleared every time a new transaction is processed.
4846
tx_cache: TransactionCache,
4947
/// Keeps rows that have not yet been inserted in the DB.
@@ -60,8 +58,21 @@ impl IndexCache {
6058
rune_cache: LruCache::new(cap),
6159
rune_total_mints_cache: LruCache::new(cap),
6260
output_cache: LruCache::new(cap),
63-
tx_output_cache: HashMap::new(),
64-
tx_cache: TransactionCache::new(network, &"".to_string(), 1, 0, &"".to_string(), 0),
61+
block_output_cache: HashMap::new(),
62+
tx_cache: TransactionCache::new(
63+
TransactionLocation {
64+
network,
65+
block_hash: "".to_string(),
66+
block_height: 1,
67+
timestamp: 0,
68+
tx_index: 0,
69+
tx_id: "".to_string(),
70+
},
71+
HashMap::new(),
72+
HashMap::new(),
73+
None,
74+
0,
75+
),
6576
db_cache: DbCache::new(),
6677
}
6778
}
@@ -73,69 +84,69 @@ impl IndexCache {
7384
/// Creates a fresh transaction index cache.
7485
pub async fn begin_transaction(
7586
&mut self,
76-
block_hash: &String,
77-
block_height: u64,
78-
tx_index: u32,
79-
tx_id: &String,
80-
timestamp: u32,
87+
location: TransactionLocation,
88+
tx_inputs: &Vec<TxIn>,
89+
eligible_outputs: HashMap<u32, ScriptBuf>,
90+
first_eligible_output: Option<u32>,
91+
total_outputs: u32,
92+
db_tx: &mut Transaction<'_>,
93+
ctx: &Context,
8194
) {
95+
let input_runes = input_rune_balances_from_tx_inputs(
96+
tx_inputs,
97+
&self.block_output_cache,
98+
&mut self.output_cache,
99+
db_tx,
100+
ctx,
101+
)
102+
.await;
103+
#[cfg(not(feature = "release"))]
104+
{
105+
for (rune_id, balances) in input_runes.iter() {
106+
try_debug!(ctx, "INPUT {rune_id} {balances:?} {location}");
107+
}
108+
if input_runes.len() > 0 {
109+
try_debug!(ctx, "First output: {first_eligible_output:?}, total_outputs: {total_outputs}");
110+
}
111+
}
82112
self.tx_cache = TransactionCache::new(
83-
self.network,
84-
block_hash,
85-
block_height,
86-
tx_index,
87-
tx_id,
88-
timestamp,
113+
location,
114+
input_runes,
115+
eligible_outputs,
116+
first_eligible_output,
117+
total_outputs,
89118
);
90-
self.tx_output_cache.clear();
91119
}
92120

93-
/// Finalizes the current transaction index cache.
121+
/// Finalizes the current transaction index cache by moving all unallocated balances to the correct output.
94122
pub fn end_transaction(&mut self, _db_tx: &mut Transaction<'_>, ctx: &Context) {
95123
let entries = self.tx_cache.allocate_remaining_balances(ctx);
96124
self.add_ledger_entries_to_db_cache(&entries);
97-
move_tx_output_cache_to_output_cache(&mut self.tx_output_cache, &mut self.output_cache);
125+
}
126+
127+
pub fn end_block(&mut self) {
128+
move_block_output_cache_to_output_cache(&mut self.block_output_cache, &mut self.output_cache);
98129
}
99130

100131
pub async fn apply_runestone(
101132
&mut self,
102133
runestone: &Runestone,
103-
tx_inputs: &Vec<TxIn>,
104-
tx_outputs: &Vec<TxOut>,
105-
db_tx: &mut Transaction<'_>,
134+
_db_tx: &mut Transaction<'_>,
106135
ctx: &Context,
107136
) {
108137
try_debug!(ctx, "{:?} {}", runestone, self.tx_cache.location);
109-
let input_balances = input_rune_balances_from_tx_inputs(
110-
tx_inputs,
111-
&self.tx_output_cache,
112-
&mut self.output_cache,
113-
db_tx,
114-
ctx,
115-
)
116-
.await;
117-
self.tx_cache.set_input_rune_balances(input_balances, ctx);
118-
self.tx_cache
119-
.apply_runestone_pointer(runestone, tx_outputs, ctx);
138+
if let Some(new_pointer) = runestone.pointer {
139+
self.tx_cache.output_pointer = Some(new_pointer);
140+
}
120141
}
121142

122143
pub async fn apply_cenotaph(
123144
&mut self,
124145
cenotaph: &Cenotaph,
125-
tx_inputs: &Vec<TxIn>,
126-
db_tx: &mut Transaction<'_>,
146+
_db_tx: &mut Transaction<'_>,
127147
ctx: &Context,
128148
) {
129149
try_debug!(ctx, "{:?} {}", cenotaph, self.tx_cache.location);
130-
let input_balances = input_rune_balances_from_tx_inputs(
131-
tx_inputs,
132-
&self.tx_output_cache,
133-
&mut self.output_cache,
134-
db_tx,
135-
ctx,
136-
)
137-
.await;
138-
self.tx_cache.set_input_rune_balances(input_balances, ctx);
139150
let entries = self.tx_cache.apply_cenotaph_input_burn(cenotaph);
140151
self.add_ledger_entries_to_db_cache(&entries);
141152
}
@@ -407,7 +418,7 @@ impl IndexCache {
407418
address,
408419
entry.amount.unwrap(),
409420
));
410-
// Add to current transaction's output cache if it's received balance.
421+
// Add to current block's output cache if it's received balance.
411422
let k = (entry.tx_id.clone(), entry.output.unwrap().0);
412423
let rune_id = RuneId::from_str(entry.rune_id.as_str()).unwrap();
413424
let balance = InputRuneBalance {
@@ -416,7 +427,7 @@ impl IndexCache {
416427
};
417428
let mut default = HashMap::new();
418429
default.insert(rune_id, vec![balance.clone()]);
419-
self.tx_output_cache
430+
self.block_output_cache
420431
.entry(k)
421432
.and_modify(|i| {
422433
i.entry(rune_id)

0 commit comments

Comments
 (0)