Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NONEVM-745 solana schema #15171

Draft
wants to merge 7 commits into
base: develop
Choose a base branch
from
Draft
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 82 additions & 0 deletions core/store/migrate/migrations/0259_add_solana_schema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
-- +goose Up
-- +goose StatementBegin
-- This removes evm from the search path, to avoid risk of an unqualified query intended to act on a Solana table accidentally
-- acting on the corresponding evm table. This makes schema qualification mandatory for all chain-specific queries.
SET search_path TO public;
dhaidashenko marked this conversation as resolved.
Show resolved Hide resolved
CREATE SCHEMA solana;

CREATE TABLE solana.log_poller_filters (
id BIGSERIAL PRIMARY KEY,
chain_id TEXT NOT NULL, -- use human-readable name instead of genesis block hash to reduce index size by 50%
name TEXT NOT NULL,
address BYTEA NOT NULL,
event_name TEXT NOT NULL,
event_sig BYTEA NOT NULL,
starting_block BIGINT NOT NULL,
event_idl TEXT,
sub_key_paths json, -- A list of subkeys to be indexed, represented by their json paths in the event struct. Forced to use json's 2d array as text[][] requires all paths to have equal length.
retention BIGINT NOT NULL DEFAULT 0, -- we don’t have to implement this initially, but good to include it in the schema
max_logs_kept BIGINT NOT NULL DEFAULT 0 -- same as retention, no need to implement yet
);

-- This generates a unique BIGINT for the log_poller_filters table from hashing (name, chain_id, address, event_sig, sub_key_paths).
-- Using an ordinary multi-column index on 5 columns would require a lot of extra storage space.
-- Note for updating this if and when we drop support for postgresql 12 & 13: hashrecordextended() can be used directly in postgresql 14, avoiding the need for a helper function.
-- The helper function is necessary only for the IMMUTABLE keyword.
CREATE OR REPLACE FUNCTION solana.f_log_poller_filter_hash(name TEXT, chain_id TEXT, address BYTEA, event_sig BYTEA, sub_key_paths json)
RETURNS BIGINT
LANGUAGE SQL IMMUTABLE COST 25 PARALLEL SAFE AS 'SELECT hashtextextended(textin(record_out(($1,$2,$3,$4,$5))), 0)';

CREATE UNIQUE INDEX IF NOT EXISTS solana_log_poller_filters_hash_key
ON solana.log_poller_filters (solana.f_log_poller_filter_hash(name, chain_id, address, event_sig, sub_key_paths));
dhaidashenko marked this conversation as resolved.
Show resolved Hide resolved

CREATE TABLE solana.logs (
id BIGSERIAL PRIMARY KEY,
filter_id BIGINT NOT NULL REFERENCES solana.log_poller_filters (id) ON DELETE CASCADE,
chain_id TEXT not null, -- use human-readable name instead of genesis block hash to reduce index size by 50%
log_index bigint not null,
block_hash bytea not null,
block_number bigint not null CHECK (block_number > 0),
block_timestamp timestamp with time zone not null,
address bytea not null,
event_sig bytea not null,
subkey_values bytea[] not null,
tx_hash bytea not null,
data bytea not null,
created_at timestamp with time zone not null,
expires_at timestamp with time zone null, -- null to indicate no timebase expiry
dhaidashenko marked this conversation as resolved.
Show resolved Hide resolved
sequence_num bigint not null
);

CREATE INDEX IF NOT EXISTS solana_logs_idx_by_timestamp ON solana.logs (chain_id, address, event_sig, block_timestamp, block_number);

CREATE INDEX IF NOT EXISTS solana_logs_idx ON solana.logs (chain_id, block_number, address, event_sig);

CREATE INDEX IF NOT EXISTS solana_logs_idx_subkey_one ON solana.logs ((subkey_values[1]));
CREATE INDEX IF NOT EXISTS solana_logs_idx_subkey_two ON solana.logs ((subkey_values[2]));
CREATE INDEX IF NOT EXISTS solana_logs_idx_subkey_three ON solana.logs ((subkey_values[3]));
CREATE INDEX IF NOT EXISTS solana_logs_idx_subkey_four ON solana.logs ((subkey_values[4]));

CREATE INDEX IF NOT EXISTS solana_logs_idx_tx_hash ON solana.logs (tx_hash);

-- Useful for the current form of those queries: WHERE chain_id = $1 AND address = $2 AND event_sig = $3 ... ORDER BY block_number, log_index
-- log_index is not included in this index because it increases the index size by ~ 10% for a likely negligible performance benefit
CREATE INDEX IF NOT EXISTS solana_logs_idx_chain_address_event_block ON solana.logs (chain_id, address, event_sig, block_number);

CREATE UNIQUE INDEX IF NOT EXISTS solana_logs_idx_chain_filter_block_logindex ON solana.logs USING btree (chain_id, filter_id, block_number, log_index);

-- +goose StatementEnd


-- +goose Down
-- +goose StatementBegin

DROP TABLE IF EXISTS solana.logs;
DROP TABLE IF EXISTS solana.log_poller_filters;

DROP FUNCTION IF EXISTS solana.f_log_poller_filter_hash(name TEXT, chain_id TEXT, address BYTEA, event_sig BYTEA, sub_key_paths json);

DROP SCHEMA solana;

SET search_path TO public,evm;
-- +goose StatementEnd
Loading