@o1-labs/mina-archive-node-graphql 0.0.6 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +92 -268
- package/build/src/blockchain/utils.js.map +1 -1
- package/build/src/config.js +86 -0
- package/build/src/config.js.map +1 -0
- package/build/src/db/archive-node-adapter/archive-node-adapter.js +29 -2
- package/build/src/db/archive-node-adapter/archive-node-adapter.js.map +1 -1
- package/build/src/db/archive-node-adapter/postgres-options.js +35 -0
- package/build/src/db/archive-node-adapter/postgres-options.js.map +1 -0
- package/build/src/db/sql/best-chain.js +5 -0
- package/build/src/db/sql/best-chain.js.map +1 -0
- package/build/src/db/sql/events-actions/queries.js +102 -21
- package/build/src/db/sql/events-actions/queries.js.map +1 -1
- package/build/src/db/sql/verification-key-updates/queries.js +100 -0
- package/build/src/db/sql/verification-key-updates/queries.js.map +1 -0
- package/build/src/db/sql/zkapp-commands/queries.js +363 -0
- package/build/src/db/sql/zkapp-commands/queries.js.map +1 -0
- package/build/src/db/sql/zkapp-commands/types.js +2 -0
- package/build/src/db/sql/zkapp-commands/types.js.map +1 -0
- package/build/src/errors/error.js +4 -1
- package/build/src/errors/error.js.map +1 -1
- package/build/src/index.js +44 -7
- package/build/src/index.js.map +1 -1
- package/build/src/resolvers.js +42 -23
- package/build/src/resolvers.js.map +1 -1
- package/build/src/schema-version.js +2 -0
- package/build/src/schema-version.js.map +1 -0
- package/build/src/server/cors.js +41 -0
- package/build/src/server/cors.js.map +1 -0
- package/build/src/server/graceful-shutdown.js +42 -0
- package/build/src/server/graceful-shutdown.js.map +1 -0
- package/build/src/server/graphql-armor.js +39 -0
- package/build/src/server/graphql-armor.js.map +1 -0
- package/build/src/server/logger.js +45 -0
- package/build/src/server/logger.js.map +1 -0
- package/build/src/server/metrics.js +72 -0
- package/build/src/server/metrics.js.map +1 -0
- package/build/src/server/plugins.js +31 -15
- package/build/src/server/plugins.js.map +1 -1
- package/build/src/server/rate-limit.js +143 -0
- package/build/src/server/rate-limit.js.map +1 -0
- package/build/src/server/readiness.js +45 -0
- package/build/src/server/readiness.js.map +1 -0
- package/build/src/server/request-logging.js +58 -0
- package/build/src/server/request-logging.js.map +1 -0
- package/build/src/server/server.js +38 -13
- package/build/src/server/server.js.map +1 -1
- package/build/src/services/actions-service/actions-service.js +26 -15
- package/build/src/services/actions-service/actions-service.js.map +1 -1
- package/build/src/services/blocks-service/blocks-service.js +10 -9
- package/build/src/services/blocks-service/blocks-service.js.map +1 -1
- package/build/src/services/network-service/network-service.js +17 -9
- package/build/src/services/network-service/network-service.js.map +1 -1
- package/build/src/services/verification-key-updates-service/verification-key-updates-service.interface.js +2 -0
- package/build/src/services/verification-key-updates-service/verification-key-updates-service.interface.js.map +1 -0
- package/build/src/services/verification-key-updates-service/verification-key-updates-service.js +41 -0
- package/build/src/services/verification-key-updates-service/verification-key-updates-service.js.map +1 -0
- package/build/src/services/zkapp-commands-service/zkapp-commands-service.interface.js +2 -0
- package/build/src/services/zkapp-commands-service/zkapp-commands-service.interface.js.map +1 -0
- package/build/src/services/zkapp-commands-service/zkapp-commands-service.js +115 -0
- package/build/src/services/zkapp-commands-service/zkapp-commands-service.js.map +1 -0
- package/build/src/tracing/jaeger-tracing.js +2 -1
- package/build/src/tracing/jaeger-tracing.js.map +1 -1
- package/build/tests/devnet-dump/action-state-invariants.js +165 -0
- package/build/tests/devnet-dump/action-state-invariants.js.map +1 -0
- package/build/tests/devnet-dump/devnet-dump.test.js +24 -10
- package/build/tests/devnet-dump/devnet-dump.test.js.map +1 -1
- package/build/tests/devnet-dump/setup.js +63 -17
- package/build/tests/devnet-dump/setup.js.map +1 -1
- package/build/tests/integration/action-state-ordering.test.js +139 -0
- package/build/tests/integration/action-state-ordering.test.js.map +1 -0
- package/build/tests/integration/action-state-setup.js +48 -0
- package/build/tests/integration/action-state-setup.js.map +1 -0
- package/build/tests/integration/consensus-vs-chain.test.js +81 -0
- package/build/tests/integration/consensus-vs-chain.test.js.map +1 -0
- package/build/tests/integration/integration.test.js +166 -2
- package/build/tests/integration/integration.test.js.map +1 -1
- package/build/tests/integration/postgres-timeout.test.js +92 -0
- package/build/tests/integration/postgres-timeout.test.js.map +1 -0
- package/build/tests/integration/setup.js +58 -1
- package/build/tests/integration/setup.js.map +1 -1
- package/build/tests/integration/verification-key-setup.js +49 -0
- package/build/tests/integration/verification-key-setup.js.map +1 -0
- package/build/tests/integration/verification-key-updates.test.js +159 -0
- package/build/tests/integration/verification-key-updates.test.js.map +1 -0
- package/build/tests/live-api/events.test.js +11 -7
- package/build/tests/live-api/events.test.js.map +1 -1
- package/build/tests/live-api/networkState.test.js +1 -0
- package/build/tests/live-api/networkState.test.js.map +1 -1
- package/build/tests/live-network/live-network.test.js +1 -0
- package/build/tests/live-network/live-network.test.js.map +1 -1
- package/build/tests/resolvers.test.js +65 -37
- package/build/tests/resolvers.test.js.map +1 -1
- package/build/tests/services/verification-key-updates-service/verification-key-updates-service.test.js +35 -0
- package/build/tests/services/verification-key-updates-service/verification-key-updates-service.test.js.map +1 -0
- package/build/tests/services/zkapp-commands-service/zkapp-commands-service.test.js +159 -0
- package/build/tests/services/zkapp-commands-service/zkapp-commands-service.test.js.map +1 -0
- package/build/tests/test-helpers.js +15 -0
- package/build/tests/test-helpers.js.map +1 -1
- package/build/tests/unit/best-chain-anchor.test.js +70 -0
- package/build/tests/unit/best-chain-anchor.test.js.map +1 -0
- package/build/tests/unit/config.test.js +106 -0
- package/build/tests/unit/config.test.js.map +1 -0
- package/build/tests/unit/cors.test.js +95 -0
- package/build/tests/unit/cors.test.js.map +1 -0
- package/build/tests/unit/error-masking.test.js +119 -0
- package/build/tests/unit/error-masking.test.js.map +1 -0
- package/build/tests/unit/graceful-shutdown.test.js +99 -0
- package/build/tests/unit/graceful-shutdown.test.js.map +1 -0
- package/build/tests/unit/graphql-armor.test.js +121 -0
- package/build/tests/unit/graphql-armor.test.js.map +1 -0
- package/build/tests/unit/logging.test.js +120 -0
- package/build/tests/unit/logging.test.js.map +1 -0
- package/build/tests/unit/metrics.test.js +114 -0
- package/build/tests/unit/metrics.test.js.map +1 -0
- package/build/tests/unit/network-service.test.js +66 -0
- package/build/tests/unit/network-service.test.js.map +1 -0
- package/build/tests/unit/postgres-options.test.js +56 -0
- package/build/tests/unit/postgres-options.test.js.map +1 -0
- package/build/tests/unit/rate-limit.test.js +271 -0
- package/build/tests/unit/rate-limit.test.js.map +1 -0
- package/build/tests/unit/readiness.test.js +75 -0
- package/build/tests/unit/readiness.test.js.map +1 -0
- package/build/tests/unit/schema-nullability.test.js +40 -0
- package/build/tests/unit/schema-nullability.test.js.map +1 -0
- package/build/tests/unit/schema-version.test.js +48 -0
- package/build/tests/unit/schema-version.test.js.map +1 -0
- package/build/tests/unit/yoga-http-contract.test.js +30 -0
- package/build/tests/unit/yoga-http-contract.test.js.map +1 -0
- package/build/tests/unit/zkapp-commands-gating.test.js +38 -0
- package/build/tests/unit/zkapp-commands-gating.test.js.map +1 -0
- package/build/zkapp/utils.js +2 -0
- package/build/zkapp/utils.js.map +1 -1
- package/package.json +33 -14
- package/schema.graphql +126 -8
- package/src/blockchain/types.ts +65 -1
- package/src/blockchain/utils.ts +26 -2
- package/src/config.ts +133 -0
- package/src/db/archive-node-adapter/archive-node-adapter.interface.ts +26 -3
- package/src/db/archive-node-adapter/archive-node-adapter.ts +65 -2
- package/src/db/archive-node-adapter/postgres-options.ts +90 -0
- package/src/db/sql/best-chain.ts +34 -0
- package/src/db/sql/events-actions/queries.ts +168 -24
- package/src/db/sql/verification-key-updates/queries.ts +132 -0
- package/src/db/sql/zkapp-commands/queries.ts +406 -0
- package/src/db/sql/zkapp-commands/types.ts +43 -0
- package/src/envionment.d.ts +20 -0
- package/src/errors/error.ts +17 -1
- package/src/index.ts +64 -7
- package/src/resolvers-types.ts +311 -24
- package/src/resolvers.ts +70 -34
- package/src/schema-version.ts +24 -0
- package/src/server/cors.ts +97 -0
- package/src/server/graceful-shutdown.ts +76 -0
- package/src/server/graphql-armor.ts +78 -0
- package/src/server/logger.ts +72 -0
- package/src/server/metrics.ts +104 -0
- package/src/server/plugins.ts +53 -19
- package/src/server/rate-limit.ts +274 -0
- package/src/server/readiness.ts +78 -0
- package/src/server/request-logging.ts +83 -0
- package/src/server/server.ts +70 -15
- package/src/services/actions-service/actions-service.ts +87 -24
- package/src/services/blocks-service/blocks-service.ts +16 -14
- package/src/services/network-service/network-service.ts +30 -12
- package/src/services/verification-key-updates-service/verification-key-updates-service.interface.ts +9 -0
- package/src/services/verification-key-updates-service/verification-key-updates-service.ts +72 -0
- package/src/services/zkapp-commands-service/zkapp-commands-service.interface.ts +9 -0
- package/src/services/zkapp-commands-service/zkapp-commands-service.ts +181 -0
- package/src/tracing/jaeger-tracing.ts +2 -1
- package/build/tests/consensus/run-compare.js +0 -40
- package/build/tests/consensus/run-compare.js.map +0 -1
- package/build/tests/consensus/select-consensus-precomputed.js +0 -80
- package/build/tests/consensus/select-consensus-precomputed.js.map +0 -1
- package/build/tests/consensus/types.js +0 -15
- package/build/tests/consensus/types.js.map +0 -1
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
import type postgres from 'postgres';
|
|
2
|
+
import { BlockStatusFilter } from '../../../blockchain/types.js';
|
|
3
|
+
import type { ZkappCommandDatabaseRow } from './types.js';
|
|
4
|
+
|
|
5
|
+
function blockRangeCte(
|
|
6
|
+
dbClient: postgres.Sql,
|
|
7
|
+
status: BlockStatusFilter,
|
|
8
|
+
to: number,
|
|
9
|
+
from: number
|
|
10
|
+
) {
|
|
11
|
+
if (status === BlockStatusFilter.canonical) {
|
|
12
|
+
return dbClient`
|
|
13
|
+
max_height AS (
|
|
14
|
+
SELECT MAX(height) AS value FROM blocks
|
|
15
|
+
),
|
|
16
|
+
block_range AS (
|
|
17
|
+
SELECT
|
|
18
|
+
b.id,
|
|
19
|
+
b.state_hash,
|
|
20
|
+
b.parent_hash,
|
|
21
|
+
b.height,
|
|
22
|
+
b.global_slot_since_genesis,
|
|
23
|
+
b.global_slot_since_hard_fork,
|
|
24
|
+
b.timestamp,
|
|
25
|
+
b.chain_status,
|
|
26
|
+
b.ledger_hash,
|
|
27
|
+
b.last_vrf_output
|
|
28
|
+
FROM blocks b
|
|
29
|
+
WHERE b.chain_status = 'canonical'
|
|
30
|
+
AND b.height >= ${from}
|
|
31
|
+
AND b.height < ${to}
|
|
32
|
+
)
|
|
33
|
+
`;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return dbClient`
|
|
37
|
+
RECURSIVE max_height AS (
|
|
38
|
+
SELECT MAX(height) AS value FROM blocks
|
|
39
|
+
),
|
|
40
|
+
pending_chain AS (
|
|
41
|
+
(
|
|
42
|
+
SELECT
|
|
43
|
+
id,
|
|
44
|
+
state_hash,
|
|
45
|
+
parent_hash,
|
|
46
|
+
parent_id,
|
|
47
|
+
height,
|
|
48
|
+
global_slot_since_genesis,
|
|
49
|
+
global_slot_since_hard_fork,
|
|
50
|
+
timestamp,
|
|
51
|
+
chain_status,
|
|
52
|
+
ledger_hash,
|
|
53
|
+
last_vrf_output
|
|
54
|
+
FROM blocks
|
|
55
|
+
WHERE height = (SELECT value FROM max_height)
|
|
56
|
+
)
|
|
57
|
+
UNION ALL
|
|
58
|
+
SELECT
|
|
59
|
+
b.id,
|
|
60
|
+
b.state_hash,
|
|
61
|
+
b.parent_hash,
|
|
62
|
+
b.parent_id,
|
|
63
|
+
b.height,
|
|
64
|
+
b.global_slot_since_genesis,
|
|
65
|
+
b.global_slot_since_hard_fork,
|
|
66
|
+
b.timestamp,
|
|
67
|
+
b.chain_status,
|
|
68
|
+
b.ledger_hash,
|
|
69
|
+
b.last_vrf_output
|
|
70
|
+
FROM blocks b
|
|
71
|
+
INNER JOIN pending_chain
|
|
72
|
+
ON b.id = pending_chain.parent_id
|
|
73
|
+
AND pending_chain.id <> pending_chain.parent_id
|
|
74
|
+
AND pending_chain.chain_status <> 'canonical'
|
|
75
|
+
),
|
|
76
|
+
full_chain AS (
|
|
77
|
+
SELECT DISTINCT
|
|
78
|
+
id,
|
|
79
|
+
state_hash,
|
|
80
|
+
parent_id,
|
|
81
|
+
parent_hash,
|
|
82
|
+
height,
|
|
83
|
+
global_slot_since_genesis,
|
|
84
|
+
global_slot_since_hard_fork,
|
|
85
|
+
timestamp,
|
|
86
|
+
chain_status,
|
|
87
|
+
ledger_hash,
|
|
88
|
+
last_vrf_output
|
|
89
|
+
FROM (
|
|
90
|
+
SELECT
|
|
91
|
+
id,
|
|
92
|
+
state_hash,
|
|
93
|
+
parent_id,
|
|
94
|
+
parent_hash,
|
|
95
|
+
height,
|
|
96
|
+
global_slot_since_genesis,
|
|
97
|
+
global_slot_since_hard_fork,
|
|
98
|
+
timestamp,
|
|
99
|
+
chain_status,
|
|
100
|
+
ledger_hash,
|
|
101
|
+
last_vrf_output
|
|
102
|
+
FROM pending_chain
|
|
103
|
+
WHERE height >= ${from}
|
|
104
|
+
AND height < ${to}
|
|
105
|
+
UNION ALL
|
|
106
|
+
SELECT
|
|
107
|
+
id,
|
|
108
|
+
state_hash,
|
|
109
|
+
parent_id,
|
|
110
|
+
parent_hash,
|
|
111
|
+
height,
|
|
112
|
+
global_slot_since_genesis,
|
|
113
|
+
global_slot_since_hard_fork,
|
|
114
|
+
timestamp,
|
|
115
|
+
chain_status,
|
|
116
|
+
ledger_hash,
|
|
117
|
+
last_vrf_output
|
|
118
|
+
FROM blocks b
|
|
119
|
+
WHERE chain_status = 'canonical'
|
|
120
|
+
AND b.height >= ${from}
|
|
121
|
+
AND b.height < ${to}
|
|
122
|
+
) AS resolved_chain
|
|
123
|
+
),
|
|
124
|
+
block_range AS (
|
|
125
|
+
SELECT
|
|
126
|
+
b.id,
|
|
127
|
+
b.state_hash,
|
|
128
|
+
b.parent_hash,
|
|
129
|
+
b.height,
|
|
130
|
+
b.global_slot_since_genesis,
|
|
131
|
+
b.global_slot_since_hard_fork,
|
|
132
|
+
b.timestamp,
|
|
133
|
+
b.chain_status,
|
|
134
|
+
b.ledger_hash,
|
|
135
|
+
b.last_vrf_output
|
|
136
|
+
FROM full_chain b
|
|
137
|
+
WHERE 1 = 1
|
|
138
|
+
${
|
|
139
|
+
status === BlockStatusFilter.all
|
|
140
|
+
? dbClient``
|
|
141
|
+
: dbClient`AND b.chain_status = ${status.toLowerCase()}`
|
|
142
|
+
}
|
|
143
|
+
)
|
|
144
|
+
`;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function accountUpdateFilterCtes(
|
|
148
|
+
dbClient: postgres.Sql,
|
|
149
|
+
accountPublicKey?: string,
|
|
150
|
+
tokenId?: string
|
|
151
|
+
) {
|
|
152
|
+
if (!accountPublicKey && !tokenId) {
|
|
153
|
+
return dbClient``;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return dbClient`
|
|
157
|
+
,
|
|
158
|
+
matching_account_identifiers AS (
|
|
159
|
+
SELECT ai.id
|
|
160
|
+
FROM account_identifiers ai
|
|
161
|
+
JOIN public_keys pk ON ai.public_key_id = pk.id
|
|
162
|
+
JOIN tokens t ON ai.token_id = t.id
|
|
163
|
+
WHERE 1 = 1
|
|
164
|
+
${
|
|
165
|
+
accountPublicKey
|
|
166
|
+
? dbClient`AND pk.value = ${accountPublicKey}`
|
|
167
|
+
: dbClient``
|
|
168
|
+
}
|
|
169
|
+
${tokenId ? dbClient`AND t.value = ${tokenId}` : dbClient``}
|
|
170
|
+
),
|
|
171
|
+
target_account_updates AS (
|
|
172
|
+
SELECT zkau.id AS account_update_id
|
|
173
|
+
FROM matching_account_identifiers mai
|
|
174
|
+
JOIN zkapp_account_update_body zkub
|
|
175
|
+
ON zkub.account_identifier_id = mai.id
|
|
176
|
+
JOIN zkapp_account_update zkau ON zkau.body_id = zkub.id
|
|
177
|
+
)
|
|
178
|
+
`;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function accountUpdateRowsJoin(
|
|
182
|
+
dbClient: postgres.Sql,
|
|
183
|
+
accountPublicKey?: string,
|
|
184
|
+
tokenId?: string
|
|
185
|
+
) {
|
|
186
|
+
if (!accountPublicKey && !tokenId) {
|
|
187
|
+
return dbClient`
|
|
188
|
+
JOIN LATERAL unnest(zkc.zkapp_account_updates_ids)
|
|
189
|
+
WITH ORDINALITY AS account_update_ids(account_update_id, account_update_order) ON true
|
|
190
|
+
JOIN zkapp_account_update zkau ON zkau.id = account_update_ids.account_update_id
|
|
191
|
+
`;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
return dbClient`
|
|
195
|
+
JOIN target_account_updates tau
|
|
196
|
+
ON tau.account_update_id = ANY(zkc.zkapp_account_updates_ids)
|
|
197
|
+
JOIN LATERAL (
|
|
198
|
+
SELECT account_update_ids.account_update_id, account_update_ids.account_update_order
|
|
199
|
+
FROM unnest(zkc.zkapp_account_updates_ids)
|
|
200
|
+
WITH ORDINALITY AS account_update_ids(account_update_id, account_update_order)
|
|
201
|
+
WHERE account_update_ids.account_update_id = tau.account_update_id
|
|
202
|
+
) account_update_ids ON true
|
|
203
|
+
JOIN zkapp_account_update zkau ON zkau.id = tau.account_update_id
|
|
204
|
+
`;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
export function getZkappCommandsQuery(
|
|
208
|
+
dbClient: postgres.Sql,
|
|
209
|
+
status: BlockStatusFilter,
|
|
210
|
+
to: number,
|
|
211
|
+
from: number,
|
|
212
|
+
accountPublicKey?: string,
|
|
213
|
+
tokenId?: string
|
|
214
|
+
) {
|
|
215
|
+
return dbClient<ZkappCommandDatabaseRow[]>`
|
|
216
|
+
WITH ${blockRangeCte(dbClient, status, to, from)}
|
|
217
|
+
${accountUpdateFilterCtes(dbClient, accountPublicKey, tokenId)}
|
|
218
|
+
SELECT
|
|
219
|
+
b.id AS block_id,
|
|
220
|
+
b.state_hash,
|
|
221
|
+
b.parent_hash,
|
|
222
|
+
b.height,
|
|
223
|
+
b.global_slot_since_genesis,
|
|
224
|
+
b.global_slot_since_hard_fork,
|
|
225
|
+
b.timestamp,
|
|
226
|
+
b.chain_status,
|
|
227
|
+
b.ledger_hash,
|
|
228
|
+
(SELECT value FROM max_height) - b.height AS distance_from_max_block_height,
|
|
229
|
+
b.last_vrf_output,
|
|
230
|
+
zkc.hash,
|
|
231
|
+
zkc.memo,
|
|
232
|
+
bzkc.sequence_no AS sequence_number,
|
|
233
|
+
fee_payer_pk.value AS fee_payer,
|
|
234
|
+
fpb.fee,
|
|
235
|
+
zkau.id AS account_update_id,
|
|
236
|
+
account_update_ids.account_update_order,
|
|
237
|
+
account_update_pk.value AS public_key,
|
|
238
|
+
t.value AS token_id,
|
|
239
|
+
zkub.authorization_kind,
|
|
240
|
+
zkub.balance_change,
|
|
241
|
+
zkub.increment_nonce,
|
|
242
|
+
zkub.call_depth,
|
|
243
|
+
COALESCE(actions.fields, '[]'::jsonb) AS actions,
|
|
244
|
+
COALESCE(events.fields, '[]'::jsonb) AS events,
|
|
245
|
+
app_state.fields AS app_state,
|
|
246
|
+
account_precondition_state.fields AS account_precondition_state,
|
|
247
|
+
account_precondition_action_state.fields AS account_precondition_action_state,
|
|
248
|
+
account_precondition.proved_state AS account_precondition_proved_state,
|
|
249
|
+
account_precondition.is_new AS account_precondition_is_new,
|
|
250
|
+
network_global_slot_bounds.global_slot_lower_bound AS network_precondition_global_slot_lower_bound,
|
|
251
|
+
network_global_slot_bounds.global_slot_upper_bound AS network_precondition_global_slot_upper_bound
|
|
252
|
+
FROM block_range b
|
|
253
|
+
JOIN blocks_zkapp_commands bzkc
|
|
254
|
+
ON b.id = bzkc.block_id
|
|
255
|
+
AND bzkc.status <> 'failed'
|
|
256
|
+
JOIN zkapp_commands zkc ON bzkc.zkapp_command_id = zkc.id
|
|
257
|
+
JOIN zkapp_fee_payer_body fpb ON zkc.zkapp_fee_payer_body_id = fpb.id
|
|
258
|
+
JOIN public_keys fee_payer_pk ON fpb.public_key_id = fee_payer_pk.id
|
|
259
|
+
${accountUpdateRowsJoin(dbClient, accountPublicKey, tokenId)}
|
|
260
|
+
JOIN zkapp_account_update_body zkub ON zkau.body_id = zkub.id
|
|
261
|
+
JOIN account_identifiers ai ON zkub.account_identifier_id = ai.id
|
|
262
|
+
JOIN public_keys account_update_pk
|
|
263
|
+
ON ai.public_key_id = account_update_pk.id
|
|
264
|
+
${
|
|
265
|
+
accountPublicKey
|
|
266
|
+
? dbClient`AND account_update_pk.value = ${accountPublicKey}`
|
|
267
|
+
: dbClient``
|
|
268
|
+
}
|
|
269
|
+
JOIN tokens t
|
|
270
|
+
ON ai.token_id = t.id
|
|
271
|
+
${tokenId ? dbClient`AND t.value = ${tokenId}` : dbClient``}
|
|
272
|
+
LEFT JOIN zkapp_updates update_body ON update_body.id = zkub.update_id
|
|
273
|
+
LEFT JOIN zkapp_states_nullable app_state_rows ON app_state_rows.id = update_body.app_state_id
|
|
274
|
+
LEFT JOIN zkapp_account_precondition account_precondition
|
|
275
|
+
ON account_precondition.id = zkub.zkapp_account_precondition_id
|
|
276
|
+
LEFT JOIN zkapp_states_nullable account_precondition_state_rows
|
|
277
|
+
ON account_precondition_state_rows.id = account_precondition.state_id
|
|
278
|
+
LEFT JOIN zkapp_action_states account_precondition_action_state_rows
|
|
279
|
+
ON account_precondition_action_state_rows.id = account_precondition.action_state_id
|
|
280
|
+
LEFT JOIN zkapp_network_precondition network_precondition
|
|
281
|
+
ON network_precondition.id = zkub.zkapp_network_precondition_id
|
|
282
|
+
LEFT JOIN zkapp_global_slot_bounds network_global_slot_bounds
|
|
283
|
+
ON network_global_slot_bounds.id = network_precondition.global_slot_since_genesis
|
|
284
|
+
LEFT JOIN LATERAL (
|
|
285
|
+
SELECT COALESCE(jsonb_agg(jsonb_build_object('fields', field_array.fields) ORDER BY event_ids.event_order), '[]'::jsonb) AS fields
|
|
286
|
+
FROM zkapp_events action_events
|
|
287
|
+
JOIN LATERAL unnest(action_events.element_ids)
|
|
288
|
+
WITH ORDINALITY AS event_ids(field_array_id, event_order) ON true
|
|
289
|
+
JOIN zkapp_field_array event_field_array ON event_field_array.id = event_ids.field_array_id
|
|
290
|
+
JOIN LATERAL (
|
|
291
|
+
SELECT COALESCE(jsonb_agg(zkf.field ORDER BY field_ids.field_order), '[]'::jsonb) AS fields
|
|
292
|
+
FROM unnest(event_field_array.element_ids)
|
|
293
|
+
WITH ORDINALITY AS field_ids(field_id, field_order)
|
|
294
|
+
JOIN zkapp_field zkf ON zkf.id = field_ids.field_id
|
|
295
|
+
) field_array ON true
|
|
296
|
+
WHERE action_events.id = zkub.actions_id
|
|
297
|
+
) actions ON true
|
|
298
|
+
LEFT JOIN LATERAL (
|
|
299
|
+
SELECT COALESCE(jsonb_agg(jsonb_build_object('fields', field_array.fields) ORDER BY event_ids.event_order), '[]'::jsonb) AS fields
|
|
300
|
+
FROM zkapp_events account_update_events
|
|
301
|
+
JOIN LATERAL unnest(account_update_events.element_ids)
|
|
302
|
+
WITH ORDINALITY AS event_ids(field_array_id, event_order) ON true
|
|
303
|
+
JOIN zkapp_field_array event_field_array ON event_field_array.id = event_ids.field_array_id
|
|
304
|
+
JOIN LATERAL (
|
|
305
|
+
SELECT COALESCE(jsonb_agg(zkf.field ORDER BY field_ids.field_order), '[]'::jsonb) AS fields
|
|
306
|
+
FROM unnest(event_field_array.element_ids)
|
|
307
|
+
WITH ORDINALITY AS field_ids(field_id, field_order)
|
|
308
|
+
JOIN zkapp_field zkf ON zkf.id = field_ids.field_id
|
|
309
|
+
) field_array ON true
|
|
310
|
+
WHERE account_update_events.id = zkub.events_id
|
|
311
|
+
) events ON true
|
|
312
|
+
LEFT JOIN LATERAL (
|
|
313
|
+
SELECT jsonb_build_object('fields', jsonb_agg(zkf.field ORDER BY state_fields.field_order)) AS fields
|
|
314
|
+
FROM (VALUES
|
|
315
|
+
(0, app_state_rows.element0), (1, app_state_rows.element1),
|
|
316
|
+
(2, app_state_rows.element2), (3, app_state_rows.element3),
|
|
317
|
+
(4, app_state_rows.element4), (5, app_state_rows.element5),
|
|
318
|
+
(6, app_state_rows.element6), (7, app_state_rows.element7),
|
|
319
|
+
(8, app_state_rows.element8), (9, app_state_rows.element9),
|
|
320
|
+
(10, app_state_rows.element10), (11, app_state_rows.element11),
|
|
321
|
+
(12, app_state_rows.element12), (13, app_state_rows.element13),
|
|
322
|
+
(14, app_state_rows.element14), (15, app_state_rows.element15),
|
|
323
|
+
(16, app_state_rows.element16), (17, app_state_rows.element17),
|
|
324
|
+
(18, app_state_rows.element18), (19, app_state_rows.element19),
|
|
325
|
+
(20, app_state_rows.element20), (21, app_state_rows.element21),
|
|
326
|
+
(22, app_state_rows.element22), (23, app_state_rows.element23),
|
|
327
|
+
(24, app_state_rows.element24), (25, app_state_rows.element25),
|
|
328
|
+
(26, app_state_rows.element26), (27, app_state_rows.element27),
|
|
329
|
+
(28, app_state_rows.element28), (29, app_state_rows.element29),
|
|
330
|
+
(30, app_state_rows.element30), (31, app_state_rows.element31)
|
|
331
|
+
) AS state_fields(field_order, field_id)
|
|
332
|
+
LEFT JOIN zkapp_field zkf ON zkf.id = state_fields.field_id
|
|
333
|
+
WHERE app_state_rows.id IS NOT NULL
|
|
334
|
+
) app_state ON true
|
|
335
|
+
LEFT JOIN LATERAL (
|
|
336
|
+
SELECT jsonb_build_object('fields', jsonb_agg(zkf.field ORDER BY state_fields.field_order)) AS fields
|
|
337
|
+
FROM (VALUES
|
|
338
|
+
(0, account_precondition_state_rows.element0), (1, account_precondition_state_rows.element1),
|
|
339
|
+
(2, account_precondition_state_rows.element2), (3, account_precondition_state_rows.element3),
|
|
340
|
+
(4, account_precondition_state_rows.element4), (5, account_precondition_state_rows.element5),
|
|
341
|
+
(6, account_precondition_state_rows.element6), (7, account_precondition_state_rows.element7),
|
|
342
|
+
(8, account_precondition_state_rows.element8), (9, account_precondition_state_rows.element9),
|
|
343
|
+
(10, account_precondition_state_rows.element10), (11, account_precondition_state_rows.element11),
|
|
344
|
+
(12, account_precondition_state_rows.element12), (13, account_precondition_state_rows.element13),
|
|
345
|
+
(14, account_precondition_state_rows.element14), (15, account_precondition_state_rows.element15),
|
|
346
|
+
(16, account_precondition_state_rows.element16), (17, account_precondition_state_rows.element17),
|
|
347
|
+
(18, account_precondition_state_rows.element18), (19, account_precondition_state_rows.element19),
|
|
348
|
+
(20, account_precondition_state_rows.element20), (21, account_precondition_state_rows.element21),
|
|
349
|
+
(22, account_precondition_state_rows.element22), (23, account_precondition_state_rows.element23),
|
|
350
|
+
(24, account_precondition_state_rows.element24), (25, account_precondition_state_rows.element25),
|
|
351
|
+
(26, account_precondition_state_rows.element26), (27, account_precondition_state_rows.element27),
|
|
352
|
+
(28, account_precondition_state_rows.element28), (29, account_precondition_state_rows.element29),
|
|
353
|
+
(30, account_precondition_state_rows.element30), (31, account_precondition_state_rows.element31)
|
|
354
|
+
) AS state_fields(field_order, field_id)
|
|
355
|
+
LEFT JOIN zkapp_field zkf ON zkf.id = state_fields.field_id
|
|
356
|
+
WHERE account_precondition_state_rows.id IS NOT NULL
|
|
357
|
+
) account_precondition_state ON true
|
|
358
|
+
LEFT JOIN LATERAL (
|
|
359
|
+
SELECT jsonb_build_object('fields', jsonb_agg(zkf.field ORDER BY action_state_fields.field_order)) AS fields
|
|
360
|
+
FROM (VALUES
|
|
361
|
+
(0, account_precondition_action_state_rows.element0),
|
|
362
|
+
(1, account_precondition_action_state_rows.element1),
|
|
363
|
+
(2, account_precondition_action_state_rows.element2),
|
|
364
|
+
(3, account_precondition_action_state_rows.element3),
|
|
365
|
+
(4, account_precondition_action_state_rows.element4)
|
|
366
|
+
) AS action_state_fields(field_order, field_id)
|
|
367
|
+
LEFT JOIN zkapp_field zkf ON zkf.id = action_state_fields.field_id
|
|
368
|
+
WHERE account_precondition_action_state_rows.id IS NOT NULL
|
|
369
|
+
) account_precondition_action_state ON true
|
|
370
|
+
ORDER BY b.height, bzkc.sequence_no, account_update_ids.account_update_order;
|
|
371
|
+
`;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
export function getZkappCommandAccountUpdateCountQuery(
|
|
375
|
+
dbClient: postgres.Sql,
|
|
376
|
+
status: BlockStatusFilter,
|
|
377
|
+
to: number,
|
|
378
|
+
from: number,
|
|
379
|
+
accountPublicKey?: string,
|
|
380
|
+
tokenId?: string
|
|
381
|
+
) {
|
|
382
|
+
if (!accountPublicKey && !tokenId) {
|
|
383
|
+
return dbClient<{ count: string }[]>`
|
|
384
|
+
WITH ${blockRangeCte(dbClient, status, to, from)}
|
|
385
|
+
SELECT COALESCE(SUM(cardinality(zkc.zkapp_account_updates_ids)), 0)::text AS count
|
|
386
|
+
FROM block_range b
|
|
387
|
+
JOIN blocks_zkapp_commands bzkc
|
|
388
|
+
ON b.id = bzkc.block_id
|
|
389
|
+
AND bzkc.status <> 'failed'
|
|
390
|
+
JOIN zkapp_commands zkc ON bzkc.zkapp_command_id = zkc.id;
|
|
391
|
+
`;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return dbClient<{ count: string }[]>`
|
|
395
|
+
WITH ${blockRangeCte(dbClient, status, to, from)}
|
|
396
|
+
${accountUpdateFilterCtes(dbClient, accountPublicKey, tokenId)}
|
|
397
|
+
SELECT COUNT(*) AS count
|
|
398
|
+
FROM block_range b
|
|
399
|
+
JOIN blocks_zkapp_commands bzkc
|
|
400
|
+
ON b.id = bzkc.block_id
|
|
401
|
+
AND bzkc.status <> 'failed'
|
|
402
|
+
JOIN zkapp_commands zkc ON bzkc.zkapp_command_id = zkc.id
|
|
403
|
+
JOIN target_account_updates tau
|
|
404
|
+
ON tau.account_update_id = ANY(zkc.zkapp_account_updates_ids);
|
|
405
|
+
`;
|
|
406
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export type RawFieldArray = {
|
|
2
|
+
fields: (string | null)[];
|
|
3
|
+
};
|
|
4
|
+
|
|
5
|
+
export type RawNestedFieldArray = {
|
|
6
|
+
fields: string[];
|
|
7
|
+
}[];
|
|
8
|
+
|
|
9
|
+
export type ZkappCommandDatabaseRow = {
|
|
10
|
+
block_id: number;
|
|
11
|
+
state_hash: string;
|
|
12
|
+
parent_hash: string;
|
|
13
|
+
height: string;
|
|
14
|
+
global_slot_since_genesis: string;
|
|
15
|
+
global_slot_since_hard_fork: string;
|
|
16
|
+
timestamp: string;
|
|
17
|
+
chain_status: string;
|
|
18
|
+
ledger_hash: string;
|
|
19
|
+
distance_from_max_block_height: string;
|
|
20
|
+
last_vrf_output: string;
|
|
21
|
+
hash: string;
|
|
22
|
+
memo: string;
|
|
23
|
+
sequence_number: number;
|
|
24
|
+
fee_payer: string;
|
|
25
|
+
fee: string;
|
|
26
|
+
account_update_id: number;
|
|
27
|
+
account_update_order: string;
|
|
28
|
+
public_key: string;
|
|
29
|
+
token_id: string;
|
|
30
|
+
authorization_kind: string;
|
|
31
|
+
balance_change: string;
|
|
32
|
+
increment_nonce: boolean;
|
|
33
|
+
call_depth: number;
|
|
34
|
+
actions: RawNestedFieldArray;
|
|
35
|
+
events: RawNestedFieldArray;
|
|
36
|
+
app_state: RawFieldArray | null;
|
|
37
|
+
account_precondition_state: RawFieldArray | null;
|
|
38
|
+
account_precondition_action_state: RawFieldArray | null;
|
|
39
|
+
account_precondition_proved_state: boolean | null;
|
|
40
|
+
account_precondition_is_new: boolean | null;
|
|
41
|
+
network_precondition_global_slot_lower_bound: number | null;
|
|
42
|
+
network_precondition_global_slot_upper_bound: number | null;
|
|
43
|
+
};
|
package/src/envionment.d.ts
CHANGED
|
@@ -4,11 +4,31 @@ declare global {
|
|
|
4
4
|
LOG_LEVEL: string;
|
|
5
5
|
PORT?: string;
|
|
6
6
|
PG_CONN: string;
|
|
7
|
+
SHUTDOWN_TIMEOUT_MS?: string;
|
|
8
|
+
PG_MAX_CONNECTIONS?: string;
|
|
9
|
+
PG_IDLE_TIMEOUT?: string;
|
|
10
|
+
PG_CONNECT_TIMEOUT?: string;
|
|
11
|
+
PG_STATEMENT_TIMEOUT?: string;
|
|
7
12
|
CORS_ORIGIN?: string;
|
|
13
|
+
READINESS_PING_TIMEOUT_MS?: string;
|
|
14
|
+
RATE_LIMIT_MAX?: string;
|
|
15
|
+
RATE_LIMIT_WINDOW_MS?: string;
|
|
16
|
+
TRUST_PROXY?: string;
|
|
17
|
+
GRAPHQL_MAX_DEPTH?: string;
|
|
18
|
+
GRAPHQL_MAX_ALIASES?: string;
|
|
19
|
+
GRAPHQL_MAX_TOKENS?: string;
|
|
20
|
+
GRAPHQL_MAX_COST?: string;
|
|
21
|
+
BLOCK_RANGE_SIZE?: string;
|
|
22
|
+
ZKAPP_COMMAND_RANGE_SIZE?: string;
|
|
23
|
+
ZKAPP_COMMAND_ACCOUNT_UPDATE_LIMIT?: string;
|
|
8
24
|
ENABLE_LOGGING?: bool;
|
|
25
|
+
ENABLE_METRICS?: bool;
|
|
9
26
|
ENABLE_INTROSPECTION?: bool;
|
|
10
27
|
ENABLE_GRAPHIQL?: bool;
|
|
11
28
|
ENABLE_JAEGER?: bool;
|
|
29
|
+
ENABLE_BLOCK_TRANSACTION_DETAILS?: bool;
|
|
30
|
+
ENABLE_ZKAPP_COMMANDS_QUERY?: bool;
|
|
31
|
+
ENABLED_QUERIES?: string;
|
|
12
32
|
JAEGER_ENDPOINT?: string;
|
|
13
33
|
JAEGER_SERVICE_NAME?: string;
|
|
14
34
|
}
|
package/src/errors/error.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { GraphQLError } from 'graphql';
|
|
2
2
|
|
|
3
|
-
export {
|
|
3
|
+
export {
|
|
4
|
+
throwGraphQLError,
|
|
5
|
+
throwActionStateError,
|
|
6
|
+
throwActionStateOutOfRangeError,
|
|
7
|
+
throwBlockRangeError,
|
|
8
|
+
};
|
|
4
9
|
|
|
5
10
|
function throwGraphQLError(message: string, code?: string, status?: number) {
|
|
6
11
|
throw new GraphQLError(message, {
|
|
@@ -15,6 +20,17 @@ function throwActionStateError(message: string) {
|
|
|
15
20
|
throwGraphQLError(message, 'ACTION_STATE_NOT_FOUND', 400);
|
|
16
21
|
}
|
|
17
22
|
|
|
23
|
+
/**
|
|
24
|
+
* The action state is a real action state of the requested account, but it sits
|
|
25
|
+
* below the block range this query covers, and the account emitted actions in
|
|
26
|
+
* between. Any list we could return would be missing those actions. Returning it
|
|
27
|
+
* silently is what makes a client fold a wrong action state, so this is an error
|
|
28
|
+
* and not a truncated answer.
|
|
29
|
+
*/
|
|
30
|
+
function throwActionStateOutOfRangeError(message: string) {
|
|
31
|
+
throwGraphQLError(message, 'ACTION_STATE_OUT_OF_RANGE', 400);
|
|
32
|
+
}
|
|
33
|
+
|
|
18
34
|
function throwBlockRangeError(message: string) {
|
|
19
35
|
throwGraphQLError(message, 'BLOCK_RANGE_ERROR', 400);
|
|
20
36
|
}
|
package/src/index.ts
CHANGED
|
@@ -3,29 +3,86 @@
|
|
|
3
3
|
import { buildContext } from './context.js';
|
|
4
4
|
import { buildServer } from './server/server.js';
|
|
5
5
|
import { buildPlugins } from './server/plugins.js';
|
|
6
|
+
import { createGracefulShutdown } from './server/graceful-shutdown.js';
|
|
7
|
+
import { assertValidConfig } from './config.js';
|
|
8
|
+
import { logger } from './server/logger.js';
|
|
6
9
|
|
|
7
10
|
const PORT = process.env.PORT || 8080;
|
|
11
|
+
const SHUTDOWN_TIMEOUT_MS = Number(process.env.SHUTDOWN_TIMEOUT_MS) || 20000;
|
|
12
|
+
|
|
13
|
+
function withTimeout(
|
|
14
|
+
label: string,
|
|
15
|
+
ms: number,
|
|
16
|
+
run: () => Promise<unknown>
|
|
17
|
+
): Promise<void> {
|
|
18
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
19
|
+
return Promise.race([
|
|
20
|
+
run(),
|
|
21
|
+
new Promise<void>((_, reject) => {
|
|
22
|
+
timer = setTimeout(
|
|
23
|
+
() => reject(new Error(`${label} timed out after ${ms}ms`)),
|
|
24
|
+
ms
|
|
25
|
+
);
|
|
26
|
+
}),
|
|
27
|
+
])
|
|
28
|
+
.then(() => undefined)
|
|
29
|
+
.finally(() => {
|
|
30
|
+
if (timer !== undefined) clearTimeout(timer);
|
|
31
|
+
});
|
|
32
|
+
}
|
|
8
33
|
|
|
9
34
|
(async function main() {
|
|
10
35
|
try {
|
|
36
|
+
assertValidConfig();
|
|
11
37
|
const context = await buildContext(process.env.PG_CONN);
|
|
12
|
-
const plugins = await buildPlugins();
|
|
38
|
+
const { plugins, provider } = await buildPlugins();
|
|
13
39
|
const server = buildServer(context, plugins);
|
|
14
40
|
|
|
15
41
|
server.listen(PORT, () => {
|
|
16
|
-
|
|
42
|
+
logger.info({ port: PORT }, 'server started');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const shutdown = createGracefulShutdown({
|
|
46
|
+
timeoutMs: SHUTDOWN_TIMEOUT_MS,
|
|
47
|
+
// Stop accepting connections and wait for in-flight requests to drain.
|
|
48
|
+
closeServer: () =>
|
|
49
|
+
new Promise<void>((resolve, reject) => {
|
|
50
|
+
server.close((error) => (error ? reject(error) : resolve()));
|
|
51
|
+
// `close` also waits on idle keep-alive sockets, which browser
|
|
52
|
+
// clients hold open for keepAliveTimeout; dropping them keeps the
|
|
53
|
+
// drain prompt so the closers below still run inside the timeout.
|
|
54
|
+
server.closeIdleConnections();
|
|
55
|
+
}),
|
|
56
|
+
closers: [
|
|
57
|
+
// Flush buffered spans without letting an unreachable collector consume
|
|
58
|
+
// the whole shutdown budget.
|
|
59
|
+
() =>
|
|
60
|
+
withTimeout('trace flush', 3000, async () => {
|
|
61
|
+
if (provider) await provider.shutdown();
|
|
62
|
+
}),
|
|
63
|
+
// Close the Postgres pool. postgres.js waits forever by default for
|
|
64
|
+
// open connections, so bound the wait and let the force timer handle any
|
|
65
|
+
// still-running queries.
|
|
66
|
+
() => withTimeout('pg pool close', 5000, () => context.db_client.close()),
|
|
67
|
+
],
|
|
17
68
|
});
|
|
18
69
|
|
|
19
70
|
['SIGINT', 'SIGTERM', 'SIGQUIT'].forEach((signal) => {
|
|
20
|
-
process.on(signal, () =>
|
|
71
|
+
process.on(signal, () => void shutdown(signal));
|
|
21
72
|
});
|
|
22
73
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
74
|
+
// Crashes exit non-zero: an exit 0 reads as a clean stop to Kubernetes and
|
|
75
|
+
// systemd, suppressing restarts and non-zero-exit alerting.
|
|
76
|
+
process.on('uncaughtException', (error) => {
|
|
77
|
+
logger.error({ err: error }, 'uncaught exception');
|
|
78
|
+
void shutdown('uncaughtException', 1);
|
|
79
|
+
});
|
|
80
|
+
process.on('unhandledRejection', (reason) => {
|
|
81
|
+
logger.error({ err: reason }, 'unhandled rejection');
|
|
82
|
+
void shutdown('unhandledRejection', 1);
|
|
26
83
|
});
|
|
27
84
|
} catch (error) {
|
|
28
|
-
|
|
85
|
+
logger.error({ err: error }, 'fatal error during startup');
|
|
29
86
|
process.exit(1); // exit with an error code
|
|
30
87
|
}
|
|
31
88
|
})();
|