From 066798688c242aef381045899b912dfabe2ac750 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Fri, 12 May 2023 11:03:40 -0400 Subject: [PATCH 01/44] inital database schema for block storage (#4) --- .gitignore | 1 + database/schema/create_schema_comet.sql | 4 ++++ database/schema/create_table_block.sql | 21 +++++++++++++++++++++ database/schema/create_table_chain_id.sql | 14 ++++++++++++++ database/schema/create_table_consensus.sql | 16 ++++++++++++++++ 5 files changed, 56 insertions(+) create mode 100644 .gitignore create mode 100644 database/schema/create_schema_comet.sql create mode 100644 database/schema/create_table_block.sql create mode 100644 database/schema/create_table_chain_id.sql create mode 100644 database/schema/create_table_consensus.sql diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..723ef36 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea \ No newline at end of file diff --git a/database/schema/create_schema_comet.sql b/database/schema/create_schema_comet.sql new file mode 100644 index 0000000..80b2137 --- /dev/null +++ b/database/schema/create_schema_comet.sql @@ -0,0 +1,4 @@ +-- SCHEMA: comet + +CREATE SCHEMA IF NOT EXISTS comet + AUTHORIZATION postgres; \ No newline at end of file diff --git a/database/schema/create_table_block.sql b/database/schema/create_table_block.sql new file mode 100644 index 0000000..f3130a4 --- /dev/null +++ b/database/schema/create_table_block.sql @@ -0,0 +1,21 @@ +-- Table: comet.block + +CREATE TABLE IF NOT EXISTS comet.block +( + header_height bigint NOT NULL, + header_chain_id smallint NOT NULL, + header_version smallint NOT NULL, + header_time timestamp with time zone NOT NULL, + CONSTRAINT block_pkey PRIMARY KEY (header_height), + CONSTRAINT chain_id_fk FOREIGN KEY (header_chain_id) + REFERENCES public.chain_id (id) MATCH SIMPLE + ON UPDATE NO ACTION + ON DELETE NO ACTION + NOT VALID, + CONSTRAINT height_positive CHECK (header_height >= 0) + ) + + TABLESPACE pg_default; + +ALTER TABLE IF EXISTS comet.block + OWNER to postgres; \ No newline at end of file diff --git a/database/schema/create_table_chain_id.sql b/database/schema/create_table_chain_id.sql new file mode 100644 index 0000000..93e9173 --- /dev/null +++ b/database/schema/create_table_chain_id.sql @@ -0,0 +1,14 @@ +-- Table: comet.chain_id + +CREATE TABLE IF NOT EXISTS comet.chain_id +( + id smallint NOT NULL DEFAULT nextval('chain_id_id_seq'::regclass), + name text COLLATE pg_catalog."default" NOT NULL, + CONSTRAINT chain_id_pkey PRIMARY KEY (id), + CONSTRAINT chain_id_name_key UNIQUE (name) + ) + + TABLESPACE pg_default; + +ALTER TABLE IF EXISTS comet.chain_id + OWNER to postgres; \ No newline at end of file diff --git a/database/schema/create_table_consensus.sql b/database/schema/create_table_consensus.sql new file mode 100644 index 0000000..c2bb0e0 --- /dev/null +++ b/database/schema/create_table_consensus.sql @@ -0,0 +1,16 @@ +-- Table: comet.consensus + +CREATE TABLE IF NOT EXISTS comet.consensus +( + id smallint NOT NULL DEFAULT nextval('consensus_id_seq'::regclass), + block uint64 NOT NULL, + app uint64 NOT NULL, + CONSTRAINT consensus_pk PRIMARY KEY (block, app), + CONSTRAINT block_app_unique UNIQUE (block, app) + INCLUDE(block, app) + ) + + TABLESPACE pg_default; + +ALTER TABLE IF EXISTS comet.consensus + OWNER to postgres; \ No newline at end of file From 8f9817e4246ffabd14cae03b6967d3981150dc00 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Fri, 12 May 2023 14:36:26 -0400 Subject: [PATCH 02/44] add uint64 domain (#4) --- database/schema/create_domain_uint64.sql | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 database/schema/create_domain_uint64.sql diff --git a/database/schema/create_domain_uint64.sql b/database/schema/create_domain_uint64.sql new file mode 100644 index 0000000..7e66700 --- /dev/null +++ b/database/schema/create_domain_uint64.sql @@ -0,0 +1,12 @@ +-- DOMAIN: comet.uint64 + +CREATE DOMAIN public.uint64 + AS numeric; + +ALTER DOMAIN public.uint64 OWNER TO postgres; + +ALTER DOMAIN public.uint64 + ADD CONSTRAINT value_max CHECK (VALUE <= '18446744073709551615'::numeric); + +ALTER DOMAIN public.uint64 + ADD CONSTRAINT value_positive CHECK (VALUE >= 0::numeric); \ No newline at end of file From 955e38a513119b062dd2d99a349af19dab936eb6 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Fri, 12 May 2023 14:57:59 -0400 Subject: [PATCH 03/44] minor fixes and renames (#4) --- README.md | 12 ++++++++++++ database/schema/create_database_data_companion.sql | 14 ++++++++++++++ database/schema/create_domain_uint64.sql | 8 ++++---- database/schema/create_table_block.sql | 2 +- database/schema/create_table_chain_id.sql | 2 +- database/schema/create_table_consensus.sql | 2 +- 6 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 database/schema/create_database_data_companion.sql diff --git a/README.md b/README.md index 2c3aa30..32921ab 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,15 @@ ### WIP (Work In Progress) This is the repository for the RPC Companion solution based on the Data Companion ADR + + +## Starting the Postgres Database + +cd ./database/docker +docker-compose -f docker-compose.yml up + +## Accessing the database with pgAdmin + +http://127.0.0.1:5050 +User: pgadmin@pgadmin.com +Password: pgadmin123 \ No newline at end of file diff --git a/database/schema/create_database_data_companion.sql b/database/schema/create_database_data_companion.sql new file mode 100644 index 0000000..3843eb8 --- /dev/null +++ b/database/schema/create_database_data_companion.sql @@ -0,0 +1,14 @@ +-- Database: data_companion + +CREATE DATABASE data_companion + WITH + OWNER = postgres + ENCODING = 'UTF8' + LC_COLLATE = 'en_US.utf8' + LC_CTYPE = 'en_US.utf8' + TABLESPACE = pg_default + CONNECTION LIMIT = -1 + IS_TEMPLATE = False; + +COMMENT ON DATABASE data_companion + IS 'CometBFT Data Companion Database'; \ No newline at end of file diff --git a/database/schema/create_domain_uint64.sql b/database/schema/create_domain_uint64.sql index 7e66700..32417db 100644 --- a/database/schema/create_domain_uint64.sql +++ b/database/schema/create_domain_uint64.sql @@ -1,12 +1,12 @@ -- DOMAIN: comet.uint64 -CREATE DOMAIN public.uint64 +CREATE DOMAIN comet.uint64 AS numeric; -ALTER DOMAIN public.uint64 OWNER TO postgres; +ALTER DOMAIN comet.uint64 OWNER TO postgres; -ALTER DOMAIN public.uint64 +ALTER DOMAIN comet.uint64 ADD CONSTRAINT value_max CHECK (VALUE <= '18446744073709551615'::numeric); -ALTER DOMAIN public.uint64 +ALTER DOMAIN comet.uint64 ADD CONSTRAINT value_positive CHECK (VALUE >= 0::numeric); \ No newline at end of file diff --git a/database/schema/create_table_block.sql b/database/schema/create_table_block.sql index f3130a4..35176f3 100644 --- a/database/schema/create_table_block.sql +++ b/database/schema/create_table_block.sql @@ -8,7 +8,7 @@ CREATE TABLE IF NOT EXISTS comet.block header_time timestamp with time zone NOT NULL, CONSTRAINT block_pkey PRIMARY KEY (header_height), CONSTRAINT chain_id_fk FOREIGN KEY (header_chain_id) - REFERENCES public.chain_id (id) MATCH SIMPLE + REFERENCES comet.chain_id (id) MATCH SIMPLE ON UPDATE NO ACTION ON DELETE NO ACTION NOT VALID, diff --git a/database/schema/create_table_chain_id.sql b/database/schema/create_table_chain_id.sql index 93e9173..55e0f63 100644 --- a/database/schema/create_table_chain_id.sql +++ b/database/schema/create_table_chain_id.sql @@ -2,7 +2,7 @@ CREATE TABLE IF NOT EXISTS comet.chain_id ( - id smallint NOT NULL DEFAULT nextval('chain_id_id_seq'::regclass), + id smallserial NOT NULL, name text COLLATE pg_catalog."default" NOT NULL, CONSTRAINT chain_id_pkey PRIMARY KEY (id), CONSTRAINT chain_id_name_key UNIQUE (name) diff --git a/database/schema/create_table_consensus.sql b/database/schema/create_table_consensus.sql index c2bb0e0..01593a7 100644 --- a/database/schema/create_table_consensus.sql +++ b/database/schema/create_table_consensus.sql @@ -2,7 +2,7 @@ CREATE TABLE IF NOT EXISTS comet.consensus ( - id smallint NOT NULL DEFAULT nextval('consensus_id_seq'::regclass), + id smallserial NOT NULL, block uint64 NOT NULL, app uint64 NOT NULL, CONSTRAINT consensus_pk PRIMARY KEY (block, app), From eb6f6dbff6f9460cb1ecd38d5f3705cce5de1a1b Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Fri, 12 May 2023 15:00:43 -0400 Subject: [PATCH 04/44] More info README (#4) --- README.md | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 32921ab..14711a3 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,25 @@ -# RPC Companion - -### WIP (Work In Progress) +# RPC Companion (Work In Progress) This is the repository for the RPC Companion solution based on the Data Companion ADR - ## Starting the Postgres Database -cd ./database/docker -docker-compose -f docker-compose.yml up +Access the Docker folder: + +`cd ./database/docker` + +Run the services + +`docker-compose -f docker-compose.yml up` ## Accessing the database with pgAdmin +Open a browser and navigate to http://127.0.0.1:5050 + +Use the following credentials: + +``` User: pgadmin@pgadmin.com -Password: pgadmin123 \ No newline at end of file +Password: pgadmin123 +``` \ No newline at end of file From 6ea65de4a41252cfb8330bef8ca289a48e57320e Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Fri, 12 May 2023 18:05:13 -0400 Subject: [PATCH 05/44] update and fix sql scripts, add sequence number (#4) --- ..._schema_comet.sql => 1_create_schema_comet.sql} | 0 ...omain_uint64.sql => 2_create_domain_uint64.sql} | 0 ..._consensus.sql => 3_create_table_consensus.sql} | 4 ++-- ...le_chain_id.sql => 4_create_table_chain_id.sql} | 0 ...te_table_block.sql => 5_create_table_block.sql} | 0 database/schema/create_database_data_companion.sql | 14 -------------- 6 files changed, 2 insertions(+), 16 deletions(-) rename database/schema/{create_schema_comet.sql => 1_create_schema_comet.sql} (100%) rename database/schema/{create_domain_uint64.sql => 2_create_domain_uint64.sql} (100%) rename database/schema/{create_table_consensus.sql => 3_create_table_consensus.sql} (83%) rename database/schema/{create_table_chain_id.sql => 4_create_table_chain_id.sql} (100%) rename database/schema/{create_table_block.sql => 5_create_table_block.sql} (100%) delete mode 100644 database/schema/create_database_data_companion.sql diff --git a/database/schema/create_schema_comet.sql b/database/schema/1_create_schema_comet.sql similarity index 100% rename from database/schema/create_schema_comet.sql rename to database/schema/1_create_schema_comet.sql diff --git a/database/schema/create_domain_uint64.sql b/database/schema/2_create_domain_uint64.sql similarity index 100% rename from database/schema/create_domain_uint64.sql rename to database/schema/2_create_domain_uint64.sql diff --git a/database/schema/create_table_consensus.sql b/database/schema/3_create_table_consensus.sql similarity index 83% rename from database/schema/create_table_consensus.sql rename to database/schema/3_create_table_consensus.sql index 01593a7..0a48094 100644 --- a/database/schema/create_table_consensus.sql +++ b/database/schema/3_create_table_consensus.sql @@ -3,8 +3,8 @@ CREATE TABLE IF NOT EXISTS comet.consensus ( id smallserial NOT NULL, - block uint64 NOT NULL, - app uint64 NOT NULL, + block comet.uint64 NOT NULL, + app comet.uint64 NOT NULL, CONSTRAINT consensus_pk PRIMARY KEY (block, app), CONSTRAINT block_app_unique UNIQUE (block, app) INCLUDE(block, app) diff --git a/database/schema/create_table_chain_id.sql b/database/schema/4_create_table_chain_id.sql similarity index 100% rename from database/schema/create_table_chain_id.sql rename to database/schema/4_create_table_chain_id.sql diff --git a/database/schema/create_table_block.sql b/database/schema/5_create_table_block.sql similarity index 100% rename from database/schema/create_table_block.sql rename to database/schema/5_create_table_block.sql diff --git a/database/schema/create_database_data_companion.sql b/database/schema/create_database_data_companion.sql deleted file mode 100644 index 3843eb8..0000000 --- a/database/schema/create_database_data_companion.sql +++ /dev/null @@ -1,14 +0,0 @@ --- Database: data_companion - -CREATE DATABASE data_companion - WITH - OWNER = postgres - ENCODING = 'UTF8' - LC_COLLATE = 'en_US.utf8' - LC_CTYPE = 'en_US.utf8' - TABLESPACE = pg_default - CONNECTION LIMIT = -1 - IS_TEMPLATE = False; - -COMMENT ON DATABASE data_companion - IS 'CometBFT Data Companion Database'; \ No newline at end of file From 3701cdd9e62449f8459ea7900d829a4f33c4f301 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Mon, 15 May 2023 11:00:30 -0400 Subject: [PATCH 06/44] refactoring some fields (#4) --- database/schema/1_create_schema_comet.sql | 3 +-- database/schema/2_create_domain_uint64.sql | 2 -- database/schema/3_create_table_consensus.sql | 9 ++----- database/schema/4_create_table_chain_id.sql | 16 +++++------ database/schema/5_create_table_block.sql | 28 ++++++++------------ 5 files changed, 20 insertions(+), 38 deletions(-) diff --git a/database/schema/1_create_schema_comet.sql b/database/schema/1_create_schema_comet.sql index 80b2137..0ba013c 100644 --- a/database/schema/1_create_schema_comet.sql +++ b/database/schema/1_create_schema_comet.sql @@ -1,4 +1,3 @@ -- SCHEMA: comet -CREATE SCHEMA IF NOT EXISTS comet - AUTHORIZATION postgres; \ No newline at end of file +CREATE SCHEMA IF NOT EXISTS comet; \ No newline at end of file diff --git a/database/schema/2_create_domain_uint64.sql b/database/schema/2_create_domain_uint64.sql index 32417db..55f8bec 100644 --- a/database/schema/2_create_domain_uint64.sql +++ b/database/schema/2_create_domain_uint64.sql @@ -3,8 +3,6 @@ CREATE DOMAIN comet.uint64 AS numeric; -ALTER DOMAIN comet.uint64 OWNER TO postgres; - ALTER DOMAIN comet.uint64 ADD CONSTRAINT value_max CHECK (VALUE <= '18446744073709551615'::numeric); diff --git a/database/schema/3_create_table_consensus.sql b/database/schema/3_create_table_consensus.sql index 0a48094..e367d4e 100644 --- a/database/schema/3_create_table_consensus.sql +++ b/database/schema/3_create_table_consensus.sql @@ -2,15 +2,10 @@ CREATE TABLE IF NOT EXISTS comet.consensus ( - id smallserial NOT NULL, + consensus_id serial NOT NULL, block comet.uint64 NOT NULL, app comet.uint64 NOT NULL, CONSTRAINT consensus_pk PRIMARY KEY (block, app), CONSTRAINT block_app_unique UNIQUE (block, app) INCLUDE(block, app) - ) - - TABLESPACE pg_default; - -ALTER TABLE IF EXISTS comet.consensus - OWNER to postgres; \ No newline at end of file +) TABLESPACE pg_default; diff --git a/database/schema/4_create_table_chain_id.sql b/database/schema/4_create_table_chain_id.sql index 55e0f63..449a02f 100644 --- a/database/schema/4_create_table_chain_id.sql +++ b/database/schema/4_create_table_chain_id.sql @@ -2,13 +2,9 @@ CREATE TABLE IF NOT EXISTS comet.chain_id ( - id smallserial NOT NULL, - name text COLLATE pg_catalog."default" NOT NULL, - CONSTRAINT chain_id_pkey PRIMARY KEY (id), - CONSTRAINT chain_id_name_key UNIQUE (name) - ) - - TABLESPACE pg_default; - -ALTER TABLE IF EXISTS comet.chain_id - OWNER to postgres; \ No newline at end of file + chain_id smallserial NOT NULL, + chain_name text NOT NULL, + CONSTRAINT chain_id_pkey PRIMARY KEY (chain_id), + CONSTRAINT chain_id_name_key UNIQUE (chain_name) +) +TABLESPACE pg_default; \ No newline at end of file diff --git a/database/schema/5_create_table_block.sql b/database/schema/5_create_table_block.sql index 35176f3..9596ed5 100644 --- a/database/schema/5_create_table_block.sql +++ b/database/schema/5_create_table_block.sql @@ -2,20 +2,14 @@ CREATE TABLE IF NOT EXISTS comet.block ( - header_height bigint NOT NULL, - header_chain_id smallint NOT NULL, - header_version smallint NOT NULL, - header_time timestamp with time zone NOT NULL, - CONSTRAINT block_pkey PRIMARY KEY (header_height), - CONSTRAINT chain_id_fk FOREIGN KEY (header_chain_id) - REFERENCES comet.chain_id (id) MATCH SIMPLE - ON UPDATE NO ACTION - ON DELETE NO ACTION - NOT VALID, - CONSTRAINT height_positive CHECK (header_height >= 0) - ) - - TABLESPACE pg_default; - -ALTER TABLE IF EXISTS comet.block - OWNER to postgres; \ No newline at end of file + height bigint NOT NULL, + chain_id smallint NOT NULL, + version integer NOT NULL, + block_time timestamp with time zone NOT NULL, + CONSTRAINT block_pkey PRIMARY KEY (height), + CONSTRAINT chain_id_fk FOREIGN KEY (chain_id) + REFERENCES comet.chain_id (chain_id) MATCH SIMPLE + ON UPDATE RESTRICT + ON DELETE RESTRICT, + CONSTRAINT height_positive CHECK (height >= 0) +) TABLESPACE pg_default; From cf130ffe16179b2d3cfe713edb478d85a4f9d3b5 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Mon, 15 May 2023 18:40:57 -0400 Subject: [PATCH 07/44] initial logic to insert some blocks (#1) --- ...ble_block.sql => 3_create_table_block.sql} | 9 +- database/schema/3_create_table_consensus.sql | 11 - database/schema/4_create_table_chain_id.sql | 10 - go.mod | 37 ++ go.sum | 520 ++++++++++++++++++ main.go | 154 ++++++ types/block.go | 4 + 7 files changed, 718 insertions(+), 27 deletions(-) rename database/schema/{5_create_table_block.sql => 3_create_table_block.sql} (55%) delete mode 100644 database/schema/3_create_table_consensus.sql delete mode 100644 database/schema/4_create_table_chain_id.sql create mode 100644 go.sum create mode 100644 main.go create mode 100644 types/block.go diff --git a/database/schema/5_create_table_block.sql b/database/schema/3_create_table_block.sql similarity index 55% rename from database/schema/5_create_table_block.sql rename to database/schema/3_create_table_block.sql index 9596ed5..10954f5 100644 --- a/database/schema/5_create_table_block.sql +++ b/database/schema/3_create_table_block.sql @@ -3,13 +3,10 @@ CREATE TABLE IF NOT EXISTS comet.block ( height bigint NOT NULL, - chain_id smallint NOT NULL, - version integer NOT NULL, block_time timestamp with time zone NOT NULL, + chain_id text NOT NULL, + version_block comet.uint64 NOT NULL, + version_app comet.uint64 NOT NULL, CONSTRAINT block_pkey PRIMARY KEY (height), - CONSTRAINT chain_id_fk FOREIGN KEY (chain_id) - REFERENCES comet.chain_id (chain_id) MATCH SIMPLE - ON UPDATE RESTRICT - ON DELETE RESTRICT, CONSTRAINT height_positive CHECK (height >= 0) ) TABLESPACE pg_default; diff --git a/database/schema/3_create_table_consensus.sql b/database/schema/3_create_table_consensus.sql deleted file mode 100644 index e367d4e..0000000 --- a/database/schema/3_create_table_consensus.sql +++ /dev/null @@ -1,11 +0,0 @@ --- Table: comet.consensus - -CREATE TABLE IF NOT EXISTS comet.consensus -( - consensus_id serial NOT NULL, - block comet.uint64 NOT NULL, - app comet.uint64 NOT NULL, - CONSTRAINT consensus_pk PRIMARY KEY (block, app), - CONSTRAINT block_app_unique UNIQUE (block, app) - INCLUDE(block, app) -) TABLESPACE pg_default; diff --git a/database/schema/4_create_table_chain_id.sql b/database/schema/4_create_table_chain_id.sql deleted file mode 100644 index 449a02f..0000000 --- a/database/schema/4_create_table_chain_id.sql +++ /dev/null @@ -1,10 +0,0 @@ --- Table: comet.chain_id - -CREATE TABLE IF NOT EXISTS comet.chain_id -( - chain_id smallserial NOT NULL, - chain_name text NOT NULL, - CONSTRAINT chain_id_pkey PRIMARY KEY (chain_id), - CONSTRAINT chain_id_name_key UNIQUE (chain_name) -) -TABLESPACE pg_default; \ No newline at end of file diff --git a/go.mod b/go.mod index 4377ab3..7f75cca 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,40 @@ module github.com/cometbft/rpc-companion go 1.20 + +require ( + github.com/cometbft/cometbft v0.37.1 + github.com/lib/pq v1.10.9 +) + +require ( + github.com/beorn7/perks v1.0.1 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.2.1 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cosmos/gogoproto v1.4.1 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect + github.com/go-kit/kit v0.12.0 // indirect + github.com/go-kit/log v0.2.1 // indirect + github.com/go-logfmt/logfmt v0.5.1 // indirect + github.com/golang/protobuf v1.5.2 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/gtank/merlin v0.1.1 // indirect + github.com/libp2p/go-buffer-pool v0.1.0 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect + github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect + github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect + github.com/pkg/errors v0.9.1 // indirect + github.com/prometheus/client_golang v1.14.0 // indirect + github.com/prometheus/client_model v0.3.0 // indirect + github.com/prometheus/common v0.37.0 // indirect + github.com/prometheus/procfs v0.8.0 // indirect + github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect + github.com/sasha-s/go-deadlock v0.3.1 // indirect + golang.org/x/crypto v0.5.0 // indirect + golang.org/x/net v0.7.0 // indirect + golang.org/x/sys v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect + google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 // indirect + google.golang.org/grpc v1.52.0 // indirect + google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..2c55083 --- /dev/null +++ b/go.sum @@ -0,0 +1,520 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/btcsuite/btcd/btcec/v2 v2.2.1 h1:xP60mv8fvp+0khmrN0zTdPC3cNm24rfeE6lh2R/Yv3E= +github.com/btcsuite/btcd/btcec/v2 v2.2.1/go.mod h1:9/CSmJxmuvqzX9Wh2fXMWToLOHhPd11lSPuIupwTkI8= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= +github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cometbft/cometbft v0.37.1 h1:KLxkQTK2hICXYq21U2hn1W5hOVYUdQgDQ1uB+90xPIg= +github.com/cometbft/cometbft v0.37.1/go.mod h1:Y2MMMN//O5K4YKd8ze4r9jmk4Y7h0ajqILXbH5JQFVs= +github.com/cosmos/gogoproto v1.4.1 h1:WoyH+0/jbCTzpKNvyav5FL1ZTWsp1im1MxEpJEzKUB8= +github.com/cosmos/gogoproto v1.4.1/go.mod h1:Ac9lzL4vFpBMcptJROQ6dQ4M3pOEK5Z/l0Q9p+LoCr4= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.12.0 h1:e4o3o3IsBfAKQh5Qbbiqyfu97Ku7jrO/JbohvztANh4= +github.com/go-kit/kit v0.12.0/go.mod h1:lHd+EkCZPIwYItmGDDRdhinkzX2A1sj+M9biaEaizzs= +github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= +github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU= +github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= +github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is= +github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8= +github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= +github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= +github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 h1:QRUSJEgZn2Snx0EmT/QLXibWjSUDjKWvXIT19NBVp94= +github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= +github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw= +github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4= +github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= +github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= +github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE= +github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo= +github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= +github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= +github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= +golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 h1:a2S6M0+660BgMNl++4JPlcAO/CjkqYItDEZwkoDQK7c= +google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6/go.mod h1:rZS5c/ZVYMaOGBfO68GWtjOw/eLaZM1X6iVtgjZ+EWg= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.52.0 h1:kd48UiU7EHsV4rnLyOJRuP/Il/UHE7gdDAQ+SZI7nZk= +google.golang.org/grpc v1.52.0/go.mod h1:pu6fVzoFb+NBYNAvQL08ic+lvB2IojljRYuun5vorUY= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8 h1:KR8+MyP7/qOlV+8Af01LtjL04bu7on42eVsxT4EyBQk= +google.golang.org/protobuf v1.28.2-0.20220831092852-f930b1dc76e8/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/main.go b/main.go new file mode 100644 index 0000000..838769a --- /dev/null +++ b/main.go @@ -0,0 +1,154 @@ +package main + +import ( + "context" + "database/sql" + "fmt" + client "github.com/cometbft/cometbft/rpc/client/http" + ctypes "github.com/cometbft/cometbft/rpc/core/types" + _ "github.com/lib/pq" + "log" + "time" +) + +const connString = "postgres://postgres:postgres@0.0.0.0:15432/postgres?sslmode=disable" + +type Storage interface { + Insert(table string, value string) (bool, error) + Get(table string, query string) ([]byte, error) + Connect(conn string) error +} + +type Fetcher interface { + Fetch(endpoint string) ([]byte, error) +} + +type Service interface { + Serve() +} + +type IngestService struct { + Fetcher Fetcher + Storage Storage +} + +type CometFetcher struct { + Endpoint string +} + +type PostgresStorage struct { + ConnectionString string + Connection *sql.DB +} + +type RESTService struct { + Version string +} + +func (c *CometFetcher) FetchBlock(height int64) (*ctypes.ResultBlock, error) { + + httpClient, err := client.New("http://localhost:26657", "/websocket") + if err != nil { + return nil, err + } + + resultBlock, err := httpClient.Block(context.Background(), &height) + if err != nil { + return nil, err + } else { + return resultBlock, nil + } +} + +func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, error) { + _, err := c.Connection.Exec("INSERT INTO comet.block (height, version_block, version_app, block_time, chain_id) values ($1,$2,$3,$4, $5)", + resultBlock.Block.Height, resultBlock.Block.Version.Block, resultBlock.Block.Version.App, resultBlock.Block.Time, resultBlock.Block.ChainID) + if err != nil { + return false, err + } else { + return true, nil + } +} + +func (c *PostgresStorage) GetBlock(height int64) (int64, error) { + var rowHeight int64 + row := c.Connection.QueryRow("SELECT height FROM comet.block WHERE height=$1", height) + switch err := row.Scan(&rowHeight); err { + case sql.ErrNoRows: + return 0, err + case nil: + return 0, err + default: + return rowHeight, err + } +} + +func (c *PostgresStorage) Connect() error { + db, err := sql.Open("postgres", c.ConnectionString) + if err != nil { + return err + } else { + c.Connection = db + } + + db.SetMaxOpenConns(100) + db.SetMaxIdleConns(50) + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + err = db.PingContext(ctx) + if err != nil { + return err + } + + return nil +} + +func main() { + + fetcher := CometFetcher{ + Endpoint: "http://localhost:26657", + } + + storage := PostgresStorage{ + ConnectionString: connString, + Connection: nil, + } + + // Connect to the database + err := storage.Connect() + if err != nil { + panic(err) + } + + for height := 1; height <= 10; height++ { + + blockFetched, err := fetcher.FetchBlock(int64(height)) + if err != nil { + log.Fatalf("Error fetching block at height %d: %s\n", height, err) + } + + inserted, err := storage.InsertBlock(*blockFetched) + if err != nil { + fmt.Printf("Error inserting block at height %d: %s\n", height, err) + } + if inserted { + fmt.Printf("Inserted height %d\n", height) + } + + block, err := storage.GetBlock(int64(height)) + if err != nil { + fmt.Printf("Error retrieving block at height %d: %s\n", height, err) + } else { + log.Printf("Block at height %d: %v", height, block) + } + } + + defer func(ps PostgresStorage) { + err := ps.Connection.Close() + if err != nil { + log.Fatalln(err) + } + }(storage) +} diff --git a/types/block.go b/types/block.go new file mode 100644 index 0000000..86d1c66 --- /dev/null +++ b/types/block.go @@ -0,0 +1,4 @@ +package types + +type Block struct { +} From 119418de9fd758e1be4f4a4501c02eb647d65481 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Wed, 17 May 2023 17:33:53 -0400 Subject: [PATCH 08/44] added more block data, refactoring schema (#1) --- database/schema/3_create_domain_uint32.sql | 10 +++++++ database/schema/3_create_table_block.sql | 12 --------- .../schema/4_create_table_result_block.sql | 18 +++++++++++++ main.go | 26 ++++++++++++------- 4 files changed, 45 insertions(+), 21 deletions(-) create mode 100644 database/schema/3_create_domain_uint32.sql delete mode 100644 database/schema/3_create_table_block.sql create mode 100644 database/schema/4_create_table_result_block.sql diff --git a/database/schema/3_create_domain_uint32.sql b/database/schema/3_create_domain_uint32.sql new file mode 100644 index 0000000..bad3626 --- /dev/null +++ b/database/schema/3_create_domain_uint32.sql @@ -0,0 +1,10 @@ +-- DOMAIN: comet.uint32 + +CREATE DOMAIN comet.uint32 + AS numeric; + +ALTER DOMAIN comet.uint32 + ADD CONSTRAINT value_max CHECK (VALUE <= '4294967295'::numeric); + +ALTER DOMAIN comet.uint32 + ADD CONSTRAINT value_positive CHECK (VALUE >= 0::numeric); \ No newline at end of file diff --git a/database/schema/3_create_table_block.sql b/database/schema/3_create_table_block.sql deleted file mode 100644 index 10954f5..0000000 --- a/database/schema/3_create_table_block.sql +++ /dev/null @@ -1,12 +0,0 @@ --- Table: comet.block - -CREATE TABLE IF NOT EXISTS comet.block -( - height bigint NOT NULL, - block_time timestamp with time zone NOT NULL, - chain_id text NOT NULL, - version_block comet.uint64 NOT NULL, - version_app comet.uint64 NOT NULL, - CONSTRAINT block_pkey PRIMARY KEY (height), - CONSTRAINT height_positive CHECK (height >= 0) -) TABLESPACE pg_default; diff --git a/database/schema/4_create_table_result_block.sql b/database/schema/4_create_table_result_block.sql new file mode 100644 index 0000000..9a003ac --- /dev/null +++ b/database/schema/4_create_table_result_block.sql @@ -0,0 +1,18 @@ +-- Table: comet.result_block + +CREATE TABLE IF NOT EXISTS comet.result_block +( + block_id_hash character(64) COLLATE pg_catalog."default" NOT NULL, + block_id_parts_hash character(64) COLLATE pg_catalog."default" NOT NULL, + block_id_parts_total comet.uint32 NOT NULL, + block_header_height bigint NOT NULL, + block_header_block_time timestamp with time zone NOT NULL, + block_header_chain_id text NOT NULL, + block_header_version_block comet.uint64 NOT NULL, + block_header_version_app comet.uint64 NOT NULL, + block_last_block_id_hash character(64) COLLATE pg_catalog."default" NOT NULL, + block_last_block_id_parts_hash character(64) COLLATE pg_catalog."default" NOT NULL, + block_last_block_id_part_total comet.uint32 NOT NULL, + CONSTRAINT block_pkey PRIMARY KEY (block_header_height), + CONSTRAINT height_positive CHECK (block_header_height >= 0) +) TABLESPACE pg_default; diff --git a/main.go b/main.go index 838769a..358809b 100644 --- a/main.go +++ b/main.go @@ -61,8 +61,18 @@ func (c *CometFetcher) FetchBlock(height int64) (*ctypes.ResultBlock, error) { } func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, error) { - _, err := c.Connection.Exec("INSERT INTO comet.block (height, version_block, version_app, block_time, chain_id) values ($1,$2,$3,$4, $5)", - resultBlock.Block.Height, resultBlock.Block.Version.Block, resultBlock.Block.Version.App, resultBlock.Block.Time, resultBlock.Block.ChainID) + _, err := c.Connection.Exec("INSERT INTO comet.result_block (block_id_hash, block_id_parts_hash, block_id_parts_total, block_header_height, block_header_version_block, block_header_version_app, block_header_block_time, block_header_chain_id, block_last_block_id_hash, block_last_block_id_parts_hash, block_last_block_id_part_total) values ($1,$2,$3,$4, $5, $6, $7, $8, $9, $10, $11)", + resultBlock.BlockID.Hash.String(), + resultBlock.BlockID.PartSetHeader.Hash.String(), + resultBlock.BlockID.PartSetHeader.Total, + resultBlock.Block.Height, + resultBlock.Block.Version.Block, + resultBlock.Block.Version.App, + resultBlock.Block.Time, + resultBlock.Block.ChainID, + resultBlock.Block.LastBlockID.Hash.String(), + resultBlock.Block.LastBlockID.PartSetHeader.Hash.String(), + resultBlock.Block.LastBlockID.PartSetHeader.Total) if err != nil { return false, err } else { @@ -72,13 +82,11 @@ func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, err func (c *PostgresStorage) GetBlock(height int64) (int64, error) { var rowHeight int64 - row := c.Connection.QueryRow("SELECT height FROM comet.block WHERE height=$1", height) - switch err := row.Scan(&rowHeight); err { - case sql.ErrNoRows: - return 0, err - case nil: + row := c.Connection.QueryRow("SELECT block_header_height FROM comet.result_block WHERE block_header_height=$1", height) + err := row.Scan(&rowHeight) + if err != nil { return 0, err - default: + } else { return rowHeight, err } } @@ -122,7 +130,7 @@ func main() { panic(err) } - for height := 1; height <= 10; height++ { + for height := 1; height <= 50; height++ { blockFetched, err := fetcher.FetchBlock(int64(height)) if err != nil { From 39065f9ed6b9eeceddb7959d0fc5b54bf338120f Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Thu, 18 May 2023 09:51:07 -0400 Subject: [PATCH 09/44] initial logic for rpc service (#3) --- main.go | 82 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 70 insertions(+), 12 deletions(-) diff --git a/main.go b/main.go index 358809b..921a112 100644 --- a/main.go +++ b/main.go @@ -4,10 +4,13 @@ import ( "context" "database/sql" "fmt" + "github.com/cometbft/cometbft/libs/json" client "github.com/cometbft/cometbft/rpc/client/http" ctypes "github.com/cometbft/cometbft/rpc/core/types" _ "github.com/lib/pq" "log" + "net/http" + "strconv" "time" ) @@ -45,6 +48,60 @@ type RESTService struct { Version string } +func (s *RESTService) Serve(storage *PostgresStorage) { + // Handler for the block endpoint + http.HandleFunc(fmt.Sprintf("/%s/block", s.Version), handleBlock) + + // Start the service + err := http.ListenAndServe(":8080", nil) + if err != nil { + log.Fatalln("There's an error starting the REST service:", err) + } else { + log.Println("Started REST service...") + } +} + +// Handles the '/v1/block' endpoint +func handleBlock(writer http.ResponseWriter, request *http.Request) { + + // Database connection + storage := PostgresStorage{ + ConnectionString: connString, + Connection: nil, + } + + // Connect to the database + err := storage.Connect() + if err != nil { + log.Println("Error connecting to storage in handleBlock: ", err) + writer.WriteHeader(http.StatusInternalServerError) + writer.Write([]byte("Internal Server Error")) + } + + writer.Header().Set("Content-Type", "application/json") + + if request.Method == "GET" { + h := request.URL.Query()["height"][0] + height, err := strconv.ParseInt(h, 10, 64) + if err != nil { + writer.WriteHeader(http.StatusBadRequest) + writer.Write([]byte("Bad Request. Invalid height")) + } + fmt.Printf("Block Request. Height: %v\n", height) + block, err := storage.GetBlock(height) + if err != nil { + log.Println("Error retrieving record from storage in handleBlock: ", err) + writer.WriteHeader(http.StatusInternalServerError) + writer.Write([]byte("Internal Server Error")) + } + resp, _ := json.Marshal(block) + writer.Write(resp) + } else { + writer.WriteHeader(http.StatusBadRequest) + writer.Write([]byte("Bad Request")) + } +} + func (c *CometFetcher) FetchBlock(height int64) (*ctypes.ResultBlock, error) { httpClient, err := client.New("http://localhost:26657", "/websocket") @@ -80,15 +137,15 @@ func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, err } } -func (c *PostgresStorage) GetBlock(height int64) (int64, error) { +func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { + resultBlock := ctypes.ResultBlock{} var rowHeight int64 row := c.Connection.QueryRow("SELECT block_header_height FROM comet.result_block WHERE block_header_height=$1", height) err := row.Scan(&rowHeight) if err != nil { - return 0, err - } else { - return rowHeight, err + resultBlock.Block.Height = rowHeight } + return resultBlock, err } func (c *PostgresStorage) Connect() error { @@ -115,10 +172,12 @@ func (c *PostgresStorage) Connect() error { func main() { + // Ingest server fetcher := CometFetcher{ Endpoint: "http://localhost:26657", } + // Database storage storage := PostgresStorage{ ConnectionString: connString, Connection: nil, @@ -130,7 +189,7 @@ func main() { panic(err) } - for height := 1; height <= 50; height++ { + for height := 1; height <= 20; height++ { blockFetched, err := fetcher.FetchBlock(int64(height)) if err != nil { @@ -144,13 +203,6 @@ func main() { if inserted { fmt.Printf("Inserted height %d\n", height) } - - block, err := storage.GetBlock(int64(height)) - if err != nil { - fmt.Printf("Error retrieving block at height %d: %s\n", height, err) - } else { - log.Printf("Block at height %d: %v", height, block) - } } defer func(ps PostgresStorage) { @@ -159,4 +211,10 @@ func main() { log.Fatalln(err) } }(storage) + + // REST server + service := RESTService{ + Version: "v1", + } + service.Serve(&storage) } From 9c95bece083dbf3f5cd58bd7f3ae437e19aa07a7 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Thu, 18 May 2023 17:54:10 -0400 Subject: [PATCH 10/44] initial logic to return block data (#3) --- main.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/main.go b/main.go index 921a112..cd92075 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "github.com/cometbft/cometbft/libs/json" client "github.com/cometbft/cometbft/rpc/client/http" ctypes "github.com/cometbft/cometbft/rpc/core/types" + "github.com/cometbft/cometbft/types" _ "github.com/lib/pq" "log" "net/http" @@ -139,12 +140,13 @@ func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, err func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { resultBlock := ctypes.ResultBlock{} - var rowHeight int64 - row := c.Connection.QueryRow("SELECT block_header_height FROM comet.result_block WHERE block_header_height=$1", height) - err := row.Scan(&rowHeight) + b := new(types.Block) + row := c.Connection.QueryRow("SELECT block_header_height, block_header_chain_id, block_header_block_time FROM comet.result_block WHERE block_header_height=$1", height) + err := row.Scan(&b.Header.Height, &b.Header.ChainID, &b.Header.Time) if err != nil { - resultBlock.Block.Height = rowHeight + return resultBlock, err } + resultBlock.Block = b return resultBlock, err } @@ -189,7 +191,7 @@ func main() { panic(err) } - for height := 1; height <= 20; height++ { + for height := 1; height <= 100; height++ { blockFetched, err := fetcher.FetchBlock(int64(height)) if err != nil { From 0b712fea8f3d1ff8675ce775761ca89cd3cee300 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Tue, 23 May 2023 17:11:47 -0400 Subject: [PATCH 11/44] started to add block data (#1) --- .../schema/4_create_table_result_block.sql | 9 ++-- main.go | 53 +++++++++++-------- 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/database/schema/4_create_table_result_block.sql b/database/schema/4_create_table_result_block.sql index 9a003ac..3a6b0c5 100644 --- a/database/schema/4_create_table_result_block.sql +++ b/database/schema/4_create_table_result_block.sql @@ -2,17 +2,18 @@ CREATE TABLE IF NOT EXISTS comet.result_block ( - block_id_hash character(64) COLLATE pg_catalog."default" NOT NULL, - block_id_parts_hash character(64) COLLATE pg_catalog."default" NOT NULL, + block_id_hash character(64) NOT NULL, + block_id_parts_hash character(64) NOT NULL, block_id_parts_total comet.uint32 NOT NULL, block_header_height bigint NOT NULL, block_header_block_time timestamp with time zone NOT NULL, block_header_chain_id text NOT NULL, block_header_version_block comet.uint64 NOT NULL, block_header_version_app comet.uint64 NOT NULL, - block_last_block_id_hash character(64) COLLATE pg_catalog."default" NOT NULL, - block_last_block_id_parts_hash character(64) COLLATE pg_catalog."default" NOT NULL, + block_last_block_id_hash character(64) NOT NULL, + block_last_block_id_parts_hash character(64) NOT NULL, block_last_block_id_part_total comet.uint32 NOT NULL, + block_data_hash bytea NOT NULL, CONSTRAINT block_pkey PRIMARY KEY (block_header_height), CONSTRAINT height_positive CHECK (block_header_height >= 0) ) TABLESPACE pg_default; diff --git a/main.go b/main.go index cd92075..942bf6c 100644 --- a/main.go +++ b/main.go @@ -119,7 +119,7 @@ func (c *CometFetcher) FetchBlock(height int64) (*ctypes.ResultBlock, error) { } func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, error) { - _, err := c.Connection.Exec("INSERT INTO comet.result_block (block_id_hash, block_id_parts_hash, block_id_parts_total, block_header_height, block_header_version_block, block_header_version_app, block_header_block_time, block_header_chain_id, block_last_block_id_hash, block_last_block_id_parts_hash, block_last_block_id_part_total) values ($1,$2,$3,$4, $5, $6, $7, $8, $9, $10, $11)", + _, err := c.Connection.Exec("INSERT INTO comet.result_block (block_id_hash, block_id_parts_hash, block_id_parts_total, block_header_height, block_header_version_block, block_header_version_app, block_header_block_time, block_header_chain_id, block_last_block_id_hash, block_last_block_id_parts_hash, block_last_block_id_part_total, block_data_hash) values ($1,$2,$3,$4, $5, $6, $7, $8, $9, $10, $11, $12)", resultBlock.BlockID.Hash.String(), resultBlock.BlockID.PartSetHeader.Hash.String(), resultBlock.BlockID.PartSetHeader.Total, @@ -130,7 +130,8 @@ func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, err resultBlock.Block.ChainID, resultBlock.Block.LastBlockID.Hash.String(), resultBlock.Block.LastBlockID.PartSetHeader.Hash.String(), - resultBlock.Block.LastBlockID.PartSetHeader.Total) + resultBlock.Block.LastBlockID.PartSetHeader.Total, + resultBlock.Block.Data.Hash()) if err != nil { return false, err } else { @@ -141,8 +142,8 @@ func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, err func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { resultBlock := ctypes.ResultBlock{} b := new(types.Block) - row := c.Connection.QueryRow("SELECT block_header_height, block_header_chain_id, block_header_block_time FROM comet.result_block WHERE block_header_height=$1", height) - err := row.Scan(&b.Header.Height, &b.Header.ChainID, &b.Header.Time) + row := c.Connection.QueryRow("SELECT block_header_height, block_header_chain_id, block_header_block_time, block_data_hash FROM comet.result_block WHERE block_header_height=$1", height) + err := row.Scan(&b.Header.Height, &b.Header.ChainID, &b.Header.Time, &b.DataHash) if err != nil { return resultBlock, err } @@ -174,11 +175,6 @@ func (c *PostgresStorage) Connect() error { func main() { - // Ingest server - fetcher := CometFetcher{ - Endpoint: "http://localhost:26657", - } - // Database storage storage := PostgresStorage{ ConnectionString: connString, @@ -191,7 +187,31 @@ func main() { panic(err) } - for height := 1; height <= 100; height++ { + // Insert some blocks + InsertBlocks(storage) + + defer func(ps PostgresStorage) { + err := ps.Connection.Close() + if err != nil { + log.Fatalln(err) + } + }(storage) + + // REST server + service := RESTService{ + Version: "v1", + } + service.Serve(&storage) +} + +func InsertBlocks(storage PostgresStorage) { + + // Ingest server + fetcher := CometFetcher{ + Endpoint: "http://localhost:26657", + } + + for height := 88050; height <= 88100; height++ { blockFetched, err := fetcher.FetchBlock(int64(height)) if err != nil { @@ -206,17 +226,4 @@ func main() { fmt.Printf("Inserted height %d\n", height) } } - - defer func(ps PostgresStorage) { - err := ps.Connection.Close() - if err != nil { - log.Fatalln(err) - } - }(storage) - - // REST server - service := RESTService{ - Version: "v1", - } - service.Serve(&storage) } From b5bfdd74d97a672e535c67f1170c19dd0f90b31c Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Tue, 23 May 2023 18:03:14 -0400 Subject: [PATCH 12/44] added logic to insert block transactions (#1) --- database/schema/5_create_table_block_data.sql | 12 ++++++ main.go | 37 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 database/schema/5_create_table_block_data.sql diff --git a/database/schema/5_create_table_block_data.sql b/database/schema/5_create_table_block_data.sql new file mode 100644 index 0000000..46caabb --- /dev/null +++ b/database/schema/5_create_table_block_data.sql @@ -0,0 +1,12 @@ +-- Table: comet.block_data + +CREATE TABLE IF NOT EXISTS comet.block_data +( + height bigint NOT NULL, + transaction bytea NOT NULL, + CONSTRAINT block_height_pkey PRIMARY KEY (height), + CONSTRAINT block_height_fk FOREIGN KEY (height) + REFERENCES comet.result_block (block_header_height) MATCH SIMPLE + ON UPDATE CASCADE + ON DELETE CASCADE +) TABLESPACE pg_default; diff --git a/main.go b/main.go index 942bf6c..192e6a4 100644 --- a/main.go +++ b/main.go @@ -132,6 +132,26 @@ func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, err resultBlock.Block.LastBlockID.PartSetHeader.Hash.String(), resultBlock.Block.LastBlockID.PartSetHeader.Total, resultBlock.Block.Data.Hash()) + + // Insert transactions if they exist + for _, tx := range resultBlock.Block.Data.Txs { + _, err := c.InsertTransaction(resultBlock.Block.Header.Height, tx) + if err != nil { + return false, err + } + } + + if err != nil { + return false, err + } else { + return true, nil + } +} + +func (c *PostgresStorage) InsertTransaction(height int64, tx types.Tx) (bool, error) { + _, err := c.Connection.Exec("INSERT INTO comet.block_data (height, transaction) values ($1,$2)", + height, + tx) if err != nil { return false, err } else { @@ -148,6 +168,23 @@ func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { return resultBlock, err } resultBlock.Block = b + + // Retrieve transactions if any + var txBytes []byte + txs, err := c.Connection.Query("SELECT transaction FROM comet.block_data WHERE height=$1", height) + if err != nil { + return resultBlock, err + } + defer txs.Close() + for txs.Next() { + err := txs.Scan(&txBytes) + if err != nil { + return resultBlock, err + } else { + resultBlock.Block.Data.Txs = append(resultBlock.Block.Data.Txs, txBytes) + } + } + return resultBlock, err } From 482e2cd6a1aaf5b9feae2e81e7d8b0c66ef91fd0 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Wed, 24 May 2023 11:02:12 -0400 Subject: [PATCH 13/44] added last_block_id information (#1) --- database/schema/4_create_table_result_block.sql | 8 ++++---- main.go | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/database/schema/4_create_table_result_block.sql b/database/schema/4_create_table_result_block.sql index 3a6b0c5..b17b959 100644 --- a/database/schema/4_create_table_result_block.sql +++ b/database/schema/4_create_table_result_block.sql @@ -2,16 +2,16 @@ CREATE TABLE IF NOT EXISTS comet.result_block ( - block_id_hash character(64) NOT NULL, - block_id_parts_hash character(64) NOT NULL, + block_id_hash bytea NOT NULL, + block_id_parts_hash bytea NOT NULL, block_id_parts_total comet.uint32 NOT NULL, block_header_height bigint NOT NULL, block_header_block_time timestamp with time zone NOT NULL, block_header_chain_id text NOT NULL, block_header_version_block comet.uint64 NOT NULL, block_header_version_app comet.uint64 NOT NULL, - block_last_block_id_hash character(64) NOT NULL, - block_last_block_id_parts_hash character(64) NOT NULL, + block_last_block_id_hash bytea NOT NULL, + block_last_block_id_parts_hash bytea NOT NULL, block_last_block_id_part_total comet.uint32 NOT NULL, block_data_hash bytea NOT NULL, CONSTRAINT block_pkey PRIMARY KEY (block_header_height), diff --git a/main.go b/main.go index 192e6a4..2dcb176 100644 --- a/main.go +++ b/main.go @@ -128,8 +128,8 @@ func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, err resultBlock.Block.Version.App, resultBlock.Block.Time, resultBlock.Block.ChainID, - resultBlock.Block.LastBlockID.Hash.String(), - resultBlock.Block.LastBlockID.PartSetHeader.Hash.String(), + resultBlock.Block.LastBlockID.Hash, + resultBlock.Block.LastBlockID.PartSetHeader.Hash, resultBlock.Block.LastBlockID.PartSetHeader.Total, resultBlock.Block.Data.Hash()) @@ -162,8 +162,8 @@ func (c *PostgresStorage) InsertTransaction(height int64, tx types.Tx) (bool, er func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { resultBlock := ctypes.ResultBlock{} b := new(types.Block) - row := c.Connection.QueryRow("SELECT block_header_height, block_header_chain_id, block_header_block_time, block_data_hash FROM comet.result_block WHERE block_header_height=$1", height) - err := row.Scan(&b.Header.Height, &b.Header.ChainID, &b.Header.Time, &b.DataHash) + row := c.Connection.QueryRow("SELECT block_header_height, block_header_chain_id, block_header_block_time, block_data_hash, block_last_block_id_hash, block_last_block_id_part_total, block_last_block_id_parts_hash FROM comet.result_block WHERE block_header_height=$1", height) + err := row.Scan(&b.Header.Height, &b.Header.ChainID, &b.Header.Time, &b.DataHash, &b.LastBlockID.Hash, &b.LastBlockID.PartSetHeader.Total, &b.LastBlockID.PartSetHeader.Hash) if err != nil { return resultBlock, err } From a22ff7ff500518748cd833a5c6fd2c0ad8869dfe Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Wed, 24 May 2023 11:12:25 -0400 Subject: [PATCH 14/44] added header_version information (#1) --- main.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 2dcb176..0ac9033 100644 --- a/main.go +++ b/main.go @@ -162,8 +162,16 @@ func (c *PostgresStorage) InsertTransaction(height int64, tx types.Tx) (bool, er func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { resultBlock := ctypes.ResultBlock{} b := new(types.Block) - row := c.Connection.QueryRow("SELECT block_header_height, block_header_chain_id, block_header_block_time, block_data_hash, block_last_block_id_hash, block_last_block_id_part_total, block_last_block_id_parts_hash FROM comet.result_block WHERE block_header_height=$1", height) - err := row.Scan(&b.Header.Height, &b.Header.ChainID, &b.Header.Time, &b.DataHash, &b.LastBlockID.Hash, &b.LastBlockID.PartSetHeader.Total, &b.LastBlockID.PartSetHeader.Hash) + row := c.Connection.QueryRow("SELECT block_header_height, block_header_chain_id, block_header_block_time, block_header_version_block, block_header_version_app, block_data_hash, block_last_block_id_hash, block_last_block_id_part_total, block_last_block_id_parts_hash FROM comet.result_block WHERE block_header_height=$1", height) + err := row.Scan(&b.Header.Height, + &b.Header.ChainID, + &b.Header.Time, + &b.Header.Version.Block, + &b.Header.Version.App, + &b.DataHash, + &b.LastBlockID.Hash, + &b.LastBlockID.PartSetHeader.Total, + &b.LastBlockID.PartSetHeader.Hash) if err != nil { return resultBlock, err } From b92accb5aed77d8fada4b1b3fb0406b6b8ec4304 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Wed, 24 May 2023 14:45:23 -0400 Subject: [PATCH 15/44] added remaining block header fields (#1) --- .../schema/4_create_table_result_block.sql | 10 ++- main.go | 77 ++++++++++++++++--- 2 files changed, 75 insertions(+), 12 deletions(-) diff --git a/database/schema/4_create_table_result_block.sql b/database/schema/4_create_table_result_block.sql index b17b959..ea65031 100644 --- a/database/schema/4_create_table_result_block.sql +++ b/database/schema/4_create_table_result_block.sql @@ -10,10 +10,18 @@ CREATE TABLE IF NOT EXISTS comet.result_block block_header_chain_id text NOT NULL, block_header_version_block comet.uint64 NOT NULL, block_header_version_app comet.uint64 NOT NULL, + block_header_data_hash bytea NOT NULL, + block_header_last_commit_hash bytea NOT NULL, + block_header_validators_hash bytea NOT NULL, + block_header_next_validators_hash bytea NOT NULL, + block_header_consensus_hash bytea NOT NULL, + block_header_app_hash bytea NOT NULL, + block_header_last_results_hash bytea NOT NULL, + block_header_evidence_hash bytea NOT NULL, + block_header_proposer_address bytea NOT NULL, block_last_block_id_hash bytea NOT NULL, block_last_block_id_parts_hash bytea NOT NULL, block_last_block_id_part_total comet.uint32 NOT NULL, - block_data_hash bytea NOT NULL, CONSTRAINT block_pkey PRIMARY KEY (block_header_height), CONSTRAINT height_positive CHECK (block_header_height >= 0) ) TABLESPACE pg_default; diff --git a/main.go b/main.go index 0ac9033..dcb0c4c 100644 --- a/main.go +++ b/main.go @@ -119,19 +119,47 @@ func (c *CometFetcher) FetchBlock(height int64) (*ctypes.ResultBlock, error) { } func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, error) { - _, err := c.Connection.Exec("INSERT INTO comet.result_block (block_id_hash, block_id_parts_hash, block_id_parts_total, block_header_height, block_header_version_block, block_header_version_app, block_header_block_time, block_header_chain_id, block_last_block_id_hash, block_last_block_id_parts_hash, block_last_block_id_part_total, block_data_hash) values ($1,$2,$3,$4, $5, $6, $7, $8, $9, $10, $11, $12)", + _, err := c.Connection.Exec("INSERT INTO comet.result_block (block_id_hash, "+ + "block_id_parts_hash, "+ + "block_id_parts_total, "+ + "block_header_height, "+ + "block_header_version_block, "+ + "block_header_version_app, "+ + "block_header_block_time, "+ + "block_header_chain_id, "+ + "block_header_last_commit_hash, "+ + "block_header_data_hash, "+ + "block_header_validators_hash, "+ + "block_header_next_validators_hash, "+ + "block_header_consensus_hash, "+ + "block_header_app_hash, "+ + "block_header_last_results_hash, "+ + "block_header_evidence_hash, "+ + "block_header_proposer_address, "+ + "block_last_block_id_hash, "+ + "block_last_block_id_parts_hash, "+ + "block_last_block_id_part_total) "+ + "values ($1,$2,$3,$4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20)", resultBlock.BlockID.Hash.String(), resultBlock.BlockID.PartSetHeader.Hash.String(), resultBlock.BlockID.PartSetHeader.Total, - resultBlock.Block.Height, - resultBlock.Block.Version.Block, - resultBlock.Block.Version.App, - resultBlock.Block.Time, - resultBlock.Block.ChainID, + resultBlock.Block.Header.Height, + resultBlock.Block.Header.Version.Block, + resultBlock.Block.Header.Version.App, + resultBlock.Block.Header.Time, + resultBlock.Block.Header.ChainID, + resultBlock.Block.Header.LastCommitHash, + resultBlock.Block.Header.DataHash, + resultBlock.Block.Header.ValidatorsHash, + resultBlock.Block.Header.NextValidatorsHash, + resultBlock.Block.Header.ConsensusHash, + resultBlock.Block.Header.AppHash, + resultBlock.Block.Header.LastResultsHash, + resultBlock.Block.Header.EvidenceHash, + resultBlock.Block.Header.ProposerAddress, resultBlock.Block.LastBlockID.Hash, resultBlock.Block.LastBlockID.PartSetHeader.Hash, - resultBlock.Block.LastBlockID.PartSetHeader.Total, - resultBlock.Block.Data.Hash()) + resultBlock.Block.LastBlockID.PartSetHeader.Total) // Insert transactions if they exist for _, tx := range resultBlock.Block.Data.Txs { @@ -162,13 +190,40 @@ func (c *PostgresStorage) InsertTransaction(height int64, tx types.Tx) (bool, er func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { resultBlock := ctypes.ResultBlock{} b := new(types.Block) - row := c.Connection.QueryRow("SELECT block_header_height, block_header_chain_id, block_header_block_time, block_header_version_block, block_header_version_app, block_data_hash, block_last_block_id_hash, block_last_block_id_part_total, block_last_block_id_parts_hash FROM comet.result_block WHERE block_header_height=$1", height) - err := row.Scan(&b.Header.Height, + row := c.Connection.QueryRow("SELECT "+ + "block_header_height, "+ + "block_header_chain_id, "+ + "block_header_block_time, "+ + "block_header_version_block, "+ + "block_header_version_app, "+ + "block_header_last_commit_hash, "+ + "block_header_data_hash, "+ + "block_header_validators_hash, "+ + "block_header_next_validators_hash, "+ + "block_header_consensus_hash, "+ + "block_header_app_hash, "+ + "block_header_last_results_hash, "+ + "block_header_evidence_hash, "+ + "block_header_proposer_address, "+ + "block_last_block_id_hash, "+ + "block_last_block_id_part_total, "+ + "block_last_block_id_parts_hash "+ + "FROM comet.result_block WHERE block_header_height=$1", height) + err := row.Scan( + &b.Header.Height, &b.Header.ChainID, &b.Header.Time, &b.Header.Version.Block, &b.Header.Version.App, - &b.DataHash, + &b.Header.LastCommitHash, + &b.Header.DataHash, + &b.Header.ValidatorsHash, + &b.Header.NextValidatorsHash, + &b.Header.ConsensusHash, + &b.Header.AppHash, + &b.Header.LastResultsHash, + &b.Header.EvidenceHash, + &b.Header.ProposerAddress, &b.LastBlockID.Hash, &b.LastBlockID.PartSetHeader.Total, &b.LastBlockID.PartSetHeader.Hash) From e683a6b0ecbc384577039db85e36b6309790ed4b Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Wed, 24 May 2023 15:07:09 -0400 Subject: [PATCH 16/44] rename last_block_id columns to match header (#4) --- database/schema/4_create_table_result_block.sql | 7 ++++--- main.go | 12 ++++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/database/schema/4_create_table_result_block.sql b/database/schema/4_create_table_result_block.sql index ea65031..a78f10d 100644 --- a/database/schema/4_create_table_result_block.sql +++ b/database/schema/4_create_table_result_block.sql @@ -19,9 +19,10 @@ CREATE TABLE IF NOT EXISTS comet.result_block block_header_last_results_hash bytea NOT NULL, block_header_evidence_hash bytea NOT NULL, block_header_proposer_address bytea NOT NULL, - block_last_block_id_hash bytea NOT NULL, - block_last_block_id_parts_hash bytea NOT NULL, - block_last_block_id_part_total comet.uint32 NOT NULL, + block_header_last_block_id_hash bytea NOT NULL, + block_header_last_block_id_parts_hash bytea NOT NULL, + block_header_last_block_id_part_total comet.uint32 NOT NULL, + CONSTRAINT block_pkey PRIMARY KEY (block_header_height), CONSTRAINT height_positive CHECK (block_header_height >= 0) ) TABLESPACE pg_default; diff --git a/main.go b/main.go index dcb0c4c..f1bc27e 100644 --- a/main.go +++ b/main.go @@ -136,9 +136,9 @@ func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, err "block_header_last_results_hash, "+ "block_header_evidence_hash, "+ "block_header_proposer_address, "+ - "block_last_block_id_hash, "+ - "block_last_block_id_parts_hash, "+ - "block_last_block_id_part_total) "+ + "block_header_last_block_id_hash, "+ + "block_header_last_block_id_parts_hash, "+ + "block_header_last_block_id_part_total) "+ "values ($1,$2,$3,$4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20)", resultBlock.BlockID.Hash.String(), resultBlock.BlockID.PartSetHeader.Hash.String(), @@ -205,9 +205,9 @@ func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { "block_header_last_results_hash, "+ "block_header_evidence_hash, "+ "block_header_proposer_address, "+ - "block_last_block_id_hash, "+ - "block_last_block_id_part_total, "+ - "block_last_block_id_parts_hash "+ + "block_header_last_block_id_hash, "+ + "block_header_last_block_id_part_total, "+ + "block_header_last_block_id_parts_hash "+ "FROM comet.result_block WHERE block_header_height=$1", height) err := row.Scan( &b.Header.Height, From 97c4bb8ddcbd0e767d2dda97c8f84b796bb908ed Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Wed, 24 May 2023 17:01:30 -0400 Subject: [PATCH 17/44] Added block last commit info (#1) --- .../schema/4_create_table_result_block.sql | 6 +- main.go | 77 ++++++++++++------- 2 files changed, 56 insertions(+), 27 deletions(-) diff --git a/database/schema/4_create_table_result_block.sql b/database/schema/4_create_table_result_block.sql index a78f10d..8b7c0d6 100644 --- a/database/schema/4_create_table_result_block.sql +++ b/database/schema/4_create_table_result_block.sql @@ -22,7 +22,11 @@ CREATE TABLE IF NOT EXISTS comet.result_block block_header_last_block_id_hash bytea NOT NULL, block_header_last_block_id_parts_hash bytea NOT NULL, block_header_last_block_id_part_total comet.uint32 NOT NULL, - + block_last_commit_height comet.uint64 NOT NULL, + block_last_commit_round comet.uint32 NOT NULL, + block_last_commit_block_id_hash bytea NOT NULL, + block_last_commit_block_id_parts_total comet.uint32 NOT NULL, + block_last_commit_block_id_parts_hash bytea NOT NULL, CONSTRAINT block_pkey PRIMARY KEY (block_header_height), CONSTRAINT height_positive CHECK (block_header_height >= 0) ) TABLESPACE pg_default; diff --git a/main.go b/main.go index f1bc27e..b233fea 100644 --- a/main.go +++ b/main.go @@ -119,29 +119,36 @@ func (c *CometFetcher) FetchBlock(height int64) (*ctypes.ResultBlock, error) { } func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, error) { - _, err := c.Connection.Exec("INSERT INTO comet.result_block (block_id_hash, "+ - "block_id_parts_hash, "+ - "block_id_parts_total, "+ - "block_header_height, "+ - "block_header_version_block, "+ - "block_header_version_app, "+ - "block_header_block_time, "+ - "block_header_chain_id, "+ - "block_header_last_commit_hash, "+ - "block_header_data_hash, "+ - "block_header_validators_hash, "+ - "block_header_next_validators_hash, "+ - "block_header_consensus_hash, "+ - "block_header_app_hash, "+ - "block_header_last_results_hash, "+ - "block_header_evidence_hash, "+ - "block_header_proposer_address, "+ - "block_header_last_block_id_hash, "+ - "block_header_last_block_id_parts_hash, "+ - "block_header_last_block_id_part_total) "+ - "values ($1,$2,$3,$4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20)", - resultBlock.BlockID.Hash.String(), - resultBlock.BlockID.PartSetHeader.Hash.String(), + _, err := c.Connection.Exec( + "INSERT INTO comet.result_block "+ + "(block_id_hash, "+ + "block_id_parts_hash, "+ + "block_id_parts_total, "+ + "block_header_height, "+ + "block_header_version_block, "+ + "block_header_version_app, "+ + "block_header_block_time, "+ + "block_header_chain_id, "+ + "block_header_last_commit_hash, "+ + "block_header_data_hash, "+ + "block_header_validators_hash, "+ + "block_header_next_validators_hash, "+ + "block_header_consensus_hash, "+ + "block_header_app_hash, "+ + "block_header_last_results_hash, "+ + "block_header_evidence_hash, "+ + "block_header_proposer_address, "+ + "block_header_last_block_id_hash, "+ + "block_header_last_block_id_parts_hash, "+ + "block_header_last_block_id_part_total, "+ + "block_last_commit_height, "+ + "block_last_commit_round, "+ + "block_last_commit_block_id_hash, "+ + "block_last_commit_block_id_parts_total, "+ + "block_last_commit_block_id_parts_hash)"+ + "values ($1,$2,$3,$4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25)", + resultBlock.BlockID.Hash, + resultBlock.BlockID.PartSetHeader.Hash, resultBlock.BlockID.PartSetHeader.Total, resultBlock.Block.Header.Height, resultBlock.Block.Header.Version.Block, @@ -159,7 +166,12 @@ func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, err resultBlock.Block.Header.ProposerAddress, resultBlock.Block.LastBlockID.Hash, resultBlock.Block.LastBlockID.PartSetHeader.Hash, - resultBlock.Block.LastBlockID.PartSetHeader.Total) + resultBlock.Block.LastBlockID.PartSetHeader.Total, + resultBlock.Block.LastCommit.Height, + resultBlock.Block.LastCommit.Round, + resultBlock.Block.LastCommit.BlockID.Hash, + resultBlock.Block.LastCommit.BlockID.PartSetHeader.Total, + resultBlock.Block.LastCommit.BlockID.PartSetHeader.Hash) // Insert transactions if they exist for _, tx := range resultBlock.Block.Data.Txs { @@ -189,6 +201,8 @@ func (c *PostgresStorage) InsertTransaction(height int64, tx types.Tx) (bool, er func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { resultBlock := ctypes.ResultBlock{} + lastCommit := types.Commit{} + b := new(types.Block) row := c.Connection.QueryRow("SELECT "+ "block_header_height, "+ @@ -207,7 +221,12 @@ func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { "block_header_proposer_address, "+ "block_header_last_block_id_hash, "+ "block_header_last_block_id_part_total, "+ - "block_header_last_block_id_parts_hash "+ + "block_header_last_block_id_parts_hash, "+ + "block_last_commit_height, "+ + "block_last_commit_round, "+ + "block_last_commit_block_id_hash, "+ + "block_last_commit_block_id_parts_total, "+ + "block_last_commit_block_id_parts_hash "+ "FROM comet.result_block WHERE block_header_height=$1", height) err := row.Scan( &b.Header.Height, @@ -226,10 +245,16 @@ func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { &b.Header.ProposerAddress, &b.LastBlockID.Hash, &b.LastBlockID.PartSetHeader.Total, - &b.LastBlockID.PartSetHeader.Hash) + &b.LastBlockID.PartSetHeader.Hash, + &lastCommit.Height, // *Commit + &lastCommit.Round, + &lastCommit.BlockID.Hash, + &lastCommit.BlockID.PartSetHeader.Total, + &lastCommit.BlockID.PartSetHeader.Hash) if err != nil { return resultBlock, err } + b.LastCommit = &lastCommit resultBlock.Block = b // Retrieve transactions if any From a73131dae3abe426bcc5b4d83830e6c5888a2dd5 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Wed, 24 May 2023 17:08:11 -0400 Subject: [PATCH 18/44] update postgres docker image version (#4) --- database/docker/docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/docker/docker-compose.yml b/database/docker/docker-compose.yml index f53b7fb..3b06ecc 100644 --- a/database/docker/docker-compose.yml +++ b/database/docker/docker-compose.yml @@ -1,7 +1,7 @@ version: '3.9' services: docker_postgres: - image: postgres:15.2-alpine + image: postgres:15.3-alpine restart: always environment: - POSTGRES_DB=postgres From 49e12915b24f208f8289116c046590d34bf1458b Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Thu, 25 May 2023 10:02:12 -0400 Subject: [PATCH 19/44] added block_id info (#1) --- main.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/main.go b/main.go index b233fea..51cfd68 100644 --- a/main.go +++ b/main.go @@ -202,9 +202,13 @@ func (c *PostgresStorage) InsertTransaction(height int64, tx types.Tx) (bool, er func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { resultBlock := ctypes.ResultBlock{} lastCommit := types.Commit{} - + bId := types.BlockID{} b := new(types.Block) + row := c.Connection.QueryRow("SELECT "+ + "block_id_hash, "+ + "block_id_parts_hash, "+ + "block_id_parts_total, "+ "block_header_height, "+ "block_header_chain_id, "+ "block_header_block_time, "+ @@ -229,6 +233,9 @@ func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { "block_last_commit_block_id_parts_hash "+ "FROM comet.result_block WHERE block_header_height=$1", height) err := row.Scan( + &bId.Hash, + &bId.PartSetHeader.Hash, + &bId.PartSetHeader.Total, &b.Header.Height, &b.Header.ChainID, &b.Header.Time, @@ -255,6 +262,7 @@ func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { return resultBlock, err } b.LastCommit = &lastCommit + resultBlock.BlockID = bId resultBlock.Block = b // Retrieve transactions if any From 8a007b572c5d3c64414092c68a66d23330d7c92b Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Thu, 25 May 2023 11:19:01 -0400 Subject: [PATCH 20/44] remove private key (no need) from block_data table (#4) --- database/schema/5_create_table_block_data.sql | 1 - 1 file changed, 1 deletion(-) diff --git a/database/schema/5_create_table_block_data.sql b/database/schema/5_create_table_block_data.sql index 46caabb..441dc80 100644 --- a/database/schema/5_create_table_block_data.sql +++ b/database/schema/5_create_table_block_data.sql @@ -4,7 +4,6 @@ CREATE TABLE IF NOT EXISTS comet.block_data ( height bigint NOT NULL, transaction bytea NOT NULL, - CONSTRAINT block_height_pkey PRIMARY KEY (height), CONSTRAINT block_height_fk FOREIGN KEY (height) REFERENCES comet.result_block (block_header_height) MATCH SIMPLE ON UPDATE CASCADE From 4db94a06e9700fbf7de839b82af3a51d0aa06794 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Thu, 25 May 2023 14:05:52 -0400 Subject: [PATCH 21/44] make endpoint configurable and retrieve last height (#1) --- main.go | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/main.go b/main.go index 51cfd68..f763311 100644 --- a/main.go +++ b/main.go @@ -11,6 +11,7 @@ import ( _ "github.com/lib/pq" "log" "net/http" + "os" "strconv" "time" ) @@ -24,7 +25,8 @@ type Storage interface { } type Fetcher interface { - Fetch(endpoint string) ([]byte, error) + FetchBlock(height int64) (*ctypes.ResultBlock, error) + FetchABCIInfo() (*ctypes.ResultABCIInfo, error) } type Service interface { @@ -91,6 +93,7 @@ func handleBlock(writer http.ResponseWriter, request *http.Request) { fmt.Printf("Block Request. Height: %v\n", height) block, err := storage.GetBlock(height) if err != nil { + // TODO: If not records retrieved return a different status log.Println("Error retrieving record from storage in handleBlock: ", err) writer.WriteHeader(http.StatusInternalServerError) writer.Write([]byte("Internal Server Error")) @@ -105,7 +108,7 @@ func handleBlock(writer http.ResponseWriter, request *http.Request) { func (c *CometFetcher) FetchBlock(height int64) (*ctypes.ResultBlock, error) { - httpClient, err := client.New("http://localhost:26657", "/websocket") + httpClient, err := client.New(c.Endpoint, "/websocket") if err != nil { return nil, err } @@ -118,6 +121,21 @@ func (c *CometFetcher) FetchBlock(height int64) (*ctypes.ResultBlock, error) { } } +func (c *CometFetcher) FetchABCIInfo() (*ctypes.ResultABCIInfo, error) { + + httpClient, err := client.New(c.Endpoint, "/websocket") + if err != nil { + return nil, err + } + + abciInfo, err := httpClient.ABCIInfo(context.Background()) + if err != nil { + return nil, err + } else { + return abciInfo, nil + } +} + func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, error) { _, err := c.Connection.Exec( "INSERT INTO comet.result_block "+ @@ -341,10 +359,18 @@ func InsertBlocks(storage PostgresStorage) { // Ingest server fetcher := CometFetcher{ - Endpoint: "http://localhost:26657", + Endpoint: os.Getenv("COMPANION_NODE_RPC"), } - for height := 88050; height <= 88100; height++ { + abciInfo, err := fetcher.FetchABCIInfo() + if err != nil { + log.Fatalf("Error fetching ABCI information: %s\n", err) + } + + numberHeights := 10 + initialHeight := abciInfo.Response.LastBlockHeight - int64(numberHeights) + + for height := initialHeight; height <= abciInfo.Response.LastBlockHeight; height++ { blockFetched, err := fetcher.FetchBlock(int64(height)) if err != nil { From 5ec97d4b5fb710aaf5c5987d20ebb1ac7353d0c4 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Thu, 25 May 2023 15:07:07 -0400 Subject: [PATCH 22/44] added last_commit_signature info (#4) --- database/schema/4_create_domain_uint8.sql | 10 ++++++++++ .../schema/6_create_table_commit_signatures.sql | 14 ++++++++++++++ ...t_block.sql => 7_create_table_result_block.sql} | 1 + 3 files changed, 25 insertions(+) create mode 100644 database/schema/4_create_domain_uint8.sql create mode 100644 database/schema/6_create_table_commit_signatures.sql rename database/schema/{4_create_table_result_block.sql => 7_create_table_result_block.sql} (95%) diff --git a/database/schema/4_create_domain_uint8.sql b/database/schema/4_create_domain_uint8.sql new file mode 100644 index 0000000..1ead75a --- /dev/null +++ b/database/schema/4_create_domain_uint8.sql @@ -0,0 +1,10 @@ +-- DOMAIN: comet.uint8 + +CREATE DOMAIN comet.uint8 + AS numeric; + +ALTER DOMAIN comet.uint8 + ADD CONSTRAINT value_max CHECK (VALUE <= '255'::numeric); + +ALTER DOMAIN comet.uint8 + ADD CONSTRAINT value_positive CHECK (VALUE >= 0::numeric); \ No newline at end of file diff --git a/database/schema/6_create_table_commit_signatures.sql b/database/schema/6_create_table_commit_signatures.sql new file mode 100644 index 0000000..028398e --- /dev/null +++ b/database/schema/6_create_table_commit_signatures.sql @@ -0,0 +1,14 @@ +-- Table: comet.last_commit_signature + +CREATE TABLE IF NOT EXISTS comet.last_commit_signature +( + height bigint NOT NULL, + block_id_flag comet.uint8 NOT NULL, + validator_address bytea NOT NULL, + signature_timestamp timestamp with time zone NOT NULL, + signature bytea NOT NULL, + CONSTRAINT last_commit_height_fk FOREIGN KEY (height) + REFERENCES comet.result_block (block_last_commit_height) MATCH SIMPLE + ON UPDATE CASCADE + ON DELETE CASCADE +) TABLESPACE pg_default; \ No newline at end of file diff --git a/database/schema/4_create_table_result_block.sql b/database/schema/7_create_table_result_block.sql similarity index 95% rename from database/schema/4_create_table_result_block.sql rename to database/schema/7_create_table_result_block.sql index 8b7c0d6..5639dba 100644 --- a/database/schema/4_create_table_result_block.sql +++ b/database/schema/7_create_table_result_block.sql @@ -28,5 +28,6 @@ CREATE TABLE IF NOT EXISTS comet.result_block block_last_commit_block_id_parts_total comet.uint32 NOT NULL, block_last_commit_block_id_parts_hash bytea NOT NULL, CONSTRAINT block_pkey PRIMARY KEY (block_header_height), + CONSTRAINT last_commit_height_unique UNIQUE (block_last_commit_height), CONSTRAINT height_positive CHECK (block_header_height >= 0) ) TABLESPACE pg_default; From ed63d1c84a55f90360cf166659334a6164b69398 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Thu, 25 May 2023 17:35:31 -0400 Subject: [PATCH 23/44] added last_commit_signatures info (#1) --- .../6_create_table_commit_signatures.sql | 4 +- main.go | 40 ++++++++++++++++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/database/schema/6_create_table_commit_signatures.sql b/database/schema/6_create_table_commit_signatures.sql index 028398e..ffc9ed5 100644 --- a/database/schema/6_create_table_commit_signatures.sql +++ b/database/schema/6_create_table_commit_signatures.sql @@ -4,9 +4,9 @@ CREATE TABLE IF NOT EXISTS comet.last_commit_signature ( height bigint NOT NULL, block_id_flag comet.uint8 NOT NULL, - validator_address bytea NOT NULL, + validator_address bytea, signature_timestamp timestamp with time zone NOT NULL, - signature bytea NOT NULL, + signature bytea, CONSTRAINT last_commit_height_fk FOREIGN KEY (height) REFERENCES comet.result_block (block_last_commit_height) MATCH SIMPLE ON UPDATE CASCADE diff --git a/main.go b/main.go index f763311..9a5dd14 100644 --- a/main.go +++ b/main.go @@ -138,7 +138,7 @@ func (c *CometFetcher) FetchABCIInfo() (*ctypes.ResultABCIInfo, error) { func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, error) { _, err := c.Connection.Exec( - "INSERT INTO comet.result_block "+ + "INSERT INTO comet.result_block"+ "(block_id_hash, "+ "block_id_parts_hash, "+ "block_id_parts_total, "+ @@ -199,6 +199,14 @@ func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, err } } + // Insert last commit signatures + for _, signature := range resultBlock.Block.LastCommit.Signatures { + _, err := c.InsertSignature(resultBlock.Block.LastCommit.Height, signature) + if err != nil { + return false, err + } + } + if err != nil { return false, err } else { @@ -217,6 +225,20 @@ func (c *PostgresStorage) InsertTransaction(height int64, tx types.Tx) (bool, er } } +func (c *PostgresStorage) InsertSignature(height int64, signature types.CommitSig) (bool, error) { + _, err := c.Connection.Exec("INSERT INTO comet.last_commit_signature (height, block_id_flag, validator_address, signature_timestamp, signature) values ($1,$2,$3,$4,$5)", + height, + signature.BlockIDFlag, + signature.ValidatorAddress, + signature.Timestamp, + signature.Signature) + if err != nil { + return false, err + } else { + return true, nil + } +} + func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { resultBlock := ctypes.ResultBlock{} lastCommit := types.Commit{} @@ -299,6 +321,22 @@ func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { } } + // Retrieve commit signatures + var signature types.CommitSig + signatures, err := c.Connection.Query("SELECT block_id_flag, validator_address, signature_timestamp, signature FROM comet.last_commit_signature WHERE height=$1", height-1) + if err != nil { + return resultBlock, err + } + defer signatures.Close() + for signatures.Next() { + err := signatures.Scan(&signature.BlockIDFlag, &signature.ValidatorAddress, &signature.Timestamp, &signature.Signature) + if err != nil { + return resultBlock, err + } else { + resultBlock.Block.LastCommit.Signatures = append(resultBlock.Block.LastCommit.Signatures, signature) + } + } + return resultBlock, err } From 6b8a428546fb3278a15ea19b79cca4820f05b9d2 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Wed, 31 May 2023 14:30:24 -0400 Subject: [PATCH 24/44] initial schema for evidence (#4) --- ...ures.sql => 6_create_table_commit_signature.sql} | 0 database/schema/7_create_table_evidence.sql | 13 +++++++++++++ ...lt_block.sql => 8_create_table_result_block.sql} | 0 3 files changed, 13 insertions(+) rename database/schema/{6_create_table_commit_signatures.sql => 6_create_table_commit_signature.sql} (100%) create mode 100644 database/schema/7_create_table_evidence.sql rename database/schema/{7_create_table_result_block.sql => 8_create_table_result_block.sql} (100%) diff --git a/database/schema/6_create_table_commit_signatures.sql b/database/schema/6_create_table_commit_signature.sql similarity index 100% rename from database/schema/6_create_table_commit_signatures.sql rename to database/schema/6_create_table_commit_signature.sql diff --git a/database/schema/7_create_table_evidence.sql b/database/schema/7_create_table_evidence.sql new file mode 100644 index 0000000..8bfda45 --- /dev/null +++ b/database/schema/7_create_table_evidence.sql @@ -0,0 +1,13 @@ +-- Table: comet.evidence + +CREATE TABLE IF NOT EXISTS comet.evidence +( + height bigint NOT NULL, + evidence_type bytea NOT NULL, + vote_a_type int NOT NULL, + vote_b_type int NOT NULL, + CONSTRAINT evidence_height_fk FOREIGN KEY (height) + REFERENCES comet.result_block (block_header_height) MATCH SIMPLE + ON UPDATE CASCADE + ON DELETE CASCADE +) TABLESPACE pg_default; \ No newline at end of file diff --git a/database/schema/7_create_table_result_block.sql b/database/schema/8_create_table_result_block.sql similarity index 100% rename from database/schema/7_create_table_result_block.sql rename to database/schema/8_create_table_result_block.sql From db032e7637c27f5c1b37dd31be938efc996995d2 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Wed, 31 May 2023 17:13:04 -0400 Subject: [PATCH 25/44] adding duplicate_vote_evidence table (#4) --- ...7_create_table_duplicate_vote_evidence.sql | 41 +++++++++++++++++++ database/schema/7_create_table_evidence.sql | 13 ------ 2 files changed, 41 insertions(+), 13 deletions(-) create mode 100644 database/schema/7_create_table_duplicate_vote_evidence.sql delete mode 100644 database/schema/7_create_table_evidence.sql diff --git a/database/schema/7_create_table_duplicate_vote_evidence.sql b/database/schema/7_create_table_duplicate_vote_evidence.sql new file mode 100644 index 0000000..0d8a310 --- /dev/null +++ b/database/schema/7_create_table_duplicate_vote_evidence.sql @@ -0,0 +1,41 @@ +-- Table: comet.duplicate_vote_evidence + +CREATE TABLE IF NOT EXISTS comet.duplicate_vote_evidence +( + height bigint NOT NULL, + evidence_type bytea NOT NULL, + + vote_a_type int NOT NULL, + vote_a_height bigint NOT NULL, + vote_a_round int NOT NULL, + vote_a_block_id_hash bytea NOT NULL, + vote_a_block_id_parts_hash bytea NOT NULL, + vote_a_block_id_parts_total comet.uint32 NOT NULL, + vote_a_timestamp timestamp with time zone NOT NULL, + vote_a_validator_address bytea NOT NULL, + vote_a_validator_index int NOT NULL, + vote_a_signature bytea NOT NULL, + vote_a_extension bytea NOT NULL, + vote_a_extension_signature bytea NOT NULL, + + vote_b_type int NOT NULL, + vote_b_height bigint NOT NULL, + vote_b_round int NOT NULL, + vote_b_block_id_hash bytea NOT NULL, + vote_b_block_id_parts_hash bytea NOT NULL, + vote_b_block_id_parts_total comet.uint32 NOT NULL, + vote_b_timestamp timestamp with time zone NOT NULL, + vote_b_validator_address bytea NOT NULL, + vote_b_validator_index int NOT NULL, + vote_b_signature bytea NOT NULL, + vote_b_extension bytea NOT NULL, + vote_b_extension_signature bytea NOT NULL, + + total_voting_power bigint NOT NULL, + validator_voting_power bigint NOT NULL, + evidence_timestamp timestamp with time zone NOT NULL, + CONSTRAINT evidence_height_fk FOREIGN KEY (height) + REFERENCES comet.result_block (block_header_height) MATCH SIMPLE + ON UPDATE CASCADE + ON DELETE CASCADE +) TABLESPACE pg_default; \ No newline at end of file diff --git a/database/schema/7_create_table_evidence.sql b/database/schema/7_create_table_evidence.sql deleted file mode 100644 index 8bfda45..0000000 --- a/database/schema/7_create_table_evidence.sql +++ /dev/null @@ -1,13 +0,0 @@ --- Table: comet.evidence - -CREATE TABLE IF NOT EXISTS comet.evidence -( - height bigint NOT NULL, - evidence_type bytea NOT NULL, - vote_a_type int NOT NULL, - vote_b_type int NOT NULL, - CONSTRAINT evidence_height_fk FOREIGN KEY (height) - REFERENCES comet.result_block (block_header_height) MATCH SIMPLE - ON UPDATE CASCADE - ON DELETE CASCADE -) TABLESPACE pg_default; \ No newline at end of file From e96f3c281e07a9f1a79ca3d74d896b7f206783ea Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Thu, 1 Jun 2023 17:56:38 -0400 Subject: [PATCH 26/44] added logic to insert duplicate vote evidence (#1) --- ...7_create_table_duplicate_vote_evidence.sql | 4 - ...ck.sql => 9_create_table_result_block.sql} | 0 main.go | 95 +++++++++++++++++-- 3 files changed, 87 insertions(+), 12 deletions(-) rename database/schema/{8_create_table_result_block.sql => 9_create_table_result_block.sql} (100%) diff --git a/database/schema/7_create_table_duplicate_vote_evidence.sql b/database/schema/7_create_table_duplicate_vote_evidence.sql index 0d8a310..f585e47 100644 --- a/database/schema/7_create_table_duplicate_vote_evidence.sql +++ b/database/schema/7_create_table_duplicate_vote_evidence.sql @@ -15,8 +15,6 @@ CREATE TABLE IF NOT EXISTS comet.duplicate_vote_evidence vote_a_validator_address bytea NOT NULL, vote_a_validator_index int NOT NULL, vote_a_signature bytea NOT NULL, - vote_a_extension bytea NOT NULL, - vote_a_extension_signature bytea NOT NULL, vote_b_type int NOT NULL, vote_b_height bigint NOT NULL, @@ -28,8 +26,6 @@ CREATE TABLE IF NOT EXISTS comet.duplicate_vote_evidence vote_b_validator_address bytea NOT NULL, vote_b_validator_index int NOT NULL, vote_b_signature bytea NOT NULL, - vote_b_extension bytea NOT NULL, - vote_b_extension_signature bytea NOT NULL, total_voting_power bigint NOT NULL, validator_voting_power bigint NOT NULL, diff --git a/database/schema/8_create_table_result_block.sql b/database/schema/9_create_table_result_block.sql similarity index 100% rename from database/schema/8_create_table_result_block.sql rename to database/schema/9_create_table_result_block.sql diff --git a/main.go b/main.go index 9a5dd14..c420b33 100644 --- a/main.go +++ b/main.go @@ -163,8 +163,8 @@ func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, err "block_last_commit_round, "+ "block_last_commit_block_id_hash, "+ "block_last_commit_block_id_parts_total, "+ - "block_last_commit_block_id_parts_hash)"+ - "values ($1,$2,$3,$4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25)", + "block_last_commit_block_id_parts_hash) "+ + "VALUES ($1,$2,$3,$4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25)", resultBlock.BlockID.Hash, resultBlock.BlockID.PartSetHeader.Hash, resultBlock.BlockID.PartSetHeader.Total, @@ -207,6 +207,23 @@ func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, err } } + // Insert evidences + for _, evidence := range resultBlock.Block.Evidence.Evidence { + switch ev := evidence.(type) { + case *types.DuplicateVoteEvidence: + var dve *types.DuplicateVoteEvidence + dve = ev + _, err = c.InsertDuplicateVoteEvidence(resultBlock.Block.Header.Height, dve) + if err != nil { + return false, err + } + case *types.LightClientAttackEvidence: + fmt.Printf("Light Client Attack") + default: + fmt.Printf("Evidence not supported") + } + } + if err != nil { return false, err } else { @@ -225,6 +242,69 @@ func (c *PostgresStorage) InsertTransaction(height int64, tx types.Tx) (bool, er } } +func (c *PostgresStorage) InsertDuplicateVoteEvidence(height int64, dve *types.DuplicateVoteEvidence) (bool, error) { + + //TODO: Find how to get the evidence type property e.g. 'tendermint/DuplicateVoteEvidence' + + _, err := c.Connection.Exec("INSERT INTO comet.duplicate_vote_evidence ("+ + "height, "+ + "evidence_type, "+ + "vote_a_type, "+ + "vote_a_height, "+ + "vote_a_round, "+ + "vote_a_block_id_hash, "+ + "vote_a_block_id_parts_hash, "+ + "vote_a_block_id_parts_total, "+ + "vote_a_timestamp, "+ + "vote_a_validator_address, "+ + "vote_a_validator_index, "+ + "vote_a_signature, "+ + "vote_b_type, "+ + "vote_b_height, "+ + "vote_b_round, "+ + "vote_b_block_id_hash, "+ + "vote_b_block_id_parts_hash, "+ + "vote_b_block_id_parts_total, "+ + "vote_b_timestamp, "+ + "vote_b_validator_address, "+ + "vote_b_validator_index, "+ + "vote_b_signature, "+ + "total_voting_power, "+ + "validator_voting_power, "+ + "evidence_timestamp) "+ + "VALUES ($1,$2,$3,$4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25)", + height, + "tendermint/DuplicateVoteEvidence", + dve.VoteA.Type, + dve.VoteA.Height, + dve.VoteA.Round, + dve.VoteA.BlockID.Hash, + dve.VoteA.BlockID.PartSetHeader.Hash, + dve.VoteA.BlockID.PartSetHeader.Total, + dve.VoteA.Timestamp, + dve.VoteA.ValidatorAddress, + dve.VoteA.ValidatorIndex, + dve.VoteA.Signature, + dve.VoteB.Type, + dve.VoteB.Height, + dve.VoteB.Round, + dve.VoteB.BlockID.Hash, + dve.VoteB.BlockID.PartSetHeader.Hash, + dve.VoteB.BlockID.PartSetHeader.Total, + dve.VoteB.Timestamp, + dve.VoteB.ValidatorAddress, + dve.VoteB.ValidatorIndex, + dve.VoteB.Signature, + dve.TotalVotingPower, + dve.ValidatorPower, + dve.Timestamp) + if err != nil { + return false, err + } else { + return true, nil + } +} + func (c *PostgresStorage) InsertSignature(height int64, signature types.CommitSig) (bool, error) { _, err := c.Connection.Exec("INSERT INTO comet.last_commit_signature (height, block_id_flag, validator_address, signature_timestamp, signature) values ($1,$2,$3,$4,$5)", height, @@ -400,15 +480,14 @@ func InsertBlocks(storage PostgresStorage) { Endpoint: os.Getenv("COMPANION_NODE_RPC"), } - abciInfo, err := fetcher.FetchABCIInfo() + numberHeights := int64(3) + initialHeightParameter := os.Getenv("COMPANION_INITIAL_HEIGHT") + initialHeight, err := strconv.ParseInt(initialHeightParameter, 10, 64) if err != nil { - log.Fatalf("Error fetching ABCI information: %s\n", err) + fmt.Printf("Invalid initial height %s: %s\n", initialHeightParameter, err) } - numberHeights := 10 - initialHeight := abciInfo.Response.LastBlockHeight - int64(numberHeights) - - for height := initialHeight; height <= abciInfo.Response.LastBlockHeight; height++ { + for height := initialHeight; height <= initialHeight+numberHeights; height++ { blockFetched, err := fetcher.FetchBlock(int64(height)) if err != nil { From 55960faa5db1cce56850280b228822f6feaf9c2d Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Fri, 2 Jun 2023 15:32:36 -0400 Subject: [PATCH 27/44] initial logic to return a duplicate vote evidence (#3) --- main.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/main.go b/main.go index c420b33..4ddea7b 100644 --- a/main.go +++ b/main.go @@ -417,6 +417,27 @@ func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { } } + // Retrieve duplicate vote evidences + dve := types.DuplicateVoteEvidence{} + dves, err := c.Connection.Query("SELECT "+ + "vote_a_type "+ + "FROM comet.duplicate_vote_evidence "+ + "WHERE height=$1", height) + if err != nil { + return resultBlock, err + } + defer dves.Close() + for dves.Next() { + voteA := types.Vote{} + err := dves.Scan(&voteA.Type) + if err != nil { + return resultBlock, err + } else { + dve.VoteA = &voteA + resultBlock.Block.Evidence.Evidence = append(resultBlock.Block.Evidence.Evidence, &dve) + } + } + return resultBlock, err } From c4933513070dfc87ac388543579c067de91068de Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Fri, 2 Jun 2023 17:03:31 -0400 Subject: [PATCH 28/44] fully implemented the duplicate vote evidence response (#3) --- main.go | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 4ddea7b..08b02d6 100644 --- a/main.go +++ b/main.go @@ -420,7 +420,29 @@ func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { // Retrieve duplicate vote evidences dve := types.DuplicateVoteEvidence{} dves, err := c.Connection.Query("SELECT "+ - "vote_a_type "+ + "vote_a_type, "+ + "vote_a_height, "+ + "vote_a_round, "+ + "vote_a_block_id_hash, "+ + "vote_a_block_id_parts_hash, "+ + "vote_a_block_id_parts_total, "+ + "vote_a_timestamp, "+ + "vote_a_validator_address, "+ + "vote_a_validator_index, "+ + "vote_a_signature, "+ + "vote_b_type, "+ + "vote_b_height, "+ + "vote_b_round, "+ + "vote_b_block_id_hash, "+ + "vote_b_block_id_parts_hash, "+ + "vote_b_block_id_parts_total, "+ + "vote_b_timestamp, "+ + "vote_b_validator_address, "+ + "vote_b_validator_index, "+ + "vote_b_signature, "+ + "total_voting_power, "+ + "validator_voting_power, "+ + "evidence_timestamp "+ "FROM comet.duplicate_vote_evidence "+ "WHERE height=$1", height) if err != nil { @@ -429,11 +451,36 @@ func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { defer dves.Close() for dves.Next() { voteA := types.Vote{} - err := dves.Scan(&voteA.Type) + voteB := types.Vote{} + err := dves.Scan( + &voteA.Type, + &voteA.Height, + &voteA.Round, + &voteA.BlockID.Hash, + &voteA.BlockID.PartSetHeader.Hash, + &voteA.BlockID.PartSetHeader.Total, + &voteA.Timestamp, + &voteA.ValidatorAddress, + &voteA.ValidatorIndex, + &voteA.Signature, + &voteB.Type, + &voteB.Height, + &voteB.Round, + &voteB.BlockID.Hash, + &voteB.BlockID.PartSetHeader.Hash, + &voteB.BlockID.PartSetHeader.Total, + &voteB.Timestamp, + &voteB.ValidatorAddress, + &voteB.ValidatorIndex, + &voteB.Signature, + &dve.TotalVotingPower, + &dve.ValidatorPower, + &dve.Timestamp) if err != nil { return resultBlock, err } else { dve.VoteA = &voteA + dve.VoteB = &voteB resultBlock.Block.Evidence.Evidence = append(resultBlock.Block.Evidence.Evidence, &dve) } } From cc3ed26530406a81c817cf45f1b0926ff28a6e82 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Fri, 2 Jun 2023 17:05:01 -0400 Subject: [PATCH 29/44] Initial schema for light client attack evidence (#4) --- .../8_create_table_light_client_attack_evidence.sql | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 database/schema/8_create_table_light_client_attack_evidence.sql diff --git a/database/schema/8_create_table_light_client_attack_evidence.sql b/database/schema/8_create_table_light_client_attack_evidence.sql new file mode 100644 index 0000000..52926a6 --- /dev/null +++ b/database/schema/8_create_table_light_client_attack_evidence.sql @@ -0,0 +1,11 @@ +-- Table: comet.light_client_attack_evidence + +CREATE TABLE IF NOT EXISTS comet.light_client_attack_evidence +( + height bigint NOT NULL, + common_height bigint NOT NULL, + CONSTRAINT evidence_height_fk FOREIGN KEY (height) + REFERENCES comet.result_block (block_header_height) MATCH SIMPLE + ON UPDATE CASCADE + ON DELETE CASCADE +) TABLESPACE pg_default; \ No newline at end of file From f29ba7d3945065fee6efe78b3d221e9698eedf95 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Mon, 5 Jun 2023 09:25:50 -0400 Subject: [PATCH 30/44] reshuffle sequence (#4) --- ...ate_table_result_block.sql => 5_create_table_result_block.sql} | 0 ..._create_table_block_data.sql => 6_create_table_block_data.sql} | 0 ...e_commit_signature.sql => 7_create_table_commit_signature.sql} | 0 ...te_evidence.sql => 8_create_table_duplicate_vote_evidence.sql} | 0 ...idence.sql => 9_create_table_light_client_attack_evidence.sql} | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename database/schema/{9_create_table_result_block.sql => 5_create_table_result_block.sql} (100%) rename database/schema/{5_create_table_block_data.sql => 6_create_table_block_data.sql} (100%) rename database/schema/{6_create_table_commit_signature.sql => 7_create_table_commit_signature.sql} (100%) rename database/schema/{7_create_table_duplicate_vote_evidence.sql => 8_create_table_duplicate_vote_evidence.sql} (100%) rename database/schema/{8_create_table_light_client_attack_evidence.sql => 9_create_table_light_client_attack_evidence.sql} (100%) diff --git a/database/schema/9_create_table_result_block.sql b/database/schema/5_create_table_result_block.sql similarity index 100% rename from database/schema/9_create_table_result_block.sql rename to database/schema/5_create_table_result_block.sql diff --git a/database/schema/5_create_table_block_data.sql b/database/schema/6_create_table_block_data.sql similarity index 100% rename from database/schema/5_create_table_block_data.sql rename to database/schema/6_create_table_block_data.sql diff --git a/database/schema/6_create_table_commit_signature.sql b/database/schema/7_create_table_commit_signature.sql similarity index 100% rename from database/schema/6_create_table_commit_signature.sql rename to database/schema/7_create_table_commit_signature.sql diff --git a/database/schema/7_create_table_duplicate_vote_evidence.sql b/database/schema/8_create_table_duplicate_vote_evidence.sql similarity index 100% rename from database/schema/7_create_table_duplicate_vote_evidence.sql rename to database/schema/8_create_table_duplicate_vote_evidence.sql diff --git a/database/schema/8_create_table_light_client_attack_evidence.sql b/database/schema/9_create_table_light_client_attack_evidence.sql similarity index 100% rename from database/schema/8_create_table_light_client_attack_evidence.sql rename to database/schema/9_create_table_light_client_attack_evidence.sql From 0d7791d19ac365c385728306850734b193706634 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Mon, 5 Jun 2023 10:19:23 -0400 Subject: [PATCH 31/44] some clean up (#1) --- main.go | 2 +- types/block.go | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) delete mode 100644 types/block.go diff --git a/main.go b/main.go index 08b02d6..36ed065 100644 --- a/main.go +++ b/main.go @@ -548,7 +548,7 @@ func InsertBlocks(storage PostgresStorage) { Endpoint: os.Getenv("COMPANION_NODE_RPC"), } - numberHeights := int64(3) + numberHeights := int64(5) initialHeightParameter := os.Getenv("COMPANION_INITIAL_HEIGHT") initialHeight, err := strconv.ParseInt(initialHeightParameter, 10, 64) if err != nil { diff --git a/types/block.go b/types/block.go deleted file mode 100644 index 86d1c66..0000000 --- a/types/block.go +++ /dev/null @@ -1,4 +0,0 @@ -package types - -type Block struct { -} From 78beb106acbf9703fa291bfd7657db84343e2685 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Wed, 7 Jun 2023 11:35:43 -0400 Subject: [PATCH 32/44] adding initial schema for light client attack evidence (#4) --- .../schema/8_create_table_duplicate_vote_evidence.sql | 2 +- .../9_create_table_light_client_attack_evidence.sql | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/database/schema/8_create_table_duplicate_vote_evidence.sql b/database/schema/8_create_table_duplicate_vote_evidence.sql index f585e47..0248797 100644 --- a/database/schema/8_create_table_duplicate_vote_evidence.sql +++ b/database/schema/8_create_table_duplicate_vote_evidence.sql @@ -30,7 +30,7 @@ CREATE TABLE IF NOT EXISTS comet.duplicate_vote_evidence total_voting_power bigint NOT NULL, validator_voting_power bigint NOT NULL, evidence_timestamp timestamp with time zone NOT NULL, - CONSTRAINT evidence_height_fk FOREIGN KEY (height) + CONSTRAINT dv_evidence_height_fk FOREIGN KEY (height) REFERENCES comet.result_block (block_header_height) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE diff --git a/database/schema/9_create_table_light_client_attack_evidence.sql b/database/schema/9_create_table_light_client_attack_evidence.sql index 52926a6..3265dcf 100644 --- a/database/schema/9_create_table_light_client_attack_evidence.sql +++ b/database/schema/9_create_table_light_client_attack_evidence.sql @@ -1,10 +1,13 @@ -- Table: comet.light_client_attack_evidence - -CREATE TABLE IF NOT EXISTS comet.light_client_attack_evidence +DROP TABLE IF EXISTS comet.light_client_attack_evidence; +CREATE TABLE comet.light_client_attack_evidence ( height bigint NOT NULL, + evidence_type bytea NOT NULL, common_height bigint NOT NULL, - CONSTRAINT evidence_height_fk FOREIGN KEY (height) + total_voting_power bigint NOT NULL, + evidence_timestamp timestamp with time zone NOT NULL, + CONSTRAINT lca_evidence_height_fk FOREIGN KEY (height) REFERENCES comet.result_block (block_header_height) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE From 1414d95e2e0655f236ee25b38e8da9b5e2ec2071 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Wed, 7 Jun 2023 11:36:32 -0400 Subject: [PATCH 33/44] initial logic to insert light client attack evidence (#1) --- main.go | 79 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 26 deletions(-) diff --git a/main.go b/main.go index 36ed065..c01be51 100644 --- a/main.go +++ b/main.go @@ -218,9 +218,14 @@ func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, err return false, err } case *types.LightClientAttackEvidence: - fmt.Printf("Light Client Attack") + var lae *types.LightClientAttackEvidence + lae = ev + _, err = c.InsertLightClientAttackEvidence(resultBlock.Block.Header.Height, lae) + if err != nil { + return false, err + } default: - fmt.Printf("Evidence not supported") + fmt.Printf("Evidence type not supported") } } @@ -242,7 +247,7 @@ func (c *PostgresStorage) InsertTransaction(height int64, tx types.Tx) (bool, er } } -func (c *PostgresStorage) InsertDuplicateVoteEvidence(height int64, dve *types.DuplicateVoteEvidence) (bool, error) { +func (c *PostgresStorage) InsertDuplicateVoteEvidence(height int64, evidence *types.DuplicateVoteEvidence) (bool, error) { //TODO: Find how to get the evidence type property e.g. 'tendermint/DuplicateVoteEvidence' @@ -275,29 +280,51 @@ func (c *PostgresStorage) InsertDuplicateVoteEvidence(height int64, dve *types.D "VALUES ($1,$2,$3,$4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25)", height, "tendermint/DuplicateVoteEvidence", - dve.VoteA.Type, - dve.VoteA.Height, - dve.VoteA.Round, - dve.VoteA.BlockID.Hash, - dve.VoteA.BlockID.PartSetHeader.Hash, - dve.VoteA.BlockID.PartSetHeader.Total, - dve.VoteA.Timestamp, - dve.VoteA.ValidatorAddress, - dve.VoteA.ValidatorIndex, - dve.VoteA.Signature, - dve.VoteB.Type, - dve.VoteB.Height, - dve.VoteB.Round, - dve.VoteB.BlockID.Hash, - dve.VoteB.BlockID.PartSetHeader.Hash, - dve.VoteB.BlockID.PartSetHeader.Total, - dve.VoteB.Timestamp, - dve.VoteB.ValidatorAddress, - dve.VoteB.ValidatorIndex, - dve.VoteB.Signature, - dve.TotalVotingPower, - dve.ValidatorPower, - dve.Timestamp) + evidence.VoteA.Type, + evidence.VoteA.Height, + evidence.VoteA.Round, + evidence.VoteA.BlockID.Hash, + evidence.VoteA.BlockID.PartSetHeader.Hash, + evidence.VoteA.BlockID.PartSetHeader.Total, + evidence.VoteA.Timestamp, + evidence.VoteA.ValidatorAddress, + evidence.VoteA.ValidatorIndex, + evidence.VoteA.Signature, + evidence.VoteB.Type, + evidence.VoteB.Height, + evidence.VoteB.Round, + evidence.VoteB.BlockID.Hash, + evidence.VoteB.BlockID.PartSetHeader.Hash, + evidence.VoteB.BlockID.PartSetHeader.Total, + evidence.VoteB.Timestamp, + evidence.VoteB.ValidatorAddress, + evidence.VoteB.ValidatorIndex, + evidence.VoteB.Signature, + evidence.TotalVotingPower, + evidence.ValidatorPower, + evidence.Timestamp) + if err != nil { + return false, err + } else { + return true, nil + } +} + +func (c *PostgresStorage) InsertLightClientAttackEvidence(height int64, evidence *types.LightClientAttackEvidence) (bool, error) { + + //TODO: Find how to get the evidence type property e.g. 'tendermint/LightClientAttackEvidence' + _, err := c.Connection.Exec("INSERT INTO comet.light_client_attack_evidence ("+ + "height, "+ + "evidence_type, "+ + "common_height, "+ + "total_voting_power, "+ + "evidence_timestamp) "+ + "VALUES ($1,$2,$3, $4, $5)", + height, + "tendermint/LightClientAttackEvidence", + evidence.CommonHeight, + evidence.TotalVotingPower, + evidence.Timestamp) if err != nil { return false, err } else { From 14838e992f221f47bdea13d5370be831651d1b46 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Wed, 7 Jun 2023 17:19:35 -0400 Subject: [PATCH 34/44] refactoring some schema names (#4) --- ...ck.sql => 5_create_table_block_result.sql} | 5 ++-- database/schema/6_create_table_block_data.sql | 2 +- .../7_create_table_block_commit_sig.sql | 15 ++++++++++ .../7_create_table_commit_signature.sql | 14 ---------- ..._create_table_evidence_duplicate_vote.sql} | 7 +++-- ...te_table_evidence_light_client_attack.sql} | 11 ++++---- main.go | 28 +++++++++---------- 7 files changed, 43 insertions(+), 39 deletions(-) rename database/schema/{5_create_table_result_block.sql => 5_create_table_block_result.sql} (93%) create mode 100644 database/schema/7_create_table_block_commit_sig.sql delete mode 100644 database/schema/7_create_table_commit_signature.sql rename database/schema/{8_create_table_duplicate_vote_evidence.sql => 8_create_table_evidence_duplicate_vote.sql} (85%) rename database/schema/{9_create_table_light_client_attack_evidence.sql => 9_create_table_evidence_light_client_attack.sql} (50%) diff --git a/database/schema/5_create_table_result_block.sql b/database/schema/5_create_table_block_result.sql similarity index 93% rename from database/schema/5_create_table_result_block.sql rename to database/schema/5_create_table_block_result.sql index 5639dba..6ae9d87 100644 --- a/database/schema/5_create_table_result_block.sql +++ b/database/schema/5_create_table_block_result.sql @@ -1,6 +1,7 @@ --- Table: comet.result_block +-- Table: comet.block_result -CREATE TABLE IF NOT EXISTS comet.result_block +DROP TABLE IF EXISTS comet.block_result CASCADE; +CREATE TABLE comet.block_result ( block_id_hash bytea NOT NULL, block_id_parts_hash bytea NOT NULL, diff --git a/database/schema/6_create_table_block_data.sql b/database/schema/6_create_table_block_data.sql index 441dc80..5dc73c3 100644 --- a/database/schema/6_create_table_block_data.sql +++ b/database/schema/6_create_table_block_data.sql @@ -5,7 +5,7 @@ CREATE TABLE IF NOT EXISTS comet.block_data height bigint NOT NULL, transaction bytea NOT NULL, CONSTRAINT block_height_fk FOREIGN KEY (height) - REFERENCES comet.result_block (block_header_height) MATCH SIMPLE + REFERENCES comet.block_result (block_header_height) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE ) TABLESPACE pg_default; diff --git a/database/schema/7_create_table_block_commit_sig.sql b/database/schema/7_create_table_block_commit_sig.sql new file mode 100644 index 0000000..1283c24 --- /dev/null +++ b/database/schema/7_create_table_block_commit_sig.sql @@ -0,0 +1,15 @@ +-- Table: comet.block_commit_sig + +DROP TABLE IF EXISTS comet.block_commit_sig; +CREATE TABLE comet.block_commit_sig +( + height bigint NOT NULL, + block_id_flag comet.uint8 NOT NULL, + validator_address bytea, + timestamp timestamp with time zone NOT NULL, + signature bytea, + CONSTRAINT block_commit_sig_height_fk FOREIGN KEY (height) + REFERENCES comet.block_result (block_last_commit_height) MATCH SIMPLE + ON UPDATE CASCADE + ON DELETE CASCADE +) TABLESPACE pg_default; \ No newline at end of file diff --git a/database/schema/7_create_table_commit_signature.sql b/database/schema/7_create_table_commit_signature.sql deleted file mode 100644 index ffc9ed5..0000000 --- a/database/schema/7_create_table_commit_signature.sql +++ /dev/null @@ -1,14 +0,0 @@ --- Table: comet.last_commit_signature - -CREATE TABLE IF NOT EXISTS comet.last_commit_signature -( - height bigint NOT NULL, - block_id_flag comet.uint8 NOT NULL, - validator_address bytea, - signature_timestamp timestamp with time zone NOT NULL, - signature bytea, - CONSTRAINT last_commit_height_fk FOREIGN KEY (height) - REFERENCES comet.result_block (block_last_commit_height) MATCH SIMPLE - ON UPDATE CASCADE - ON DELETE CASCADE -) TABLESPACE pg_default; \ No newline at end of file diff --git a/database/schema/8_create_table_duplicate_vote_evidence.sql b/database/schema/8_create_table_evidence_duplicate_vote.sql similarity index 85% rename from database/schema/8_create_table_duplicate_vote_evidence.sql rename to database/schema/8_create_table_evidence_duplicate_vote.sql index 0248797..8d626af 100644 --- a/database/schema/8_create_table_duplicate_vote_evidence.sql +++ b/database/schema/8_create_table_evidence_duplicate_vote.sql @@ -1,6 +1,7 @@ --- Table: comet.duplicate_vote_evidence +-- Table: comet.evidence_duplicate_vote -CREATE TABLE IF NOT EXISTS comet.duplicate_vote_evidence +DROP TABLE IF EXISTS comet.evidence_duplicate_vote; +CREATE TABLE comet.evidence_duplicate_vote ( height bigint NOT NULL, evidence_type bytea NOT NULL, @@ -31,7 +32,7 @@ CREATE TABLE IF NOT EXISTS comet.duplicate_vote_evidence validator_voting_power bigint NOT NULL, evidence_timestamp timestamp with time zone NOT NULL, CONSTRAINT dv_evidence_height_fk FOREIGN KEY (height) - REFERENCES comet.result_block (block_header_height) MATCH SIMPLE + REFERENCES comet.block_result (block_header_height) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE ) TABLESPACE pg_default; \ No newline at end of file diff --git a/database/schema/9_create_table_light_client_attack_evidence.sql b/database/schema/9_create_table_evidence_light_client_attack.sql similarity index 50% rename from database/schema/9_create_table_light_client_attack_evidence.sql rename to database/schema/9_create_table_evidence_light_client_attack.sql index 3265dcf..6272f91 100644 --- a/database/schema/9_create_table_light_client_attack_evidence.sql +++ b/database/schema/9_create_table_evidence_light_client_attack.sql @@ -1,14 +1,15 @@ --- Table: comet.light_client_attack_evidence -DROP TABLE IF EXISTS comet.light_client_attack_evidence; -CREATE TABLE comet.light_client_attack_evidence +-- Table: comet.evidence_light_client_attack + +DROP TABLE IF EXISTS comet.evidence_light_client_attack; +CREATE TABLE comet.evidence_light_client_attack ( height bigint NOT NULL, evidence_type bytea NOT NULL, common_height bigint NOT NULL, total_voting_power bigint NOT NULL, - evidence_timestamp timestamp with time zone NOT NULL, + timestamp timestamp with time zone NOT NULL, CONSTRAINT lca_evidence_height_fk FOREIGN KEY (height) - REFERENCES comet.result_block (block_header_height) MATCH SIMPLE + REFERENCES comet.block_result (block_header_height) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE ) TABLESPACE pg_default; \ No newline at end of file diff --git a/main.go b/main.go index c01be51..348ffb0 100644 --- a/main.go +++ b/main.go @@ -138,7 +138,7 @@ func (c *CometFetcher) FetchABCIInfo() (*ctypes.ResultABCIInfo, error) { func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, error) { _, err := c.Connection.Exec( - "INSERT INTO comet.result_block"+ + "INSERT INTO comet.block_result"+ "(block_id_hash, "+ "block_id_parts_hash, "+ "block_id_parts_total, "+ @@ -201,7 +201,7 @@ func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, err // Insert last commit signatures for _, signature := range resultBlock.Block.LastCommit.Signatures { - _, err := c.InsertSignature(resultBlock.Block.LastCommit.Height, signature) + _, err := c.InsertCommitSignature(resultBlock.Block.LastCommit.Height, signature) if err != nil { return false, err } @@ -251,7 +251,7 @@ func (c *PostgresStorage) InsertDuplicateVoteEvidence(height int64, evidence *ty //TODO: Find how to get the evidence type property e.g. 'tendermint/DuplicateVoteEvidence' - _, err := c.Connection.Exec("INSERT INTO comet.duplicate_vote_evidence ("+ + _, err := c.Connection.Exec("INSERT INTO comet.evidence_duplicate_vote ("+ "height, "+ "evidence_type, "+ "vote_a_type, "+ @@ -313,12 +313,12 @@ func (c *PostgresStorage) InsertDuplicateVoteEvidence(height int64, evidence *ty func (c *PostgresStorage) InsertLightClientAttackEvidence(height int64, evidence *types.LightClientAttackEvidence) (bool, error) { //TODO: Find how to get the evidence type property e.g. 'tendermint/LightClientAttackEvidence' - _, err := c.Connection.Exec("INSERT INTO comet.light_client_attack_evidence ("+ + _, err := c.Connection.Exec("INSERT INTO comet.evidence_light_client_attack ("+ "height, "+ "evidence_type, "+ "common_height, "+ "total_voting_power, "+ - "evidence_timestamp) "+ + "timestamp) "+ "VALUES ($1,$2,$3, $4, $5)", height, "tendermint/LightClientAttackEvidence", @@ -332,13 +332,13 @@ func (c *PostgresStorage) InsertLightClientAttackEvidence(height int64, evidence } } -func (c *PostgresStorage) InsertSignature(height int64, signature types.CommitSig) (bool, error) { - _, err := c.Connection.Exec("INSERT INTO comet.last_commit_signature (height, block_id_flag, validator_address, signature_timestamp, signature) values ($1,$2,$3,$4,$5)", +func (c *PostgresStorage) InsertCommitSignature(height int64, commitSig types.CommitSig) (bool, error) { + _, err := c.Connection.Exec("INSERT INTO comet.block_commit_sig (height, block_id_flag, validator_address, timestamp, signature) values ($1,$2,$3,$4,$5)", height, - signature.BlockIDFlag, - signature.ValidatorAddress, - signature.Timestamp, - signature.Signature) + commitSig.BlockIDFlag, + commitSig.ValidatorAddress, + commitSig.Timestamp, + commitSig.Signature) if err != nil { return false, err } else { @@ -378,7 +378,7 @@ func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { "block_last_commit_block_id_hash, "+ "block_last_commit_block_id_parts_total, "+ "block_last_commit_block_id_parts_hash "+ - "FROM comet.result_block WHERE block_header_height=$1", height) + "FROM comet.block_result WHERE block_header_height=$1", height) err := row.Scan( &bId.Hash, &bId.PartSetHeader.Hash, @@ -430,7 +430,7 @@ func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { // Retrieve commit signatures var signature types.CommitSig - signatures, err := c.Connection.Query("SELECT block_id_flag, validator_address, signature_timestamp, signature FROM comet.last_commit_signature WHERE height=$1", height-1) + signatures, err := c.Connection.Query("SELECT block_id_flag, validator_address, timestamp, signature FROM comet.block_commit_sig WHERE height=$1", resultBlock.Block.LastCommit.Height) if err != nil { return resultBlock, err } @@ -470,7 +470,7 @@ func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { "total_voting_power, "+ "validator_voting_power, "+ "evidence_timestamp "+ - "FROM comet.duplicate_vote_evidence "+ + "FROM comet.evidence_duplicate_vote "+ "WHERE height=$1", height) if err != nil { return resultBlock, err From 778f632dfa0a0f0cee263b7acf0a9a679da5c5c4 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Wed, 7 Jun 2023 17:32:07 -0400 Subject: [PATCH 35/44] initial logic to return light client attack evidence (#3) --- main.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/main.go b/main.go index 348ffb0..f140f28 100644 --- a/main.go +++ b/main.go @@ -512,6 +512,30 @@ func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { } } + // Retrieve light client attack evidences + lcaev := types.LightClientAttackEvidence{} + lcaevs, err := c.Connection.Query("SELECT "+ + "common_height, "+ + "total_voting_power, "+ + "timestamp "+ + "FROM comet.evidence_light_client_attack "+ + "WHERE height=$1", height) + if err != nil { + return resultBlock, err + } + defer lcaevs.Close() + for lcaevs.Next() { + err := lcaevs.Scan( + &lcaev.CommonHeight, + &lcaev.TotalVotingPower, + &lcaev.Timestamp) + if err != nil { + return resultBlock, err + } else { + resultBlock.Block.Evidence.Evidence = append(resultBlock.Block.Evidence.Evidence, &lcaev) + } + } + return resultBlock, err } From 4834d83af7aeb41ae67fdc86157fb73be2736ab0 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Mon, 19 Jun 2023 15:13:35 -0400 Subject: [PATCH 36/44] simplified schema creation merged into one file (#4) --- database/schema/1_create_schema_comet.sql | 3 - database/schema/2_create_domain_uint64.sql | 10 - database/schema/3_create_domain_uint32.sql | 10 - database/schema/4_create_domain_uint8.sql | 10 - .../schema/5_create_table_block_result.sql | 34 ---- database/schema/6_create_table_block_data.sql | 11 -- .../7_create_table_block_commit_sig.sql | 15 -- ...8_create_table_evidence_duplicate_vote.sql | 38 ---- ...ate_table_evidence_light_client_attack.sql | 15 -- database/schema/create_database_schema.sql | 172 ++++++++++++++++++ 10 files changed, 172 insertions(+), 146 deletions(-) delete mode 100644 database/schema/1_create_schema_comet.sql delete mode 100644 database/schema/2_create_domain_uint64.sql delete mode 100644 database/schema/3_create_domain_uint32.sql delete mode 100644 database/schema/4_create_domain_uint8.sql delete mode 100644 database/schema/5_create_table_block_result.sql delete mode 100644 database/schema/6_create_table_block_data.sql delete mode 100644 database/schema/7_create_table_block_commit_sig.sql delete mode 100644 database/schema/8_create_table_evidence_duplicate_vote.sql delete mode 100644 database/schema/9_create_table_evidence_light_client_attack.sql create mode 100644 database/schema/create_database_schema.sql diff --git a/database/schema/1_create_schema_comet.sql b/database/schema/1_create_schema_comet.sql deleted file mode 100644 index 0ba013c..0000000 --- a/database/schema/1_create_schema_comet.sql +++ /dev/null @@ -1,3 +0,0 @@ --- SCHEMA: comet - -CREATE SCHEMA IF NOT EXISTS comet; \ No newline at end of file diff --git a/database/schema/2_create_domain_uint64.sql b/database/schema/2_create_domain_uint64.sql deleted file mode 100644 index 55f8bec..0000000 --- a/database/schema/2_create_domain_uint64.sql +++ /dev/null @@ -1,10 +0,0 @@ --- DOMAIN: comet.uint64 - -CREATE DOMAIN comet.uint64 - AS numeric; - -ALTER DOMAIN comet.uint64 - ADD CONSTRAINT value_max CHECK (VALUE <= '18446744073709551615'::numeric); - -ALTER DOMAIN comet.uint64 - ADD CONSTRAINT value_positive CHECK (VALUE >= 0::numeric); \ No newline at end of file diff --git a/database/schema/3_create_domain_uint32.sql b/database/schema/3_create_domain_uint32.sql deleted file mode 100644 index bad3626..0000000 --- a/database/schema/3_create_domain_uint32.sql +++ /dev/null @@ -1,10 +0,0 @@ --- DOMAIN: comet.uint32 - -CREATE DOMAIN comet.uint32 - AS numeric; - -ALTER DOMAIN comet.uint32 - ADD CONSTRAINT value_max CHECK (VALUE <= '4294967295'::numeric); - -ALTER DOMAIN comet.uint32 - ADD CONSTRAINT value_positive CHECK (VALUE >= 0::numeric); \ No newline at end of file diff --git a/database/schema/4_create_domain_uint8.sql b/database/schema/4_create_domain_uint8.sql deleted file mode 100644 index 1ead75a..0000000 --- a/database/schema/4_create_domain_uint8.sql +++ /dev/null @@ -1,10 +0,0 @@ --- DOMAIN: comet.uint8 - -CREATE DOMAIN comet.uint8 - AS numeric; - -ALTER DOMAIN comet.uint8 - ADD CONSTRAINT value_max CHECK (VALUE <= '255'::numeric); - -ALTER DOMAIN comet.uint8 - ADD CONSTRAINT value_positive CHECK (VALUE >= 0::numeric); \ No newline at end of file diff --git a/database/schema/5_create_table_block_result.sql b/database/schema/5_create_table_block_result.sql deleted file mode 100644 index 6ae9d87..0000000 --- a/database/schema/5_create_table_block_result.sql +++ /dev/null @@ -1,34 +0,0 @@ --- Table: comet.block_result - -DROP TABLE IF EXISTS comet.block_result CASCADE; -CREATE TABLE comet.block_result -( - block_id_hash bytea NOT NULL, - block_id_parts_hash bytea NOT NULL, - block_id_parts_total comet.uint32 NOT NULL, - block_header_height bigint NOT NULL, - block_header_block_time timestamp with time zone NOT NULL, - block_header_chain_id text NOT NULL, - block_header_version_block comet.uint64 NOT NULL, - block_header_version_app comet.uint64 NOT NULL, - block_header_data_hash bytea NOT NULL, - block_header_last_commit_hash bytea NOT NULL, - block_header_validators_hash bytea NOT NULL, - block_header_next_validators_hash bytea NOT NULL, - block_header_consensus_hash bytea NOT NULL, - block_header_app_hash bytea NOT NULL, - block_header_last_results_hash bytea NOT NULL, - block_header_evidence_hash bytea NOT NULL, - block_header_proposer_address bytea NOT NULL, - block_header_last_block_id_hash bytea NOT NULL, - block_header_last_block_id_parts_hash bytea NOT NULL, - block_header_last_block_id_part_total comet.uint32 NOT NULL, - block_last_commit_height comet.uint64 NOT NULL, - block_last_commit_round comet.uint32 NOT NULL, - block_last_commit_block_id_hash bytea NOT NULL, - block_last_commit_block_id_parts_total comet.uint32 NOT NULL, - block_last_commit_block_id_parts_hash bytea NOT NULL, - CONSTRAINT block_pkey PRIMARY KEY (block_header_height), - CONSTRAINT last_commit_height_unique UNIQUE (block_last_commit_height), - CONSTRAINT height_positive CHECK (block_header_height >= 0) -) TABLESPACE pg_default; diff --git a/database/schema/6_create_table_block_data.sql b/database/schema/6_create_table_block_data.sql deleted file mode 100644 index 5dc73c3..0000000 --- a/database/schema/6_create_table_block_data.sql +++ /dev/null @@ -1,11 +0,0 @@ --- Table: comet.block_data - -CREATE TABLE IF NOT EXISTS comet.block_data -( - height bigint NOT NULL, - transaction bytea NOT NULL, - CONSTRAINT block_height_fk FOREIGN KEY (height) - REFERENCES comet.block_result (block_header_height) MATCH SIMPLE - ON UPDATE CASCADE - ON DELETE CASCADE -) TABLESPACE pg_default; diff --git a/database/schema/7_create_table_block_commit_sig.sql b/database/schema/7_create_table_block_commit_sig.sql deleted file mode 100644 index 1283c24..0000000 --- a/database/schema/7_create_table_block_commit_sig.sql +++ /dev/null @@ -1,15 +0,0 @@ --- Table: comet.block_commit_sig - -DROP TABLE IF EXISTS comet.block_commit_sig; -CREATE TABLE comet.block_commit_sig -( - height bigint NOT NULL, - block_id_flag comet.uint8 NOT NULL, - validator_address bytea, - timestamp timestamp with time zone NOT NULL, - signature bytea, - CONSTRAINT block_commit_sig_height_fk FOREIGN KEY (height) - REFERENCES comet.block_result (block_last_commit_height) MATCH SIMPLE - ON UPDATE CASCADE - ON DELETE CASCADE -) TABLESPACE pg_default; \ No newline at end of file diff --git a/database/schema/8_create_table_evidence_duplicate_vote.sql b/database/schema/8_create_table_evidence_duplicate_vote.sql deleted file mode 100644 index 8d626af..0000000 --- a/database/schema/8_create_table_evidence_duplicate_vote.sql +++ /dev/null @@ -1,38 +0,0 @@ --- Table: comet.evidence_duplicate_vote - -DROP TABLE IF EXISTS comet.evidence_duplicate_vote; -CREATE TABLE comet.evidence_duplicate_vote -( - height bigint NOT NULL, - evidence_type bytea NOT NULL, - - vote_a_type int NOT NULL, - vote_a_height bigint NOT NULL, - vote_a_round int NOT NULL, - vote_a_block_id_hash bytea NOT NULL, - vote_a_block_id_parts_hash bytea NOT NULL, - vote_a_block_id_parts_total comet.uint32 NOT NULL, - vote_a_timestamp timestamp with time zone NOT NULL, - vote_a_validator_address bytea NOT NULL, - vote_a_validator_index int NOT NULL, - vote_a_signature bytea NOT NULL, - - vote_b_type int NOT NULL, - vote_b_height bigint NOT NULL, - vote_b_round int NOT NULL, - vote_b_block_id_hash bytea NOT NULL, - vote_b_block_id_parts_hash bytea NOT NULL, - vote_b_block_id_parts_total comet.uint32 NOT NULL, - vote_b_timestamp timestamp with time zone NOT NULL, - vote_b_validator_address bytea NOT NULL, - vote_b_validator_index int NOT NULL, - vote_b_signature bytea NOT NULL, - - total_voting_power bigint NOT NULL, - validator_voting_power bigint NOT NULL, - evidence_timestamp timestamp with time zone NOT NULL, - CONSTRAINT dv_evidence_height_fk FOREIGN KEY (height) - REFERENCES comet.block_result (block_header_height) MATCH SIMPLE - ON UPDATE CASCADE - ON DELETE CASCADE -) TABLESPACE pg_default; \ No newline at end of file diff --git a/database/schema/9_create_table_evidence_light_client_attack.sql b/database/schema/9_create_table_evidence_light_client_attack.sql deleted file mode 100644 index 6272f91..0000000 --- a/database/schema/9_create_table_evidence_light_client_attack.sql +++ /dev/null @@ -1,15 +0,0 @@ --- Table: comet.evidence_light_client_attack - -DROP TABLE IF EXISTS comet.evidence_light_client_attack; -CREATE TABLE comet.evidence_light_client_attack -( - height bigint NOT NULL, - evidence_type bytea NOT NULL, - common_height bigint NOT NULL, - total_voting_power bigint NOT NULL, - timestamp timestamp with time zone NOT NULL, - CONSTRAINT lca_evidence_height_fk FOREIGN KEY (height) - REFERENCES comet.block_result (block_header_height) MATCH SIMPLE - ON UPDATE CASCADE - ON DELETE CASCADE -) TABLESPACE pg_default; \ No newline at end of file diff --git a/database/schema/create_database_schema.sql b/database/schema/create_database_schema.sql new file mode 100644 index 0000000..88f0c6f --- /dev/null +++ b/database/schema/create_database_schema.sql @@ -0,0 +1,172 @@ +-- SCHEMA: comet + +CREATE SCHEMA IF NOT EXISTS comet; + +-- DOMAIN: comet.uint8 + +DO $$ BEGIN + CREATE DOMAIN comet.uint8 AS numeric; + + ALTER DOMAIN comet.uint8 + ADD CONSTRAINT value_max CHECK (VALUE <= '255'::numeric); + + ALTER DOMAIN comet.uint8 + ADD CONSTRAINT value_positive CHECK (VALUE >= 0::numeric); +EXCEPTION + WHEN duplicate_object THEN null; +END $$; + +-- DOMAIN: comet.uint32 + +DO $$ BEGIN + CREATE DOMAIN comet.uint32 AS numeric; + + ALTER DOMAIN comet.uint32 + ADD CONSTRAINT value_max CHECK (VALUE <= '4294967295'::numeric); + + ALTER DOMAIN comet.uint32 + ADD CONSTRAINT value_positive CHECK (VALUE >= 0::numeric); +EXCEPTION + WHEN duplicate_object THEN null; +END $$; + +-- DOMAIN: comet.uint64 + +DO $$ BEGIN + CREATE DOMAIN comet.uint64 + AS numeric; + + ALTER DOMAIN comet.uint64 OWNER TO postgres; + + ALTER DOMAIN comet.uint64 + ADD CONSTRAINT value_max CHECK (VALUE <= '18446744073709551615'::numeric); + + ALTER DOMAIN comet.uint64 + ADD CONSTRAINT value_positive CHECK (VALUE >= 0::numeric); + EXCEPTION + WHEN duplicate_object THEN null; +END $$; + +-- TABLE: comet.block_result + +DROP TABLE IF EXISTS comet.block_result CASCADE; + +CREATE TABLE comet.block_result +( + block_id_hash bytea NOT NULL, + block_id_parts_hash bytea NOT NULL, + block_id_parts_total comet.uint32 NOT NULL, + block_header_height bigint NOT NULL, + block_header_block_time timestamp with time zone NOT NULL, + block_header_chain_id text NOT NULL, + block_header_version_block comet.uint64 NOT NULL, + block_header_version_app comet.uint64 NOT NULL, + block_header_data_hash bytea NOT NULL, + block_header_last_commit_hash bytea NOT NULL, + block_header_validators_hash bytea NOT NULL, + block_header_next_validators_hash bytea NOT NULL, + block_header_consensus_hash bytea NOT NULL, + block_header_app_hash bytea NOT NULL, + block_header_last_results_hash bytea NOT NULL, + block_header_evidence_hash bytea NOT NULL, + block_header_proposer_address bytea NOT NULL, + block_header_last_block_id_hash bytea NOT NULL, + block_header_last_block_id_parts_hash bytea NOT NULL, + block_header_last_block_id_part_total comet.uint32 NOT NULL, + block_last_commit_height comet.uint64 NOT NULL, + block_last_commit_round comet.uint32 NOT NULL, + block_last_commit_block_id_hash bytea NOT NULL, + block_last_commit_block_id_parts_total comet.uint32 NOT NULL, + block_last_commit_block_id_parts_hash bytea NOT NULL, + CONSTRAINT block_pkey PRIMARY KEY (block_header_height), + CONSTRAINT last_commit_height_unique UNIQUE (block_last_commit_height), + CONSTRAINT height_positive CHECK (block_header_height >= 0) +); + +-- TABLE: comet.block_data + +DROP TABLE IF EXISTS comet.block_data CASCADE; + +CREATE TABLE comet.block_data +( + height bigint NOT NULL, + transaction bytea NOT NULL, + CONSTRAINT block_height_fk FOREIGN KEY (height) + REFERENCES comet.block_result (block_header_height) MATCH SIMPLE + ON UPDATE CASCADE + ON DELETE CASCADE +); + +-- TABLE: comet.block_commit_sig + +DROP TABLE IF EXISTS comet.block_commit_sig; + +CREATE TABLE comet.block_commit_sig +( + height bigint NOT NULL, + block_id_flag comet.uint8 NOT NULL, + validator_address bytea, + timestamp timestamp with time zone NOT NULL, + signature bytea, + CONSTRAINT block_commit_sig_height_fk FOREIGN KEY (height) + REFERENCES comet.block_result (block_last_commit_height) MATCH SIMPLE + ON UPDATE CASCADE + ON DELETE CASCADE +); + +-- TABLE: comet.evidence_duplicate_vote + +DROP TABLE IF EXISTS comet.evidence_duplicate_vote; + +CREATE TABLE comet.evidence_duplicate_vote +( + height bigint NOT NULL, + evidence_type bytea NOT NULL, + + vote_a_type int NOT NULL, + vote_a_height bigint NOT NULL, + vote_a_round int NOT NULL, + vote_a_block_id_hash bytea NOT NULL, + vote_a_block_id_parts_hash bytea NOT NULL, + vote_a_block_id_parts_total comet.uint32 NOT NULL, + vote_a_timestamp timestamp with time zone NOT NULL, + vote_a_validator_address bytea NOT NULL, + vote_a_validator_index int NOT NULL, + vote_a_signature bytea NOT NULL, + + vote_b_type int NOT NULL, + vote_b_height bigint NOT NULL, + vote_b_round int NOT NULL, + vote_b_block_id_hash bytea NOT NULL, + vote_b_block_id_parts_hash bytea NOT NULL, + vote_b_block_id_parts_total comet.uint32 NOT NULL, + vote_b_timestamp timestamp with time zone NOT NULL, + vote_b_validator_address bytea NOT NULL, + vote_b_validator_index int NOT NULL, + vote_b_signature bytea NOT NULL, + + total_voting_power bigint NOT NULL, + validator_voting_power bigint NOT NULL, + evidence_timestamp timestamp with time zone NOT NULL, + CONSTRAINT dv_evidence_height_fk FOREIGN KEY (height) + REFERENCES comet.block_result (block_header_height) MATCH SIMPLE + ON UPDATE CASCADE + ON DELETE CASCADE +); + +-- TABLE: comet.evidence_light_client_attack + +DROP TABLE IF EXISTS comet.evidence_light_client_attack; + +CREATE TABLE comet.evidence_light_client_attack +( + height bigint NOT NULL, + evidence_type bytea NOT NULL, + common_height bigint NOT NULL, + total_voting_power bigint NOT NULL, + timestamp timestamp with time zone NOT NULL, + CONSTRAINT lca_evidence_height_fk FOREIGN KEY (height) + REFERENCES comet.block_result (block_header_height) MATCH SIMPLE + ON UPDATE CASCADE + ON DELETE CASCADE +); From f1c48767bea35a72cf63ed7c949b843547b0b3e3 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Mon, 19 Jun 2023 18:00:42 -0400 Subject: [PATCH 37/44] initial service commands implementation #1 #3 --- commands/ingest/ingest.go | 18 ++ commands/root.go | 39 +++ commands/rpc/rpc.go | 18 ++ go.mod | 3 + go.sum | 9 + insert.go | 624 ++++++++++++++++++++++++++++++++++++++ main.go | 619 +------------------------------------ 7 files changed, 713 insertions(+), 617 deletions(-) create mode 100644 commands/ingest/ingest.go create mode 100644 commands/root.go create mode 100644 commands/rpc/rpc.go create mode 100644 insert.go diff --git a/commands/ingest/ingest.go b/commands/ingest/ingest.go new file mode 100644 index 0000000..4b62029 --- /dev/null +++ b/commands/ingest/ingest.go @@ -0,0 +1,18 @@ +package ingest + +import ( + "github.com/spf13/cobra" +) + +// IngestCmd ingest service commands +var IngestCmd = &cobra.Command{ + Use: "ingest", + Short: "Ingest Service commands", + Long: `The Ingest Service pulls data from a CometBFT full node and store the information in a database`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Help() + }, +} + +func init() { +} diff --git a/commands/root.go b/commands/root.go new file mode 100644 index 0000000..17399f0 --- /dev/null +++ b/commands/root.go @@ -0,0 +1,39 @@ +package commands + +import ( + ingest "github.com/cometbft/rpc-companion/commands/ingest" + rpc "github.com/cometbft/rpc-companion/commands/rpc" + "github.com/spf13/cobra" +) + +// RootCmd represents the base command when called without any subcommands +var RootCmd = &cobra.Command{ + Use: "rpc-companion", + Short: "RPC Companion - CometBFT", + Long: `RPC Companion is an implementation of a Data Companion for CometBFT based chains`, +} + +// Execute adds all child commands to the root command and sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the rootCmd. +func Execute() { + cobra.CheckErr(RootCmd.Execute()) +} + +func init() { + + options := cobra.CompletionOptions{ + DisableDefaultCmd: true, + DisableNoDescFlag: true, + DisableDescriptions: false, + } + RootCmd.CompletionOptions = options + + cobra.EnableCommandSorting = true + + RootCmd.AddCommand(ingest.IngestCmd) + RootCmd.AddCommand(rpc.RpcCmd) +} + +func initConfig() { + +} diff --git a/commands/rpc/rpc.go b/commands/rpc/rpc.go new file mode 100644 index 0000000..5750b79 --- /dev/null +++ b/commands/rpc/rpc.go @@ -0,0 +1,18 @@ +package rpc + +import ( + "github.com/spf13/cobra" +) + +// RpcCmd RPC service commands +var RpcCmd = &cobra.Command{ + Use: "rpc", + Short: "RPC Service commands", + Long: `The RPC Service expose a RPC endpoint compatible with the CometBFT RPC endpoint.`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Help() + }, +} + +func init() { +} diff --git a/go.mod b/go.mod index 7f75cca..f67e4c3 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.20 require ( github.com/cometbft/cometbft v0.37.1 github.com/lib/pq v1.10.9 + github.com/spf13/cobra v1.6.1 ) require ( @@ -19,6 +20,7 @@ require ( github.com/golang/protobuf v1.5.2 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/gtank/merlin v0.1.1 // indirect + github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect @@ -30,6 +32,7 @@ require ( github.com/prometheus/procfs v0.8.0 // indirect github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect + github.com/spf13/pflag v1.0.5 // indirect golang.org/x/crypto v0.5.0 // indirect golang.org/x/net v0.7.0 // indirect golang.org/x/sys v0.5.0 // indirect diff --git a/go.sum b/go.sum index 2c55083..3172a84 100644 --- a/go.sum +++ b/go.sum @@ -58,6 +58,7 @@ github.com/cometbft/cometbft v0.37.1 h1:KLxkQTK2hICXYq21U2hn1W5hOVYUdQgDQ1uB+90x github.com/cometbft/cometbft v0.37.1/go.mod h1:Y2MMMN//O5K4YKd8ze4r9jmk4Y7h0ajqILXbH5JQFVs= github.com/cosmos/gogoproto v1.4.1 h1:WoyH+0/jbCTzpKNvyav5FL1ZTWsp1im1MxEpJEzKUB8= github.com/cosmos/gogoproto v1.4.1/go.mod h1:Ac9lzL4vFpBMcptJROQ6dQ4M3pOEK5Z/l0Q9p+LoCr4= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= @@ -144,6 +145,8 @@ github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/b github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= +github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -213,11 +216,16 @@ github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0ua github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sasha-s/go-deadlock v0.3.1 h1:sqv7fDNShgjcaxkO0JNcOAlr8B9+cV5Ey/OB71efZx0= github.com/sasha-s/go-deadlock v0.3.1/go.mod h1:F73l+cr82YSh10GxyRI6qZiCgK64VaZjwesgfQ1/iLM= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= +github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= @@ -508,6 +516,7 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/insert.go b/insert.go new file mode 100644 index 0000000..90c4f67 --- /dev/null +++ b/insert.go @@ -0,0 +1,624 @@ +package main + +import ( + "context" + "database/sql" + "fmt" + "github.com/cometbft/cometbft/libs/json" + client "github.com/cometbft/cometbft/rpc/client/http" + ctypes "github.com/cometbft/cometbft/rpc/core/types" + "github.com/cometbft/cometbft/types" + _ "github.com/lib/pq" + "log" + "net/http" + "os" + "strconv" + "time" +) + +const connString = "postgres://postgres:postgres@0.0.0.0:15432/postgres?sslmode=disable" + +type Storage interface { + Insert(table string, value string) (bool, error) + Get(table string, query string) ([]byte, error) + Connect(conn string) error +} + +type Fetcher interface { + FetchBlock(height int64) (*ctypes.ResultBlock, error) + FetchABCIInfo() (*ctypes.ResultABCIInfo, error) +} + +type Service interface { + Serve() +} + +type IngestService struct { + Fetcher Fetcher + Storage Storage +} + +type CometFetcher struct { + Endpoint string +} + +type PostgresStorage struct { + ConnectionString string + Connection *sql.DB +} + +type RESTService struct { + Version string +} + +func (s *RESTService) Serve(storage *PostgresStorage) { + // Handler for the block endpoint + http.HandleFunc(fmt.Sprintf("/%s/block", s.Version), handleBlock) + + // Start the service + err := http.ListenAndServe(":8080", nil) + if err != nil { + log.Fatalln("There's an error starting the REST service:", err) + } else { + log.Println("Started REST service...") + } +} + +// Handles the '/v1/block' endpoint +func handleBlock(writer http.ResponseWriter, request *http.Request) { + + // Database connection + storage := PostgresStorage{ + ConnectionString: connString, + Connection: nil, + } + + // Connect to the database + err := storage.Connect() + if err != nil { + log.Println("Error connecting to storage in handleBlock: ", err) + writer.WriteHeader(http.StatusInternalServerError) + writer.Write([]byte("Internal Server Error")) + } + + writer.Header().Set("Content-Type", "application/json") + + if request.Method == "GET" { + h := request.URL.Query()["height"][0] + height, err := strconv.ParseInt(h, 10, 64) + if err != nil { + writer.WriteHeader(http.StatusBadRequest) + writer.Write([]byte("Bad Request. Invalid height")) + } + fmt.Printf("Block Request. Height: %v\n", height) + block, err := storage.GetBlock(height) + if err != nil { + // TODO: If not records retrieved return a different status + log.Println("Error retrieving record from storage in handleBlock: ", err) + writer.WriteHeader(http.StatusInternalServerError) + writer.Write([]byte("Internal Server Error")) + } + resp, _ := json.Marshal(block) + writer.Write(resp) + } else { + writer.WriteHeader(http.StatusBadRequest) + writer.Write([]byte("Bad Request")) + } +} + +func (c *CometFetcher) FetchBlock(height int64) (*ctypes.ResultBlock, error) { + + httpClient, err := client.New(c.Endpoint, "/websocket") + if err != nil { + return nil, err + } + + resultBlock, err := httpClient.Block(context.Background(), &height) + if err != nil { + return nil, err + } else { + return resultBlock, nil + } +} + +func (c *CometFetcher) FetchABCIInfo() (*ctypes.ResultABCIInfo, error) { + + httpClient, err := client.New(c.Endpoint, "/websocket") + if err != nil { + return nil, err + } + + abciInfo, err := httpClient.ABCIInfo(context.Background()) + if err != nil { + return nil, err + } else { + return abciInfo, nil + } +} + +func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, error) { + _, err := c.Connection.Exec( + "INSERT INTO comet.block_result"+ + "(block_id_hash, "+ + "block_id_parts_hash, "+ + "block_id_parts_total, "+ + "block_header_height, "+ + "block_header_version_block, "+ + "block_header_version_app, "+ + "block_header_block_time, "+ + "block_header_chain_id, "+ + "block_header_last_commit_hash, "+ + "block_header_data_hash, "+ + "block_header_validators_hash, "+ + "block_header_next_validators_hash, "+ + "block_header_consensus_hash, "+ + "block_header_app_hash, "+ + "block_header_last_results_hash, "+ + "block_header_evidence_hash, "+ + "block_header_proposer_address, "+ + "block_header_last_block_id_hash, "+ + "block_header_last_block_id_parts_hash, "+ + "block_header_last_block_id_part_total, "+ + "block_last_commit_height, "+ + "block_last_commit_round, "+ + "block_last_commit_block_id_hash, "+ + "block_last_commit_block_id_parts_total, "+ + "block_last_commit_block_id_parts_hash) "+ + "VALUES ($1,$2,$3,$4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25)", + resultBlock.BlockID.Hash, + resultBlock.BlockID.PartSetHeader.Hash, + resultBlock.BlockID.PartSetHeader.Total, + resultBlock.Block.Header.Height, + resultBlock.Block.Header.Version.Block, + resultBlock.Block.Header.Version.App, + resultBlock.Block.Header.Time, + resultBlock.Block.Header.ChainID, + resultBlock.Block.Header.LastCommitHash, + resultBlock.Block.Header.DataHash, + resultBlock.Block.Header.ValidatorsHash, + resultBlock.Block.Header.NextValidatorsHash, + resultBlock.Block.Header.ConsensusHash, + resultBlock.Block.Header.AppHash, + resultBlock.Block.Header.LastResultsHash, + resultBlock.Block.Header.EvidenceHash, + resultBlock.Block.Header.ProposerAddress, + resultBlock.Block.LastBlockID.Hash, + resultBlock.Block.LastBlockID.PartSetHeader.Hash, + resultBlock.Block.LastBlockID.PartSetHeader.Total, + resultBlock.Block.LastCommit.Height, + resultBlock.Block.LastCommit.Round, + resultBlock.Block.LastCommit.BlockID.Hash, + resultBlock.Block.LastCommit.BlockID.PartSetHeader.Total, + resultBlock.Block.LastCommit.BlockID.PartSetHeader.Hash) + + // Insert transactions if they exist + for _, tx := range resultBlock.Block.Data.Txs { + _, err := c.InsertTransaction(resultBlock.Block.Header.Height, tx) + if err != nil { + return false, err + } + } + + // Insert last commit signatures + for _, signature := range resultBlock.Block.LastCommit.Signatures { + _, err := c.InsertCommitSignature(resultBlock.Block.LastCommit.Height, signature) + if err != nil { + return false, err + } + } + + // Insert evidences + for _, evidence := range resultBlock.Block.Evidence.Evidence { + switch ev := evidence.(type) { + case *types.DuplicateVoteEvidence: + var dve *types.DuplicateVoteEvidence + dve = ev + _, err = c.InsertDuplicateVoteEvidence(resultBlock.Block.Header.Height, dve) + if err != nil { + return false, err + } + case *types.LightClientAttackEvidence: + var lae *types.LightClientAttackEvidence + lae = ev + _, err = c.InsertLightClientAttackEvidence(resultBlock.Block.Header.Height, lae) + if err != nil { + return false, err + } + default: + fmt.Printf("Evidence type not supported") + } + } + + if err != nil { + return false, err + } else { + return true, nil + } +} + +func (c *PostgresStorage) InsertTransaction(height int64, tx types.Tx) (bool, error) { + _, err := c.Connection.Exec("INSERT INTO comet.block_data (height, transaction) values ($1,$2)", + height, + tx) + if err != nil { + return false, err + } else { + return true, nil + } +} + +func (c *PostgresStorage) InsertDuplicateVoteEvidence(height int64, evidence *types.DuplicateVoteEvidence) (bool, error) { + + //TODO: Find how to get the evidence type property e.g. 'tendermint/DuplicateVoteEvidence' + + _, err := c.Connection.Exec("INSERT INTO comet.evidence_duplicate_vote ("+ + "height, "+ + "evidence_type, "+ + "vote_a_type, "+ + "vote_a_height, "+ + "vote_a_round, "+ + "vote_a_block_id_hash, "+ + "vote_a_block_id_parts_hash, "+ + "vote_a_block_id_parts_total, "+ + "vote_a_timestamp, "+ + "vote_a_validator_address, "+ + "vote_a_validator_index, "+ + "vote_a_signature, "+ + "vote_b_type, "+ + "vote_b_height, "+ + "vote_b_round, "+ + "vote_b_block_id_hash, "+ + "vote_b_block_id_parts_hash, "+ + "vote_b_block_id_parts_total, "+ + "vote_b_timestamp, "+ + "vote_b_validator_address, "+ + "vote_b_validator_index, "+ + "vote_b_signature, "+ + "total_voting_power, "+ + "validator_voting_power, "+ + "evidence_timestamp) "+ + "VALUES ($1,$2,$3,$4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25)", + height, + "tendermint/DuplicateVoteEvidence", + evidence.VoteA.Type, + evidence.VoteA.Height, + evidence.VoteA.Round, + evidence.VoteA.BlockID.Hash, + evidence.VoteA.BlockID.PartSetHeader.Hash, + evidence.VoteA.BlockID.PartSetHeader.Total, + evidence.VoteA.Timestamp, + evidence.VoteA.ValidatorAddress, + evidence.VoteA.ValidatorIndex, + evidence.VoteA.Signature, + evidence.VoteB.Type, + evidence.VoteB.Height, + evidence.VoteB.Round, + evidence.VoteB.BlockID.Hash, + evidence.VoteB.BlockID.PartSetHeader.Hash, + evidence.VoteB.BlockID.PartSetHeader.Total, + evidence.VoteB.Timestamp, + evidence.VoteB.ValidatorAddress, + evidence.VoteB.ValidatorIndex, + evidence.VoteB.Signature, + evidence.TotalVotingPower, + evidence.ValidatorPower, + evidence.Timestamp) + if err != nil { + return false, err + } else { + return true, nil + } +} + +func (c *PostgresStorage) InsertLightClientAttackEvidence(height int64, evidence *types.LightClientAttackEvidence) (bool, error) { + + //TODO: Find how to get the evidence type property e.g. 'tendermint/LightClientAttackEvidence' + _, err := c.Connection.Exec("INSERT INTO comet.evidence_light_client_attack ("+ + "height, "+ + "evidence_type, "+ + "common_height, "+ + "total_voting_power, "+ + "timestamp) "+ + "VALUES ($1,$2,$3, $4, $5)", + height, + "tendermint/LightClientAttackEvidence", + evidence.CommonHeight, + evidence.TotalVotingPower, + evidence.Timestamp) + if err != nil { + return false, err + } else { + return true, nil + } +} + +func (c *PostgresStorage) InsertCommitSignature(height int64, commitSig types.CommitSig) (bool, error) { + _, err := c.Connection.Exec("INSERT INTO comet.block_commit_sig (height, block_id_flag, validator_address, timestamp, signature) values ($1,$2,$3,$4,$5)", + height, + commitSig.BlockIDFlag, + commitSig.ValidatorAddress, + commitSig.Timestamp, + commitSig.Signature) + if err != nil { + return false, err + } else { + return true, nil + } +} + +func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { + resultBlock := ctypes.ResultBlock{} + lastCommit := types.Commit{} + bId := types.BlockID{} + b := new(types.Block) + + row := c.Connection.QueryRow("SELECT "+ + "block_id_hash, "+ + "block_id_parts_hash, "+ + "block_id_parts_total, "+ + "block_header_height, "+ + "block_header_chain_id, "+ + "block_header_block_time, "+ + "block_header_version_block, "+ + "block_header_version_app, "+ + "block_header_last_commit_hash, "+ + "block_header_data_hash, "+ + "block_header_validators_hash, "+ + "block_header_next_validators_hash, "+ + "block_header_consensus_hash, "+ + "block_header_app_hash, "+ + "block_header_last_results_hash, "+ + "block_header_evidence_hash, "+ + "block_header_proposer_address, "+ + "block_header_last_block_id_hash, "+ + "block_header_last_block_id_part_total, "+ + "block_header_last_block_id_parts_hash, "+ + "block_last_commit_height, "+ + "block_last_commit_round, "+ + "block_last_commit_block_id_hash, "+ + "block_last_commit_block_id_parts_total, "+ + "block_last_commit_block_id_parts_hash "+ + "FROM comet.block_result WHERE block_header_height=$1", height) + err := row.Scan( + &bId.Hash, + &bId.PartSetHeader.Hash, + &bId.PartSetHeader.Total, + &b.Header.Height, + &b.Header.ChainID, + &b.Header.Time, + &b.Header.Version.Block, + &b.Header.Version.App, + &b.Header.LastCommitHash, + &b.Header.DataHash, + &b.Header.ValidatorsHash, + &b.Header.NextValidatorsHash, + &b.Header.ConsensusHash, + &b.Header.AppHash, + &b.Header.LastResultsHash, + &b.Header.EvidenceHash, + &b.Header.ProposerAddress, + &b.LastBlockID.Hash, + &b.LastBlockID.PartSetHeader.Total, + &b.LastBlockID.PartSetHeader.Hash, + &lastCommit.Height, // *Commit + &lastCommit.Round, + &lastCommit.BlockID.Hash, + &lastCommit.BlockID.PartSetHeader.Total, + &lastCommit.BlockID.PartSetHeader.Hash) + if err != nil { + return resultBlock, err + } + b.LastCommit = &lastCommit + resultBlock.BlockID = bId + resultBlock.Block = b + + // Retrieve transactions if any + var txBytes []byte + txs, err := c.Connection.Query("SELECT transaction FROM comet.block_data WHERE height=$1", height) + if err != nil { + return resultBlock, err + } + defer txs.Close() + for txs.Next() { + err := txs.Scan(&txBytes) + if err != nil { + return resultBlock, err + } else { + resultBlock.Block.Data.Txs = append(resultBlock.Block.Data.Txs, txBytes) + } + } + + // Retrieve commit signatures + var signature types.CommitSig + signatures, err := c.Connection.Query("SELECT block_id_flag, validator_address, timestamp, signature FROM comet.block_commit_sig WHERE height=$1", resultBlock.Block.LastCommit.Height) + if err != nil { + return resultBlock, err + } + defer signatures.Close() + for signatures.Next() { + err := signatures.Scan(&signature.BlockIDFlag, &signature.ValidatorAddress, &signature.Timestamp, &signature.Signature) + if err != nil { + return resultBlock, err + } else { + resultBlock.Block.LastCommit.Signatures = append(resultBlock.Block.LastCommit.Signatures, signature) + } + } + + // Retrieve duplicate vote evidences + dve := types.DuplicateVoteEvidence{} + dves, err := c.Connection.Query("SELECT "+ + "vote_a_type, "+ + "vote_a_height, "+ + "vote_a_round, "+ + "vote_a_block_id_hash, "+ + "vote_a_block_id_parts_hash, "+ + "vote_a_block_id_parts_total, "+ + "vote_a_timestamp, "+ + "vote_a_validator_address, "+ + "vote_a_validator_index, "+ + "vote_a_signature, "+ + "vote_b_type, "+ + "vote_b_height, "+ + "vote_b_round, "+ + "vote_b_block_id_hash, "+ + "vote_b_block_id_parts_hash, "+ + "vote_b_block_id_parts_total, "+ + "vote_b_timestamp, "+ + "vote_b_validator_address, "+ + "vote_b_validator_index, "+ + "vote_b_signature, "+ + "total_voting_power, "+ + "validator_voting_power, "+ + "evidence_timestamp "+ + "FROM comet.evidence_duplicate_vote "+ + "WHERE height=$1", height) + if err != nil { + return resultBlock, err + } + defer dves.Close() + for dves.Next() { + voteA := types.Vote{} + voteB := types.Vote{} + err := dves.Scan( + &voteA.Type, + &voteA.Height, + &voteA.Round, + &voteA.BlockID.Hash, + &voteA.BlockID.PartSetHeader.Hash, + &voteA.BlockID.PartSetHeader.Total, + &voteA.Timestamp, + &voteA.ValidatorAddress, + &voteA.ValidatorIndex, + &voteA.Signature, + &voteB.Type, + &voteB.Height, + &voteB.Round, + &voteB.BlockID.Hash, + &voteB.BlockID.PartSetHeader.Hash, + &voteB.BlockID.PartSetHeader.Total, + &voteB.Timestamp, + &voteB.ValidatorAddress, + &voteB.ValidatorIndex, + &voteB.Signature, + &dve.TotalVotingPower, + &dve.ValidatorPower, + &dve.Timestamp) + if err != nil { + return resultBlock, err + } else { + dve.VoteA = &voteA + dve.VoteB = &voteB + resultBlock.Block.Evidence.Evidence = append(resultBlock.Block.Evidence.Evidence, &dve) + } + } + + // Retrieve light client attack evidences + lcaev := types.LightClientAttackEvidence{} + lcaevs, err := c.Connection.Query("SELECT "+ + "common_height, "+ + "total_voting_power, "+ + "timestamp "+ + "FROM comet.evidence_light_client_attack "+ + "WHERE height=$1", height) + if err != nil { + return resultBlock, err + } + defer lcaevs.Close() + for lcaevs.Next() { + err := lcaevs.Scan( + &lcaev.CommonHeight, + &lcaev.TotalVotingPower, + &lcaev.Timestamp) + if err != nil { + return resultBlock, err + } else { + resultBlock.Block.Evidence.Evidence = append(resultBlock.Block.Evidence.Evidence, &lcaev) + } + } + + return resultBlock, err +} + +func (c *PostgresStorage) Connect() error { + db, err := sql.Open("postgres", c.ConnectionString) + if err != nil { + return err + } else { + c.Connection = db + } + + db.SetMaxOpenConns(100) + db.SetMaxIdleConns(50) + + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + err = db.PingContext(ctx) + if err != nil { + return err + } + + return nil +} + +func insert() { + + // Database storage + storage := PostgresStorage{ + ConnectionString: connString, + Connection: nil, + } + + // Connect to the database + err := storage.Connect() + if err != nil { + panic(err) + } + + // Insert some blocks + InsertBlocks(storage) + + defer func(ps PostgresStorage) { + err := ps.Connection.Close() + if err != nil { + log.Fatalln(err) + } + }(storage) + + // REST server + service := RESTService{ + Version: "v1", + } + service.Serve(&storage) +} + +func InsertBlocks(storage PostgresStorage) { + + // Ingest server + fetcher := CometFetcher{ + Endpoint: os.Getenv("COMPANION_NODE_RPC"), + } + + numberHeights := int64(5) + initialHeightParameter := os.Getenv("COMPANION_INITIAL_HEIGHT") + initialHeight, err := strconv.ParseInt(initialHeightParameter, 10, 64) + if err != nil { + fmt.Printf("Invalid initial height %s: %s\n", initialHeightParameter, err) + } + + for height := initialHeight; height <= initialHeight+numberHeights; height++ { + + blockFetched, err := fetcher.FetchBlock(int64(height)) + if err != nil { + log.Fatalf("Error fetching block at height %d: %s\n", height, err) + } + + inserted, err := storage.InsertBlock(*blockFetched) + if err != nil { + fmt.Printf("Error inserting block at height %d: %s\n", height, err) + } + if inserted { + fmt.Printf("Inserted height %d\n", height) + } + } +} diff --git a/main.go b/main.go index f140f28..9144017 100644 --- a/main.go +++ b/main.go @@ -1,624 +1,9 @@ package main import ( - "context" - "database/sql" - "fmt" - "github.com/cometbft/cometbft/libs/json" - client "github.com/cometbft/cometbft/rpc/client/http" - ctypes "github.com/cometbft/cometbft/rpc/core/types" - "github.com/cometbft/cometbft/types" - _ "github.com/lib/pq" - "log" - "net/http" - "os" - "strconv" - "time" + "github.com/cometbft/rpc-companion/commands" ) -const connString = "postgres://postgres:postgres@0.0.0.0:15432/postgres?sslmode=disable" - -type Storage interface { - Insert(table string, value string) (bool, error) - Get(table string, query string) ([]byte, error) - Connect(conn string) error -} - -type Fetcher interface { - FetchBlock(height int64) (*ctypes.ResultBlock, error) - FetchABCIInfo() (*ctypes.ResultABCIInfo, error) -} - -type Service interface { - Serve() -} - -type IngestService struct { - Fetcher Fetcher - Storage Storage -} - -type CometFetcher struct { - Endpoint string -} - -type PostgresStorage struct { - ConnectionString string - Connection *sql.DB -} - -type RESTService struct { - Version string -} - -func (s *RESTService) Serve(storage *PostgresStorage) { - // Handler for the block endpoint - http.HandleFunc(fmt.Sprintf("/%s/block", s.Version), handleBlock) - - // Start the service - err := http.ListenAndServe(":8080", nil) - if err != nil { - log.Fatalln("There's an error starting the REST service:", err) - } else { - log.Println("Started REST service...") - } -} - -// Handles the '/v1/block' endpoint -func handleBlock(writer http.ResponseWriter, request *http.Request) { - - // Database connection - storage := PostgresStorage{ - ConnectionString: connString, - Connection: nil, - } - - // Connect to the database - err := storage.Connect() - if err != nil { - log.Println("Error connecting to storage in handleBlock: ", err) - writer.WriteHeader(http.StatusInternalServerError) - writer.Write([]byte("Internal Server Error")) - } - - writer.Header().Set("Content-Type", "application/json") - - if request.Method == "GET" { - h := request.URL.Query()["height"][0] - height, err := strconv.ParseInt(h, 10, 64) - if err != nil { - writer.WriteHeader(http.StatusBadRequest) - writer.Write([]byte("Bad Request. Invalid height")) - } - fmt.Printf("Block Request. Height: %v\n", height) - block, err := storage.GetBlock(height) - if err != nil { - // TODO: If not records retrieved return a different status - log.Println("Error retrieving record from storage in handleBlock: ", err) - writer.WriteHeader(http.StatusInternalServerError) - writer.Write([]byte("Internal Server Error")) - } - resp, _ := json.Marshal(block) - writer.Write(resp) - } else { - writer.WriteHeader(http.StatusBadRequest) - writer.Write([]byte("Bad Request")) - } -} - -func (c *CometFetcher) FetchBlock(height int64) (*ctypes.ResultBlock, error) { - - httpClient, err := client.New(c.Endpoint, "/websocket") - if err != nil { - return nil, err - } - - resultBlock, err := httpClient.Block(context.Background(), &height) - if err != nil { - return nil, err - } else { - return resultBlock, nil - } -} - -func (c *CometFetcher) FetchABCIInfo() (*ctypes.ResultABCIInfo, error) { - - httpClient, err := client.New(c.Endpoint, "/websocket") - if err != nil { - return nil, err - } - - abciInfo, err := httpClient.ABCIInfo(context.Background()) - if err != nil { - return nil, err - } else { - return abciInfo, nil - } -} - -func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, error) { - _, err := c.Connection.Exec( - "INSERT INTO comet.block_result"+ - "(block_id_hash, "+ - "block_id_parts_hash, "+ - "block_id_parts_total, "+ - "block_header_height, "+ - "block_header_version_block, "+ - "block_header_version_app, "+ - "block_header_block_time, "+ - "block_header_chain_id, "+ - "block_header_last_commit_hash, "+ - "block_header_data_hash, "+ - "block_header_validators_hash, "+ - "block_header_next_validators_hash, "+ - "block_header_consensus_hash, "+ - "block_header_app_hash, "+ - "block_header_last_results_hash, "+ - "block_header_evidence_hash, "+ - "block_header_proposer_address, "+ - "block_header_last_block_id_hash, "+ - "block_header_last_block_id_parts_hash, "+ - "block_header_last_block_id_part_total, "+ - "block_last_commit_height, "+ - "block_last_commit_round, "+ - "block_last_commit_block_id_hash, "+ - "block_last_commit_block_id_parts_total, "+ - "block_last_commit_block_id_parts_hash) "+ - "VALUES ($1,$2,$3,$4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25)", - resultBlock.BlockID.Hash, - resultBlock.BlockID.PartSetHeader.Hash, - resultBlock.BlockID.PartSetHeader.Total, - resultBlock.Block.Header.Height, - resultBlock.Block.Header.Version.Block, - resultBlock.Block.Header.Version.App, - resultBlock.Block.Header.Time, - resultBlock.Block.Header.ChainID, - resultBlock.Block.Header.LastCommitHash, - resultBlock.Block.Header.DataHash, - resultBlock.Block.Header.ValidatorsHash, - resultBlock.Block.Header.NextValidatorsHash, - resultBlock.Block.Header.ConsensusHash, - resultBlock.Block.Header.AppHash, - resultBlock.Block.Header.LastResultsHash, - resultBlock.Block.Header.EvidenceHash, - resultBlock.Block.Header.ProposerAddress, - resultBlock.Block.LastBlockID.Hash, - resultBlock.Block.LastBlockID.PartSetHeader.Hash, - resultBlock.Block.LastBlockID.PartSetHeader.Total, - resultBlock.Block.LastCommit.Height, - resultBlock.Block.LastCommit.Round, - resultBlock.Block.LastCommit.BlockID.Hash, - resultBlock.Block.LastCommit.BlockID.PartSetHeader.Total, - resultBlock.Block.LastCommit.BlockID.PartSetHeader.Hash) - - // Insert transactions if they exist - for _, tx := range resultBlock.Block.Data.Txs { - _, err := c.InsertTransaction(resultBlock.Block.Header.Height, tx) - if err != nil { - return false, err - } - } - - // Insert last commit signatures - for _, signature := range resultBlock.Block.LastCommit.Signatures { - _, err := c.InsertCommitSignature(resultBlock.Block.LastCommit.Height, signature) - if err != nil { - return false, err - } - } - - // Insert evidences - for _, evidence := range resultBlock.Block.Evidence.Evidence { - switch ev := evidence.(type) { - case *types.DuplicateVoteEvidence: - var dve *types.DuplicateVoteEvidence - dve = ev - _, err = c.InsertDuplicateVoteEvidence(resultBlock.Block.Header.Height, dve) - if err != nil { - return false, err - } - case *types.LightClientAttackEvidence: - var lae *types.LightClientAttackEvidence - lae = ev - _, err = c.InsertLightClientAttackEvidence(resultBlock.Block.Header.Height, lae) - if err != nil { - return false, err - } - default: - fmt.Printf("Evidence type not supported") - } - } - - if err != nil { - return false, err - } else { - return true, nil - } -} - -func (c *PostgresStorage) InsertTransaction(height int64, tx types.Tx) (bool, error) { - _, err := c.Connection.Exec("INSERT INTO comet.block_data (height, transaction) values ($1,$2)", - height, - tx) - if err != nil { - return false, err - } else { - return true, nil - } -} - -func (c *PostgresStorage) InsertDuplicateVoteEvidence(height int64, evidence *types.DuplicateVoteEvidence) (bool, error) { - - //TODO: Find how to get the evidence type property e.g. 'tendermint/DuplicateVoteEvidence' - - _, err := c.Connection.Exec("INSERT INTO comet.evidence_duplicate_vote ("+ - "height, "+ - "evidence_type, "+ - "vote_a_type, "+ - "vote_a_height, "+ - "vote_a_round, "+ - "vote_a_block_id_hash, "+ - "vote_a_block_id_parts_hash, "+ - "vote_a_block_id_parts_total, "+ - "vote_a_timestamp, "+ - "vote_a_validator_address, "+ - "vote_a_validator_index, "+ - "vote_a_signature, "+ - "vote_b_type, "+ - "vote_b_height, "+ - "vote_b_round, "+ - "vote_b_block_id_hash, "+ - "vote_b_block_id_parts_hash, "+ - "vote_b_block_id_parts_total, "+ - "vote_b_timestamp, "+ - "vote_b_validator_address, "+ - "vote_b_validator_index, "+ - "vote_b_signature, "+ - "total_voting_power, "+ - "validator_voting_power, "+ - "evidence_timestamp) "+ - "VALUES ($1,$2,$3,$4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25)", - height, - "tendermint/DuplicateVoteEvidence", - evidence.VoteA.Type, - evidence.VoteA.Height, - evidence.VoteA.Round, - evidence.VoteA.BlockID.Hash, - evidence.VoteA.BlockID.PartSetHeader.Hash, - evidence.VoteA.BlockID.PartSetHeader.Total, - evidence.VoteA.Timestamp, - evidence.VoteA.ValidatorAddress, - evidence.VoteA.ValidatorIndex, - evidence.VoteA.Signature, - evidence.VoteB.Type, - evidence.VoteB.Height, - evidence.VoteB.Round, - evidence.VoteB.BlockID.Hash, - evidence.VoteB.BlockID.PartSetHeader.Hash, - evidence.VoteB.BlockID.PartSetHeader.Total, - evidence.VoteB.Timestamp, - evidence.VoteB.ValidatorAddress, - evidence.VoteB.ValidatorIndex, - evidence.VoteB.Signature, - evidence.TotalVotingPower, - evidence.ValidatorPower, - evidence.Timestamp) - if err != nil { - return false, err - } else { - return true, nil - } -} - -func (c *PostgresStorage) InsertLightClientAttackEvidence(height int64, evidence *types.LightClientAttackEvidence) (bool, error) { - - //TODO: Find how to get the evidence type property e.g. 'tendermint/LightClientAttackEvidence' - _, err := c.Connection.Exec("INSERT INTO comet.evidence_light_client_attack ("+ - "height, "+ - "evidence_type, "+ - "common_height, "+ - "total_voting_power, "+ - "timestamp) "+ - "VALUES ($1,$2,$3, $4, $5)", - height, - "tendermint/LightClientAttackEvidence", - evidence.CommonHeight, - evidence.TotalVotingPower, - evidence.Timestamp) - if err != nil { - return false, err - } else { - return true, nil - } -} - -func (c *PostgresStorage) InsertCommitSignature(height int64, commitSig types.CommitSig) (bool, error) { - _, err := c.Connection.Exec("INSERT INTO comet.block_commit_sig (height, block_id_flag, validator_address, timestamp, signature) values ($1,$2,$3,$4,$5)", - height, - commitSig.BlockIDFlag, - commitSig.ValidatorAddress, - commitSig.Timestamp, - commitSig.Signature) - if err != nil { - return false, err - } else { - return true, nil - } -} - -func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { - resultBlock := ctypes.ResultBlock{} - lastCommit := types.Commit{} - bId := types.BlockID{} - b := new(types.Block) - - row := c.Connection.QueryRow("SELECT "+ - "block_id_hash, "+ - "block_id_parts_hash, "+ - "block_id_parts_total, "+ - "block_header_height, "+ - "block_header_chain_id, "+ - "block_header_block_time, "+ - "block_header_version_block, "+ - "block_header_version_app, "+ - "block_header_last_commit_hash, "+ - "block_header_data_hash, "+ - "block_header_validators_hash, "+ - "block_header_next_validators_hash, "+ - "block_header_consensus_hash, "+ - "block_header_app_hash, "+ - "block_header_last_results_hash, "+ - "block_header_evidence_hash, "+ - "block_header_proposer_address, "+ - "block_header_last_block_id_hash, "+ - "block_header_last_block_id_part_total, "+ - "block_header_last_block_id_parts_hash, "+ - "block_last_commit_height, "+ - "block_last_commit_round, "+ - "block_last_commit_block_id_hash, "+ - "block_last_commit_block_id_parts_total, "+ - "block_last_commit_block_id_parts_hash "+ - "FROM comet.block_result WHERE block_header_height=$1", height) - err := row.Scan( - &bId.Hash, - &bId.PartSetHeader.Hash, - &bId.PartSetHeader.Total, - &b.Header.Height, - &b.Header.ChainID, - &b.Header.Time, - &b.Header.Version.Block, - &b.Header.Version.App, - &b.Header.LastCommitHash, - &b.Header.DataHash, - &b.Header.ValidatorsHash, - &b.Header.NextValidatorsHash, - &b.Header.ConsensusHash, - &b.Header.AppHash, - &b.Header.LastResultsHash, - &b.Header.EvidenceHash, - &b.Header.ProposerAddress, - &b.LastBlockID.Hash, - &b.LastBlockID.PartSetHeader.Total, - &b.LastBlockID.PartSetHeader.Hash, - &lastCommit.Height, // *Commit - &lastCommit.Round, - &lastCommit.BlockID.Hash, - &lastCommit.BlockID.PartSetHeader.Total, - &lastCommit.BlockID.PartSetHeader.Hash) - if err != nil { - return resultBlock, err - } - b.LastCommit = &lastCommit - resultBlock.BlockID = bId - resultBlock.Block = b - - // Retrieve transactions if any - var txBytes []byte - txs, err := c.Connection.Query("SELECT transaction FROM comet.block_data WHERE height=$1", height) - if err != nil { - return resultBlock, err - } - defer txs.Close() - for txs.Next() { - err := txs.Scan(&txBytes) - if err != nil { - return resultBlock, err - } else { - resultBlock.Block.Data.Txs = append(resultBlock.Block.Data.Txs, txBytes) - } - } - - // Retrieve commit signatures - var signature types.CommitSig - signatures, err := c.Connection.Query("SELECT block_id_flag, validator_address, timestamp, signature FROM comet.block_commit_sig WHERE height=$1", resultBlock.Block.LastCommit.Height) - if err != nil { - return resultBlock, err - } - defer signatures.Close() - for signatures.Next() { - err := signatures.Scan(&signature.BlockIDFlag, &signature.ValidatorAddress, &signature.Timestamp, &signature.Signature) - if err != nil { - return resultBlock, err - } else { - resultBlock.Block.LastCommit.Signatures = append(resultBlock.Block.LastCommit.Signatures, signature) - } - } - - // Retrieve duplicate vote evidences - dve := types.DuplicateVoteEvidence{} - dves, err := c.Connection.Query("SELECT "+ - "vote_a_type, "+ - "vote_a_height, "+ - "vote_a_round, "+ - "vote_a_block_id_hash, "+ - "vote_a_block_id_parts_hash, "+ - "vote_a_block_id_parts_total, "+ - "vote_a_timestamp, "+ - "vote_a_validator_address, "+ - "vote_a_validator_index, "+ - "vote_a_signature, "+ - "vote_b_type, "+ - "vote_b_height, "+ - "vote_b_round, "+ - "vote_b_block_id_hash, "+ - "vote_b_block_id_parts_hash, "+ - "vote_b_block_id_parts_total, "+ - "vote_b_timestamp, "+ - "vote_b_validator_address, "+ - "vote_b_validator_index, "+ - "vote_b_signature, "+ - "total_voting_power, "+ - "validator_voting_power, "+ - "evidence_timestamp "+ - "FROM comet.evidence_duplicate_vote "+ - "WHERE height=$1", height) - if err != nil { - return resultBlock, err - } - defer dves.Close() - for dves.Next() { - voteA := types.Vote{} - voteB := types.Vote{} - err := dves.Scan( - &voteA.Type, - &voteA.Height, - &voteA.Round, - &voteA.BlockID.Hash, - &voteA.BlockID.PartSetHeader.Hash, - &voteA.BlockID.PartSetHeader.Total, - &voteA.Timestamp, - &voteA.ValidatorAddress, - &voteA.ValidatorIndex, - &voteA.Signature, - &voteB.Type, - &voteB.Height, - &voteB.Round, - &voteB.BlockID.Hash, - &voteB.BlockID.PartSetHeader.Hash, - &voteB.BlockID.PartSetHeader.Total, - &voteB.Timestamp, - &voteB.ValidatorAddress, - &voteB.ValidatorIndex, - &voteB.Signature, - &dve.TotalVotingPower, - &dve.ValidatorPower, - &dve.Timestamp) - if err != nil { - return resultBlock, err - } else { - dve.VoteA = &voteA - dve.VoteB = &voteB - resultBlock.Block.Evidence.Evidence = append(resultBlock.Block.Evidence.Evidence, &dve) - } - } - - // Retrieve light client attack evidences - lcaev := types.LightClientAttackEvidence{} - lcaevs, err := c.Connection.Query("SELECT "+ - "common_height, "+ - "total_voting_power, "+ - "timestamp "+ - "FROM comet.evidence_light_client_attack "+ - "WHERE height=$1", height) - if err != nil { - return resultBlock, err - } - defer lcaevs.Close() - for lcaevs.Next() { - err := lcaevs.Scan( - &lcaev.CommonHeight, - &lcaev.TotalVotingPower, - &lcaev.Timestamp) - if err != nil { - return resultBlock, err - } else { - resultBlock.Block.Evidence.Evidence = append(resultBlock.Block.Evidence.Evidence, &lcaev) - } - } - - return resultBlock, err -} - -func (c *PostgresStorage) Connect() error { - db, err := sql.Open("postgres", c.ConnectionString) - if err != nil { - return err - } else { - c.Connection = db - } - - db.SetMaxOpenConns(100) - db.SetMaxIdleConns(50) - - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - - err = db.PingContext(ctx) - if err != nil { - return err - } - - return nil -} - func main() { - - // Database storage - storage := PostgresStorage{ - ConnectionString: connString, - Connection: nil, - } - - // Connect to the database - err := storage.Connect() - if err != nil { - panic(err) - } - - // Insert some blocks - InsertBlocks(storage) - - defer func(ps PostgresStorage) { - err := ps.Connection.Close() - if err != nil { - log.Fatalln(err) - } - }(storage) - - // REST server - service := RESTService{ - Version: "v1", - } - service.Serve(&storage) -} - -func InsertBlocks(storage PostgresStorage) { - - // Ingest server - fetcher := CometFetcher{ - Endpoint: os.Getenv("COMPANION_NODE_RPC"), - } - - numberHeights := int64(5) - initialHeightParameter := os.Getenv("COMPANION_INITIAL_HEIGHT") - initialHeight, err := strconv.ParseInt(initialHeightParameter, 10, 64) - if err != nil { - fmt.Printf("Invalid initial height %s: %s\n", initialHeightParameter, err) - } - - for height := initialHeight; height <= initialHeight+numberHeights; height++ { - - blockFetched, err := fetcher.FetchBlock(int64(height)) - if err != nil { - log.Fatalf("Error fetching block at height %d: %s\n", height, err) - } - - inserted, err := storage.InsertBlock(*blockFetched) - if err != nil { - fmt.Printf("Error inserting block at height %d: %s\n", height, err) - } - if inserted { - fmt.Printf("Inserted height %d\n", height) - } - } + commands.Execute() } From 90f78903bfc20d7b8aa7c27b91ee0a4dc49aad29 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Tue, 20 Jun 2023 14:33:10 -0400 Subject: [PATCH 38/44] refactoring logic into services, initial ingest service implementation (#1) --- commands/ingest/ingest.go | 5 +- commands/ingest/start.go | 51 ++++ ingest/fetcher.go | 10 + ingest/rpc_fetcher.go | 41 +++ ingest/service.go | 30 +++ insert.go | 522 +------------------------------------- storage/postgresql.go | 484 +++++++++++++++++++++++++++++++++++ storage/storage.go | 19 ++ 8 files changed, 641 insertions(+), 521 deletions(-) create mode 100644 commands/ingest/start.go create mode 100644 ingest/fetcher.go create mode 100644 ingest/rpc_fetcher.go create mode 100644 ingest/service.go create mode 100644 storage/postgresql.go create mode 100644 storage/storage.go diff --git a/commands/ingest/ingest.go b/commands/ingest/ingest.go index 4b62029..07c264a 100644 --- a/commands/ingest/ingest.go +++ b/commands/ingest/ingest.go @@ -8,11 +8,14 @@ import ( var IngestCmd = &cobra.Command{ Use: "ingest", Short: "Ingest Service commands", - Long: `The Ingest Service pulls data from a CometBFT full node and store the information in a database`, + Long: `The Ingest Service pulls data from a CometBFT full node and store the information in a database. + +There should be just one running instance of the Ingest Service targeting a full node.`, Run: func(cmd *cobra.Command, args []string) { cmd.Help() }, } func init() { + IngestCmd.AddCommand(StartCmd) } diff --git a/commands/ingest/start.go b/commands/ingest/start.go new file mode 100644 index 0000000..40b717f --- /dev/null +++ b/commands/ingest/start.go @@ -0,0 +1,51 @@ +package ingest + +import ( + "fmt" + "github.com/cometbft/rpc-companion/ingest" + "github.com/spf13/cobra" + "log" + "os" + "strconv" +) + +const connString = "postgres://postgres:postgres@0.0.0.0:15432/postgres?sslmode=disable" + +// StartCmd start ingest service +var StartCmd = &cobra.Command{ + Use: "start", + Short: "Start Ingest Service", + Long: `The start command runs an instance of the Ingest Service`, + Run: func(cmd *cobra.Command, args []string) { + + //Instantiate a new Ingest Service + ingestSvc := ingest.NewService(connString) + + //Insert some blocks + numberHeights := int64(5) + initialHeightParameter := os.Getenv("COMPANION_INITIAL_HEIGHT") + initialHeight, err := strconv.ParseInt(initialHeightParameter, 10, 64) + if err != nil { + fmt.Printf("Invalid initial height %s: %s\n", initialHeightParameter, err) + } + + for height := initialHeight; height <= initialHeight+numberHeights; height++ { + + blockFetched, err := ingestSvc.Fetcher.FetchBlock(int64(height)) + if err != nil { + log.Fatalf("Error fetching block at height %d: %s\n", height, err) + } + + inserted, err := ingestSvc.Storage.InsertBlock(*blockFetched) + if err != nil { + fmt.Printf("Error inserting block at height %d: %s\n", height, err) + } + if inserted { + fmt.Printf("Inserted height %d\n", height) + } + } + }, +} + +func init() { +} diff --git a/ingest/fetcher.go b/ingest/fetcher.go new file mode 100644 index 0000000..df10182 --- /dev/null +++ b/ingest/fetcher.go @@ -0,0 +1,10 @@ +package ingest + +import ( + ctypes "github.com/cometbft/cometbft/rpc/core/types" +) + +type Fetcher interface { + FetchBlock(height int64) (*ctypes.ResultBlock, error) + FetchABCIInfo() (*ctypes.ResultABCIInfo, error) +} diff --git a/ingest/rpc_fetcher.go b/ingest/rpc_fetcher.go new file mode 100644 index 0000000..515b59d --- /dev/null +++ b/ingest/rpc_fetcher.go @@ -0,0 +1,41 @@ +package ingest + +import ( + "context" + client "github.com/cometbft/cometbft/rpc/client/http" + ctypes "github.com/cometbft/cometbft/rpc/core/types" +) + +type RPCFetcher struct { + Endpoint string +} + +func (c *RPCFetcher) FetchBlock(height int64) (*ctypes.ResultBlock, error) { + + httpClient, err := client.New(c.Endpoint, "/websocket") + if err != nil { + return nil, err + } + + resultBlock, err := httpClient.Block(context.Background(), &height) + if err != nil { + return nil, err + } else { + return resultBlock, nil + } +} + +func (c *RPCFetcher) FetchABCIInfo() (*ctypes.ResultABCIInfo, error) { + + httpClient, err := client.New(c.Endpoint, "/websocket") + if err != nil { + return nil, err + } + + abciInfo, err := httpClient.ABCIInfo(context.Background()) + if err != nil { + return nil, err + } else { + return abciInfo, nil + } +} diff --git a/ingest/service.go b/ingest/service.go new file mode 100644 index 0000000..a887e88 --- /dev/null +++ b/ingest/service.go @@ -0,0 +1,30 @@ +package ingest + +import ( + storage "github.com/cometbft/rpc-companion/storage" + "os" +) + +type Service struct { + Fetcher Fetcher + Storage storage.IStorage +} + +func NewService(connStr string) Service { + + // Database + db := storage.PostgresStorage{ + ConnectionString: connStr, + } + + // RPC Fetcher + fetcher := RPCFetcher{ + Endpoint: os.Getenv("COMPANION_NODE_RPC"), + } + + // Return an Ingest Service + return Service{ + Fetcher: &fetcher, + Storage: &db, + } +} diff --git a/insert.go b/insert.go index 90c4f67..4250260 100644 --- a/insert.go +++ b/insert.go @@ -1,52 +1,19 @@ package main +/* import ( - "context" - "database/sql" "fmt" "github.com/cometbft/cometbft/libs/json" - client "github.com/cometbft/cometbft/rpc/client/http" - ctypes "github.com/cometbft/cometbft/rpc/core/types" - "github.com/cometbft/cometbft/types" _ "github.com/lib/pq" "log" "net/http" - "os" "strconv" - "time" ) -const connString = "postgres://postgres:postgres@0.0.0.0:15432/postgres?sslmode=disable" - -type Storage interface { - Insert(table string, value string) (bool, error) - Get(table string, query string) ([]byte, error) - Connect(conn string) error -} - -type Fetcher interface { - FetchBlock(height int64) (*ctypes.ResultBlock, error) - FetchABCIInfo() (*ctypes.ResultABCIInfo, error) -} - type Service interface { Serve() } -type IngestService struct { - Fetcher Fetcher - Storage Storage -} - -type CometFetcher struct { - Endpoint string -} - -type PostgresStorage struct { - ConnectionString string - Connection *sql.DB -} - type RESTService struct { Version string } @@ -106,461 +73,6 @@ func handleBlock(writer http.ResponseWriter, request *http.Request) { } } -func (c *CometFetcher) FetchBlock(height int64) (*ctypes.ResultBlock, error) { - - httpClient, err := client.New(c.Endpoint, "/websocket") - if err != nil { - return nil, err - } - - resultBlock, err := httpClient.Block(context.Background(), &height) - if err != nil { - return nil, err - } else { - return resultBlock, nil - } -} - -func (c *CometFetcher) FetchABCIInfo() (*ctypes.ResultABCIInfo, error) { - - httpClient, err := client.New(c.Endpoint, "/websocket") - if err != nil { - return nil, err - } - - abciInfo, err := httpClient.ABCIInfo(context.Background()) - if err != nil { - return nil, err - } else { - return abciInfo, nil - } -} - -func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, error) { - _, err := c.Connection.Exec( - "INSERT INTO comet.block_result"+ - "(block_id_hash, "+ - "block_id_parts_hash, "+ - "block_id_parts_total, "+ - "block_header_height, "+ - "block_header_version_block, "+ - "block_header_version_app, "+ - "block_header_block_time, "+ - "block_header_chain_id, "+ - "block_header_last_commit_hash, "+ - "block_header_data_hash, "+ - "block_header_validators_hash, "+ - "block_header_next_validators_hash, "+ - "block_header_consensus_hash, "+ - "block_header_app_hash, "+ - "block_header_last_results_hash, "+ - "block_header_evidence_hash, "+ - "block_header_proposer_address, "+ - "block_header_last_block_id_hash, "+ - "block_header_last_block_id_parts_hash, "+ - "block_header_last_block_id_part_total, "+ - "block_last_commit_height, "+ - "block_last_commit_round, "+ - "block_last_commit_block_id_hash, "+ - "block_last_commit_block_id_parts_total, "+ - "block_last_commit_block_id_parts_hash) "+ - "VALUES ($1,$2,$3,$4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25)", - resultBlock.BlockID.Hash, - resultBlock.BlockID.PartSetHeader.Hash, - resultBlock.BlockID.PartSetHeader.Total, - resultBlock.Block.Header.Height, - resultBlock.Block.Header.Version.Block, - resultBlock.Block.Header.Version.App, - resultBlock.Block.Header.Time, - resultBlock.Block.Header.ChainID, - resultBlock.Block.Header.LastCommitHash, - resultBlock.Block.Header.DataHash, - resultBlock.Block.Header.ValidatorsHash, - resultBlock.Block.Header.NextValidatorsHash, - resultBlock.Block.Header.ConsensusHash, - resultBlock.Block.Header.AppHash, - resultBlock.Block.Header.LastResultsHash, - resultBlock.Block.Header.EvidenceHash, - resultBlock.Block.Header.ProposerAddress, - resultBlock.Block.LastBlockID.Hash, - resultBlock.Block.LastBlockID.PartSetHeader.Hash, - resultBlock.Block.LastBlockID.PartSetHeader.Total, - resultBlock.Block.LastCommit.Height, - resultBlock.Block.LastCommit.Round, - resultBlock.Block.LastCommit.BlockID.Hash, - resultBlock.Block.LastCommit.BlockID.PartSetHeader.Total, - resultBlock.Block.LastCommit.BlockID.PartSetHeader.Hash) - - // Insert transactions if they exist - for _, tx := range resultBlock.Block.Data.Txs { - _, err := c.InsertTransaction(resultBlock.Block.Header.Height, tx) - if err != nil { - return false, err - } - } - - // Insert last commit signatures - for _, signature := range resultBlock.Block.LastCommit.Signatures { - _, err := c.InsertCommitSignature(resultBlock.Block.LastCommit.Height, signature) - if err != nil { - return false, err - } - } - - // Insert evidences - for _, evidence := range resultBlock.Block.Evidence.Evidence { - switch ev := evidence.(type) { - case *types.DuplicateVoteEvidence: - var dve *types.DuplicateVoteEvidence - dve = ev - _, err = c.InsertDuplicateVoteEvidence(resultBlock.Block.Header.Height, dve) - if err != nil { - return false, err - } - case *types.LightClientAttackEvidence: - var lae *types.LightClientAttackEvidence - lae = ev - _, err = c.InsertLightClientAttackEvidence(resultBlock.Block.Header.Height, lae) - if err != nil { - return false, err - } - default: - fmt.Printf("Evidence type not supported") - } - } - - if err != nil { - return false, err - } else { - return true, nil - } -} - -func (c *PostgresStorage) InsertTransaction(height int64, tx types.Tx) (bool, error) { - _, err := c.Connection.Exec("INSERT INTO comet.block_data (height, transaction) values ($1,$2)", - height, - tx) - if err != nil { - return false, err - } else { - return true, nil - } -} - -func (c *PostgresStorage) InsertDuplicateVoteEvidence(height int64, evidence *types.DuplicateVoteEvidence) (bool, error) { - - //TODO: Find how to get the evidence type property e.g. 'tendermint/DuplicateVoteEvidence' - - _, err := c.Connection.Exec("INSERT INTO comet.evidence_duplicate_vote ("+ - "height, "+ - "evidence_type, "+ - "vote_a_type, "+ - "vote_a_height, "+ - "vote_a_round, "+ - "vote_a_block_id_hash, "+ - "vote_a_block_id_parts_hash, "+ - "vote_a_block_id_parts_total, "+ - "vote_a_timestamp, "+ - "vote_a_validator_address, "+ - "vote_a_validator_index, "+ - "vote_a_signature, "+ - "vote_b_type, "+ - "vote_b_height, "+ - "vote_b_round, "+ - "vote_b_block_id_hash, "+ - "vote_b_block_id_parts_hash, "+ - "vote_b_block_id_parts_total, "+ - "vote_b_timestamp, "+ - "vote_b_validator_address, "+ - "vote_b_validator_index, "+ - "vote_b_signature, "+ - "total_voting_power, "+ - "validator_voting_power, "+ - "evidence_timestamp) "+ - "VALUES ($1,$2,$3,$4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25)", - height, - "tendermint/DuplicateVoteEvidence", - evidence.VoteA.Type, - evidence.VoteA.Height, - evidence.VoteA.Round, - evidence.VoteA.BlockID.Hash, - evidence.VoteA.BlockID.PartSetHeader.Hash, - evidence.VoteA.BlockID.PartSetHeader.Total, - evidence.VoteA.Timestamp, - evidence.VoteA.ValidatorAddress, - evidence.VoteA.ValidatorIndex, - evidence.VoteA.Signature, - evidence.VoteB.Type, - evidence.VoteB.Height, - evidence.VoteB.Round, - evidence.VoteB.BlockID.Hash, - evidence.VoteB.BlockID.PartSetHeader.Hash, - evidence.VoteB.BlockID.PartSetHeader.Total, - evidence.VoteB.Timestamp, - evidence.VoteB.ValidatorAddress, - evidence.VoteB.ValidatorIndex, - evidence.VoteB.Signature, - evidence.TotalVotingPower, - evidence.ValidatorPower, - evidence.Timestamp) - if err != nil { - return false, err - } else { - return true, nil - } -} - -func (c *PostgresStorage) InsertLightClientAttackEvidence(height int64, evidence *types.LightClientAttackEvidence) (bool, error) { - - //TODO: Find how to get the evidence type property e.g. 'tendermint/LightClientAttackEvidence' - _, err := c.Connection.Exec("INSERT INTO comet.evidence_light_client_attack ("+ - "height, "+ - "evidence_type, "+ - "common_height, "+ - "total_voting_power, "+ - "timestamp) "+ - "VALUES ($1,$2,$3, $4, $5)", - height, - "tendermint/LightClientAttackEvidence", - evidence.CommonHeight, - evidence.TotalVotingPower, - evidence.Timestamp) - if err != nil { - return false, err - } else { - return true, nil - } -} - -func (c *PostgresStorage) InsertCommitSignature(height int64, commitSig types.CommitSig) (bool, error) { - _, err := c.Connection.Exec("INSERT INTO comet.block_commit_sig (height, block_id_flag, validator_address, timestamp, signature) values ($1,$2,$3,$4,$5)", - height, - commitSig.BlockIDFlag, - commitSig.ValidatorAddress, - commitSig.Timestamp, - commitSig.Signature) - if err != nil { - return false, err - } else { - return true, nil - } -} - -func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { - resultBlock := ctypes.ResultBlock{} - lastCommit := types.Commit{} - bId := types.BlockID{} - b := new(types.Block) - - row := c.Connection.QueryRow("SELECT "+ - "block_id_hash, "+ - "block_id_parts_hash, "+ - "block_id_parts_total, "+ - "block_header_height, "+ - "block_header_chain_id, "+ - "block_header_block_time, "+ - "block_header_version_block, "+ - "block_header_version_app, "+ - "block_header_last_commit_hash, "+ - "block_header_data_hash, "+ - "block_header_validators_hash, "+ - "block_header_next_validators_hash, "+ - "block_header_consensus_hash, "+ - "block_header_app_hash, "+ - "block_header_last_results_hash, "+ - "block_header_evidence_hash, "+ - "block_header_proposer_address, "+ - "block_header_last_block_id_hash, "+ - "block_header_last_block_id_part_total, "+ - "block_header_last_block_id_parts_hash, "+ - "block_last_commit_height, "+ - "block_last_commit_round, "+ - "block_last_commit_block_id_hash, "+ - "block_last_commit_block_id_parts_total, "+ - "block_last_commit_block_id_parts_hash "+ - "FROM comet.block_result WHERE block_header_height=$1", height) - err := row.Scan( - &bId.Hash, - &bId.PartSetHeader.Hash, - &bId.PartSetHeader.Total, - &b.Header.Height, - &b.Header.ChainID, - &b.Header.Time, - &b.Header.Version.Block, - &b.Header.Version.App, - &b.Header.LastCommitHash, - &b.Header.DataHash, - &b.Header.ValidatorsHash, - &b.Header.NextValidatorsHash, - &b.Header.ConsensusHash, - &b.Header.AppHash, - &b.Header.LastResultsHash, - &b.Header.EvidenceHash, - &b.Header.ProposerAddress, - &b.LastBlockID.Hash, - &b.LastBlockID.PartSetHeader.Total, - &b.LastBlockID.PartSetHeader.Hash, - &lastCommit.Height, // *Commit - &lastCommit.Round, - &lastCommit.BlockID.Hash, - &lastCommit.BlockID.PartSetHeader.Total, - &lastCommit.BlockID.PartSetHeader.Hash) - if err != nil { - return resultBlock, err - } - b.LastCommit = &lastCommit - resultBlock.BlockID = bId - resultBlock.Block = b - - // Retrieve transactions if any - var txBytes []byte - txs, err := c.Connection.Query("SELECT transaction FROM comet.block_data WHERE height=$1", height) - if err != nil { - return resultBlock, err - } - defer txs.Close() - for txs.Next() { - err := txs.Scan(&txBytes) - if err != nil { - return resultBlock, err - } else { - resultBlock.Block.Data.Txs = append(resultBlock.Block.Data.Txs, txBytes) - } - } - - // Retrieve commit signatures - var signature types.CommitSig - signatures, err := c.Connection.Query("SELECT block_id_flag, validator_address, timestamp, signature FROM comet.block_commit_sig WHERE height=$1", resultBlock.Block.LastCommit.Height) - if err != nil { - return resultBlock, err - } - defer signatures.Close() - for signatures.Next() { - err := signatures.Scan(&signature.BlockIDFlag, &signature.ValidatorAddress, &signature.Timestamp, &signature.Signature) - if err != nil { - return resultBlock, err - } else { - resultBlock.Block.LastCommit.Signatures = append(resultBlock.Block.LastCommit.Signatures, signature) - } - } - - // Retrieve duplicate vote evidences - dve := types.DuplicateVoteEvidence{} - dves, err := c.Connection.Query("SELECT "+ - "vote_a_type, "+ - "vote_a_height, "+ - "vote_a_round, "+ - "vote_a_block_id_hash, "+ - "vote_a_block_id_parts_hash, "+ - "vote_a_block_id_parts_total, "+ - "vote_a_timestamp, "+ - "vote_a_validator_address, "+ - "vote_a_validator_index, "+ - "vote_a_signature, "+ - "vote_b_type, "+ - "vote_b_height, "+ - "vote_b_round, "+ - "vote_b_block_id_hash, "+ - "vote_b_block_id_parts_hash, "+ - "vote_b_block_id_parts_total, "+ - "vote_b_timestamp, "+ - "vote_b_validator_address, "+ - "vote_b_validator_index, "+ - "vote_b_signature, "+ - "total_voting_power, "+ - "validator_voting_power, "+ - "evidence_timestamp "+ - "FROM comet.evidence_duplicate_vote "+ - "WHERE height=$1", height) - if err != nil { - return resultBlock, err - } - defer dves.Close() - for dves.Next() { - voteA := types.Vote{} - voteB := types.Vote{} - err := dves.Scan( - &voteA.Type, - &voteA.Height, - &voteA.Round, - &voteA.BlockID.Hash, - &voteA.BlockID.PartSetHeader.Hash, - &voteA.BlockID.PartSetHeader.Total, - &voteA.Timestamp, - &voteA.ValidatorAddress, - &voteA.ValidatorIndex, - &voteA.Signature, - &voteB.Type, - &voteB.Height, - &voteB.Round, - &voteB.BlockID.Hash, - &voteB.BlockID.PartSetHeader.Hash, - &voteB.BlockID.PartSetHeader.Total, - &voteB.Timestamp, - &voteB.ValidatorAddress, - &voteB.ValidatorIndex, - &voteB.Signature, - &dve.TotalVotingPower, - &dve.ValidatorPower, - &dve.Timestamp) - if err != nil { - return resultBlock, err - } else { - dve.VoteA = &voteA - dve.VoteB = &voteB - resultBlock.Block.Evidence.Evidence = append(resultBlock.Block.Evidence.Evidence, &dve) - } - } - - // Retrieve light client attack evidences - lcaev := types.LightClientAttackEvidence{} - lcaevs, err := c.Connection.Query("SELECT "+ - "common_height, "+ - "total_voting_power, "+ - "timestamp "+ - "FROM comet.evidence_light_client_attack "+ - "WHERE height=$1", height) - if err != nil { - return resultBlock, err - } - defer lcaevs.Close() - for lcaevs.Next() { - err := lcaevs.Scan( - &lcaev.CommonHeight, - &lcaev.TotalVotingPower, - &lcaev.Timestamp) - if err != nil { - return resultBlock, err - } else { - resultBlock.Block.Evidence.Evidence = append(resultBlock.Block.Evidence.Evidence, &lcaev) - } - } - - return resultBlock, err -} - -func (c *PostgresStorage) Connect() error { - db, err := sql.Open("postgres", c.ConnectionString) - if err != nil { - return err - } else { - c.Connection = db - } - - db.SetMaxOpenConns(100) - db.SetMaxIdleConns(50) - - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - - err = db.PingContext(ctx) - if err != nil { - return err - } - - return nil -} - func insert() { // Database storage @@ -591,34 +103,4 @@ func insert() { } service.Serve(&storage) } - -func InsertBlocks(storage PostgresStorage) { - - // Ingest server - fetcher := CometFetcher{ - Endpoint: os.Getenv("COMPANION_NODE_RPC"), - } - - numberHeights := int64(5) - initialHeightParameter := os.Getenv("COMPANION_INITIAL_HEIGHT") - initialHeight, err := strconv.ParseInt(initialHeightParameter, 10, 64) - if err != nil { - fmt.Printf("Invalid initial height %s: %s\n", initialHeightParameter, err) - } - - for height := initialHeight; height <= initialHeight+numberHeights; height++ { - - blockFetched, err := fetcher.FetchBlock(int64(height)) - if err != nil { - log.Fatalf("Error fetching block at height %d: %s\n", height, err) - } - - inserted, err := storage.InsertBlock(*blockFetched) - if err != nil { - fmt.Printf("Error inserting block at height %d: %s\n", height, err) - } - if inserted { - fmt.Printf("Inserted height %d\n", height) - } - } -} +*/ diff --git a/storage/postgresql.go b/storage/postgresql.go new file mode 100644 index 0000000..86812d6 --- /dev/null +++ b/storage/postgresql.go @@ -0,0 +1,484 @@ +package storage + +import ( + "context" + "database/sql" + "fmt" + ctypes "github.com/cometbft/cometbft/rpc/core/types" + "github.com/cometbft/cometbft/types" + _ "github.com/lib/pq" + "time" +) + +type PostgresStorage struct { + ConnectionString string +} + +func (c *PostgresStorage) Connect() (*sql.DB, error) { + db, err := sql.Open("postgres", c.ConnectionString) + if err != nil { + return nil, err + } else { + return db, nil + } +} + +func (c *PostgresStorage) Disconnect(conn *sql.DB) error { + err := conn.Close() + if err != nil { + return err + } else { + return nil + } +} + +func (c *PostgresStorage) Ping() error { + conn, err := c.Connect() + if err != nil { + return err + } else { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + err = conn.PingContext(ctx) + if err != nil { + return err + } else { + return nil + } + } +} + +func (c *PostgresStorage) InsertBlock(resultBlock ctypes.ResultBlock) (bool, error) { + conn, err := c.Connect() + defer conn.Close() + if err != nil { + return false, err + } else { + _, err := conn.Exec( + "INSERT INTO comet.block_result"+ + "(block_id_hash, "+ + "block_id_parts_hash, "+ + "block_id_parts_total, "+ + "block_header_height, "+ + "block_header_version_block, "+ + "block_header_version_app, "+ + "block_header_block_time, "+ + "block_header_chain_id, "+ + "block_header_last_commit_hash, "+ + "block_header_data_hash, "+ + "block_header_validators_hash, "+ + "block_header_next_validators_hash, "+ + "block_header_consensus_hash, "+ + "block_header_app_hash, "+ + "block_header_last_results_hash, "+ + "block_header_evidence_hash, "+ + "block_header_proposer_address, "+ + "block_header_last_block_id_hash, "+ + "block_header_last_block_id_parts_hash, "+ + "block_header_last_block_id_part_total, "+ + "block_last_commit_height, "+ + "block_last_commit_round, "+ + "block_last_commit_block_id_hash, "+ + "block_last_commit_block_id_parts_total, "+ + "block_last_commit_block_id_parts_hash) "+ + "VALUES ($1,$2,$3,$4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25)", + resultBlock.BlockID.Hash, + resultBlock.BlockID.PartSetHeader.Hash, + resultBlock.BlockID.PartSetHeader.Total, + resultBlock.Block.Header.Height, + resultBlock.Block.Header.Version.Block, + resultBlock.Block.Header.Version.App, + resultBlock.Block.Header.Time, + resultBlock.Block.Header.ChainID, + resultBlock.Block.Header.LastCommitHash, + resultBlock.Block.Header.DataHash, + resultBlock.Block.Header.ValidatorsHash, + resultBlock.Block.Header.NextValidatorsHash, + resultBlock.Block.Header.ConsensusHash, + resultBlock.Block.Header.AppHash, + resultBlock.Block.Header.LastResultsHash, + resultBlock.Block.Header.EvidenceHash, + resultBlock.Block.Header.ProposerAddress, + resultBlock.Block.LastBlockID.Hash, + resultBlock.Block.LastBlockID.PartSetHeader.Hash, + resultBlock.Block.LastBlockID.PartSetHeader.Total, + resultBlock.Block.LastCommit.Height, + resultBlock.Block.LastCommit.Round, + resultBlock.Block.LastCommit.BlockID.Hash, + resultBlock.Block.LastCommit.BlockID.PartSetHeader.Total, + resultBlock.Block.LastCommit.BlockID.PartSetHeader.Hash) + + // Insert transactions if they exist + for _, tx := range resultBlock.Block.Data.Txs { + _, err := c.InsertTransaction(resultBlock.Block.Header.Height, tx) + if err != nil { + return false, err + } + } + + // Insert last commit signatures + for _, signature := range resultBlock.Block.LastCommit.Signatures { + _, err := c.InsertCommitSignature(resultBlock.Block.LastCommit.Height, signature) + if err != nil { + return false, err + } + } + + // Insert evidences + for _, evidence := range resultBlock.Block.Evidence.Evidence { + switch ev := evidence.(type) { + case *types.DuplicateVoteEvidence: + var dve *types.DuplicateVoteEvidence + dve = ev + _, err = c.InsertDuplicateVoteEvidence(resultBlock.Block.Header.Height, dve) + if err != nil { + return false, err + } + case *types.LightClientAttackEvidence: + var lae *types.LightClientAttackEvidence + lae = ev + _, err = c.InsertLightClientAttackEvidence(resultBlock.Block.Header.Height, lae) + if err != nil { + return false, err + } + default: + fmt.Printf("Evidence type not supported") + } + } + + if err != nil { + return false, err + } else { + return true, nil + } + } +} + +func (c *PostgresStorage) InsertTransaction(height int64, tx types.Tx) (bool, error) { + conn, err := c.Connect() + defer conn.Close() + if err != nil { + return false, err + } else { + _, err := conn.Exec("INSERT INTO comet.block_data (height, transaction) values ($1,$2)", + height, + tx) + if err != nil { + return false, err + } else { + return true, nil + } + } +} + +func (c *PostgresStorage) InsertDuplicateVoteEvidence(height int64, evidence *types.DuplicateVoteEvidence) (bool, error) { + conn, err := c.Connect() + defer conn.Close() + if err != nil { + return false, err + } else { + //TODO: Find how to get the evidence type property e.g. 'tendermint/DuplicateVoteEvidence' + _, err := conn.Exec("INSERT INTO comet.evidence_duplicate_vote ("+ + "height, "+ + "evidence_type, "+ + "vote_a_type, "+ + "vote_a_height, "+ + "vote_a_round, "+ + "vote_a_block_id_hash, "+ + "vote_a_block_id_parts_hash, "+ + "vote_a_block_id_parts_total, "+ + "vote_a_timestamp, "+ + "vote_a_validator_address, "+ + "vote_a_validator_index, "+ + "vote_a_signature, "+ + "vote_b_type, "+ + "vote_b_height, "+ + "vote_b_round, "+ + "vote_b_block_id_hash, "+ + "vote_b_block_id_parts_hash, "+ + "vote_b_block_id_parts_total, "+ + "vote_b_timestamp, "+ + "vote_b_validator_address, "+ + "vote_b_validator_index, "+ + "vote_b_signature, "+ + "total_voting_power, "+ + "validator_voting_power, "+ + "evidence_timestamp) "+ + "VALUES ($1,$2,$3,$4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25)", + height, + "tendermint/DuplicateVoteEvidence", + evidence.VoteA.Type, + evidence.VoteA.Height, + evidence.VoteA.Round, + evidence.VoteA.BlockID.Hash, + evidence.VoteA.BlockID.PartSetHeader.Hash, + evidence.VoteA.BlockID.PartSetHeader.Total, + evidence.VoteA.Timestamp, + evidence.VoteA.ValidatorAddress, + evidence.VoteA.ValidatorIndex, + evidence.VoteA.Signature, + evidence.VoteB.Type, + evidence.VoteB.Height, + evidence.VoteB.Round, + evidence.VoteB.BlockID.Hash, + evidence.VoteB.BlockID.PartSetHeader.Hash, + evidence.VoteB.BlockID.PartSetHeader.Total, + evidence.VoteB.Timestamp, + evidence.VoteB.ValidatorAddress, + evidence.VoteB.ValidatorIndex, + evidence.VoteB.Signature, + evidence.TotalVotingPower, + evidence.ValidatorPower, + evidence.Timestamp) + if err != nil { + return false, err + } else { + return true, nil + } + } +} + +func (c *PostgresStorage) InsertLightClientAttackEvidence(height int64, evidence *types.LightClientAttackEvidence) (bool, error) { + conn, err := c.Connect() + defer conn.Close() + if err != nil { + return false, err + } else { + //TODO: Find how to get the evidence type property e.g. 'tendermint/LightClientAttackEvidence' + _, err := conn.Exec("INSERT INTO comet.evidence_light_client_attack ("+ + "height, "+ + "evidence_type, "+ + "common_height, "+ + "total_voting_power, "+ + "timestamp) "+ + "VALUES ($1,$2,$3, $4, $5)", + height, + "tendermint/LightClientAttackEvidence", + evidence.CommonHeight, + evidence.TotalVotingPower, + evidence.Timestamp) + if err != nil { + return false, err + } else { + return true, nil + } + } +} + +func (c *PostgresStorage) InsertCommitSignature(height int64, commitSig types.CommitSig) (bool, error) { + conn, err := c.Connect() + defer conn.Close() + if err != nil { + return false, err + } else { + _, err := conn.Exec("INSERT INTO comet.block_commit_sig (height, block_id_flag, validator_address, timestamp, signature) values ($1,$2,$3,$4,$5)", + height, + commitSig.BlockIDFlag, + commitSig.ValidatorAddress, + commitSig.Timestamp, + commitSig.Signature) + if err != nil { + return false, err + } else { + return true, nil + } + } +} + +func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { + resultBlock := ctypes.ResultBlock{} + conn, err := c.Connect() + defer conn.Close() + if err != nil { + return resultBlock, err + } else { + lastCommit := types.Commit{} + bId := types.BlockID{} + b := new(types.Block) + row := conn.QueryRow("SELECT "+ + "block_id_hash, "+ + "block_id_parts_hash, "+ + "block_id_parts_total, "+ + "block_header_height, "+ + "block_header_chain_id, "+ + "block_header_block_time, "+ + "block_header_version_block, "+ + "block_header_version_app, "+ + "block_header_last_commit_hash, "+ + "block_header_data_hash, "+ + "block_header_validators_hash, "+ + "block_header_next_validators_hash, "+ + "block_header_consensus_hash, "+ + "block_header_app_hash, "+ + "block_header_last_results_hash, "+ + "block_header_evidence_hash, "+ + "block_header_proposer_address, "+ + "block_header_last_block_id_hash, "+ + "block_header_last_block_id_part_total, "+ + "block_header_last_block_id_parts_hash, "+ + "block_last_commit_height, "+ + "block_last_commit_round, "+ + "block_last_commit_block_id_hash, "+ + "block_last_commit_block_id_parts_total, "+ + "block_last_commit_block_id_parts_hash "+ + "FROM comet.block_result WHERE block_header_height=$1", height) + err := row.Scan( + &bId.Hash, + &bId.PartSetHeader.Hash, + &bId.PartSetHeader.Total, + &b.Header.Height, + &b.Header.ChainID, + &b.Header.Time, + &b.Header.Version.Block, + &b.Header.Version.App, + &b.Header.LastCommitHash, + &b.Header.DataHash, + &b.Header.ValidatorsHash, + &b.Header.NextValidatorsHash, + &b.Header.ConsensusHash, + &b.Header.AppHash, + &b.Header.LastResultsHash, + &b.Header.EvidenceHash, + &b.Header.ProposerAddress, + &b.LastBlockID.Hash, + &b.LastBlockID.PartSetHeader.Total, + &b.LastBlockID.PartSetHeader.Hash, + &lastCommit.Height, // *Commit + &lastCommit.Round, + &lastCommit.BlockID.Hash, + &lastCommit.BlockID.PartSetHeader.Total, + &lastCommit.BlockID.PartSetHeader.Hash) + if err != nil { + return resultBlock, err + } + b.LastCommit = &lastCommit + resultBlock.BlockID = bId + resultBlock.Block = b + + // Retrieve transactions if any + var txBytes []byte + txs, err := conn.Query("SELECT transaction FROM comet.block_data WHERE height=$1", height) + if err != nil { + return resultBlock, err + } + defer txs.Close() + for txs.Next() { + err := txs.Scan(&txBytes) + if err != nil { + return resultBlock, err + } else { + resultBlock.Block.Data.Txs = append(resultBlock.Block.Data.Txs, txBytes) + } + } + + // Retrieve commit signatures + var signature types.CommitSig + signatures, err := conn.Query("SELECT block_id_flag, validator_address, timestamp, signature FROM comet.block_commit_sig WHERE height=$1", resultBlock.Block.LastCommit.Height) + if err != nil { + return resultBlock, err + } + defer signatures.Close() + for signatures.Next() { + err := signatures.Scan(&signature.BlockIDFlag, &signature.ValidatorAddress, &signature.Timestamp, &signature.Signature) + if err != nil { + return resultBlock, err + } else { + resultBlock.Block.LastCommit.Signatures = append(resultBlock.Block.LastCommit.Signatures, signature) + } + } + + // Retrieve duplicate vote evidences + dve := types.DuplicateVoteEvidence{} + dves, err := conn.Query("SELECT "+ + "vote_a_type, "+ + "vote_a_height, "+ + "vote_a_round, "+ + "vote_a_block_id_hash, "+ + "vote_a_block_id_parts_hash, "+ + "vote_a_block_id_parts_total, "+ + "vote_a_timestamp, "+ + "vote_a_validator_address, "+ + "vote_a_validator_index, "+ + "vote_a_signature, "+ + "vote_b_type, "+ + "vote_b_height, "+ + "vote_b_round, "+ + "vote_b_block_id_hash, "+ + "vote_b_block_id_parts_hash, "+ + "vote_b_block_id_parts_total, "+ + "vote_b_timestamp, "+ + "vote_b_validator_address, "+ + "vote_b_validator_index, "+ + "vote_b_signature, "+ + "total_voting_power, "+ + "validator_voting_power, "+ + "evidence_timestamp "+ + "FROM comet.evidence_duplicate_vote "+ + "WHERE height=$1", height) + if err != nil { + return resultBlock, err + } + defer dves.Close() + for dves.Next() { + voteA := types.Vote{} + voteB := types.Vote{} + err := dves.Scan( + &voteA.Type, + &voteA.Height, + &voteA.Round, + &voteA.BlockID.Hash, + &voteA.BlockID.PartSetHeader.Hash, + &voteA.BlockID.PartSetHeader.Total, + &voteA.Timestamp, + &voteA.ValidatorAddress, + &voteA.ValidatorIndex, + &voteA.Signature, + &voteB.Type, + &voteB.Height, + &voteB.Round, + &voteB.BlockID.Hash, + &voteB.BlockID.PartSetHeader.Hash, + &voteB.BlockID.PartSetHeader.Total, + &voteB.Timestamp, + &voteB.ValidatorAddress, + &voteB.ValidatorIndex, + &voteB.Signature, + &dve.TotalVotingPower, + &dve.ValidatorPower, + &dve.Timestamp) + if err != nil { + return resultBlock, err + } else { + dve.VoteA = &voteA + dve.VoteB = &voteB + resultBlock.Block.Evidence.Evidence = append(resultBlock.Block.Evidence.Evidence, &dve) + } + } + + // Retrieve light client attack evidences + lcaev := types.LightClientAttackEvidence{} + lcaevs, err := conn.Query("SELECT "+ + "common_height, "+ + "total_voting_power, "+ + "timestamp "+ + "FROM comet.evidence_light_client_attack "+ + "WHERE height=$1", height) + if err != nil { + return resultBlock, err + } + defer lcaevs.Close() + for lcaevs.Next() { + err := lcaevs.Scan( + &lcaev.CommonHeight, + &lcaev.TotalVotingPower, + &lcaev.Timestamp) + if err != nil { + return resultBlock, err + } else { + resultBlock.Block.Evidence.Evidence = append(resultBlock.Block.Evidence.Evidence, &lcaev) + } + } + + return resultBlock, err + } +} diff --git a/storage/storage.go b/storage/storage.go new file mode 100644 index 0000000..87354cc --- /dev/null +++ b/storage/storage.go @@ -0,0 +1,19 @@ +package storage + +import ( + "database/sql" + "github.com/cometbft/cometbft/rpc/core/types" + "github.com/cometbft/cometbft/types" +) + +type IStorage interface { + Connect() (*sql.DB, error) + Disconnect(db *sql.DB) error + Ping() error + InsertBlock(resultBlock coretypes.ResultBlock) (bool, error) + InsertTransaction(height int64, tx types.Tx) (bool, error) + InsertDuplicateVoteEvidence(height int64, evidence *types.DuplicateVoteEvidence) (bool, error) + InsertLightClientAttackEvidence(height int64, evidence *types.LightClientAttackEvidence) (bool, error) + InsertCommitSignature(height int64, commitSig types.CommitSig) (bool, error) + GetBlock(height int64) (coretypes.ResultBlock, error) +} From 3c9a97a77221f373497b92df43994fe2be74ac7b Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Tue, 20 Jun 2023 17:12:04 -0400 Subject: [PATCH 39/44] implemented RPC as a service (#3) --- commands/ingest/start.go | 1 + commands/rpc/rpc.go | 1 + commands/rpc/start.go | 32 ++++++++++++ insert.go | 106 --------------------------------------- rpc/service.go | 98 ++++++++++++++++++++++++++++++++++++ 5 files changed, 132 insertions(+), 106 deletions(-) create mode 100644 commands/rpc/start.go delete mode 100644 insert.go create mode 100644 rpc/service.go diff --git a/commands/ingest/start.go b/commands/ingest/start.go index 40b717f..44f5618 100644 --- a/commands/ingest/start.go +++ b/commands/ingest/start.go @@ -9,6 +9,7 @@ import ( "strconv" ) +// TODO: make this configurable via a config or parameter const connString = "postgres://postgres:postgres@0.0.0.0:15432/postgres?sslmode=disable" // StartCmd start ingest service diff --git a/commands/rpc/rpc.go b/commands/rpc/rpc.go index 5750b79..c29af7c 100644 --- a/commands/rpc/rpc.go +++ b/commands/rpc/rpc.go @@ -15,4 +15,5 @@ var RpcCmd = &cobra.Command{ } func init() { + RpcCmd.AddCommand(StartCmd) } diff --git a/commands/rpc/start.go b/commands/rpc/start.go new file mode 100644 index 0000000..d858733 --- /dev/null +++ b/commands/rpc/start.go @@ -0,0 +1,32 @@ +package rpc + +import ( + "github.com/cometbft/rpc-companion/rpc" + "github.com/spf13/cobra" + "log" +) + +// TODO: make this configurable via a config or parameter +const connString = "postgres://postgres:postgres@0.0.0.0:15432/postgres?sslmode=disable" + +// StartCmd start RPC service +var StartCmd = &cobra.Command{ + Use: "start", + Short: "Start RPC Service", + Long: `The start command runs an instance of the RPC Service`, + Run: func(cmd *cobra.Command, args []string) { + + //Instantiate a new Ingest Service + rpcSvc := rpc.NewService(connString) + err := rpcSvc.Serve() + if err != nil { + log.Fatalln("There's an error starting the RPC service:", err) + } else { + log.Println("Started RPC service...") + } + + }, +} + +func init() { +} diff --git a/insert.go b/insert.go deleted file mode 100644 index 4250260..0000000 --- a/insert.go +++ /dev/null @@ -1,106 +0,0 @@ -package main - -/* -import ( - "fmt" - "github.com/cometbft/cometbft/libs/json" - _ "github.com/lib/pq" - "log" - "net/http" - "strconv" -) - -type Service interface { - Serve() -} - -type RESTService struct { - Version string -} - -func (s *RESTService) Serve(storage *PostgresStorage) { - // Handler for the block endpoint - http.HandleFunc(fmt.Sprintf("/%s/block", s.Version), handleBlock) - - // Start the service - err := http.ListenAndServe(":8080", nil) - if err != nil { - log.Fatalln("There's an error starting the REST service:", err) - } else { - log.Println("Started REST service...") - } -} - -// Handles the '/v1/block' endpoint -func handleBlock(writer http.ResponseWriter, request *http.Request) { - - // Database connection - storage := PostgresStorage{ - ConnectionString: connString, - Connection: nil, - } - - // Connect to the database - err := storage.Connect() - if err != nil { - log.Println("Error connecting to storage in handleBlock: ", err) - writer.WriteHeader(http.StatusInternalServerError) - writer.Write([]byte("Internal Server Error")) - } - - writer.Header().Set("Content-Type", "application/json") - - if request.Method == "GET" { - h := request.URL.Query()["height"][0] - height, err := strconv.ParseInt(h, 10, 64) - if err != nil { - writer.WriteHeader(http.StatusBadRequest) - writer.Write([]byte("Bad Request. Invalid height")) - } - fmt.Printf("Block Request. Height: %v\n", height) - block, err := storage.GetBlock(height) - if err != nil { - // TODO: If not records retrieved return a different status - log.Println("Error retrieving record from storage in handleBlock: ", err) - writer.WriteHeader(http.StatusInternalServerError) - writer.Write([]byte("Internal Server Error")) - } - resp, _ := json.Marshal(block) - writer.Write(resp) - } else { - writer.WriteHeader(http.StatusBadRequest) - writer.Write([]byte("Bad Request")) - } -} - -func insert() { - - // Database storage - storage := PostgresStorage{ - ConnectionString: connString, - Connection: nil, - } - - // Connect to the database - err := storage.Connect() - if err != nil { - panic(err) - } - - // Insert some blocks - InsertBlocks(storage) - - defer func(ps PostgresStorage) { - err := ps.Connection.Close() - if err != nil { - log.Fatalln(err) - } - }(storage) - - // REST server - service := RESTService{ - Version: "v1", - } - service.Serve(&storage) -} -*/ diff --git a/rpc/service.go b/rpc/service.go new file mode 100644 index 0000000..8746c3e --- /dev/null +++ b/rpc/service.go @@ -0,0 +1,98 @@ +package rpc + +import ( + "encoding/json" + "fmt" + "github.com/cometbft/cometbft/rpc/jsonrpc/types" + "github.com/cometbft/rpc-companion/storage" + "log" + "net/http" + "strconv" +) + +type Service struct { + Storage storage.IStorage +} + +func NewService(connStr string) Service { + + // Database + db := storage.PostgresStorage{ + ConnectionString: connStr, + } + + // Return an Ingest Service + return Service{ + Storage: &db, + } +} + +func (s *Service) Serve() error { + + // Handler for the block endpoint + http.HandleFunc("/v1/block", s.handleBlock) + + // Start the service + err := http.ListenAndServe(":8080", nil) // TODO: Make the port configurable + if err != nil { + return err + } else { + return nil + } +} + +// Handles the '/v1/block' endpoint +func (s *Service) handleBlock(writer http.ResponseWriter, request *http.Request) { + writer.Header().Set("Content-Type", "application/json") + conn, err := s.Storage.Connect() + defer conn.Close() + if err != nil { + log.Println("Error connecting to storage in handleBlock: ", err) + writer.WriteHeader(http.StatusInternalServerError) + writer.Write([]byte("Internal Server Error")) + } else { + if request.Method == "GET" { + h := request.URL.Query()["height"][0] + height, err := strconv.ParseInt(h, 10, 64) + if err != nil { + writer.WriteHeader(http.StatusBadRequest) + writer.Write([]byte("Bad Request. Invalid height")) + } + fmt.Printf("Block Request. Height: %v\n", height) + block, err := s.Storage.GetBlock(height) + if err != nil { + // TODO: If not records retrieved return a different status + log.Println("Error retrieving record from storage in handleBlock: ", err) + writer.WriteHeader(http.StatusInternalServerError) + writer.Write([]byte("Internal Server Error")) + } + // Return response + blockJSON, err := json.Marshal(block) + id := types.JSONRPCStringID("id") + if err != nil { + log.Println("Error marshalling block: ", err) + writer.WriteHeader(http.StatusInternalServerError) + writer.Write([]byte("Internal Server Error")) + } else { + RPCResponse := types.RPCResponse{ + JSONRPC: "2.0", + ID: id, + Result: blockJSON, + Error: nil, + } + resp, err := json.Marshal(RPCResponse) + if err != nil { + log.Println("Error marshalling RPCResponse: ", err) + writer.WriteHeader(http.StatusInternalServerError) + writer.Write([]byte("Internal Server Error")) + } else { + writer.WriteHeader(http.StatusOK) + writer.Write(resp) + } + } + } else { + writer.WriteHeader(http.StatusBadRequest) + writer.Write([]byte("Bad Request")) + } + } +} From 4a8c39b4474baf7d762f03afd918d108315feef8 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Wed, 21 Jun 2023 17:14:04 -0400 Subject: [PATCH 40/44] fixed logic to return proper json using CometBFT libs/json (#3) --- rpc/service.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/rpc/service.go b/rpc/service.go index 8746c3e..1c420be 100644 --- a/rpc/service.go +++ b/rpc/service.go @@ -1,8 +1,8 @@ package rpc import ( - "encoding/json" "fmt" + cmtjson "github.com/cometbft/cometbft/libs/json" "github.com/cometbft/cometbft/rpc/jsonrpc/types" "github.com/cometbft/rpc-companion/storage" "log" @@ -67,20 +67,20 @@ func (s *Service) handleBlock(writer http.ResponseWriter, request *http.Request) writer.Write([]byte("Internal Server Error")) } // Return response - blockJSON, err := json.Marshal(block) - id := types.JSONRPCStringID("id") + //TODO: Empty objects return 'null' should return '[]' + blockJSON, err := cmtjson.Marshal(block) if err != nil { log.Println("Error marshalling block: ", err) writer.WriteHeader(http.StatusInternalServerError) writer.Write([]byte("Internal Server Error")) } else { - RPCResponse := types.RPCResponse{ + var RPCResponse = types.RPCResponse{ JSONRPC: "2.0", - ID: id, + ID: nil, //TODO: Figure out a way to properly return this avoiding error 'cannot encode unregistered type types.JSONRPCIntID' Result: blockJSON, Error: nil, } - resp, err := json.Marshal(RPCResponse) + resp, err := cmtjson.Marshal(RPCResponse) if err != nil { log.Println("Error marshalling RPCResponse: ", err) writer.WriteHeader(http.StatusInternalServerError) From eefe263fed1003211a19286c531cb8176f0ec7a7 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Thu, 22 Jun 2023 16:37:52 -0400 Subject: [PATCH 41/44] minor refactoring (#3) --- commands/ingest/start.go | 2 +- commands/rpc/start.go | 9 ++------- rpc/service.go | 9 ++------- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/commands/ingest/start.go b/commands/ingest/start.go index 44f5618..5397555 100644 --- a/commands/ingest/start.go +++ b/commands/ingest/start.go @@ -23,7 +23,7 @@ var StartCmd = &cobra.Command{ ingestSvc := ingest.NewService(connString) //Insert some blocks - numberHeights := int64(5) + numberHeights := int64(10) initialHeightParameter := os.Getenv("COMPANION_INITIAL_HEIGHT") initialHeight, err := strconv.ParseInt(initialHeightParameter, 10, 64) if err != nil { diff --git a/commands/rpc/start.go b/commands/rpc/start.go index d858733..69e100b 100644 --- a/commands/rpc/start.go +++ b/commands/rpc/start.go @@ -3,7 +3,6 @@ package rpc import ( "github.com/cometbft/rpc-companion/rpc" "github.com/spf13/cobra" - "log" ) // TODO: make this configurable via a config or parameter @@ -18,13 +17,9 @@ var StartCmd = &cobra.Command{ //Instantiate a new Ingest Service rpcSvc := rpc.NewService(connString) - err := rpcSvc.Serve() - if err != nil { - log.Fatalln("There's an error starting the RPC service:", err) - } else { - log.Println("Started RPC service...") - } + //Start the service + rpcSvc.Serve() }, } diff --git a/rpc/service.go b/rpc/service.go index 1c420be..0b7416e 100644 --- a/rpc/service.go +++ b/rpc/service.go @@ -27,18 +27,13 @@ func NewService(connStr string) Service { } } -func (s *Service) Serve() error { +func (s *Service) Serve() { // Handler for the block endpoint http.HandleFunc("/v1/block", s.handleBlock) // Start the service - err := http.ListenAndServe(":8080", nil) // TODO: Make the port configurable - if err != nil { - return err - } else { - return nil - } + log.Fatalln(http.ListenAndServe(":8080", nil)) // TODO: Make the port configurable } // Handles the '/v1/block' endpoint From 757e1424748492bc076ea773ef6eca1fcedb9a80 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Fri, 23 Jun 2023 15:48:58 -0400 Subject: [PATCH 42/44] adding logic to store validator struct (#4) --- database/schema/create_database_schema.sql | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/database/schema/create_database_schema.sql b/database/schema/create_database_schema.sql index 88f0c6f..9550204 100644 --- a/database/schema/create_database_schema.sql +++ b/database/schema/create_database_schema.sql @@ -170,3 +170,17 @@ CREATE TABLE comet.evidence_light_client_attack ON UPDATE CASCADE ON DELETE CASCADE ); + +DROP TABLE IF EXISTS comet.validator; + +CREATE TABLE comet.validator +( + id bigserial NOT NULL, + address bytea NOT NULL, + pub_key_type bytea NOT NULL, + pub_key_value bytea NOT NULL, + voting_power bigint NOT NULL, + proposer_priority bigint NOT NULL, + CONSTRAINT validator_pkey PRIMARY KEY (id), + CONSTRAINT unique_validator UNIQUE (pub_key_type, pub_key_value, voting_power) +); From eb8d65c70e894ed0a079fbd285a7f0078c06c01a Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Mon, 26 Jun 2023 16:14:59 -0400 Subject: [PATCH 43/44] added logic to add normalized byzantine validator for lca evidence (#4, #1) --- database/schema/create_database_schema.sql | 31 +++++++++-- storage/postgresql.go | 62 +++++++++++++++++++--- 2 files changed, 81 insertions(+), 12 deletions(-) diff --git a/database/schema/create_database_schema.sql b/database/schema/create_database_schema.sql index 9550204..a28ecc7 100644 --- a/database/schema/create_database_schema.sql +++ b/database/schema/create_database_schema.sql @@ -43,8 +43,8 @@ DO $$ BEGIN ALTER DOMAIN comet.uint64 ADD CONSTRAINT value_positive CHECK (VALUE >= 0::numeric); - EXCEPTION - WHEN duplicate_object THEN null; +EXCEPTION + WHEN duplicate_object THEN null; END $$; -- TABLE: comet.block_result @@ -156,22 +156,26 @@ CREATE TABLE comet.evidence_duplicate_vote -- TABLE: comet.evidence_light_client_attack -DROP TABLE IF EXISTS comet.evidence_light_client_attack; +DROP TABLE IF EXISTS comet.evidence_light_client_attack CASCADE; CREATE TABLE comet.evidence_light_client_attack ( + id bigserial NOT NULL, height bigint NOT NULL, evidence_type bytea NOT NULL, common_height bigint NOT NULL, total_voting_power bigint NOT NULL, timestamp timestamp with time zone NOT NULL, + CONSTRAINT evidence_light_client_attack_pkey PRIMARY KEY (id), CONSTRAINT lca_evidence_height_fk FOREIGN KEY (height) REFERENCES comet.block_result (block_header_height) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE ); -DROP TABLE IF EXISTS comet.validator; +-- TABLE: comet.validator + +DROP TABLE IF EXISTS comet.validator CASCADE; CREATE TABLE comet.validator ( @@ -184,3 +188,22 @@ CREATE TABLE comet.validator CONSTRAINT validator_pkey PRIMARY KEY (id), CONSTRAINT unique_validator UNIQUE (pub_key_type, pub_key_value, voting_power) ); + +-- TABLE: comet.evidence_light_client_attack_byzantine_validator + +DROP TABLE IF EXISTS comet.evidence_light_client_attack_byzantine_validator; + +CREATE TABLE comet.evidence_light_client_attack_byzantine_validator +( + evidence_id bigint NOT NULL, + validator_id bigint NOT NULL, + CONSTRAINT evidence_light_client_attack_byzantine_validator_pkey PRIMARY KEY (evidence_id, validator_id), + CONSTRAINT ev_lca_byzantine_validator_fk FOREIGN KEY (validator_id) + REFERENCES comet.validator (id) MATCH SIMPLE + ON UPDATE NO ACTION + ON DELETE NO ACTION, + CONSTRAINT ev_lca_fk FOREIGN KEY (evidence_id) + REFERENCES comet.evidence_light_client_attack (id) MATCH SIMPLE + ON UPDATE NO ACTION + ON DELETE NO ACTION +); \ No newline at end of file diff --git a/storage/postgresql.go b/storage/postgresql.go index 86812d6..012f196 100644 --- a/storage/postgresql.go +++ b/storage/postgresql.go @@ -239,32 +239,78 @@ func (c *PostgresStorage) InsertDuplicateVoteEvidence(height int64, evidence *ty } func (c *PostgresStorage) InsertLightClientAttackEvidence(height int64, evidence *types.LightClientAttackEvidence) (bool, error) { + evID := int64(0) conn, err := c.Connect() defer conn.Close() if err != nil { return false, err } else { //TODO: Find how to get the evidence type property e.g. 'tendermint/LightClientAttackEvidence' - _, err := conn.Exec("INSERT INTO comet.evidence_light_client_attack ("+ - "height, "+ - "evidence_type, "+ - "common_height, "+ - "total_voting_power, "+ - "timestamp) "+ - "VALUES ($1,$2,$3, $4, $5)", + err := conn.QueryRow("INSERT INTO comet.evidence_light_client_attack (height, evidence_type, common_height, total_voting_power, timestamp) VALUES ($1,$2,$3, $4, $5) RETURNING id", height, "tendermint/LightClientAttackEvidence", evidence.CommonHeight, evidence.TotalVotingPower, - evidence.Timestamp) + evidence.Timestamp).Scan(&evID) if err != nil { return false, err } else { + // Insert byzantine validators + for _, validator := range evidence.ByzantineValidators { + valID, err := c.InsertValidator(validator) + if err != nil { + return false, err + } else { + //Insert an entry into a light client evidence to byzantine validator table (1-N) + _, err := c.InsertEvidenceLCAByzantineValidator(evID, valID) + if err != nil { + return false, err + } + } + } return true, nil } } } +func (c *PostgresStorage) InsertValidator(v *types.Validator) (int64, error) { + id := int64(0) + conn, err := c.Connect() + defer conn.Close() + if err != nil { + return id, err + } else { + err := conn.QueryRow("INSERT INTO comet.validator (address, pub_key_type, pub_key_value, voting_power, proposer_priority) SELECT $1,$2,$3,$4,$5 WHERE NOT EXISTS (SELECT address FROM comet.validator WHERE address=$1 AND voting_power=$4) RETURNING id;", + v.Address, + v.PubKey.Type(), + v.PubKey.Bytes(), + v.VotingPower, + v.ProposerPriority).Scan(&id) + if err != nil { + return id, err + } else { + return id, nil + } + } +} + +func (c *PostgresStorage) InsertEvidenceLCAByzantineValidator(evID int64, valID int64) (sql.Result, error) { + conn, err := c.Connect() + defer conn.Close() + if err != nil { + return nil, err + } else { + r, err := conn.Exec("INSERT INTO comet.evidence_light_client_attack_byzantine_validator(evidence_id, validator_id) VALUES ($1, $2);", + evID, + valID) + if err != nil { + return nil, err + } else { + return r, nil + } + } +} + func (c *PostgresStorage) InsertCommitSignature(height int64, commitSig types.CommitSig) (bool, error) { conn, err := c.Connect() defer conn.Close() From 56c676a7027efa13e1bf5ad78782bc712e9c6225 Mon Sep 17 00:00:00 2001 From: Andy Nogueira Date: Tue, 27 Jun 2023 13:09:12 -0400 Subject: [PATCH 44/44] added byzantine validators return in light client attack evidence (#3) --- storage/postgresql.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/storage/postgresql.go b/storage/postgresql.go index 012f196..6e8e3d5 100644 --- a/storage/postgresql.go +++ b/storage/postgresql.go @@ -504,6 +504,7 @@ func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { // Retrieve light client attack evidences lcaev := types.LightClientAttackEvidence{} lcaevs, err := conn.Query("SELECT "+ + "id, "+ "common_height, "+ "total_voting_power, "+ "timestamp "+ @@ -514,13 +515,32 @@ func (c *PostgresStorage) GetBlock(height int64) (ctypes.ResultBlock, error) { } defer lcaevs.Close() for lcaevs.Next() { + var id int64 err := lcaevs.Scan( + &id, &lcaev.CommonHeight, &lcaev.TotalVotingPower, &lcaev.Timestamp) if err != nil { return resultBlock, err } else { + //Retrieve byzantine validators + // Retrieve commit signatures + var validator types.Validator + bValidators, err := conn.Query("SELECT V.address, v.voting_power, v.proposer_priority FROM comet.evidence_light_client_attack_byzantine_validator E JOIN comet.validator V ON E.validator_id = V.id WHERE E.evidence_id=$1;", id) + if err != nil { + return resultBlock, err + } + defer bValidators.Close() + for bValidators.Next() { + //TODO: Logic to retrieve pub_key + err := bValidators.Scan(&validator.Address, &validator.VotingPower, &validator.ProposerPriority) + if err != nil { + return resultBlock, err + } else { + lcaev.ByzantineValidators = append(lcaev.ByzantineValidators, &validator) + } + } resultBlock.Block.Evidence.Evidence = append(resultBlock.Block.Evidence.Evidence, &lcaev) } }