From fe5ce2355808ea7a180eee6ea1e5a4e23dca9e06 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Tue, 18 Jan 2022 10:38:30 +0800 Subject: [PATCH 01/24] Commit migration scripts and some of the implemented views. --- ...104331_create_view_vd_delegations.down.sql | 5 + ...17104331_create_view_vd_delegations.up.sql | 13 + ...17110519_create_view_vd_evidences.down.sql | 1 + ...0117110519_create_view_vd_evidences.up.sql | 8 + ...create_view_vd_redelegation_queue.down.sql | 1 + ...5_create_view_vd_redelegation_queue.up.sql | 6 + ...1937_create_view_vd_redelegations.down.sql | 3 + ...111937_create_view_vd_redelegations.up.sql | 12 + ...iew_vd_unbonding_delegation_queue.down.sql | 1 + ..._view_vd_unbonding_delegation_queue.up.sql | 6 + ...ate_view_vd_unbonding_delegations.down.sql | 5 + ...reate_view_vd_unbonding_delegations.up.sql | 13 + ...eate_view_vd_unbonding_validators.down.sql | 1 + ...create_view_vd_unbonding_validators.up.sql | 6 + ...7133017_create_view_vd_validators.down.sql | 9 + ...117133017_create_view_vd_validators.up.sql | 25 ++ .../validator_delegation/view/delegations.go | 279 +++++++++++++++++- .../validator_delegation/view/evidences.go | 73 ++++- .../view/redelegation_queue.go | 140 ++++++++- .../view/redelegations.go | 6 +- .../view/unbonding_delegation_queue.go | 3 +- .../view/unbonding_delegations.go | 8 +- .../view/unbonding_validators.go | 8 +- .../validator_delegation/view/validators.go | 9 +- 24 files changed, 605 insertions(+), 36 deletions(-) create mode 100644 projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.down.sql create mode 100644 projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.up.sql create mode 100644 projection/validator_delegation/migrations/20220117110519_create_view_vd_evidences.down.sql create mode 100644 projection/validator_delegation/migrations/20220117110519_create_view_vd_evidences.up.sql create mode 100644 projection/validator_delegation/migrations/20220117111405_create_view_vd_redelegation_queue.down.sql create mode 100644 projection/validator_delegation/migrations/20220117111405_create_view_vd_redelegation_queue.up.sql create mode 100644 projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.down.sql create mode 100644 projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.up.sql create mode 100644 projection/validator_delegation/migrations/20220117130920_create_view_vd_unbonding_delegation_queue.down.sql create mode 100644 projection/validator_delegation/migrations/20220117130920_create_view_vd_unbonding_delegation_queue.up.sql create mode 100644 projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.down.sql create mode 100644 projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.up.sql create mode 100644 projection/validator_delegation/migrations/20220117132223_create_view_vd_unbonding_validators.down.sql create mode 100644 projection/validator_delegation/migrations/20220117132223_create_view_vd_unbonding_validators.up.sql create mode 100644 projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.down.sql create mode 100644 projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql diff --git a/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.down.sql b/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.down.sql new file mode 100644 index 00000000..1cfb512c --- /dev/null +++ b/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.down.sql @@ -0,0 +1,5 @@ +DROP INDEX IF EXISTS view_vd_delegations_delegator_height_index; + +DROP INDEX IF EXISTS view_vd_delegations_validator_height_index; + +DROP TABLE IF EXISTS view_vd_delegations; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.up.sql b/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.up.sql new file mode 100644 index 00000000..67efce83 --- /dev/null +++ b/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.up.sql @@ -0,0 +1,13 @@ +CREATE TABLE view_vd_delegations ( + id BIGSERIAL, + height BIGINT NOT NULL, + validator_address VARCHAR NOT NULL, + delegator_address VARCHAR NOT NULL, + shares VARCHAR NOT NULL, + PRIMARY KEY (id), + UNIQUE(validator_address, delegator_address, height) +); + +CREATE INDEX view_vd_delegations_validator_height_index ON view_vd_delegations USING btree (validator_address, height); + +CREATE INDEX view_vd_delegations_delegator_height_index ON view_vd_delegations USING btree (delegator_address, height); \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117110519_create_view_vd_evidences.down.sql b/projection/validator_delegation/migrations/20220117110519_create_view_vd_evidences.down.sql new file mode 100644 index 00000000..f1997639 --- /dev/null +++ b/projection/validator_delegation/migrations/20220117110519_create_view_vd_evidences.down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS view_vd_evidences; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117110519_create_view_vd_evidences.up.sql b/projection/validator_delegation/migrations/20220117110519_create_view_vd_evidences.up.sql new file mode 100644 index 00000000..e8f3071f --- /dev/null +++ b/projection/validator_delegation/migrations/20220117110519_create_view_vd_evidences.up.sql @@ -0,0 +1,8 @@ +CREATE TABLE view_vd_evidences ( + id BIGSERIAL, + height BIGINT NOT NULL, + tendermint_address VARCHAR NOT NULL, + infraction_height BIGINT NOT NULL, + raw_evidence JSONB NOT NULL, + PRIMARY KEY (id) +); diff --git a/projection/validator_delegation/migrations/20220117111405_create_view_vd_redelegation_queue.down.sql b/projection/validator_delegation/migrations/20220117111405_create_view_vd_redelegation_queue.down.sql new file mode 100644 index 00000000..21791710 --- /dev/null +++ b/projection/validator_delegation/migrations/20220117111405_create_view_vd_redelegation_queue.down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS view_vd_redelegation_queue; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117111405_create_view_vd_redelegation_queue.up.sql b/projection/validator_delegation/migrations/20220117111405_create_view_vd_redelegation_queue.up.sql new file mode 100644 index 00000000..89cc4bb8 --- /dev/null +++ b/projection/validator_delegation/migrations/20220117111405_create_view_vd_redelegation_queue.up.sql @@ -0,0 +1,6 @@ +CREATE TABLE view_vd_redelegation_queue ( + id BIGSERIAL, + completion_time BIGINT NOT NULL UNIQUE, + dvv_triplets JSONB NOT NULL, + PRIMARY KEY (id) +); diff --git a/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.down.sql b/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.down.sql new file mode 100644 index 00000000..bdf5e83a --- /dev/null +++ b/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.down.sql @@ -0,0 +1,3 @@ +DROP INDEX IF EXISTS view_vd_redelegations_src_validator_height_index; + +DROP TABLE IF EXISTS view_vd_redelegations; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.up.sql b/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.up.sql new file mode 100644 index 00000000..d49d3bc4 --- /dev/null +++ b/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.up.sql @@ -0,0 +1,12 @@ +CREATE TABLE view_vd_redelegations ( + id BIGSERIAL, + height BIGINT NOT NULL, + delegator_address VARCHAR NOT NULL, + validator_src_address VARCHAR NOT NULL, + validator_dst_address VARCHAR NOT NULL, + entries JSONB NOT NULL, + PRIMARY KEY (id), + UNIQUE(delegator_address, validator_src_address, validator_dst_address, height) +); + +CREATE INDEX view_vd_redelegations_src_validator_height_index ON view_vd_redelegations USING btree (validator_src_address, height); \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117130920_create_view_vd_unbonding_delegation_queue.down.sql b/projection/validator_delegation/migrations/20220117130920_create_view_vd_unbonding_delegation_queue.down.sql new file mode 100644 index 00000000..c2b0d4a1 --- /dev/null +++ b/projection/validator_delegation/migrations/20220117130920_create_view_vd_unbonding_delegation_queue.down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS view_vd_unbonding_delegation_queue; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117130920_create_view_vd_unbonding_delegation_queue.up.sql b/projection/validator_delegation/migrations/20220117130920_create_view_vd_unbonding_delegation_queue.up.sql new file mode 100644 index 00000000..4638701b --- /dev/null +++ b/projection/validator_delegation/migrations/20220117130920_create_view_vd_unbonding_delegation_queue.up.sql @@ -0,0 +1,6 @@ +CREATE TABLE view_vd_unbonding_delegation_queue ( + id BIGSERIAL, + completion_time BIGINT NOT NULL UNIQUE, + dv_pairs JSONB NOT NULL, + PRIMARY KEY (id) +); diff --git a/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.down.sql b/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.down.sql new file mode 100644 index 00000000..bc3e2643 --- /dev/null +++ b/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.down.sql @@ -0,0 +1,5 @@ +DROP INDEX IF EXISTS view_vd_unbonding_delegations_delegator_height_index; + +DROP INDEX IF EXISTS view_vd_unbonding_delegations_validator_height_index; + +DROP TABLE IF EXISTS view_vd_unbonding_delegations; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.up.sql b/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.up.sql new file mode 100644 index 00000000..409beafb --- /dev/null +++ b/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.up.sql @@ -0,0 +1,13 @@ +CREATE TABLE view_vd_unbonding_delegations ( + id BIGSERIAL, + height BIGINT NOT NULL, + delegator_address VARCHAR NOT NULL, + validator_address VARCHAR NOT NULL, + entries JSONB NOT NULL, + PRIMARY KEY (id), + UNIQUE(delegator_address, validator_address, height) +); + +CREATE INDEX view_vd_unbonding_delegations_validator_height_index ON view_vd_unbonding_delegations USING btree (validator_address, height); + +CREATE INDEX view_vd_unbonding_delegations_delegator_height_index ON view_vd_unbonding_delegations USING btree (delegator_address, height); \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117132223_create_view_vd_unbonding_validators.down.sql b/projection/validator_delegation/migrations/20220117132223_create_view_vd_unbonding_validators.down.sql new file mode 100644 index 00000000..85f88a62 --- /dev/null +++ b/projection/validator_delegation/migrations/20220117132223_create_view_vd_unbonding_validators.down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS view_vd_unbonding_validators; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117132223_create_view_vd_unbonding_validators.up.sql b/projection/validator_delegation/migrations/20220117132223_create_view_vd_unbonding_validators.up.sql new file mode 100644 index 00000000..553eb5c2 --- /dev/null +++ b/projection/validator_delegation/migrations/20220117132223_create_view_vd_unbonding_validators.up.sql @@ -0,0 +1,6 @@ +CREATE TABLE view_vd_unbonding_validators ( + id BIGSERIAL, + operator_address VARCHAR NOT NULL UNIQUE, + unbonding_time BIGINT NOT NULL, + PRIMARY KEY (id) +); diff --git a/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.down.sql b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.down.sql new file mode 100644 index 00000000..ac04d37f --- /dev/null +++ b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.down.sql @@ -0,0 +1,9 @@ +DROP INDEX IF EXISTS view_vd_validators_height_index; + +DROP INDEX IF EXISTS view_vd_validators_tendermint_height_index; + +DROP INDEX IF EXISTS view_vd_validators_consensus_height_index; + +DROP INDEX IF EXISTS view_vd_validators_operator_height_index; + +DROP TABLE IF EXISTS view_vd_validators; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql new file mode 100644 index 00000000..c79df7eb --- /dev/null +++ b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql @@ -0,0 +1,25 @@ +CREATE TABLE view_vd_validators ( + id BIGSERIAL, + height BIGINT NOT NULL, + operator_address VARCHAR NOT NULL, + consensus_node_address VARCHAR NOT NULL, + tendermint_address VARCHAR NOT NULL, + status VARCHAR NOT NULL, + jailed BOOLEAN NOT NULL, + power VARCHAR NOT NULL, + unbonding_height BIGINT NOT NULL, + unbonding_time BIGINT NOT NULL, + tokens VARCHAR NOT NULL, + shares VARCHAR NOT NULL, + min_self_delegation VARCHAR NOT NULL, + PRIMARY KEY (id), + UNIQUE(operator_address, consensus_node_address, tendermint_address, height) +); + +CREATE INDEX view_vd_validators_operator_height_index ON view_vd_validators USING btree (operator_address, height); + +CREATE INDEX view_vd_validators_consensus_height_index ON view_vd_validators USING btree (consensus_node_address, height); + +CREATE INDEX view_vd_validators_tendermint_height_index ON view_vd_validators USING btree (tendermint_address, height); + +CREATE INDEX view_vd_validators_height_index ON view_vd_validators USING btree (height); diff --git a/projection/validator_delegation/view/delegations.go b/projection/validator_delegation/view/delegations.go index 2f7b9324..22494896 100644 --- a/projection/validator_delegation/view/delegations.go +++ b/projection/validator_delegation/view/delegations.go @@ -1,7 +1,11 @@ package view import ( + "errors" + "fmt" + "github.com/crypto-com/chain-indexing/appinterface/pagination" + pagination_appinterface "github.com/crypto-com/chain-indexing/appinterface/pagination" "github.com/crypto-com/chain-indexing/appinterface/rdb" "github.com/crypto-com/chain-indexing/usecase/coin" ) @@ -39,21 +43,125 @@ func NewDelegationsView(handle *rdb.Handle) Delegations { func (view *DelegationsView) Clone(previousHeight, currentHeight int64) error { + sql, sqlErr := view.rdb.StmtBuilder.ReplacePlaceholders(`INSERT INTO view_vd_delegations( + height, + validator_address, + delegator_address, + shares + ) SELECT + ?, + validator_address, + delegator_address, + shares? + FROM view_vd_delegations WHERE height = ? + `) + if sqlErr != nil { + return fmt.Errorf("error building delegation clone sql: %v: %w", sqlErr, rdb.ErrBuildSQLStmt) + } + sqlArgs := []interface{}{ + currentHeight, + previousHeight, + } + + if _, execErr := view.rdb.Exec(sql, sqlArgs...); execErr != nil { + return fmt.Errorf("error cloning delegation into the table: %v: %w", execErr, rdb.ErrWrite) + } + return nil } func (view *DelegationsView) Insert(row DelegationRow) error { + sql, sqlArgs, err := view.rdb.StmtBuilder. + Insert( + "view_vd_delegations", + ). + Columns( + "height", + "validator_address", + "delegator_address", + "shares", + ). + Values( + row.Height, + row.ValidatorAddress, + row.DelegatorAddress, + row.Shares.String(), + ). + ToSql() + + if err != nil { + return fmt.Errorf("error building delegation insertion sql: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + result, err := view.rdb.Exec(sql, sqlArgs...) + if err != nil { + return fmt.Errorf("error inserting delegation into the table: %v: %w", err, rdb.ErrWrite) + } + if result.RowsAffected() != 1 { + return fmt.Errorf("error inserting delegation into the table: no rows inserted: %w", rdb.ErrWrite) + } + return nil } func (view *DelegationsView) Update(row DelegationRow) error { + sql, sqlArgs, err := view.rdb.StmtBuilder. + Update( + "view_vd_delegations", + ). + SetMap(map[string]interface{}{ + "shares": row.Shares.String(), + }). + Where( + "validator_address = ? AND delegator_address = ? AND height = ?", + row.ValidatorAddress, + row.DelegatorAddress, + row.Height, + ). + ToSql() + + if err != nil { + return fmt.Errorf("error building delegation update sql: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + result, err := view.rdb.Exec(sql, sqlArgs...) + if err != nil { + return fmt.Errorf("error updating delegation into the table: %v: %w", err, rdb.ErrWrite) + } + if result.RowsAffected() != 1 { + return fmt.Errorf("error updating delegation into the table: no row updated: %w", rdb.ErrWrite) + } + return nil } func (view *DelegationsView) Delete(row DelegationRow) error { + sql, sqlArgs, err := view.rdb.StmtBuilder. + Delete( + "view_vd_delegations", + ). + Where( + "validator_address = ? AND delegator_address = ? AND height = ?", + row.ValidatorAddress, + row.DelegatorAddress, + row.Height, + ). + ToSql() + if err != nil { + return fmt.Errorf("error building delegation deletion sql: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + result, err := view.rdb.Exec(sql, sqlArgs...) + if err != nil { + return fmt.Errorf("error deleting delegation from the table: %v: %w", err, rdb.ErrWrite) + } + if result.RowsAffected() != 1 { + return fmt.Errorf("error deleting delegation into the table: no row deleted: %w", rdb.ErrWrite) + } + return nil } @@ -63,33 +171,180 @@ func (view *DelegationsView) FindBy( height int64, ) (DelegationRow, bool, error) { - // TODO need to handle the case when row NOT exist + sql, sqlArgs, err := view.rdb.StmtBuilder. + Select( + "shares", + ). + From("view_vd_delegations"). + Where( + "validator_address = ? AND delegator_address = ? AND height = ?", + validatorAddress, + delegatorAddress, + height, + ). + ToSql() + if err != nil { + return DelegationRow{}, false, fmt.Errorf("error building select delegation sql: %v: %w", err, rdb.ErrPrepare) + } + + var delegation DelegationRow + delegation.Height = height + delegation.ValidatorAddress = validatorAddress + delegation.DelegatorAddress = delegatorAddress + + var sharesInString string + if err = view.rdb.QueryRow(sql, sqlArgs...).Scan( + &sharesInString, + ); err != nil { + if errors.Is(err, rdb.ErrNoRows) { + // When the row is not found, do not return error + return DelegationRow{}, false, nil + } + return DelegationRow{}, false, fmt.Errorf("error scanning delegation: %v: %w", err, rdb.ErrQuery) + } - return DelegationRow{}, false, nil + delegation.Shares, err = coin.NewDecFromStr(sharesInString) + if err != nil { + return DelegationRow{}, false, fmt.Errorf("error parsing shares to coin.Dec: %v: %w", err, rdb.ErrQuery) + } + + return delegation, true, nil } func (view *DelegationsView) ListByValidatorAddr( validatorAddress string, height int64, - pagination *pagination.Pagination, -) ([]DelegationRow, *pagination.PaginationResult, error) { + pagination *pagination_appinterface.Pagination, +) ([]DelegationRow, *pagination_appinterface.PaginationResult, error) { + + stmtBuilder := view.rdb.StmtBuilder. + Select( + "delegator_address", + "shares", + ). + From( + "view_vd_delegations", + ). + Where( + "validator_address = ? AND height = ?", + validatorAddress, + height, + ) + + rDbPagination := rdb.NewRDbPaginationBuilder( + pagination, + view.rdb, + ).BuildStmt(stmtBuilder) + sql, sqlArgs, err := rDbPagination.ToStmtBuilder().ToSql() + if err != nil { + return nil, nil, fmt.Errorf("error building delegations select SQL: %v, %w", err, rdb.ErrBuildSQLStmt) + } + + rowsResult, err := view.rdb.Query(sql, sqlArgs...) + if err != nil { + return nil, nil, fmt.Errorf("error executing delegations select SQL: %v: %w", err, rdb.ErrQuery) + } + defer rowsResult.Close() + + delegations := make([]DelegationRow, 0) + for rowsResult.Next() { + var delegation DelegationRow + delegation.Height = height + delegation.ValidatorAddress = validatorAddress + + var sharesInString string + if err = rowsResult.Scan( + &delegation.DelegatorAddress, + &sharesInString, + ); err != nil { + return nil, nil, fmt.Errorf("error scanning delegation row: %v: %w", err, rdb.ErrQuery) + } + + delegation.Shares, err = coin.NewDecFromStr(sharesInString) + if err != nil { + return nil, nil, fmt.Errorf("error parsing shares to coin.Dec: %v: %w", err, rdb.ErrQuery) + } + + delegations = append(delegations, delegation) + } + + paginationResult, err := rDbPagination.Result() + if err != nil { + return nil, nil, fmt.Errorf("error preparing pagination result: %v", err) + } - return nil, nil, nil + return delegations, paginationResult, nil } func (view *DelegationsView) ListByDelegatorAddr( delegatorAddress string, height int64, - pagination *pagination.Pagination, -) ([]DelegationRow, *pagination.PaginationResult, error) { + pagination *pagination_appinterface.Pagination, +) ([]DelegationRow, *pagination_appinterface.PaginationResult, error) { + + stmtBuilder := view.rdb.StmtBuilder. + Select( + "validator_address", + "shares", + ). + From( + "view_vd_delegations", + ). + Where( + "delegator_address = ? AND height = ?", + delegatorAddress, + height, + ) + + rDbPagination := rdb.NewRDbPaginationBuilder( + pagination, + view.rdb, + ).BuildStmt(stmtBuilder) + sql, sqlArgs, err := rDbPagination.ToStmtBuilder().ToSql() + if err != nil { + return nil, nil, fmt.Errorf("error building delegations select SQL: %v, %w", err, rdb.ErrBuildSQLStmt) + } + + rowsResult, err := view.rdb.Query(sql, sqlArgs...) + if err != nil { + return nil, nil, fmt.Errorf("error executing delegations select SQL: %v: %w", err, rdb.ErrQuery) + } + defer rowsResult.Close() + + delegations := make([]DelegationRow, 0) + for rowsResult.Next() { + var delegation DelegationRow + delegation.Height = height + delegation.DelegatorAddress = delegatorAddress + + var sharesInString string + if err = rowsResult.Scan( + &delegation.ValidatorAddress, + &sharesInString, + ); err != nil { + return nil, nil, fmt.Errorf("error scanning delegation row: %v: %w", err, rdb.ErrQuery) + } + + delegation.Shares, err = coin.NewDecFromStr(sharesInString) + if err != nil { + return nil, nil, fmt.Errorf("error parsing shares to coin.Dec: %v: %w", err, rdb.ErrQuery) + } + + delegations = append(delegations, delegation) + } + + paginationResult, err := rDbPagination.Result() + if err != nil { + return nil, nil, fmt.Errorf("error preparing pagination result: %v", err) + } - return nil, nil, nil + return delegations, paginationResult, nil } -// TODO: -// - UNIQUE(height, validatorAddress, delegatorAddress) -// - INDEX(height, validatorAddress) -// - INDEX(height, delegatorAddress) +// Notes: +// - UNIQUE(validatorAddress, delegatorAddress, height) +// - INDEX(validatorAddress, height) +// - INDEX(delegatorAddress, height) type DelegationRow struct { Height int64 `json:"height"` ValidatorAddress string `json:"validatorAddress"` diff --git a/projection/validator_delegation/view/evidences.go b/projection/validator_delegation/view/evidences.go index a435dde8..6618cc8c 100644 --- a/projection/validator_delegation/view/evidences.go +++ b/projection/validator_delegation/view/evidences.go @@ -1,8 +1,11 @@ package view import ( + "fmt" + "github.com/crypto-com/chain-indexing/appinterface/rdb" "github.com/crypto-com/chain-indexing/usecase/model" + jsoniter "github.com/json-iterator/go" ) type Evidences interface { @@ -22,15 +25,79 @@ func NewEvidencesView(handle *rdb.Handle) Evidences { func (view *EvidencesView) Insert(row EvidenceRow) error { + rawEvidenceJSON, err := jsoniter.MarshalToString(row.RawEvidence) + if err != nil { + return fmt.Errorf("error JSON marshalling RawEvidence for insertion: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + sql, sqlArgs, err := view.rdb.StmtBuilder. + Insert( + "view_vd_evidences", + ). + Columns( + "height", + "tendermint_address", + "infraction_height", + "raw_evidence", + ). + Values( + row.Height, + row.TendermintAddress, + row.InfractionHeight, + rawEvidenceJSON, + ). + ToSql() + + if err != nil { + return fmt.Errorf("error building evidence insertion sql: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + result, err := view.rdb.Exec(sql, sqlArgs...) + if err != nil { + return fmt.Errorf("error inserting evidence into the table: %v: %w", err, rdb.ErrWrite) + } + if result.RowsAffected() != 1 { + return fmt.Errorf("error inserting evidence into the table: no rows inserted: %w", rdb.ErrWrite) + } + return nil } func (view *EvidencesView) FindBy(height int64, tendermintAddress string) (EvidenceRow, error) { - // TODO: It seems it is possible that tendermint could put two evidences on a same height. - // Maybe in this function, we should SELECT all matched rows and then return the first one in the list. + sql, sqlArgs, err := view.rdb.StmtBuilder. + Select( + "infraction_height", + "raw_evidence", + ). + From("view_vd_evidences"). + Where( + "tendermint_address = ? AND height = ?", + tendermintAddress, + height, + ). + ToSql() + if err != nil { + return EvidenceRow{}, fmt.Errorf("error building select evidence sql: %v: %w", err, rdb.ErrPrepare) + } + + var evidence EvidenceRow + evidence.Height = height + evidence.TendermintAddress = tendermintAddress + + var rawEvidenceJSON string + if err = view.rdb.QueryRow(sql, sqlArgs...).Scan( + &evidence.InfractionHeight, + &rawEvidenceJSON, + ); err != nil { + return EvidenceRow{}, fmt.Errorf("error scanning evidence: %v: %w", err, rdb.ErrQuery) + } + + if err = jsoniter.UnmarshalFromString(rawEvidenceJSON, &evidence.RawEvidence); err != nil { + return EvidenceRow{}, fmt.Errorf("error unmarshalling RawEvidence JSON: %v: %w", err, rdb.ErrQuery) + } - return EvidenceRow{}, nil + return evidence, nil } // NOTES: Don't add UNIQUE constraint on (Height, TendermintAddress) now. diff --git a/projection/validator_delegation/view/redelegation_queue.go b/projection/validator_delegation/view/redelegation_queue.go index 47978033..387dc2a0 100644 --- a/projection/validator_delegation/view/redelegation_queue.go +++ b/projection/validator_delegation/view/redelegation_queue.go @@ -1,8 +1,12 @@ package view import ( + "errors" + "fmt" + "github.com/crypto-com/chain-indexing/appinterface/rdb" "github.com/crypto-com/chain-indexing/external/utctime" + jsoniter "github.com/json-iterator/go" ) type RedelegationQueue interface { @@ -23,28 +27,150 @@ func NewRedelegationQueueView(handle *rdb.Handle) RedelegationQueue { func (view *RedelegationQueueView) Upsert(row RedelegationQueueRow) error { + dvvTripletsJSON, err := jsoniter.MarshalToString(row.DVVTriplets) + if err != nil { + return fmt.Errorf("error JSON marshalling DVVTriplets for upsertion: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + sql, sqlArgs, err := view.rdb.StmtBuilder. + Insert( + "view_vd_redelegation_queue", + ). + Columns( + "completion_time", + "dvv_triplets", + ). + Values( + view.rdb.Tton(&row.CompletionTime), + dvvTripletsJSON, + ). + Suffix("ON CONFLICT(completion_time) DO UPDATE SET dvv_triplets = EXCLUDED.dvv_triplets"). + ToSql() + + if err != nil { + return fmt.Errorf("error building RedelegationQueueRow upsertion sql: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + result, err := view.rdb.Exec(sql, sqlArgs...) + if err != nil { + return fmt.Errorf("error upserting RedelegationQueueRow into the table: %v: %w", err, rdb.ErrWrite) + } + if result.RowsAffected() != 1 { + return fmt.Errorf("error upserting RedelegationQueueRow into the table: no rows inserted: %w", rdb.ErrWrite) + } + return nil } func (view *RedelegationQueueView) FindBy(completionTime utctime.UTCTime) (RedelegationQueueRow, bool, error) { - // TODO handle the row not found + sql, sqlArgs, err := view.rdb.StmtBuilder. + Select( + "dvv_triplets", + ). + From("view_vd_redelegation_queue"). + Where( + "completion_time = ?", + view.rdb.Tton(&completionTime), + ). + ToSql() + if err != nil { + return RedelegationQueueRow{}, false, fmt.Errorf("error building select RedelegationQueueRow sql: %v: %w", err, rdb.ErrPrepare) + } + + var row RedelegationQueueRow + row.CompletionTime = completionTime + + var dvvTripletsJSON string + if err = view.rdb.QueryRow(sql, sqlArgs...).Scan( + &dvvTripletsJSON, + ); err != nil { + if errors.Is(err, rdb.ErrNoRows) { + // When the row is not found, do not return error + return RedelegationQueueRow{}, false, nil + } + return RedelegationQueueRow{}, false, fmt.Errorf("error scanning RedelegationQueueRow: %v: %w", err, rdb.ErrQuery) + } - return RedelegationQueueRow{}, true, nil + if err = jsoniter.UnmarshalFromString(dvvTripletsJSON, &row.DVVTriplets); err != nil { + return RedelegationQueueRow{}, false, fmt.Errorf("error unmarshalling DVVTriplets JSON: %v: %w", err, rdb.ErrQuery) + } + + return row, true, nil } func (view *RedelegationQueueView) DequeueAllMatureRedelegationQueue(blockTime utctime.UTCTime) ([]DVVTriplet, error) { - // TODO find all mature RedelegationQueueRow, then concate their DVVTriplets + // Find all mature RedelegationQueueRow, then concate their DVVTriplets + + sql, sqlArgs, err := view.rdb.StmtBuilder. + Select( + "dvv_triplets", + ). + From( + "view_vd_redelegation_queue", + ). + Where( + "completion_time <= ?", + blockTime, + ). + ToSql() + if err != nil { + return nil, fmt.Errorf("error building mature RedelegationQueueRow select SQL: %v, %w", err, rdb.ErrBuildSQLStmt) + } + + rowsResult, err := view.rdb.Query(sql, sqlArgs...) + if err != nil { + return nil, fmt.Errorf("error executing mature RedelegationQueueRow select SQL: %v: %w", err, rdb.ErrQuery) + } + defer rowsResult.Close() + + matureDVVTriplets := make([]DVVTriplet, 0) + for rowsResult.Next() { + + var dvvTripletsJSON string + if err = rowsResult.Scan( + &dvvTripletsJSON, + ); err != nil { + return nil, fmt.Errorf("error scanning RedelegationQueueRow: %v: %w", err, rdb.ErrQuery) + } - // Optional TODO: de-duplicate, a same DVVTriplet could appear multiple times, we should avoid that + var dvvTriplets []DVVTriplet + if err = jsoniter.UnmarshalFromString(dvvTripletsJSON, &dvvTriplets); err != nil { + return nil, fmt.Errorf("error unmarshalling DVVTriplets JSON: %v: %w", err, rdb.ErrQuery) + } - // TODO Delete the mature rows + matureDVVTriplets = append(matureDVVTriplets, dvvTriplets...) + } + + // TODO: De-duplicate the return slice. A same DVVTriplet could appear multiple times, we could avoid it here. + // At the moment, we are following CosmosSDK implementation, so not doing the de-duplicate. + + // Delete the mature rows + + sql, sqlArgs, err = view.rdb.StmtBuilder. + Delete( + "view_vd_redelegation_queue", + ). + Where( + "completion_time <= ?", + blockTime, + ). + ToSql() + if err != nil { + return nil, fmt.Errorf("error building RedelegationQueueRow deletion sql: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + _, err = view.rdb.Exec(sql, sqlArgs...) + if err != nil { + return nil, fmt.Errorf("error deleting RedelegationQueueRow from the table: %v: %w", err, rdb.ErrWrite) + } - return nil, nil + return matureDVVTriplets, nil } -// TODO UNIQUE CompletionTime +// NOTES: +// - UNIQUE CompletionTime type RedelegationQueueRow struct { CompletionTime utctime.UTCTime `json:"completionTime"` DVVTriplets []DVVTriplet `json:"dvvTriplets"` diff --git a/projection/validator_delegation/view/redelegations.go b/projection/validator_delegation/view/redelegations.go index 2ca1d341..d7d5ea44 100644 --- a/projection/validator_delegation/view/redelegations.go +++ b/projection/validator_delegation/view/redelegations.go @@ -62,9 +62,9 @@ func (view *RedelegationsView) ListBySrcValidator( return nil, nil } -// TODO: -// - UNIQUE(height, delegatorAddress, validatorSrcAddress, validatorDstAddress) -// - Index(height, validatorSrcAddress) +// Notes: +// - UNIQUE(delegatorAddress, validatorSrcAddress, validatorDstAddress, height) +// - Index(validatorSrcAddress, height) type RedelegationRow struct { Height int64 `json:"height"` DelegatorAddress string `json:"delegatorAddress"` diff --git a/projection/validator_delegation/view/unbonding_delegation_queue.go b/projection/validator_delegation/view/unbonding_delegation_queue.go index d0587371..8674c488 100644 --- a/projection/validator_delegation/view/unbonding_delegation_queue.go +++ b/projection/validator_delegation/view/unbonding_delegation_queue.go @@ -45,7 +45,8 @@ func (view *UnbondingDelegationQueueView) DequeueAllMatureUnbondingDelegationQue return nil, nil } -// TODO UNIQUE CompletionTime +// NOTES: +// - UNIQUE CompletionTime type UnbondingDelegationQueueRow struct { CompletionTime utctime.UTCTime `json:"completionTime"` DVPairs []DVPair `json:"dvPairs"` diff --git a/projection/validator_delegation/view/unbonding_delegations.go b/projection/validator_delegation/view/unbonding_delegations.go index 5878d0a3..0d752420 100644 --- a/projection/validator_delegation/view/unbonding_delegations.go +++ b/projection/validator_delegation/view/unbonding_delegations.go @@ -59,10 +59,10 @@ func (view *UnbondingDelegationsView) ListByValidator( return nil, nil } -// TODO: -// - UNIQUE(height, delegatorAddress, validatorAddress) -// - INDEX(height, validatorAddress) -// - INDEX(height, delegatorAddress) +// NOTES: +// - UNIQUE(delegatorAddress, validatorAddress, height) +// - INDEX(validatorAddress, height) +// - INDEX(delegatorAddress, height) type UnbondingDelegationRow struct { Height int64 `json:"height"` DelegatorAddress string `json:"delegatorAddress"` diff --git a/projection/validator_delegation/view/unbonding_validators.go b/projection/validator_delegation/view/unbonding_validators.go index 29eea908..fa471247 100644 --- a/projection/validator_delegation/view/unbonding_validators.go +++ b/projection/validator_delegation/view/unbonding_validators.go @@ -43,8 +43,10 @@ func (view *UnbondingValidatorsView) DeleteMatureEntries(blockTime utctime.UTCTi return nil } -// TODO: UNIQUE OperatorAddress +// NOTES: +// - UNIQUE OperatorAddress type UnbondingValidatorRow struct { - OperatorAddress string `json:"operatorAddress"` - UnbondingTime utctime.UTCTime `json:"UnbondingTime"` + OperatorAddress string `json:"operatorAddress"` + // UnbondingTime is the time when Unbonding is finished + UnbondingTime utctime.UTCTime `json:"UnbondingTime"` } diff --git a/projection/validator_delegation/view/validators.go b/projection/validator_delegation/view/validators.go index 00ffdc84..2e930d50 100644 --- a/projection/validator_delegation/view/validators.go +++ b/projection/validator_delegation/view/validators.go @@ -88,9 +88,12 @@ func (view *ValidatorsView) List( // - power = 0: Validator.Status = Unbonding, UnbondingValidator entry created // - UnbondingValidator complete Unbonding period: Validator.Status = Unbonded -// TODO: -// - UNIQUE(height, operatorAddress) -// - UNIQUE(height, consensusNodeAddress) +// NOTES: +// - UNIQUE(operatorAddress, consensusNodeAddress, tendermintAddress, height) +// - INDEX(operatorAddress, height) +// - INDEX(consensusNodeAddress, height) +// - INDEX(tendermintAddress, height) +// - INDEX(height) type ValidatorRow struct { Height int64 `json:"height"` From 1670d06eb9a18b91d196f090d9b1be3c078de94f Mon Sep 17 00:00:00 2001 From: Yang Song Date: Wed, 19 Jan 2022 11:45:33 +0800 Subject: [PATCH 02/24] Implemented remaining views. --- ...7133017_create_view_vd_validators.down.sql | 6 - ...117133017_create_view_vd_validators.up.sql | 10 +- .../validator_delegation/view/delegations.go | 6 +- .../view/redelegation_queue.go | 8 +- .../view/redelegations.go | 180 ++++++++- .../view/unbonding_delegation_queue.go | 134 ++++++- .../view/unbonding_delegations.go | 171 ++++++++- .../view/unbonding_validators.go | 117 +++++- .../validator_delegation/view/validators.go | 354 +++++++++++++++++- 9 files changed, 940 insertions(+), 46 deletions(-) diff --git a/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.down.sql b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.down.sql index ac04d37f..3d9e6dcf 100644 --- a/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.down.sql +++ b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.down.sql @@ -1,9 +1,3 @@ DROP INDEX IF EXISTS view_vd_validators_height_index; -DROP INDEX IF EXISTS view_vd_validators_tendermint_height_index; - -DROP INDEX IF EXISTS view_vd_validators_consensus_height_index; - -DROP INDEX IF EXISTS view_vd_validators_operator_height_index; - DROP TABLE IF EXISTS view_vd_validators; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql index c79df7eb..c92806eb 100644 --- a/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql +++ b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql @@ -13,13 +13,9 @@ CREATE TABLE view_vd_validators ( shares VARCHAR NOT NULL, min_self_delegation VARCHAR NOT NULL, PRIMARY KEY (id), - UNIQUE(operator_address, consensus_node_address, tendermint_address, height) + UNIQUE(operator_address, height) + UNIQUE(consensus_node_address, height) + UNIQUE(tendermint_address, height) ); -CREATE INDEX view_vd_validators_operator_height_index ON view_vd_validators USING btree (operator_address, height); - -CREATE INDEX view_vd_validators_consensus_height_index ON view_vd_validators USING btree (consensus_node_address, height); - -CREATE INDEX view_vd_validators_tendermint_height_index ON view_vd_validators USING btree (tendermint_address, height); - CREATE INDEX view_vd_validators_height_index ON view_vd_validators USING btree (height); diff --git a/projection/validator_delegation/view/delegations.go b/projection/validator_delegation/view/delegations.go index 22494896..421a670f 100644 --- a/projection/validator_delegation/view/delegations.go +++ b/projection/validator_delegation/view/delegations.go @@ -52,7 +52,7 @@ func (view *DelegationsView) Clone(previousHeight, currentHeight int64) error { ?, validator_address, delegator_address, - shares? + shares FROM view_vd_delegations WHERE height = ? `) if sqlErr != nil { @@ -99,7 +99,7 @@ func (view *DelegationsView) Insert(row DelegationRow) error { return fmt.Errorf("error inserting delegation into the table: %v: %w", err, rdb.ErrWrite) } if result.RowsAffected() != 1 { - return fmt.Errorf("error inserting delegation into the table: no rows inserted: %w", rdb.ErrWrite) + return fmt.Errorf("error inserting delegation into the table: rows inserted: %v: %w", result.RowsAffected(), rdb.ErrWrite) } return nil @@ -131,7 +131,7 @@ func (view *DelegationsView) Update(row DelegationRow) error { return fmt.Errorf("error updating delegation into the table: %v: %w", err, rdb.ErrWrite) } if result.RowsAffected() != 1 { - return fmt.Errorf("error updating delegation into the table: no row updated: %w", rdb.ErrWrite) + return fmt.Errorf("error updating delegation into the table: row updated: %v: %w", result.RowsAffected(), rdb.ErrWrite) } return nil diff --git a/projection/validator_delegation/view/redelegation_queue.go b/projection/validator_delegation/view/redelegation_queue.go index 387dc2a0..1b161372 100644 --- a/projection/validator_delegation/view/redelegation_queue.go +++ b/projection/validator_delegation/view/redelegation_queue.go @@ -112,7 +112,7 @@ func (view *RedelegationQueueView) DequeueAllMatureRedelegationQueue(blockTime u ). Where( "completion_time <= ?", - blockTime, + view.rdb.Tton(&blockTime), ). ToSql() if err != nil { @@ -143,8 +143,8 @@ func (view *RedelegationQueueView) DequeueAllMatureRedelegationQueue(blockTime u matureDVVTriplets = append(matureDVVTriplets, dvvTriplets...) } - // TODO: De-duplicate the return slice. A same DVVTriplet could appear multiple times, we could avoid it here. - // At the moment, we are following CosmosSDK implementation, so not doing the de-duplicate. + // Optional TODO: De-duplicate the return slice. A same DVVTriplet could appear multiple times, we could avoid it here. + // At the moment, we are following CosmosSDK implementation, so not doing the de-duplicate. // Delete the mature rows @@ -154,7 +154,7 @@ func (view *RedelegationQueueView) DequeueAllMatureRedelegationQueue(blockTime u ). Where( "completion_time <= ?", - blockTime, + view.rdb.Tton(&blockTime), ). ToSql() if err != nil { diff --git a/projection/validator_delegation/view/redelegations.go b/projection/validator_delegation/view/redelegations.go index d7d5ea44..2c672c42 100644 --- a/projection/validator_delegation/view/redelegations.go +++ b/projection/validator_delegation/view/redelegations.go @@ -1,11 +1,14 @@ package view import ( + "errors" + "fmt" "time" "github.com/crypto-com/chain-indexing/appinterface/rdb" "github.com/crypto-com/chain-indexing/external/utctime" "github.com/crypto-com/chain-indexing/usecase/coin" + jsoniter "github.com/json-iterator/go" ) type Redelegations interface { @@ -29,16 +32,104 @@ func NewRedelegationsView(handle *rdb.Handle) Redelegations { func (view *RedelegationsView) Clone(previousHeight, currentHeight int64) error { + sql, sqlErr := view.rdb.StmtBuilder.ReplacePlaceholders(`INSERT INTO view_vd_redelegations( + height, + delegator_address, + validator_src_address, + validator_dst_address, + entries + ) SELECT + ?, + delegator_address, + validator_src_address, + validator_dst_address, + entries + FROM view_vd_redelegations WHERE height = ? + `) + if sqlErr != nil { + return fmt.Errorf("error building redelegation clone sql: %v: %w", sqlErr, rdb.ErrBuildSQLStmt) + } + sqlArgs := []interface{}{ + currentHeight, + previousHeight, + } + + if _, execErr := view.rdb.Exec(sql, sqlArgs...); execErr != nil { + return fmt.Errorf("error cloning redelegation into the table: %v: %w", execErr, rdb.ErrWrite) + } + return nil } func (view *RedelegationsView) Upsert(row RedelegationRow) error { + entriesJSON, err := jsoniter.MarshalToString(row.Entries) + if err != nil { + return fmt.Errorf("error JSON marshalling RedelegationRow.Entries for upsertion: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + sql, sqlArgs, err := view.rdb.StmtBuilder. + Insert( + "view_vd_redelegations", + ). + Columns( + "height", + "delegator_address", + "validator_src_address", + "validator_dst_address", + "entries", + ). + Values( + row.Height, + row.DelegatorAddress, + row.ValidatorSrcAddress, + row.ValidatorDstAddress, + entriesJSON, + ). + Suffix("ON CONFLICT(delegator_address, validator_src_address, validator_dst_address, height) DO UPDATE SET entries = EXCLUDED.entries"). + ToSql() + + if err != nil { + return fmt.Errorf("error building redelegation upsertion sql: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + result, err := view.rdb.Exec(sql, sqlArgs...) + if err != nil { + return fmt.Errorf("error upserting redelegation into the table: %v: %w", err, rdb.ErrWrite) + } + if result.RowsAffected() != 1 { + return fmt.Errorf("error upserting redelegation into the table: no row upserted: %w", rdb.ErrWrite) + } + return nil } func (view *RedelegationsView) Delete(row RedelegationRow) error { + sql, sqlArgs, err := view.rdb.StmtBuilder. + Delete( + "view_vd_redelegations", + ). + Where( + "delegator_address = ? AND validator_src_address = ? AND validator_dst_address = ? AND height = ?", + row.DelegatorAddress, + row.ValidatorSrcAddress, + row.ValidatorDstAddress, + row.Height, + ). + ToSql() + if err != nil { + return fmt.Errorf("error building redelegation deletion sql: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + result, err := view.rdb.Exec(sql, sqlArgs...) + if err != nil { + return fmt.Errorf("error deleting redelegation from the table: %v: %w", err, rdb.ErrWrite) + } + if result.RowsAffected() != 1 { + return fmt.Errorf("error deleting redelegation from the table: no row deleted: %w", rdb.ErrWrite) + } + return nil } @@ -49,9 +140,45 @@ func (view *RedelegationsView) FindBy( height int64, ) (RedelegationRow, bool, error) { - // TODO Handle the error when row is NOT FOUND + sql, sqlArgs, err := view.rdb.StmtBuilder. + Select( + "entries", + ). + From("view_vd_redelegations"). + Where( + "delegator_address = ? AND validator_src_address = ? AND validator_dst_address = ? AND height = ?", + delegatorAddress, + validatorSrcAddress, + validatorDstAddress, + height, + ). + ToSql() + if err != nil { + return RedelegationRow{}, false, fmt.Errorf("error building select redelegation sql: %v: %w", err, rdb.ErrPrepare) + } + + var redelegation RedelegationRow + redelegation.Height = height + redelegation.DelegatorAddress = delegatorAddress + redelegation.ValidatorSrcAddress = validatorSrcAddress + redelegation.ValidatorDstAddress = validatorDstAddress + + var entriesJSON string + if err = view.rdb.QueryRow(sql, sqlArgs...).Scan( + &entriesJSON, + ); err != nil { + if errors.Is(err, rdb.ErrNoRows) { + // When the row is not found, do not return error + return RedelegationRow{}, false, nil + } + return RedelegationRow{}, false, fmt.Errorf("error scanning redelegation: %v: %w", err, rdb.ErrQuery) + } + + if err = jsoniter.UnmarshalFromString(entriesJSON, &redelegation.Entries); err != nil { + return RedelegationRow{}, false, fmt.Errorf("error unmarshalling RedelegationRow.Entries JSON: %v: %w", err, rdb.ErrQuery) + } - return RedelegationRow{}, true, nil + return redelegation, true, nil } func (view *RedelegationsView) ListBySrcValidator( @@ -59,7 +186,54 @@ func (view *RedelegationsView) ListBySrcValidator( height int64, ) ([]RedelegationRow, error) { - return nil, nil + sql, sqlArgs, err := view.rdb.StmtBuilder. + Select( + "delegator_address", + "validator_dst_address", + "entries", + ). + From( + "view_vd_redelegations", + ). + Where( + "validator_src_address = ? AND height = ?", + validatorSrcAddress, + height, + ). + ToSql() + if err != nil { + return nil, fmt.Errorf("error building redelegation select by src validator SQL: %v, %w", err, rdb.ErrBuildSQLStmt) + } + + rowsResult, err := view.rdb.Query(sql, sqlArgs...) + if err != nil { + return nil, fmt.Errorf("error executing redelegation select by src validator SQL: %v: %w", err, rdb.ErrQuery) + } + defer rowsResult.Close() + + redelegations := make([]RedelegationRow, 0) + for rowsResult.Next() { + var redelegation RedelegationRow + redelegation.Height = height + redelegation.ValidatorSrcAddress = validatorSrcAddress + + var entriesJSON string + if err = rowsResult.Scan( + &redelegation.DelegatorAddress, + &redelegation.ValidatorSrcAddress, + &entriesJSON, + ); err != nil { + return nil, fmt.Errorf("error scanning redelegation row: %v: %w", err, rdb.ErrQuery) + } + + if err = jsoniter.UnmarshalFromString(entriesJSON, &redelegation.Entries); err != nil { + return nil, fmt.Errorf("error unmarshalling RedelegationRow.Entries JSON: %v: %w", err, rdb.ErrQuery) + } + + redelegations = append(redelegations, redelegation) + } + + return redelegations, nil } // Notes: diff --git a/projection/validator_delegation/view/unbonding_delegation_queue.go b/projection/validator_delegation/view/unbonding_delegation_queue.go index 8674c488..10d686ac 100644 --- a/projection/validator_delegation/view/unbonding_delegation_queue.go +++ b/projection/validator_delegation/view/unbonding_delegation_queue.go @@ -1,8 +1,12 @@ package view import ( + "errors" + "fmt" + "github.com/crypto-com/chain-indexing/appinterface/rdb" "github.com/crypto-com/chain-indexing/external/utctime" + jsoniter "github.com/json-iterator/go" ) type UnbondingDelegationQueue interface { @@ -23,26 +27,146 @@ func NewUnbondingDelegationQueueView(handle *rdb.Handle) UnbondingDelegationQueu func (view *UnbondingDelegationQueueView) Upsert(row UnbondingDelegationQueueRow) error { + dvPairsJSON, err := jsoniter.MarshalToString(row.DVPairs) + if err != nil { + return fmt.Errorf("error JSON marshalling DVPairs for upsertion: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + sql, sqlArgs, err := view.rdb.StmtBuilder. + Insert( + "view_vd_unbonding_delegation_queue", + ). + Columns( + "completion_time", + "dv_pairs", + ). + Values( + view.rdb.Tton(&row.CompletionTime), + dvPairsJSON, + ). + Suffix("ON CONFLICT(completion_time) DO UPDATE SET dv_pairs = EXCLUDED.dv_pairs"). + ToSql() + + if err != nil { + return fmt.Errorf("error building UnbondingDelegationQueueRow upsertion sql: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + result, err := view.rdb.Exec(sql, sqlArgs...) + if err != nil { + return fmt.Errorf("error upserting UnbondingDelegationQueueRow into the table: %v: %w", err, rdb.ErrWrite) + } + if result.RowsAffected() != 1 { + return fmt.Errorf("error upserting UnbondingDelegationQueueRow into the table: no rows inserted: %w", rdb.ErrWrite) + } + return nil } func (view *UnbondingDelegationQueueView) FindBy(completionTime utctime.UTCTime) (UnbondingDelegationQueueRow, bool, error) { + + sql, sqlArgs, err := view.rdb.StmtBuilder. + Select( + "dv_pairs", + ). + From("view_vd_unbonding_delegation_queue"). + Where( + "completion_time = ?", + view.rdb.Tton(&completionTime), + ). + ToSql() + if err != nil { + return UnbondingDelegationQueueRow{}, false, fmt.Errorf("error building select UnbondingDelegationQueueRow sql: %v: %w", err, rdb.ErrPrepare) + } + var row UnbondingDelegationQueueRow + row.CompletionTime = completionTime + + var dvPairsJSON string + if err = view.rdb.QueryRow(sql, sqlArgs...).Scan( + &dvPairsJSON, + ); err != nil { + if errors.Is(err, rdb.ErrNoRows) { + // When the row is not found, do not return error + return UnbondingDelegationQueueRow{}, false, nil + } + return UnbondingDelegationQueueRow{}, false, fmt.Errorf("error scanning RedelegationQueueRow: %v: %w", err, rdb.ErrQuery) + } - // TODO handle the row not found + if err = jsoniter.UnmarshalFromString(dvPairsJSON, &row.DVPairs); err != nil { + return UnbondingDelegationQueueRow{}, false, fmt.Errorf("error unmarshalling DVPairs JSON: %v: %w", err, rdb.ErrQuery) + } return row, true, nil } func (view *UnbondingDelegationQueueView) DequeueAllMatureUnbondingDelegationQueue(blockTime utctime.UTCTime) ([]DVPair, error) { - // TODO find all mature UnbondingDelegationQueueRow, then concate their DVPairs + // Find all mature UnbondingDelegationQueueRow, then concate their DVPairs + + sql, sqlArgs, err := view.rdb.StmtBuilder. + Select( + "dv_pairs", + ). + From( + "view_vd_unbonding_delegation_queue", + ). + Where( + "completion_time <= ?", + view.rdb.Tton(&blockTime), + ). + ToSql() + if err != nil { + return nil, fmt.Errorf("error building mature UnbondingDelegationQueueRow select SQL: %v, %w", err, rdb.ErrBuildSQLStmt) + } + + rowsResult, err := view.rdb.Query(sql, sqlArgs...) + if err != nil { + return nil, fmt.Errorf("error executing mature UnbondingDelegationQueueRow select SQL: %v: %w", err, rdb.ErrQuery) + } + defer rowsResult.Close() + + matureDVPairs := make([]DVPair, 0) + for rowsResult.Next() { + + var dvPairsJSON string + if err = rowsResult.Scan( + &dvPairsJSON, + ); err != nil { + return nil, fmt.Errorf("error scanning UnbondingDelegationQueueRow: %v: %w", err, rdb.ErrQuery) + } - // Optional TODO: de-duplicate, a same DVPair could appear multiple times, we should avoid that + var dvPairs []DVPair + if err = jsoniter.UnmarshalFromString(dvPairsJSON, &dvPairs); err != nil { + return nil, fmt.Errorf("error unmarshalling DVPairs JSON: %v: %w", err, rdb.ErrQuery) + } - // TODO Delete the mature rows + matureDVPairs = append(matureDVPairs, dvPairs...) + } + + // Optional TODO: De-duplicate the return slice. A same DVPair could appear multiple times, we could avoid it here. + // At the moment, we are following CosmosSDK implementation, so not doing the de-duplicate. + + // Delete the mature rows + + sql, sqlArgs, err = view.rdb.StmtBuilder. + Delete( + "view_vd_unbonding_delegation_queue", + ). + Where( + "completion_time <= ?", + view.rdb.Tton(&blockTime), + ). + ToSql() + if err != nil { + return nil, fmt.Errorf("error building UnbondingDelegationQueueRow deletion sql: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + _, err = view.rdb.Exec(sql, sqlArgs...) + if err != nil { + return nil, fmt.Errorf("error deleting UnbondingDelegationQueueRow from the table: %v: %w", err, rdb.ErrWrite) + } - return nil, nil + return matureDVPairs, nil } // NOTES: diff --git a/projection/validator_delegation/view/unbonding_delegations.go b/projection/validator_delegation/view/unbonding_delegations.go index 0d752420..5c807348 100644 --- a/projection/validator_delegation/view/unbonding_delegations.go +++ b/projection/validator_delegation/view/unbonding_delegations.go @@ -1,11 +1,14 @@ package view import ( + "errors" + "fmt" "time" "github.com/crypto-com/chain-indexing/appinterface/rdb" "github.com/crypto-com/chain-indexing/external/utctime" "github.com/crypto-com/chain-indexing/usecase/coin" + jsoniter "github.com/json-iterator/go" ) type UnbondingDelegations interface { @@ -29,16 +32,99 @@ func NewUnbondingDelegationsView(handle *rdb.Handle) UnbondingDelegations { func (view *UnbondingDelegationsView) Clone(previousHeight, currentHeight int64) error { + sql, sqlErr := view.rdb.StmtBuilder.ReplacePlaceholders(`INSERT INTO view_vd_unbonding_delegations( + height, + delegator_address, + validator_address, + entries + ) SELECT + ?, + delegator_address, + validator_address, + entries + FROM view_vd_unbonding_delegations WHERE height = ? + `) + if sqlErr != nil { + return fmt.Errorf("error building UnbondingDelegation clone sql: %v: %w", sqlErr, rdb.ErrBuildSQLStmt) + } + sqlArgs := []interface{}{ + currentHeight, + previousHeight, + } + + if _, execErr := view.rdb.Exec(sql, sqlArgs...); execErr != nil { + return fmt.Errorf("error cloning UnbondingDelegation into the table: %v: %w", execErr, rdb.ErrWrite) + } + return nil } func (view *UnbondingDelegationsView) Upsert(row UnbondingDelegationRow) error { + entriesJSON, err := jsoniter.MarshalToString(row.Entries) + if err != nil { + return fmt.Errorf("error JSON marshalling UnbondingDelegationRow.Entries for upsertion: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + sql, sqlArgs, err := view.rdb.StmtBuilder. + Insert( + "view_vd_unbonding_delegations", + ). + Columns( + "height", + "delegator_address", + "validator_address", + "entries", + ). + Values( + row.Height, + row.DelegatorAddress, + row.ValidatorAddress, + entriesJSON, + ). + Suffix("ON CONFLICT(delegator_address, validator_address, height) DO UPDATE SET entries = EXCLUDED.entries"). + ToSql() + + if err != nil { + return fmt.Errorf("error building UnbondingDelegation upsertion sql: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + result, err := view.rdb.Exec(sql, sqlArgs...) + if err != nil { + return fmt.Errorf("error upserting UnbondingDelegation into the table: %v: %w", err, rdb.ErrWrite) + } + if result.RowsAffected() != 1 { + return fmt.Errorf("error upserting UnbondingDelegation into the table: no row upserted: %w", rdb.ErrWrite) + } + return nil } func (view *UnbondingDelegationsView) Delete(row UnbondingDelegationRow) error { + sql, sqlArgs, err := view.rdb.StmtBuilder. + Delete( + "view_vd_unbonding_delegations", + ). + Where( + "delegator_address = ? AND validator_address = ? AND height = ?", + row.DelegatorAddress, + row.ValidatorAddress, + row.Height, + ). + ToSql() + if err != nil { + return fmt.Errorf("error building UnbondingDelegation deletion sql: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + result, err := view.rdb.Exec(sql, sqlArgs...) + if err != nil { + return fmt.Errorf("error deleting UnbondingDelegation from the table: %v: %w", err, rdb.ErrWrite) + } + if result.RowsAffected() != 1 { + return fmt.Errorf("error deleting UnbondingDelegation from the table: no row deleted: %w", rdb.ErrWrite) + } + return nil } @@ -48,7 +134,43 @@ func (view *UnbondingDelegationsView) FindBy( height int64, ) (UnbondingDelegationRow, bool, error) { - return UnbondingDelegationRow{}, true, nil + sql, sqlArgs, err := view.rdb.StmtBuilder. + Select( + "entries", + ). + From("view_vd_unbonding_delegations"). + Where( + "delegator_address = ? AND validator_address = ? AND height = ?", + delegatorAddress, + validatorAddress, + height, + ). + ToSql() + if err != nil { + return UnbondingDelegationRow{}, false, fmt.Errorf("error building select UnbondingDelegation sql: %v: %w", err, rdb.ErrPrepare) + } + + var unbondingDelegation UnbondingDelegationRow + unbondingDelegation.Height = height + unbondingDelegation.DelegatorAddress = delegatorAddress + unbondingDelegation.ValidatorAddress = validatorAddress + + var entriesJSON string + if err = view.rdb.QueryRow(sql, sqlArgs...).Scan( + &entriesJSON, + ); err != nil { + if errors.Is(err, rdb.ErrNoRows) { + // When the row is not found, do not return error + return UnbondingDelegationRow{}, false, nil + } + return UnbondingDelegationRow{}, false, fmt.Errorf("error scanning UnbondingDelegation: %v: %w", err, rdb.ErrQuery) + } + + if err = jsoniter.UnmarshalFromString(entriesJSON, &unbondingDelegation.Entries); err != nil { + return UnbondingDelegationRow{}, false, fmt.Errorf("error unmarshalling UnbondingDelegation.Entries JSON: %v: %w", err, rdb.ErrQuery) + } + + return unbondingDelegation, true, nil } func (view *UnbondingDelegationsView) ListByValidator( @@ -56,7 +178,52 @@ func (view *UnbondingDelegationsView) ListByValidator( height int64, ) ([]UnbondingDelegationRow, error) { - return nil, nil + sql, sqlArgs, err := view.rdb.StmtBuilder. + Select( + "delegator_address", + "entries", + ). + From( + "view_vd_unbonding_delegations", + ). + Where( + "validator_address = ? AND height = ?", + validatorAddress, + height, + ). + ToSql() + if err != nil { + return nil, fmt.Errorf("error building UnbondingDelegation select by validator SQL: %v, %w", err, rdb.ErrBuildSQLStmt) + } + + rowsResult, err := view.rdb.Query(sql, sqlArgs...) + if err != nil { + return nil, fmt.Errorf("error executing UnbondingDelegation select by validator SQL: %v: %w", err, rdb.ErrQuery) + } + defer rowsResult.Close() + + unbondingDelegations := make([]UnbondingDelegationRow, 0) + for rowsResult.Next() { + var unbondingDelegation UnbondingDelegationRow + unbondingDelegation.Height = height + unbondingDelegation.ValidatorAddress = validatorAddress + + var entriesJSON string + if err = rowsResult.Scan( + &unbondingDelegation.DelegatorAddress, + &entriesJSON, + ); err != nil { + return nil, fmt.Errorf("error scanning UnbondingDelegation row: %v: %w", err, rdb.ErrQuery) + } + + if err = jsoniter.UnmarshalFromString(entriesJSON, &unbondingDelegation.Entries); err != nil { + return nil, fmt.Errorf("error unmarshalling UnbondingDelegationRow.Entries JSON: %v: %w", err, rdb.ErrQuery) + } + + unbondingDelegations = append(unbondingDelegations, unbondingDelegation) + } + + return unbondingDelegations, nil } // NOTES: diff --git a/projection/validator_delegation/view/unbonding_validators.go b/projection/validator_delegation/view/unbonding_validators.go index fa471247..868ed004 100644 --- a/projection/validator_delegation/view/unbonding_validators.go +++ b/projection/validator_delegation/view/unbonding_validators.go @@ -1,12 +1,14 @@ package view import ( + "fmt" + "github.com/crypto-com/chain-indexing/appinterface/rdb" "github.com/crypto-com/chain-indexing/external/utctime" ) type UnbondingValidators interface { - Insert(operatorAddress string, UnbondingTime utctime.UTCTime) error + Insert(operatorAddress string, unbondingTime utctime.UTCTime) error RemoveIfExist(operatorAddress string) error GetMatureEntries(blockTime utctime.UTCTime) ([]UnbondingValidatorRow, error) DeleteMatureEntries(blockTime utctime.UTCTime) error @@ -22,24 +24,131 @@ func NewUnbondingValidatorsView(handle *rdb.Handle) UnbondingValidators { } } -func (view *UnbondingValidatorsView) Insert(operatorAddress string, UnbondingTime utctime.UTCTime) error { +func (view *UnbondingValidatorsView) Insert(operatorAddress string, unbondingTime utctime.UTCTime) error { + + sql, sqlArgs, err := view.rdb.StmtBuilder. + Insert( + "view_vd_unbonding_validators", + ). + Columns( + "operator_address", + "unbonding_time", + ). + Values( + operatorAddress, + view.rdb.Tton(&unbondingTime), + ). + ToSql() + + if err != nil { + return fmt.Errorf("error building UnbondingValidator insertion sql: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + result, err := view.rdb.Exec(sql, sqlArgs...) + if err != nil { + return fmt.Errorf("error inserting UnbondingValidator into the table: %v: %w", err, rdb.ErrWrite) + } + if result.RowsAffected() != 1 { + return fmt.Errorf("error inserting UnbondingValidator into the table: rows inserted: %v: %w", result.RowsAffected(), rdb.ErrWrite) + } return nil } func (view *UnbondingValidatorsView) RemoveIfExist(operatorAddress string) error { - // First to check if the row exist, then remove it + + sql, sqlArgs, err := view.rdb.StmtBuilder. + Delete( + "view_vd_unbonding_validators", + ). + Where( + "operator_address = ?", + operatorAddress, + ). + ToSql() + if err != nil { + return fmt.Errorf("error building UnbondingValidator deletion sql: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + // Not checking the number of rows deleted here, as it could be 0 or 1. + _, err = view.rdb.Exec(sql, sqlArgs...) + if err != nil { + return fmt.Errorf("error deleting UnbondingValidator from the table: %v: %w", err, rdb.ErrWrite) + } return nil } func (view *UnbondingValidatorsView) GetMatureEntries(blockTime utctime.UTCTime) ([]UnbondingValidatorRow, error) { - return nil, nil + sql, sqlArgs, err := view.rdb.StmtBuilder. + Select( + "operator_address", + "unbonding_time", + ). + From( + "view_vd_unbonding_validators", + ). + Where( + "unbonding_time <= ?", + view.rdb.Tton(&blockTime), + ). + ToSql() + if err != nil { + return nil, fmt.Errorf("error building mature UnbondingValidatorRow select SQL: %v, %w", err, rdb.ErrBuildSQLStmt) + } + + rowsResult, err := view.rdb.Query(sql, sqlArgs...) + if err != nil { + return nil, fmt.Errorf("error executing mature UnbondingValidatorRow select SQL: %v: %w", err, rdb.ErrQuery) + } + defer rowsResult.Close() + + matureRows := make([]UnbondingValidatorRow, 0) + for rowsResult.Next() { + + var row UnbondingValidatorRow + unbondingTimeReader := view.rdb.NtotReader() + + if err = rowsResult.Scan( + &row.OperatorAddress, + unbondingTimeReader.ScannableArg(), + ); err != nil { + return nil, fmt.Errorf("error scanning UnbondingValidatorRow: %v: %w", err, rdb.ErrQuery) + } + + unbondingTime, parseErr := unbondingTimeReader.Parse() + if parseErr != nil { + return nil, fmt.Errorf("error parsing unbondingTime: %v: %w", parseErr, rdb.ErrQuery) + } + row.UnbondingTime = *unbondingTime + + matureRows = append(matureRows, row) + } + + return matureRows, nil } func (view *UnbondingValidatorsView) DeleteMatureEntries(blockTime utctime.UTCTime) error { + sql, sqlArgs, err := view.rdb.StmtBuilder. + Delete( + "view_vd_unbonding_validators", + ). + Where( + "unbonding_time <= ?", + view.rdb.Tton(&blockTime), + ). + ToSql() + if err != nil { + return fmt.Errorf("error building UnbondingValidatorRow deletion sql: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + _, err = view.rdb.Exec(sql, sqlArgs...) + if err != nil { + return fmt.Errorf("error deleting UnbondingValidatorRow from the table: %v: %w", err, rdb.ErrWrite) + } + return nil } diff --git a/projection/validator_delegation/view/validators.go b/projection/validator_delegation/view/validators.go index 2e930d50..6023904b 100644 --- a/projection/validator_delegation/view/validators.go +++ b/projection/validator_delegation/view/validators.go @@ -1,6 +1,9 @@ package view import ( + "errors" + "fmt" + "github.com/crypto-com/chain-indexing/appinterface/pagination" "github.com/crypto-com/chain-indexing/appinterface/rdb" "github.com/crypto-com/chain-indexing/external/utctime" @@ -15,7 +18,6 @@ type Validators interface { Delete(row ValidatorRow) error FindByOperatorAddr(operatorAddress string, height int64) (ValidatorRow, bool, error) FindByConsensusNodeAddr(consensusNodeAddress string, height int64) (ValidatorRow, bool, error) - FindByTendermintAddr(tendermintAddress string, height int64) (ValidatorRow, error) List(height int64, pagination *pagination.Pagination) ([]ValidatorRow, *pagination.PaginationResult, error) } @@ -31,41 +33,278 @@ func NewValidatorsView(handle *rdb.Handle) Validators { func (view *ValidatorsView) Clone(previousHeight, currentHeight int64) error { + sql, sqlErr := view.rdb.StmtBuilder.ReplacePlaceholders(`INSERT INTO view_vd_validators( + height, + operator_address, + consensus_node_address, + tendermint_address, + status, + jailed, + power, + unbonding_height, + unbonding_time, + tokens, + shares, + min_self_delegation + ) SELECT + ?, + operator_address, + consensus_node_address, + tendermint_address, + status, + jailed, + power, + unbonding_height, + unbonding_time, + tokens, + shares, + min_self_delegation + FROM view_vd_validators WHERE height = ? + `) + if sqlErr != nil { + return fmt.Errorf("error building validator clone sql: %v: %w", sqlErr, rdb.ErrBuildSQLStmt) + } + sqlArgs := []interface{}{ + currentHeight, + previousHeight, + } + + if _, execErr := view.rdb.Exec(sql, sqlArgs...); execErr != nil { + return fmt.Errorf("error cloning validator into the table: %v: %w", execErr, rdb.ErrWrite) + } + return nil } func (view *ValidatorsView) Insert(row ValidatorRow) error { + sql, sqlArgs, err := view.rdb.StmtBuilder. + Insert( + "view_vd_validators", + ). + Columns( + "height", + "operator_address", + "consensus_node_address", + "tendermint_address", + "status", + "jailed", + "power", + "unbonding_height", + "unbonding_time", + "tokens", + "shares", + "min_self_delegation", + ). + Values( + row.Height, + row.OperatorAddress, + row.ConsensusNodeAddress, + row.TendermintAddress, + row.Status, + row.Jailed, + row.Power, + row.UnbondingHeight, + view.rdb.Tton(&row.UnbondingTime), + row.Tokens.String(), + row.Shares.String(), + row.MinSelfDelegation.String(), + ). + ToSql() + + if err != nil { + return fmt.Errorf("error building validator insertion sql: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + result, err := view.rdb.Exec(sql, sqlArgs...) + if err != nil { + return fmt.Errorf("error inserting validator into the table: %v: %w", err, rdb.ErrWrite) + } + if result.RowsAffected() != 1 { + return fmt.Errorf("error inserting validator into the table: rows inserted: %v: %w", result.RowsAffected(), rdb.ErrWrite) + } + return nil } func (view *ValidatorsView) Update(row ValidatorRow) error { + sql, sqlArgs, err := view.rdb.StmtBuilder. + Update( + "view_vd_validators", + ). + SetMap(map[string]interface{}{ + "status": row.Status, + "jailed": row.Jailed, + "power": row.Power, + "unbonding_height": row.UnbondingHeight, + "unbonding_time": view.rdb.Tton(&row.UnbondingTime), + "tokens": row.Tokens.String(), + "shares": row.Shares.String(), + "min_self_delegation": row.MinSelfDelegation.String(), + }). + Where( + "operator_address = ? AND height = ?", + row.OperatorAddress, + row.Height, + ). + ToSql() + + if err != nil { + return fmt.Errorf("error building validator update sql: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + result, err := view.rdb.Exec(sql, sqlArgs...) + if err != nil { + return fmt.Errorf("error updating validator into the table: %v: %w", err, rdb.ErrWrite) + } + if result.RowsAffected() != 1 { + return fmt.Errorf("error updating validator into the table: row updated: %v: %w", result.RowsAffected(), rdb.ErrWrite) + } + return nil } func (view *ValidatorsView) Delete(row ValidatorRow) error { + sql, sqlArgs, err := view.rdb.StmtBuilder. + Delete( + "view_vd_validators", + ). + Where( + "operator_address = ? AND height = ?", + row.OperatorAddress, + row.Height, + ). + ToSql() + if err != nil { + return fmt.Errorf("error building validator deletion sql: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + result, err := view.rdb.Exec(sql, sqlArgs...) + if err != nil { + return fmt.Errorf("error deleting validator from the table: %v: %w", err, rdb.ErrWrite) + } + if result.RowsAffected() != 1 { + return fmt.Errorf("error deleting validator into the table: row deleted: %v: %w", result.RowsAffected(), rdb.ErrWrite) + } + return nil } func (view *ValidatorsView) FindByOperatorAddr(operatorAddress string, height int64) (ValidatorRow, bool, error) { - // TODO handle the error when validator is NOT FOUND + row, found, err := view.findBy(&operatorAddress, nil, height) + if err != nil { + return ValidatorRow{}, false, fmt.Errorf("error finding validator by OperatorAddr: %v", err) + } - return ValidatorRow{}, true, nil + return row, found, nil } func (view *ValidatorsView) FindByConsensusNodeAddr(consensusNodeAddress string, height int64) (ValidatorRow, bool, error) { - // TODO handle the error when validator is NOT FOUND + row, found, err := view.findBy(nil, &consensusNodeAddress, height) + if err != nil { + return ValidatorRow{}, false, fmt.Errorf("error finding validator by OperatorAddr: %v", err) + } - return ValidatorRow{}, true, nil + return row, found, nil } -func (view *ValidatorsView) FindByTendermintAddr(tendermintAddress string, height int64) (ValidatorRow, error) { +func (view *ValidatorsView) findBy( + maybeOperatorAddress *string, + maybeConsensusNodeAddress *string, + height int64, +) (ValidatorRow, bool, error) { + + stmtBuilder := view.rdb.StmtBuilder. + Select( + "operator_address", + "consensus_node_address", + "tendermint_address", + "status", + "jailed", + "power", + "unbonding_height", + "unbonding_time", + "tokens", + "shares", + "min_self_delegation", + ). + From("view_vd_validators") + + if maybeOperatorAddress != nil { + stmtBuilder = stmtBuilder.Where( + "operator_address = ? AND height = ?", + *maybeOperatorAddress, + height, + ) + } else if maybeConsensusNodeAddress != nil { + stmtBuilder = stmtBuilder.Where( + "consensus_node_address = ? AND height = ?", + *maybeConsensusNodeAddress, + height, + ) + } else { + return ValidatorRow{}, false, errors.New("no address provided for finding validator") + } - return ValidatorRow{}, nil + sql, sqlArgs, err := stmtBuilder.ToSql() + if err != nil { + return ValidatorRow{}, false, fmt.Errorf("error building select validator sql: %v: %w", err, rdb.ErrPrepare) + } + + var validator ValidatorRow + validator.Height = height + + unbondingTimeReader := view.rdb.NtotReader() + var tokensInString string + var sharesInString string + var minSelfDelegationInString string + if err = view.rdb.QueryRow(sql, sqlArgs...).Scan( + &validator.OperatorAddress, + &validator.ConsensusNodeAddress, + &validator.TendermintAddress, + &validator.Status, + &validator.Jailed, + &validator.Power, + &validator.UnbondingHeight, + unbondingTimeReader.ScannableArg(), + &tokensInString, + &sharesInString, + &minSelfDelegationInString, + ); err != nil { + if errors.Is(err, rdb.ErrNoRows) { + // When the row is not found, do not return error + return ValidatorRow{}, false, nil + } + return ValidatorRow{}, false, fmt.Errorf("error scanning validator: %v: %w", err, rdb.ErrQuery) + } + + unbondingTime, parseErr := unbondingTimeReader.Parse() + if parseErr != nil { + return ValidatorRow{}, false, fmt.Errorf("error parsing unbondingTime: %v: %w", parseErr, rdb.ErrQuery) + } + validator.UnbondingTime = *unbondingTime + + var ok bool + validator.Tokens, ok = coin.NewIntFromString(tokensInString) + if !ok { + return ValidatorRow{}, false, fmt.Errorf("error parsing tokens to coin.Int: %w", rdb.ErrQuery) + } + + validator.Shares, err = coin.NewDecFromStr(sharesInString) + if err != nil { + return ValidatorRow{}, false, fmt.Errorf("error parsing shares to coin.Dec: %v: %w", err, rdb.ErrQuery) + } + + validator.MinSelfDelegation, ok = coin.NewIntFromString(minSelfDelegationInString) + if !ok { + return ValidatorRow{}, false, fmt.Errorf("error parsing min_self_delegation to coin.Int: %w", rdb.ErrQuery) + } + + return validator, true, nil } func (view *ValidatorsView) List( @@ -77,7 +316,99 @@ func (view *ValidatorsView) List( error, ) { - return nil, nil, nil + stmtBuilder := view.rdb.StmtBuilder. + Select( + "operator_address", + "consensus_node_address", + "tendermint_address", + "status", + "jailed", + "power", + "unbonding_height", + "unbonding_time", + "tokens", + "shares", + "min_self_delegation", + ). + From( + "view_vd_validators", + ). + Where( + "height = ?", + height, + ) + + rDbPagination := rdb.NewRDbPaginationBuilder( + pagination, + view.rdb, + ).BuildStmt(stmtBuilder) + sql, sqlArgs, err := rDbPagination.ToStmtBuilder().ToSql() + if err != nil { + return nil, nil, fmt.Errorf("error building validators select SQL: %v, %w", err, rdb.ErrBuildSQLStmt) + } + + rowsResult, err := view.rdb.Query(sql, sqlArgs...) + if err != nil { + return nil, nil, fmt.Errorf("error executing validators select SQL: %v: %w", err, rdb.ErrQuery) + } + defer rowsResult.Close() + + validators := make([]ValidatorRow, 0) + for rowsResult.Next() { + var validator ValidatorRow + validator.Height = height + + unbondingTimeReader := view.rdb.NtotReader() + var tokensInString string + var sharesInString string + var minSelfDelegationInString string + if err = rowsResult.Scan( + &validator.OperatorAddress, + &validator.ConsensusNodeAddress, + &validator.TendermintAddress, + &validator.Status, + &validator.Jailed, + &validator.Power, + &validator.UnbondingHeight, + unbondingTimeReader.ScannableArg(), + &tokensInString, + &sharesInString, + &minSelfDelegationInString, + ); err != nil { + return nil, nil, fmt.Errorf("error scanning delegation row: %v: %w", err, rdb.ErrQuery) + } + + unbondingTime, parseErr := unbondingTimeReader.Parse() + if parseErr != nil { + return nil, nil, fmt.Errorf("error parsing unbondingTime: %v: %w", parseErr, rdb.ErrQuery) + } + validator.UnbondingTime = *unbondingTime + + var ok bool + validator.Tokens, ok = coin.NewIntFromString(tokensInString) + if !ok { + return nil, nil, fmt.Errorf("error parsing tokens to coin.Int: %w", rdb.ErrQuery) + } + + validator.Shares, err = coin.NewDecFromStr(sharesInString) + if err != nil { + return nil, nil, fmt.Errorf("error parsing shares to coin.Dec: %v: %w", err, rdb.ErrQuery) + } + + validator.MinSelfDelegation, ok = coin.NewIntFromString(minSelfDelegationInString) + if !ok { + return nil, nil, fmt.Errorf("error parsing min_self_delegation to coin.Int: %w", rdb.ErrQuery) + } + + validators = append(validators, validator) + } + + paginationResult, err := rDbPagination.Result() + if err != nil { + return nil, nil, fmt.Errorf("error preparing pagination result: %v", err) + } + + return validators, paginationResult, nil } // Notes on `Validator.Status`: @@ -89,10 +420,9 @@ func (view *ValidatorsView) List( // - UnbondingValidator complete Unbonding period: Validator.Status = Unbonded // NOTES: -// - UNIQUE(operatorAddress, consensusNodeAddress, tendermintAddress, height) -// - INDEX(operatorAddress, height) -// - INDEX(consensusNodeAddress, height) -// - INDEX(tendermintAddress, height) +// - UNIQUE(operatorAddress, height) +// - UNIQUE(consensusNodeAddress, height) +// - UNIQUE(tendermintAddress, height) // - INDEX(height) type ValidatorRow struct { Height int64 `json:"height"` From 9dcbc8af673249319616fad07bebe524cdf708e1 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Wed, 19 Jan 2022 14:33:33 +0800 Subject: [PATCH 03/24] Add logic for projection prepare config --- .../validator_delegation.go | 99 ++++++++++++++++--- 1 file changed, 86 insertions(+), 13 deletions(-) diff --git a/projection/validator_delegation/validator_delegation.go b/projection/validator_delegation/validator_delegation.go index 7075ce1c..9d2085e7 100644 --- a/projection/validator_delegation/validator_delegation.go +++ b/projection/validator_delegation/validator_delegation.go @@ -1,10 +1,13 @@ package validator_delegation import ( + "errors" "fmt" "strconv" "time" + "github.com/mitchellh/mapstructure" + "github.com/crypto-com/chain-indexing/appinterface/projection/rdbprojectionbase" "github.com/crypto-com/chain-indexing/appinterface/rdb" event_entity "github.com/crypto-com/chain-indexing/entity/event" @@ -20,6 +23,89 @@ import ( var _ projection_entity.Projection = &ValidatorDelegation{} +type Config struct { + accountAddressPrefix string + validatorAddressPrefix string + conNodeAddressPrefix string + // set in genesis `unbonding_time` + unbondingTime time.Duration + // set in genesis `slash_fraction_double_sign` + slashFractionDoubleSign coin.Dec + // set in genesis `slash_fraction_downtime` + slashFractionDowntime coin.Dec + // PowerReduction - is the amount of staking tokens required for 1 unit of consensus-engine power. + // Currently, this returns a global variable that the app developer can tweak. + // https://github.com/cosmos/cosmos-sdk/blob/0cb7fd081e05317ed7a2f13b0e142349a163fe4d/x/staking/keeper/params.go#L46 + defaultPowerReduction coin.Int +} + +type RawConfig struct { + unbondingTime string `mapstructure:"unbonding_time"` + slashFractionDoubleSign string `mapstructure:"slash_fraction_double_sign"` + slashFractionDowntime string `mapstructure:"slash_fraction_downtime"` + defaultPowerReduction string `mapstructure:"default_power_reduction"` +} + +func RawConfigFromInterface(data interface{}) (RawConfig, error) { + rawConfig := RawConfig{} + + decoderConfig := &mapstructure.DecoderConfig{ + WeaklyTypedInput: true, + Result: &rawConfig, + } + decoder, decoderErr := mapstructure.NewDecoder(decoderConfig) + if decoderErr != nil { + return rawConfig, fmt.Errorf("error creating projection config decoder: %v", decoderErr) + } + + if err := decoder.Decode(data); err != nil { + return rawConfig, fmt.Errorf("error decoding projection ValidatorDelegation config: %v", err) + } + + return rawConfig, nil +} + +func PrepareConfig( + rawConfig RawConfig, + accountAddressPrefix string, + validatorAddressPrefix string, + conNodeAddressPrefix string, +) (Config, error) { + + config := Config{} + config.accountAddressPrefix = accountAddressPrefix + config.validatorAddressPrefix = validatorAddressPrefix + config.conNodeAddressPrefix = conNodeAddressPrefix + + var err error + var ok bool + + config.unbondingTime, err = time.ParseDuration(rawConfig.unbondingTime) + if err != nil { + return config, fmt.Errorf("error parsing unbondingTime from RawConfig: %v", err) + } + + config.slashFractionDoubleSign, err = coin.NewDecFromStr(rawConfig.slashFractionDoubleSign) + if err != nil { + return config, fmt.Errorf("error parsing slashFractionDoubleSign from RawConfig: %v", err) + } + + config.slashFractionDowntime, err = coin.NewDecFromStr(rawConfig.slashFractionDowntime) + if err != nil { + return config, fmt.Errorf("error parsing slashFractionDowntime from RawConfig: %v", err) + } + + config.defaultPowerReduction, ok = coin.NewIntFromString(rawConfig.defaultPowerReduction) + if !ok { + return config, errors.New("error parsing defaultPowerReduction from RawConfig") + } + + fmt.Println(config) + fmt.Printf(">>>>>>>>>>>>\n") + + return config, nil +} + var ( NewValidators = view.NewValidatorsView NewUnbondingValidators = view.NewUnbondingValidatorsView @@ -43,19 +129,6 @@ type ValidatorDelegation struct { migrationHelper migrationhelper.MigrationHelper } -type Config struct { - accountAddressPrefix string - validatorAddressPrefix string - conNodeAddressPrefix string - unbondingTime time.Duration // set in genesis `unbonding_time` - slashFractionDoubleSign coin.Dec // set in genesis `slash_fraction_double_sign` - slashFractionDowntime coin.Dec // set in genesis `slash_fraction_downtime` - // PowerReduction - is the amount of staking tokens required for 1 unit of consensus-engine power. - // Currently, this returns a global variable that the app developer can tweak. - // https://github.com/cosmos/cosmos-sdk/blob/0cb7fd081e05317ed7a2f13b0e142349a163fe4d/x/staking/keeper/params.go#L46 - defaultPowerReduction coin.Int -} - func NewValidatorDelegation( logger applogger.Logger, rdbConn rdb.Conn, From cd561ef0929656bc61c4c88f89a486e516b971dc Mon Sep 17 00:00:00 2001 From: Yang Song Date: Wed, 19 Jan 2022 17:50:31 +0800 Subject: [PATCH 04/24] Add config init. Fixed migration script. --- projection/validator_delegation/delegation.go | 4 +- .../validator_delegation/handle_end_block.go | 4 +- ...117133017_create_view_vd_validators.up.sql | 4 +- .../validator_delegation/redelegation.go | 2 +- projection/validator_delegation/slash.go | 2 +- projection/validator_delegation/validator.go | 2 +- .../validator_delegation.go | 66 +++++++++---------- 7 files changed, 41 insertions(+), 43 deletions(-) diff --git a/projection/validator_delegation/delegation.go b/projection/validator_delegation/delegation.go index 5c9bbdeb..cd4a6233 100644 --- a/projection/validator_delegation/delegation.go +++ b/projection/validator_delegation/delegation.go @@ -214,8 +214,8 @@ func (projection *ValidatorDelegation) unbond( isOperatorDelegation, err := utils.IsValAddrEqualsDelAddr( validatorAddress, delegatorAddress, - projection.config.validatorAddressPrefix, - projection.config.accountAddressPrefix, + projection.config.ValidatorAddressPrefix, + projection.config.AccountAddressPrefix, ) if err != nil { return coin.ZeroInt(), fmt.Errorf("error in checking if ValidatorAddr and DelegatorAddr are the same address: %v", err) diff --git a/projection/validator_delegation/handle_end_block.go b/projection/validator_delegation/handle_end_block.go index 1902c06d..efa69a33 100644 --- a/projection/validator_delegation/handle_end_block.go +++ b/projection/validator_delegation/handle_end_block.go @@ -17,7 +17,7 @@ func (projection *ValidatorDelegation) handlePowerChanged( power string, ) error { - consensusNodeAddress, err := utils.GetConsensusNodeAddress(tendermintPubKey, projection.config.conNodeAddressPrefix) + consensusNodeAddress, err := utils.GetConsensusNodeAddress(tendermintPubKey, projection.config.ConNodeAddressPrefix) if err != nil { return fmt.Errorf("error getting consensusNodeAddress from tendermint pub key: %v", err) } @@ -40,7 +40,7 @@ func (projection *ValidatorDelegation) handlePowerChanged( // UnbondingHeight is the height when Unbonding start // UnbondingTime is the time when Unbonding is finished validator.UnbondingHeight = height - validator.UnbondingTime = blockTime.Add(projection.config.unbondingTime) + validator.UnbondingTime = blockTime.Add(projection.config.UnbondingTime) // Insert the validator to UnbondingValidators set if err := unbondingValidatorsView.Insert(validator.OperatorAddress, validator.UnbondingTime); err != nil { diff --git a/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql index c92806eb..27519678 100644 --- a/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql +++ b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql @@ -13,8 +13,8 @@ CREATE TABLE view_vd_validators ( shares VARCHAR NOT NULL, min_self_delegation VARCHAR NOT NULL, PRIMARY KEY (id), - UNIQUE(operator_address, height) - UNIQUE(consensus_node_address, height) + UNIQUE(operator_address, height), + UNIQUE(consensus_node_address, height), UNIQUE(tendermint_address, height) ); diff --git a/projection/validator_delegation/redelegation.go b/projection/validator_delegation/redelegation.go index 33dc74fd..6a235270 100644 --- a/projection/validator_delegation/redelegation.go +++ b/projection/validator_delegation/redelegation.go @@ -105,7 +105,7 @@ func (projection *ValidatorDelegation) calculateRedelegationCompleteTime( switch { case !found || validator.IsBonded(): // the longest wait - just unbonding period from now - completionTime = blockTime.Add(projection.config.unbondingTime) + completionTime = blockTime.Add(projection.config.UnbondingTime) return completionTime, false, nil diff --git a/projection/validator_delegation/slash.go b/projection/validator_delegation/slash.go index d9664f6c..2f137e19 100644 --- a/projection/validator_delegation/slash.go +++ b/projection/validator_delegation/slash.go @@ -52,7 +52,7 @@ func (projection *ValidatorDelegation) handleSlash( return fmt.Errorf("attempted to slash with a negative slash factor: %v", slashFactor) } - amount := utils.TokensFromConsensusPower(power, projection.config.defaultPowerReduction) + amount := utils.TokensFromConsensusPower(power, projection.config.DefaultPowerReduction) slashAmountDec := amount.ToDec().Mul(slashFactor) slashAmount := slashAmountDec.TruncateInt() diff --git a/projection/validator_delegation/validator.go b/projection/validator_delegation/validator.go index 5fedace2..1c3d0487 100644 --- a/projection/validator_delegation/validator.go +++ b/projection/validator_delegation/validator.go @@ -21,7 +21,7 @@ func (projection *ValidatorDelegation) handleCreateNewValidator( minSelfDelegationInString string, ) error { - consensusNodeAddress, err := utils.GetConsensusNodeAddress(tendermintPubKey, projection.config.conNodeAddressPrefix) + consensusNodeAddress, err := utils.GetConsensusNodeAddress(tendermintPubKey, projection.config.ConNodeAddressPrefix) if err != nil { return fmt.Errorf("error in GetConsensusNodeAddress: %v", err) } diff --git a/projection/validator_delegation/validator_delegation.go b/projection/validator_delegation/validator_delegation.go index 9d2085e7..f562e981 100644 --- a/projection/validator_delegation/validator_delegation.go +++ b/projection/validator_delegation/validator_delegation.go @@ -24,84 +24,82 @@ import ( var _ projection_entity.Projection = &ValidatorDelegation{} type Config struct { - accountAddressPrefix string - validatorAddressPrefix string - conNodeAddressPrefix string + AccountAddressPrefix string + ValidatorAddressPrefix string + ConNodeAddressPrefix string // set in genesis `unbonding_time` - unbondingTime time.Duration + UnbondingTime time.Duration // set in genesis `slash_fraction_double_sign` - slashFractionDoubleSign coin.Dec + SlashFractionDoubleSign coin.Dec // set in genesis `slash_fraction_downtime` - slashFractionDowntime coin.Dec + SlashFractionDowntime coin.Dec // PowerReduction - is the amount of staking tokens required for 1 unit of consensus-engine power. // Currently, this returns a global variable that the app developer can tweak. // https://github.com/cosmos/cosmos-sdk/blob/0cb7fd081e05317ed7a2f13b0e142349a163fe4d/x/staking/keeper/params.go#L46 - defaultPowerReduction coin.Int + DefaultPowerReduction coin.Int } -type RawConfig struct { - unbondingTime string `mapstructure:"unbonding_time"` - slashFractionDoubleSign string `mapstructure:"slash_fraction_double_sign"` - slashFractionDowntime string `mapstructure:"slash_fraction_downtime"` - defaultPowerReduction string `mapstructure:"default_power_reduction"` +type CustomConfig struct { + UnbondingTime time.Duration `mapstructure:"unbonding_time"` + SlashFractionDoubleSign string `mapstructure:"slash_fraction_double_sign"` + SlashFractionDowntime string `mapstructure:"slash_fraction_downtime"` + DefaultPowerReduction string `mapstructure:"default_power_reduction"` } -func RawConfigFromInterface(data interface{}) (RawConfig, error) { - rawConfig := RawConfig{} +func CustomConfigFromInterface(data interface{}) (CustomConfig, error) { + customConfig := CustomConfig{} decoderConfig := &mapstructure.DecoderConfig{ WeaklyTypedInput: true, - Result: &rawConfig, + DecodeHook: mapstructure.ComposeDecodeHookFunc( + mapstructure.StringToTimeDurationHookFunc(), + ), + Result: &customConfig, } decoder, decoderErr := mapstructure.NewDecoder(decoderConfig) if decoderErr != nil { - return rawConfig, fmt.Errorf("error creating projection config decoder: %v", decoderErr) + return customConfig, fmt.Errorf("error creating projection config decoder: %v", decoderErr) } if err := decoder.Decode(data); err != nil { - return rawConfig, fmt.Errorf("error decoding projection ValidatorDelegation config: %v", err) + return customConfig, fmt.Errorf("error decoding projection ValidatorDelegation config: %v", err) } - return rawConfig, nil + return customConfig, nil } func PrepareConfig( - rawConfig RawConfig, + customConfig CustomConfig, accountAddressPrefix string, validatorAddressPrefix string, conNodeAddressPrefix string, ) (Config, error) { config := Config{} - config.accountAddressPrefix = accountAddressPrefix - config.validatorAddressPrefix = validatorAddressPrefix - config.conNodeAddressPrefix = conNodeAddressPrefix + config.AccountAddressPrefix = accountAddressPrefix + config.ValidatorAddressPrefix = validatorAddressPrefix + config.ConNodeAddressPrefix = conNodeAddressPrefix + config.UnbondingTime = customConfig.UnbondingTime var err error var ok bool - config.unbondingTime, err = time.ParseDuration(rawConfig.unbondingTime) - if err != nil { - return config, fmt.Errorf("error parsing unbondingTime from RawConfig: %v", err) - } - - config.slashFractionDoubleSign, err = coin.NewDecFromStr(rawConfig.slashFractionDoubleSign) + config.SlashFractionDoubleSign, err = coin.NewDecFromStr(customConfig.SlashFractionDoubleSign) if err != nil { return config, fmt.Errorf("error parsing slashFractionDoubleSign from RawConfig: %v", err) } - - config.slashFractionDowntime, err = coin.NewDecFromStr(rawConfig.slashFractionDowntime) + config.SlashFractionDowntime, err = coin.NewDecFromStr(customConfig.SlashFractionDowntime) if err != nil { return config, fmt.Errorf("error parsing slashFractionDowntime from RawConfig: %v", err) } - - config.defaultPowerReduction, ok = coin.NewIntFromString(rawConfig.defaultPowerReduction) + config.DefaultPowerReduction, ok = coin.NewIntFromString(customConfig.DefaultPowerReduction) if !ok { return config, errors.New("error parsing defaultPowerReduction from RawConfig") } fmt.Println(config) fmt.Printf(">>>>>>>>>>>>\n") + time.Sleep(10 * time.Second) return config, nil } @@ -329,7 +327,7 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event typedEvent.ConsensusNodeAddress, distributionHeight, power, - projection.config.slashFractionDowntime, + projection.config.SlashFractionDowntime, ); err != nil { return fmt.Errorf("error in handling slash event with missing_signature: %v", err) } @@ -368,7 +366,7 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event typedEvent.ConsensusNodeAddress, distributionHeight, power, - projection.config.slashFractionDoubleSign, + projection.config.SlashFractionDoubleSign, ); err != nil { return fmt.Errorf("error in handling slash event with double_sign: %v", err) } From 23000b2efca5499726a7d344fb9f8dc4fb8aa4e9 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Fri, 21 Jan 2022 13:42:14 +0800 Subject: [PATCH 05/24] Added logic for handle MsgCreateValidator in Genesis --- .../validator_delegation/handle_end_block.go | 1 + projection/validator_delegation/validator.go | 73 ++++++++++++++++++- .../validator_delegation.go | 6 +- 3 files changed, 73 insertions(+), 7 deletions(-) diff --git a/projection/validator_delegation/handle_end_block.go b/projection/validator_delegation/handle_end_block.go index efa69a33..79a305da 100644 --- a/projection/validator_delegation/handle_end_block.go +++ b/projection/validator_delegation/handle_end_block.go @@ -57,6 +57,7 @@ func (projection *ValidatorDelegation) handlePowerChanged( return fmt.Errorf("error removing unbonding validator entry: %v", err) } } + validator.Power = power // Update the validator if err := validatorsView.Update(validator); err != nil { diff --git a/projection/validator_delegation/validator.go b/projection/validator_delegation/validator.go index 1c3d0487..ea9406ea 100644 --- a/projection/validator_delegation/validator.go +++ b/projection/validator_delegation/validator.go @@ -11,6 +11,75 @@ import ( "github.com/crypto-com/chain-indexing/usecase/coin" ) +func (projection *ValidatorDelegation) handleGenesisCreateNewValidator( + rdbTxHandle *rdb.Handle, + height int64, + validatorAddress string, + delegatorAddress string, + tendermintPubKey string, + amount coin.Int, + minSelfDelegationInString string, +) error { + + consensusNodeAddress, err := utils.GetConsensusNodeAddress(tendermintPubKey, projection.config.ConNodeAddressPrefix) + if err != nil { + return fmt.Errorf("error in GetConsensusNodeAddress: %v", err) + } + + tendermintAddress, err := utils.GetTendermintAddress(tendermintPubKey) + if err != nil { + return fmt.Errorf("error in GetTendermintAddress: %v", err) + } + + minSelfDelegation, ok := coin.NewIntFromString(minSelfDelegationInString) + if !ok { + return fmt.Errorf("Failed to parse minSelfDelegationInString: %v", minSelfDelegationInString) + } + + // Insert an ValidatorRow. + validatorsView := NewValidators(rdbTxHandle) + validatorRow := view.ValidatorRow{ + Height: height, + + OperatorAddress: validatorAddress, + ConsensusNodeAddress: consensusNodeAddress, + TendermintAddress: tendermintAddress, + + // For MsgCreateValidator in genesis block, we assumed they are always BONDED. + // Here, as genesis has no block_results and power_changed event, we just set the power as `1`, + // indicating that's a bonded validator. + // + // TODO: What if gen_txs contains more validators than maximum validators? + // In that case, may consider parsing `max_validators` from genesis. + // And only marked top `max_validators` validators as bonded. + Status: types.BONDED, + Jailed: false, + Power: "1", + + UnbondingHeight: int64(0), + UnbondingTime: utctime.UTCTime{}, + + Tokens: coin.ZeroInt(), + Shares: coin.ZeroDec(), + MinSelfDelegation: minSelfDelegation, + } + if err := validatorsView.Insert(validatorRow); err != nil { + return fmt.Errorf("error inserting ValidatorRow: %v", err) + } + + if _, err := projection.handleDelegate( + rdbTxHandle, + height, + validatorAddress, + delegatorAddress, + amount, + ); err != nil { + return fmt.Errorf("error handling Delegate: %v", err) + } + + return nil +} + func (projection *ValidatorDelegation) handleCreateNewValidator( rdbTxHandle *rdb.Handle, height int64, @@ -57,7 +126,7 @@ func (projection *ValidatorDelegation) handleCreateNewValidator( MinSelfDelegation: minSelfDelegation, } if err := validatorsView.Insert(validatorRow); err != nil { - return fmt.Errorf("error validatorsView.Insert(): %v", err) + return fmt.Errorf("error inserting ValidatorRow: %v", err) } if _, err := projection.handleDelegate( @@ -67,7 +136,7 @@ func (projection *ValidatorDelegation) handleCreateNewValidator( delegatorAddress, amount, ); err != nil { - return fmt.Errorf("error in projection.handleDelegate(): %v", err) + return fmt.Errorf("error handling Delegate: %v", err) } return nil diff --git a/projection/validator_delegation/validator_delegation.go b/projection/validator_delegation/validator_delegation.go index f562e981..4d026d2c 100644 --- a/projection/validator_delegation/validator_delegation.go +++ b/projection/validator_delegation/validator_delegation.go @@ -97,10 +97,6 @@ func PrepareConfig( return config, errors.New("error parsing defaultPowerReduction from RawConfig") } - fmt.Println(config) - fmt.Printf(">>>>>>>>>>>>\n") - time.Sleep(10 * time.Second) - return config, nil } @@ -242,7 +238,7 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event for _, event := range events { if typedEvent, ok := event.(*event_usecase.CreateGenesisValidator); ok { - if err := projection.handleCreateNewValidator( + if err := projection.handleGenesisCreateNewValidator( rdbTxHandle, height, typedEvent.ValidatorAddress, From 69ad576d870c6d3e2f0525dceed88ba424f35ad7 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Fri, 21 Jan 2022 13:42:58 +0800 Subject: [PATCH 06/24] Added test APIs to fetch validators and delegations --- .../httpapi/handlers/validator_delegation.go | 198 ++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 infrastructure/httpapi/handlers/validator_delegation.go diff --git a/infrastructure/httpapi/handlers/validator_delegation.go b/infrastructure/httpapi/handlers/validator_delegation.go new file mode 100644 index 00000000..63adf0f2 --- /dev/null +++ b/infrastructure/httpapi/handlers/validator_delegation.go @@ -0,0 +1,198 @@ +package handlers + +import ( + "errors" + "fmt" + "strconv" + "strings" + + "github.com/valyala/fasthttp" + + "github.com/crypto-com/chain-indexing/appinterface/rdb" + applogger "github.com/crypto-com/chain-indexing/external/logger" + "github.com/crypto-com/chain-indexing/infrastructure/httpapi" + validator_delegation_view "github.com/crypto-com/chain-indexing/projection/validator_delegation/view" +) + +type ValidatorDelegation struct { + logger applogger.Logger + + accountAddressPrefix string + validatorAddressPrefix string + consNodeAddressPrefix string + + validatorsView validator_delegation_view.Validators + delegationsView validator_delegation_view.Delegations +} + +func NewValidatorDelegation( + logger applogger.Logger, + accountAddressPrefix string, + validatorAddressPrefix string, + consNodeAddressPrefix string, + rdbHandle *rdb.Handle, +) *ValidatorDelegation { + return &ValidatorDelegation{ + logger.WithFields(applogger.LogFields{ + "module": "ValidatorDelegationHandler", + }), + + accountAddressPrefix, + validatorAddressPrefix, + consNodeAddressPrefix, + + validator_delegation_view.NewValidatorsView(rdbHandle), + validator_delegation_view.NewDelegationsView(rdbHandle), + } +} + +func (handler *ValidatorDelegation) FindValidatorByAddress(ctx *fasthttp.RequestCtx) { + + height, err := parseInputHeight(ctx) + if err != nil { + httpapi.BadRequest(ctx, fmt.Errorf("error parsing input height: %v", err)) + return + } + + address, ok := ctx.UserValue("address").(string) + if !ok { + httpapi.BadRequest(ctx, errors.New("error parsing input address")) + return + } + + var validator validator_delegation_view.ValidatorRow + var found bool + + if strings.HasPrefix(address, handler.consNodeAddressPrefix) { + + validator, found, err = handler.validatorsView.FindByConsensusNodeAddr(address, height) + if err != nil { + handler.logger.Errorf("error finding validator by ConsensusNodeAddress: %v", err) + httpapi.InternalServerError(ctx) + return + } + if !found { + httpapi.NotFound(ctx) + return + } + + } else if strings.HasPrefix(address, handler.validatorAddressPrefix) { + + validator, found, err = handler.validatorsView.FindByOperatorAddr(address, height) + if err != nil { + handler.logger.Errorf("error finding validaotr by OperatorAddress: %v", err) + httpapi.InternalServerError(ctx) + return + } + if !found { + httpapi.NotFound(ctx) + return + } + + } else { + httpapi.BadRequest(ctx, errors.New("invalid address")) + return + } + + httpapi.Success(ctx, validator) +} + +func (handler *ValidatorDelegation) ListValidator(ctx *fasthttp.RequestCtx) { + + pagination, err := httpapi.ParsePagination(ctx) + if err != nil { + ctx.SetStatusCode(fasthttp.StatusBadRequest) + return + } + + height, err := parseInputHeight(ctx) + if err != nil { + httpapi.BadRequest(ctx, fmt.Errorf("error parsing input height: %v", err)) + return + } + + validators, paginationResult, err := handler.validatorsView.List(height, pagination) + if err != nil { + handler.logger.Errorf("error listing validators: %v", err) + httpapi.InternalServerError(ctx) + return + } + + httpapi.SuccessWithPagination(ctx, validators, paginationResult) +} + +func (handler *ValidatorDelegation) ListDelegationByValidator(ctx *fasthttp.RequestCtx) { + + pagination, err := httpapi.ParsePagination(ctx) + if err != nil { + ctx.SetStatusCode(fasthttp.StatusBadRequest) + return + } + + height, err := parseInputHeight(ctx) + if err != nil { + httpapi.BadRequest(ctx, fmt.Errorf("error parsing input height: %v", err)) + return + } + + address, ok := ctx.UserValue("address").(string) + if !ok { + httpapi.BadRequest(ctx, errors.New("error parsing input address")) + return + } + + delegations, paginationResult, err := handler.delegationsView.ListByValidatorAddr(address, height, pagination) + if err != nil { + handler.logger.Errorf("error listing delegations by ValidatorAddress: %v", err) + httpapi.InternalServerError(ctx) + return + } + + httpapi.SuccessWithPagination(ctx, delegations, paginationResult) +} + +func (handler *ValidatorDelegation) ListDelegationByDelegator(ctx *fasthttp.RequestCtx) { + + pagination, err := httpapi.ParsePagination(ctx) + if err != nil { + ctx.SetStatusCode(fasthttp.StatusBadRequest) + return + } + + height, err := parseInputHeight(ctx) + if err != nil { + httpapi.BadRequest(ctx, fmt.Errorf("error parsing input height: %v", err)) + return + } + + address, ok := ctx.UserValue("address").(string) + if !ok { + httpapi.BadRequest(ctx, errors.New("error parsing input address")) + return + } + + delegations, paginationResult, err := handler.delegationsView.ListByDelegatorAddr(address, height, pagination) + if err != nil { + handler.logger.Errorf("error listing delegations by DelegatorAddress: %v", err) + httpapi.InternalServerError(ctx) + return + } + + httpapi.SuccessWithPagination(ctx, delegations, paginationResult) +} + +func parseInputHeight(ctx *fasthttp.RequestCtx) (int64, error) { + + queryArgs := ctx.QueryArgs() + if queryArgs.Has("height") { + + heightInString := string(queryArgs.Peek("height")) + return strconv.ParseInt(heightInString, 10, 64) + + } else { + // TODO: If no input height, then use latest height as height + // return validator_delegation_view.LATEST_HEIGHT, nil + return 0, errors.New("No input height") + } + +} From 46f686eba13230d6bda6b732302d61636953ed43 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Mon, 24 Jan 2022 11:12:22 +0800 Subject: [PATCH 07/24] Add temporary operation performance log DB schema. --- ...02425_create_view_vd_operation_performance_log.down.sql | 1 + ...4102425_create_view_vd_operation_performance_log.up.sql | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.down.sql create mode 100644 projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.up.sql diff --git a/projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.down.sql b/projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.down.sql new file mode 100644 index 00000000..2b0ea9f8 --- /dev/null +++ b/projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS view_vd_operation_performance_log; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.up.sql b/projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.up.sql new file mode 100644 index 00000000..1fff2957 --- /dev/null +++ b/projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.up.sql @@ -0,0 +1,7 @@ +CREATE TABLE view_vd_operation_performance_log ( + id BIGSERIAL, + height BIGINT NOT NULL, + action VARCHAR NOT NULL, + duration BIGINT NOT NULL, + PRIMARY KEY (id) +); From 2413edf8e858a3dcef932af2c84c1a36d5f67c46 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Mon, 24 Jan 2022 11:38:02 +0800 Subject: [PATCH 08/24] Add height index on delegations table --- ...220124112840_create_view_vd_delegations_height_index.down.sql | 1 + ...20220124112840_create_view_vd_delegations_height_index.up.sql | 1 + 2 files changed, 2 insertions(+) create mode 100644 projection/validator_delegation/migrations/20220124112840_create_view_vd_delegations_height_index.down.sql create mode 100644 projection/validator_delegation/migrations/20220124112840_create_view_vd_delegations_height_index.up.sql diff --git a/projection/validator_delegation/migrations/20220124112840_create_view_vd_delegations_height_index.down.sql b/projection/validator_delegation/migrations/20220124112840_create_view_vd_delegations_height_index.down.sql new file mode 100644 index 00000000..2ba90791 --- /dev/null +++ b/projection/validator_delegation/migrations/20220124112840_create_view_vd_delegations_height_index.down.sql @@ -0,0 +1 @@ +DROP INDEX IF EXISTS view_vd_delegations_height_index; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220124112840_create_view_vd_delegations_height_index.up.sql b/projection/validator_delegation/migrations/20220124112840_create_view_vd_delegations_height_index.up.sql new file mode 100644 index 00000000..eb944f35 --- /dev/null +++ b/projection/validator_delegation/migrations/20220124112840_create_view_vd_delegations_height_index.up.sql @@ -0,0 +1 @@ +CREATE INDEX view_vd_delegations_height_index ON view_vd_delegations USING btree (height); \ No newline at end of file From 50e375b9fca0f71490ebc9a300c4420d2ca59819 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Mon, 24 Jan 2022 11:52:23 +0800 Subject: [PATCH 09/24] Refactor migrations --- .../20220117104331_create_view_vd_delegations.down.sql | 2 ++ .../migrations/20220117104331_create_view_vd_delegations.up.sql | 2 ++ ...20124112840_create_view_vd_delegations_height_index.down.sql | 1 - ...0220124112840_create_view_vd_delegations_height_index.up.sql | 1 - 4 files changed, 4 insertions(+), 2 deletions(-) delete mode 100644 projection/validator_delegation/migrations/20220124112840_create_view_vd_delegations_height_index.down.sql delete mode 100644 projection/validator_delegation/migrations/20220124112840_create_view_vd_delegations_height_index.up.sql diff --git a/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.down.sql b/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.down.sql index 1cfb512c..84819986 100644 --- a/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.down.sql +++ b/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.down.sql @@ -2,4 +2,6 @@ DROP INDEX IF EXISTS view_vd_delegations_delegator_height_index; DROP INDEX IF EXISTS view_vd_delegations_validator_height_index; +DROP INDEX IF EXISTS view_vd_delegations_height_index; + DROP TABLE IF EXISTS view_vd_delegations; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.up.sql b/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.up.sql index 67efce83..53f726b4 100644 --- a/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.up.sql +++ b/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.up.sql @@ -8,6 +8,8 @@ CREATE TABLE view_vd_delegations ( UNIQUE(validator_address, delegator_address, height) ); +CREATE INDEX view_vd_delegations_height_index ON view_vd_delegations USING btree (height); + CREATE INDEX view_vd_delegations_validator_height_index ON view_vd_delegations USING btree (validator_address, height); CREATE INDEX view_vd_delegations_delegator_height_index ON view_vd_delegations USING btree (delegator_address, height); \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220124112840_create_view_vd_delegations_height_index.down.sql b/projection/validator_delegation/migrations/20220124112840_create_view_vd_delegations_height_index.down.sql deleted file mode 100644 index 2ba90791..00000000 --- a/projection/validator_delegation/migrations/20220124112840_create_view_vd_delegations_height_index.down.sql +++ /dev/null @@ -1 +0,0 @@ -DROP INDEX IF EXISTS view_vd_delegations_height_index; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220124112840_create_view_vd_delegations_height_index.up.sql b/projection/validator_delegation/migrations/20220124112840_create_view_vd_delegations_height_index.up.sql deleted file mode 100644 index eb944f35..00000000 --- a/projection/validator_delegation/migrations/20220124112840_create_view_vd_delegations_height_index.up.sql +++ /dev/null @@ -1 +0,0 @@ -CREATE INDEX view_vd_delegations_height_index ON view_vd_delegations USING btree (height); \ No newline at end of file From 0e7583754008c8306a97f001a51ea7099bf57a34 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Tue, 25 Jan 2022 11:57:01 +0800 Subject: [PATCH 10/24] Fixed validator json fields --- projection/validator_delegation/view/validators.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projection/validator_delegation/view/validators.go b/projection/validator_delegation/view/validators.go index 6023904b..4077692e 100644 --- a/projection/validator_delegation/view/validators.go +++ b/projection/validator_delegation/view/validators.go @@ -437,9 +437,9 @@ type ValidatorRow struct { // `UnbondingHeight` and `UnbondingTime` only useful when `Status` is `Unbonding` // The height start the Unbonding - UnbondingHeight int64 `json:"UnbondingHeight"` + UnbondingHeight int64 `json:"unbondingHeight"` // The time when Unbonding is finished - UnbondingTime utctime.UTCTime `json:"UnbondingTime"` + UnbondingTime utctime.UTCTime `json:"unbondingTime"` Tokens coin.Int `json:"tokens"` Shares coin.Dec `json:"shares"` From 24c890e431a25055eac2b344f1dcdbf2f139d8a7 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Fri, 28 Jan 2022 15:05:35 +0800 Subject: [PATCH 11/24] Fix a bug that validator is not removed when its token decrease to 0. --- projection/validator_delegation/handle_end_block.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/projection/validator_delegation/handle_end_block.go b/projection/validator_delegation/handle_end_block.go index 79a305da..34b6aac9 100644 --- a/projection/validator_delegation/handle_end_block.go +++ b/projection/validator_delegation/handle_end_block.go @@ -99,6 +99,13 @@ func (projection *ValidatorDelegation) handleMatureUnbondingValidators( return fmt.Errorf("error updating validator: %v", err) } + // Remove validator if the shares is zero + if validator.Shares.IsZero() { + if err := validatorsView.Delete(validator); err != nil { + return fmt.Errorf("error deleting validator: %v", err) + } + } + } // Remove those mature UnbondingValidator entry From 826fc2549b69412aee842339cb8cf4889b0e7a17 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Fri, 28 Jan 2022 18:06:56 +0800 Subject: [PATCH 12/24] Update migrations script to test range type performance --- ...20117104331_create_view_vd_delegations.down.sql | 8 ++------ ...0220117104331_create_view_vd_delegations.up.sql | 14 ++++++-------- ...eate_view_vd_operation_performance_log.down.sql | 2 ++ ...create_view_vd_operation_performance_log.up.sql | 2 ++ 4 files changed, 12 insertions(+), 14 deletions(-) diff --git a/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.down.sql b/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.down.sql index 84819986..87cfa3ed 100644 --- a/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.down.sql +++ b/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.down.sql @@ -1,7 +1,3 @@ -DROP INDEX IF EXISTS view_vd_delegations_delegator_height_index; +DROP TABLE IF EXISTS view_vd_delegations; -DROP INDEX IF EXISTS view_vd_delegations_validator_height_index; - -DROP INDEX IF EXISTS view_vd_delegations_height_index; - -DROP TABLE IF EXISTS view_vd_delegations; \ No newline at end of file +DROP EXTENSION IF EXISTS btree_gist; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.up.sql b/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.up.sql index 53f726b4..0ebe3f0b 100644 --- a/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.up.sql +++ b/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.up.sql @@ -1,15 +1,13 @@ +CREATE EXTENSION btree_gist; + CREATE TABLE view_vd_delegations ( id BIGSERIAL, - height BIGINT NOT NULL, + height INT8RANGE NOT NULL, validator_address VARCHAR NOT NULL, delegator_address VARCHAR NOT NULL, shares VARCHAR NOT NULL, PRIMARY KEY (id), - UNIQUE(validator_address, delegator_address, height) + -- Below is a constraint and it is also an index. + -- It prevents a delegation record appear twice at any given height. + EXCLUDE USING gist (validator_address WITH =, delegator_address WITH =, height WITH &&) ); - -CREATE INDEX view_vd_delegations_height_index ON view_vd_delegations USING btree (height); - -CREATE INDEX view_vd_delegations_validator_height_index ON view_vd_delegations USING btree (validator_address, height); - -CREATE INDEX view_vd_delegations_delegator_height_index ON view_vd_delegations USING btree (delegator_address, height); \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.down.sql b/projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.down.sql index 2b0ea9f8..453594fe 100644 --- a/projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.down.sql +++ b/projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.down.sql @@ -1 +1,3 @@ +DROP INDEX IF EXISTS view_vd_operation_performance_log_height_index; + DROP TABLE IF EXISTS view_vd_operation_performance_log; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.up.sql b/projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.up.sql index 1fff2957..7441734a 100644 --- a/projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.up.sql +++ b/projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.up.sql @@ -5,3 +5,5 @@ CREATE TABLE view_vd_operation_performance_log ( duration BIGINT NOT NULL, PRIMARY KEY (id) ); + +CREATE INDEX view_vd_operation_performance_log_height_index ON view_vd_operation_performance_log USING btree (height); From 1d33b462d9906c8805cb8768c9b4ab408e238a44 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Fri, 4 Feb 2022 15:41:46 +0800 Subject: [PATCH 13/24] Apply range types for other tables in the new projection. --- ...17111937_create_view_vd_redelegations.down.sql | 2 -- ...0117111937_create_view_vd_redelegations.up.sql | 13 +++++++++---- ..._create_view_vd_unbonding_delegations.down.sql | 4 ---- ...00_create_view_vd_unbonding_delegations.up.sql | 10 ++++------ ...20117133017_create_view_vd_validators.down.sql | 2 -- ...0220117133017_create_view_vd_validators.up.sql | 15 +++++++++------ 6 files changed, 22 insertions(+), 24 deletions(-) diff --git a/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.down.sql b/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.down.sql index bdf5e83a..f60bf6d8 100644 --- a/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.down.sql +++ b/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.down.sql @@ -1,3 +1 @@ -DROP INDEX IF EXISTS view_vd_redelegations_src_validator_height_index; - DROP TABLE IF EXISTS view_vd_redelegations; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.up.sql b/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.up.sql index d49d3bc4..e7fc1546 100644 --- a/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.up.sql +++ b/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.up.sql @@ -1,12 +1,17 @@ CREATE TABLE view_vd_redelegations ( id BIGSERIAL, - height BIGINT NOT NULL, + height INT8RANGE NOT NULL, delegator_address VARCHAR NOT NULL, validator_src_address VARCHAR NOT NULL, validator_dst_address VARCHAR NOT NULL, entries JSONB NOT NULL, PRIMARY KEY (id), - UNIQUE(delegator_address, validator_src_address, validator_dst_address, height) + -- Below is a constraint and it is also an index. + -- It prevents a delegation record appear twice at any given height. + EXCLUDE USING gist ( + delegator_address WITH =, + validator_src_address WITH =, + validator_dst_address WITH =, + height WITH && + ) ); - -CREATE INDEX view_vd_redelegations_src_validator_height_index ON view_vd_redelegations USING btree (validator_src_address, height); \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.down.sql b/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.down.sql index bc3e2643..8276bc82 100644 --- a/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.down.sql +++ b/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.down.sql @@ -1,5 +1 @@ -DROP INDEX IF EXISTS view_vd_unbonding_delegations_delegator_height_index; - -DROP INDEX IF EXISTS view_vd_unbonding_delegations_validator_height_index; - DROP TABLE IF EXISTS view_vd_unbonding_delegations; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.up.sql b/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.up.sql index 409beafb..0cc98c3c 100644 --- a/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.up.sql +++ b/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.up.sql @@ -1,13 +1,11 @@ CREATE TABLE view_vd_unbonding_delegations ( id BIGSERIAL, - height BIGINT NOT NULL, + height INT8RANGE NOT NULL, delegator_address VARCHAR NOT NULL, validator_address VARCHAR NOT NULL, entries JSONB NOT NULL, PRIMARY KEY (id), - UNIQUE(delegator_address, validator_address, height) + -- Below is a constraint and it is also an index. + -- It prevents a delegation record appear twice at any given height. + EXCLUDE USING gist (delegator_address WITH =, validator_address WITH =, height WITH &&) ); - -CREATE INDEX view_vd_unbonding_delegations_validator_height_index ON view_vd_unbonding_delegations USING btree (validator_address, height); - -CREATE INDEX view_vd_unbonding_delegations_delegator_height_index ON view_vd_unbonding_delegations USING btree (delegator_address, height); \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.down.sql b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.down.sql index 3d9e6dcf..1edb1c84 100644 --- a/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.down.sql +++ b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.down.sql @@ -1,3 +1 @@ -DROP INDEX IF EXISTS view_vd_validators_height_index; - DROP TABLE IF EXISTS view_vd_validators; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql index 27519678..37f67f69 100644 --- a/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql +++ b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql @@ -1,6 +1,6 @@ CREATE TABLE view_vd_validators ( id BIGSERIAL, - height BIGINT NOT NULL, + height INT8RANGE NOT NULL, operator_address VARCHAR NOT NULL, consensus_node_address VARCHAR NOT NULL, tendermint_address VARCHAR NOT NULL, @@ -13,9 +13,12 @@ CREATE TABLE view_vd_validators ( shares VARCHAR NOT NULL, min_self_delegation VARCHAR NOT NULL, PRIMARY KEY (id), - UNIQUE(operator_address, height), - UNIQUE(consensus_node_address, height), - UNIQUE(tendermint_address, height) + -- Below is a constraint and it is also an index. + -- It prevents a delegation record appear twice at any given height. + EXCLUDE USING gist ( + operator_address WITH =, + consensus_node_address WITH =, + tendermint_address WITH =, + height WITH && + ) ); - -CREATE INDEX view_vd_validators_height_index ON view_vd_validators USING btree (height); From c321a08258252c55314e3aa5e7dc12c82e13ef3d Mon Sep 17 00:00:00 2001 From: Yang Song Date: Mon, 7 Feb 2022 13:36:40 +0800 Subject: [PATCH 14/24] Apply range type to delegations, unbondingDelegations, redelegations and validators tables. --- .../validator_delegation/redelegation.go | 14 +- projection/validator_delegation/slash.go | 4 +- .../unbonding_delegation.go | 14 +- .../validator_delegation/view/delegations.go | 169 ++++++------ .../view/redelegations.go | 245 ++++++++++++++---- .../view/unbonding_delegations.go | 239 +++++++++++++---- .../validator_delegation/view/validators.go | 187 ++++++------- 7 files changed, 578 insertions(+), 294 deletions(-) diff --git a/projection/validator_delegation/redelegation.go b/projection/validator_delegation/redelegation.go index 6a235270..d6149efd 100644 --- a/projection/validator_delegation/redelegation.go +++ b/projection/validator_delegation/redelegation.go @@ -139,6 +139,10 @@ func (projection *ValidatorDelegation) setRedelegationEntry( } if found { red.AddEntry(creationHeight, completionTime, balance, sharesDst) + + if err := redelegationsView.Update(red); err != nil { + return red, fmt.Errorf("error updating reledegation record: %v", err) + } } else { red = view.NewRedelegationRow( delegatorAddress, @@ -149,10 +153,10 @@ func (projection *ValidatorDelegation) setRedelegationEntry( balance, sharesDst, ) - } - if err := redelegationsView.Upsert(red); err != nil { - return red, fmt.Errorf("error upserting reledegation record: %v", err) + if err := redelegationsView.Insert(red); err != nil { + return red, fmt.Errorf("error inserting reledegation record: %v", err) + } } return red, nil @@ -194,8 +198,8 @@ func (projection *ValidatorDelegation) completeRedelegation( } else { - if err := redelegationsView.Upsert(red); err != nil { - return fmt.Errorf("error upserting reledegation record: %v", err) + if err := redelegationsView.Update(red); err != nil { + return fmt.Errorf("error updating reledegation record: %v", err) } } diff --git a/projection/validator_delegation/slash.go b/projection/validator_delegation/slash.go index 2f137e19..2fa9adfe 100644 --- a/projection/validator_delegation/slash.go +++ b/projection/validator_delegation/slash.go @@ -193,8 +193,8 @@ func (projection *ValidatorDelegation) slashUnbondingDelegation( } unbondingDelegationsView := NewUnbondingDelegations(rdbTxHandle) - if err := unbondingDelegationsView.Upsert(unbondingDelegation); err != nil { - return coin.ZeroInt(), fmt.Errorf("error upserting unbonding delegation record: %v", err) + if err := unbondingDelegationsView.Update(unbondingDelegation); err != nil { + return coin.ZeroInt(), fmt.Errorf("error updating unbonding delegation record: %v", err) } return totalSlashAmount, nil diff --git a/projection/validator_delegation/unbonding_delegation.go b/projection/validator_delegation/unbonding_delegation.go index c1588ced..1714cefa 100644 --- a/projection/validator_delegation/unbonding_delegation.go +++ b/projection/validator_delegation/unbonding_delegation.go @@ -26,12 +26,16 @@ func (projection *ValidatorDelegation) setUnbondingDelegationEntry( } if found { ubd.AddEntry(creationHeight, completionTime, balance) + + if err := unbondingDelegationsView.Update(ubd); err != nil { + return ubd, fmt.Errorf("error updating unbonding delegation record: %v", err) + } } else { ubd = view.NewUnbondingDelegationRow(delegatorAddress, validatorAddress, creationHeight, completionTime, balance) - } - if err := unbondingDelegationsView.Upsert(ubd); err != nil { - return ubd, fmt.Errorf("error upserting unbonding delegation record: %v", err) + if err := unbondingDelegationsView.Insert(ubd); err != nil { + return ubd, fmt.Errorf("error inserting unbonding delegation record: %v", err) + } } return ubd, nil @@ -72,8 +76,8 @@ func (projection *ValidatorDelegation) completeUnbonding( } else { - if err := unbondingDelegationsView.Upsert(ubd); err != nil { - return fmt.Errorf("error upserting unbonding delegation: %v", err) + if err := unbondingDelegationsView.Update(ubd); err != nil { + return fmt.Errorf("error updating unbonding delegation: %v", err) } } diff --git a/projection/validator_delegation/view/delegations.go b/projection/validator_delegation/view/delegations.go index 421a670f..4e113d57 100644 --- a/projection/validator_delegation/view/delegations.go +++ b/projection/validator_delegation/view/delegations.go @@ -4,15 +4,12 @@ import ( "errors" "fmt" - "github.com/crypto-com/chain-indexing/appinterface/pagination" pagination_appinterface "github.com/crypto-com/chain-indexing/appinterface/pagination" "github.com/crypto-com/chain-indexing/appinterface/rdb" "github.com/crypto-com/chain-indexing/usecase/coin" ) type Delegations interface { - Clone(previousHeight int64, currentHeight int64) error - Insert(row DelegationRow) error Update(row DelegationRow) error Delete(row DelegationRow) error @@ -22,13 +19,13 @@ type Delegations interface { ListByValidatorAddr( validatorAddress string, height int64, - pagination *pagination.Pagination, - ) ([]DelegationRow, *pagination.PaginationResult, error) + pagination *pagination_appinterface.Pagination, + ) ([]DelegationRow, *pagination_appinterface.PaginationResult, error) ListByDelegatorAddr( delegatorAddress string, height int64, - pagination *pagination.Pagination, - ) ([]DelegationRow, *pagination.PaginationResult, error) + pagination *pagination_appinterface.Pagination, + ) ([]DelegationRow, *pagination_appinterface.PaginationResult, error) } type DelegationsView struct { @@ -41,35 +38,6 @@ func NewDelegationsView(handle *rdb.Handle) Delegations { } } -func (view *DelegationsView) Clone(previousHeight, currentHeight int64) error { - - sql, sqlErr := view.rdb.StmtBuilder.ReplacePlaceholders(`INSERT INTO view_vd_delegations( - height, - validator_address, - delegator_address, - shares - ) SELECT - ?, - validator_address, - delegator_address, - shares - FROM view_vd_delegations WHERE height = ? - `) - if sqlErr != nil { - return fmt.Errorf("error building delegation clone sql: %v: %w", sqlErr, rdb.ErrBuildSQLStmt) - } - sqlArgs := []interface{}{ - currentHeight, - previousHeight, - } - - if _, execErr := view.rdb.Exec(sql, sqlArgs...); execErr != nil { - return fmt.Errorf("error cloning delegation into the table: %v: %w", execErr, rdb.ErrWrite) - } - - return nil -} - func (view *DelegationsView) Insert(row DelegationRow) error { sql, sqlArgs, err := view.rdb.StmtBuilder. @@ -83,7 +51,7 @@ func (view *DelegationsView) Insert(row DelegationRow) error { "shares", ). Values( - row.Height, + fmt.Sprintf("[%v,)", row.Height), row.ValidatorAddress, row.DelegatorAddress, row.Shares.String(), @@ -107,59 +75,112 @@ func (view *DelegationsView) Insert(row DelegationRow) error { func (view *DelegationsView) Update(row DelegationRow) error { - sql, sqlArgs, err := view.rdb.StmtBuilder. - Update( - "view_vd_delegations", - ). - SetMap(map[string]interface{}{ - "shares": row.Shares.String(), - }). - Where( - "validator_address = ? AND delegator_address = ? AND height = ?", - row.ValidatorAddress, - row.DelegatorAddress, - row.Height, - ). - ToSql() - + // Check if there is an record's lower bound start with this height. + found, err := view.checkIfDelegationRecordExistByHeightLowerBound(row) if err != nil { - return fmt.Errorf("error building delegation update sql: %v: %w", err, rdb.ErrBuildSQLStmt) + return fmt.Errorf("error in checking new delegation record existence at this height: %v", err) } - result, err := view.rdb.Exec(sql, sqlArgs...) - if err != nil { - return fmt.Errorf("error updating delegation into the table: %v: %w", err, rdb.ErrWrite) - } - if result.RowsAffected() != 1 { - return fmt.Errorf("error updating delegation into the table: row updated: %v: %w", result.RowsAffected(), rdb.ErrWrite) + if found { + // If there is a record lower(height) == row.Height, then update the existed one + + sql, sqlArgs, err := view.rdb.StmtBuilder. + Update( + "view_vd_delegations", + ). + SetMap(map[string]interface{}{ + "shares": row.Shares.String(), + }). + Where( + "validator_address = ? AND delegator_address = ? AND height @> ?::int8", + row.ValidatorAddress, + row.DelegatorAddress, + row.Height, + ). + ToSql() + + if err != nil { + return fmt.Errorf("error building delegation update sql: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + result, err := view.rdb.Exec(sql, sqlArgs...) + if err != nil { + return fmt.Errorf("error updating delegation into the table: %v: %w", err, rdb.ErrWrite) + } + if result.RowsAffected() != 1 { + return fmt.Errorf("error updating delegation into the table: row updated: %v: %w", result.RowsAffected(), rdb.ErrWrite) + } + + } else { + // Else, update the previous record's height range, then insert a new record + + err := view.setDelegationRecordHeightUpperBound(row) + if err != nil { + return fmt.Errorf("error updating delegation.Height upper bound: %v", err) + } + err = view.Insert(row) + if err != nil { + return fmt.Errorf("error inserting a new record for this delegation: %v", err) + } + } return nil } -func (view *DelegationsView) Delete(row DelegationRow) error { +func (view *DelegationsView) checkIfDelegationRecordExistByHeightLowerBound(row DelegationRow) (bool, error) { sql, sqlArgs, err := view.rdb.StmtBuilder. - Delete( - "view_vd_delegations", + Select( + "COUNT(*)", ). + From("view_vd_delegations"). Where( - "validator_address = ? AND delegator_address = ? AND height = ?", + "validator_address = ? AND delegator_address = ? AND lower(height) = ?", row.ValidatorAddress, row.DelegatorAddress, row.Height, ). ToSql() if err != nil { - return fmt.Errorf("error building delegation deletion sql: %v: %w", err, rdb.ErrBuildSQLStmt) + return false, fmt.Errorf("error building 'checking delegation at specific lower(height) sql: %v: %w", err, rdb.ErrPrepare) } - result, err := view.rdb.Exec(sql, sqlArgs...) - if err != nil { - return fmt.Errorf("error deleting delegation from the table: %v: %w", err, rdb.ErrWrite) + var count int64 + if err = view.rdb.QueryRow(sql, sqlArgs...).Scan( + &count, + ); err != nil { + return false, fmt.Errorf("error scanning count: %v: %w", err, rdb.ErrQuery) } - if result.RowsAffected() != 1 { - return fmt.Errorf("error deleting delegation into the table: no row deleted: %w", rdb.ErrWrite) + + return count == 1, nil +} + +func (view *DelegationsView) Delete(row DelegationRow) error { + + return view.setDelegationRecordHeightUpperBound(row) +} + +func (view *DelegationsView) setDelegationRecordHeightUpperBound(row DelegationRow) error { + + // Set the upper bound for record height: `[, row.Height)`. + sql, sqlErr := view.rdb.StmtBuilder.ReplacePlaceholders(` + UPDATE view_vd_delegations + SET height = int8range(lower(height), ?, '[)') + WHERE validator_address = ? AND delegator_address = ? AND height @> ?::int8 + `) + if sqlErr != nil { + return fmt.Errorf("error building delegation upper(height) update sql: %v: %w", sqlErr, rdb.ErrBuildSQLStmt) + } + sqlArgs := []interface{}{ + row.Height, + row.ValidatorAddress, + row.DelegatorAddress, + row.Height, + } + + if _, execErr := view.rdb.Exec(sql, sqlArgs...); execErr != nil { + return fmt.Errorf("error executing delegation upper(height)update sql: %v: %w", execErr, rdb.ErrWrite) } return nil @@ -177,7 +198,7 @@ func (view *DelegationsView) FindBy( ). From("view_vd_delegations"). Where( - "validator_address = ? AND delegator_address = ? AND height = ?", + "validator_address = ? AND delegator_address = ? AND height @> ?::int8", validatorAddress, delegatorAddress, height, @@ -226,7 +247,7 @@ func (view *DelegationsView) ListByValidatorAddr( "view_vd_delegations", ). Where( - "validator_address = ? AND height = ?", + "validator_address = ? AND height @> ?::int8", validatorAddress, height, ) @@ -291,7 +312,7 @@ func (view *DelegationsView) ListByDelegatorAddr( "view_vd_delegations", ). Where( - "delegator_address = ? AND height = ?", + "delegator_address = ? AND height @> ?::int8", delegatorAddress, height, ) @@ -341,10 +362,6 @@ func (view *DelegationsView) ListByDelegatorAddr( return delegations, paginationResult, nil } -// Notes: -// - UNIQUE(validatorAddress, delegatorAddress, height) -// - INDEX(validatorAddress, height) -// - INDEX(delegatorAddress, height) type DelegationRow struct { Height int64 `json:"height"` ValidatorAddress string `json:"validatorAddress"` diff --git a/projection/validator_delegation/view/redelegations.go b/projection/validator_delegation/view/redelegations.go index 2c672c42..6774882d 100644 --- a/projection/validator_delegation/view/redelegations.go +++ b/projection/validator_delegation/view/redelegations.go @@ -5,6 +5,7 @@ import ( "fmt" "time" + pagination_appinterface "github.com/crypto-com/chain-indexing/appinterface/pagination" "github.com/crypto-com/chain-indexing/appinterface/rdb" "github.com/crypto-com/chain-indexing/external/utctime" "github.com/crypto-com/chain-indexing/usecase/coin" @@ -12,12 +13,18 @@ import ( ) type Redelegations interface { - Clone(previousHeight int64, currentHeight int64) error - - Upsert(row RedelegationRow) error + Insert(row RedelegationRow) error + Update(row RedelegationRow) error Delete(row RedelegationRow) error FindBy(delegatorAddress, validatorSrcAddress, validatorDstAddress string, height int64) (RedelegationRow, bool, error) + // For internal projection logic ListBySrcValidator(validatorSrcAddress string, height int64) ([]RedelegationRow, error) + // For HTTP API + ListBySrcValidatorWithPagination( + validatorSrcAddress string, + height int64, + pagination *pagination_appinterface.Pagination, + ) ([]RedelegationRow, *pagination_appinterface.PaginationResult, error) } type RedelegationsView struct { @@ -30,38 +37,7 @@ func NewRedelegationsView(handle *rdb.Handle) Redelegations { } } -func (view *RedelegationsView) Clone(previousHeight, currentHeight int64) error { - - sql, sqlErr := view.rdb.StmtBuilder.ReplacePlaceholders(`INSERT INTO view_vd_redelegations( - height, - delegator_address, - validator_src_address, - validator_dst_address, - entries - ) SELECT - ?, - delegator_address, - validator_src_address, - validator_dst_address, - entries - FROM view_vd_redelegations WHERE height = ? - `) - if sqlErr != nil { - return fmt.Errorf("error building redelegation clone sql: %v: %w", sqlErr, rdb.ErrBuildSQLStmt) - } - sqlArgs := []interface{}{ - currentHeight, - previousHeight, - } - - if _, execErr := view.rdb.Exec(sql, sqlArgs...); execErr != nil { - return fmt.Errorf("error cloning redelegation into the table: %v: %w", execErr, rdb.ErrWrite) - } - - return nil -} - -func (view *RedelegationsView) Upsert(row RedelegationRow) error { +func (view *RedelegationsView) Insert(row RedelegationRow) error { entriesJSON, err := jsoniter.MarshalToString(row.Entries) if err != nil { @@ -80,38 +56,99 @@ func (view *RedelegationsView) Upsert(row RedelegationRow) error { "entries", ). Values( - row.Height, + fmt.Sprintf("[%v,)", row.Height), row.DelegatorAddress, row.ValidatorSrcAddress, row.ValidatorDstAddress, entriesJSON, ). - Suffix("ON CONFLICT(delegator_address, validator_src_address, validator_dst_address, height) DO UPDATE SET entries = EXCLUDED.entries"). ToSql() if err != nil { - return fmt.Errorf("error building redelegation upsertion sql: %v: %w", err, rdb.ErrBuildSQLStmt) + return fmt.Errorf("error building redelegation insertion sql: %v: %w", err, rdb.ErrBuildSQLStmt) } result, err := view.rdb.Exec(sql, sqlArgs...) if err != nil { - return fmt.Errorf("error upserting redelegation into the table: %v: %w", err, rdb.ErrWrite) + return fmt.Errorf("error inserting redelegation into the table: %v: %w", err, rdb.ErrWrite) } if result.RowsAffected() != 1 { - return fmt.Errorf("error upserting redelegation into the table: no row upserted: %w", rdb.ErrWrite) + return fmt.Errorf("error inserting redelegation into the table: no row upserted: %w", rdb.ErrWrite) } return nil } -func (view *RedelegationsView) Delete(row RedelegationRow) error { +func (view *RedelegationsView) Update(row RedelegationRow) error { + + // Check if there is an record's lower bound start with this height. + found, err := view.checkIfRedelegationRecordExistByHeightLowerBound(row) + if err != nil { + return fmt.Errorf("error in checking new Redelegation record existence at this height: %v", err) + } + + if found { + // If there is a record lower(height) == row.Height, then update the existed one + + entriesJSON, err := jsoniter.MarshalToString(row.Entries) + if err != nil { + return fmt.Errorf("error JSON marshalling RedelegationRow.Entries for upsertion: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + sql, sqlArgs, err := view.rdb.StmtBuilder. + Update( + "view_vd_redelegations", + ). + SetMap(map[string]interface{}{ + "entries": entriesJSON, + }). + Where( + "delegator_address = ? AND validator_src_address = ? AND validator_dst_address = ? AND height @> ?::int8", + row.DelegatorAddress, + row.ValidatorSrcAddress, + row.ValidatorDstAddress, + row.Height, + ). + ToSql() + + if err != nil { + return fmt.Errorf("error building Redelegation update sql: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + result, err := view.rdb.Exec(sql, sqlArgs...) + if err != nil { + return fmt.Errorf("error updating Redelegation into the table: %v: %w", err, rdb.ErrWrite) + } + if result.RowsAffected() != 1 { + return fmt.Errorf("error updating Redelegation into the table: row updated: %v: %w", result.RowsAffected(), rdb.ErrWrite) + } + + } else { + // If there is not an existed record, then update the previous record's height range and insert a new record + + err := view.setRedelegationRecordHeightUpperBound(row) + if err != nil { + return fmt.Errorf("error updating Redelegation.Height upper bound: %v", err) + } + err = view.Insert(row) + if err != nil { + return fmt.Errorf("error inserting a new record for this Redelegation: %v", err) + } + + } + + return nil +} + +func (view *RedelegationsView) checkIfRedelegationRecordExistByHeightLowerBound(row RedelegationRow) (bool, error) { sql, sqlArgs, err := view.rdb.StmtBuilder. - Delete( - "view_vd_redelegations", + Select( + "COUNT(*)", ). + From("view_vd_redelegations"). Where( - "delegator_address = ? AND validator_src_address = ? AND validator_dst_address = ? AND height = ?", + "delegator_address = ? AND validator_src_address = ? AND validator_dst_address = ? AND lower(height) = ?", row.DelegatorAddress, row.ValidatorSrcAddress, row.ValidatorDstAddress, @@ -119,15 +156,45 @@ func (view *RedelegationsView) Delete(row RedelegationRow) error { ). ToSql() if err != nil { - return fmt.Errorf("error building redelegation deletion sql: %v: %w", err, rdb.ErrBuildSQLStmt) + return false, fmt.Errorf("error building 'checking Redelegation at specific lower(height) sql: %v: %w", err, rdb.ErrPrepare) } - result, err := view.rdb.Exec(sql, sqlArgs...) - if err != nil { - return fmt.Errorf("error deleting redelegation from the table: %v: %w", err, rdb.ErrWrite) + var count int64 + if err = view.rdb.QueryRow(sql, sqlArgs...).Scan( + &count, + ); err != nil { + return false, fmt.Errorf("error scanning count: %v: %w", err, rdb.ErrQuery) } - if result.RowsAffected() != 1 { - return fmt.Errorf("error deleting redelegation from the table: no row deleted: %w", rdb.ErrWrite) + + return count == 1, nil +} + +func (view *RedelegationsView) Delete(row RedelegationRow) error { + + return view.setRedelegationRecordHeightUpperBound(row) +} + +func (view *RedelegationsView) setRedelegationRecordHeightUpperBound(row RedelegationRow) error { + + // Set the upper bound for record height: `[, row.Height)`. + sql, sqlErr := view.rdb.StmtBuilder.ReplacePlaceholders(` + UPDATE view_vd_redelegations + SET height = int8range(lower(height), ?, '[)') + WHERE delegator_address = ? AND validator_src_address = ? AND validator_dst_address = ? AND height @> ?::int8 + `) + if sqlErr != nil { + return fmt.Errorf("error building Redelegation upper(height) update sql: %v: %w", sqlErr, rdb.ErrBuildSQLStmt) + } + sqlArgs := []interface{}{ + row.Height, + row.DelegatorAddress, + row.ValidatorSrcAddress, + row.ValidatorDstAddress, + row.Height, + } + + if _, execErr := view.rdb.Exec(sql, sqlArgs...); execErr != nil { + return fmt.Errorf("error executing Redelegation upper(height)update sql: %v: %w", execErr, rdb.ErrWrite) } return nil @@ -146,7 +213,7 @@ func (view *RedelegationsView) FindBy( ). From("view_vd_redelegations"). Where( - "delegator_address = ? AND validator_src_address = ? AND validator_dst_address = ? AND height = ?", + "delegator_address = ? AND validator_src_address = ? AND validator_dst_address = ? AND height @> ?::int8", delegatorAddress, validatorSrcAddress, validatorDstAddress, @@ -196,7 +263,7 @@ func (view *RedelegationsView) ListBySrcValidator( "view_vd_redelegations", ). Where( - "validator_src_address = ? AND height = ?", + "validator_src_address = ? AND height @> ?::int8", validatorSrcAddress, height, ). @@ -220,7 +287,7 @@ func (view *RedelegationsView) ListBySrcValidator( var entriesJSON string if err = rowsResult.Scan( &redelegation.DelegatorAddress, - &redelegation.ValidatorSrcAddress, + &redelegation.ValidatorDstAddress, &entriesJSON, ); err != nil { return nil, fmt.Errorf("error scanning redelegation row: %v: %w", err, rdb.ErrQuery) @@ -236,9 +303,72 @@ func (view *RedelegationsView) ListBySrcValidator( return redelegations, nil } -// Notes: -// - UNIQUE(delegatorAddress, validatorSrcAddress, validatorDstAddress, height) -// - Index(validatorSrcAddress, height) +func (view *RedelegationsView) ListBySrcValidatorWithPagination( + validatorSrcAddress string, + height int64, + pagination *pagination_appinterface.Pagination, +) ([]RedelegationRow, *pagination_appinterface.PaginationResult, error) { + + stmtBuilder := view.rdb.StmtBuilder. + Select( + "delegator_address", + "validator_dst_address", + "entries", + ). + From( + "view_vd_redelegations", + ). + Where( + "validator_src_address = ? AND height @> ?::int8", + validatorSrcAddress, + height, + ) + + rDbPagination := rdb.NewRDbPaginationBuilder( + pagination, + view.rdb, + ).BuildStmt(stmtBuilder) + sql, sqlArgs, err := rDbPagination.ToStmtBuilder().ToSql() + if err != nil { + return nil, nil, fmt.Errorf("error building redelegation select by src validator SQL: %v, %w", err, rdb.ErrBuildSQLStmt) + } + + rowsResult, err := view.rdb.Query(sql, sqlArgs...) + if err != nil { + return nil, nil, fmt.Errorf("error executing redelegation select by src validator SQL: %v: %w", err, rdb.ErrQuery) + } + defer rowsResult.Close() + + redelegations := make([]RedelegationRow, 0) + for rowsResult.Next() { + var redelegation RedelegationRow + redelegation.Height = height + redelegation.ValidatorSrcAddress = validatorSrcAddress + + var entriesJSON string + if err = rowsResult.Scan( + &redelegation.DelegatorAddress, + &redelegation.ValidatorDstAddress, + &entriesJSON, + ); err != nil { + return nil, nil, fmt.Errorf("error scanning redelegation row: %v: %w", err, rdb.ErrQuery) + } + + if err = jsoniter.UnmarshalFromString(entriesJSON, &redelegation.Entries); err != nil { + return nil, nil, fmt.Errorf("error unmarshalling RedelegationRow.Entries JSON: %v: %w", err, rdb.ErrQuery) + } + + redelegations = append(redelegations, redelegation) + } + + paginationResult, err := rDbPagination.Result() + if err != nil { + return nil, nil, fmt.Errorf("error preparing pagination result: %v", err) + } + + return redelegations, paginationResult, nil +} + type RedelegationRow struct { Height int64 `json:"height"` DelegatorAddress string `json:"delegatorAddress"` @@ -257,9 +387,10 @@ func NewRedelegationRow( sharesDst coin.Dec, ) RedelegationRow { return RedelegationRow{ + Height: creationHeight, DelegatorAddress: delegatorAddress, ValidatorSrcAddress: validatorSrcAddress, - ValidatorDstAddress: validatorSrcAddress, + ValidatorDstAddress: validatorDstAddress, Entries: []RedelegationEntry{ NewRedelegationEntry(creationHeight, completionTime, balance, sharesDst), }, diff --git a/projection/validator_delegation/view/unbonding_delegations.go b/projection/validator_delegation/view/unbonding_delegations.go index 5c807348..5e488ca6 100644 --- a/projection/validator_delegation/view/unbonding_delegations.go +++ b/projection/validator_delegation/view/unbonding_delegations.go @@ -5,6 +5,7 @@ import ( "fmt" "time" + pagination_appinterface "github.com/crypto-com/chain-indexing/appinterface/pagination" "github.com/crypto-com/chain-indexing/appinterface/rdb" "github.com/crypto-com/chain-indexing/external/utctime" "github.com/crypto-com/chain-indexing/usecase/coin" @@ -12,12 +13,18 @@ import ( ) type UnbondingDelegations interface { - Clone(previousHeight int64, currentHeight int64) error - - Upsert(row UnbondingDelegationRow) error + Insert(row UnbondingDelegationRow) error + Update(row UnbondingDelegationRow) error Delete(row UnbondingDelegationRow) error FindBy(delegatorAddress, validatorAddress string, height int64) (UnbondingDelegationRow, bool, error) + // For internal projection logic ListByValidator(validatorAddress string, height int64) ([]UnbondingDelegationRow, error) + // For HTTP API + ListByValidatorWithPagination( + validatorAddress string, + height int64, + pagination *pagination_appinterface.Pagination, + ) ([]UnbondingDelegationRow, *pagination_appinterface.PaginationResult, error) } type UnbondingDelegationsView struct { @@ -30,40 +37,10 @@ func NewUnbondingDelegationsView(handle *rdb.Handle) UnbondingDelegations { } } -func (view *UnbondingDelegationsView) Clone(previousHeight, currentHeight int64) error { - - sql, sqlErr := view.rdb.StmtBuilder.ReplacePlaceholders(`INSERT INTO view_vd_unbonding_delegations( - height, - delegator_address, - validator_address, - entries - ) SELECT - ?, - delegator_address, - validator_address, - entries - FROM view_vd_unbonding_delegations WHERE height = ? - `) - if sqlErr != nil { - return fmt.Errorf("error building UnbondingDelegation clone sql: %v: %w", sqlErr, rdb.ErrBuildSQLStmt) - } - sqlArgs := []interface{}{ - currentHeight, - previousHeight, - } - - if _, execErr := view.rdb.Exec(sql, sqlArgs...); execErr != nil { - return fmt.Errorf("error cloning UnbondingDelegation into the table: %v: %w", execErr, rdb.ErrWrite) - } - - return nil -} - -func (view *UnbondingDelegationsView) Upsert(row UnbondingDelegationRow) error { - +func (view *UnbondingDelegationsView) Insert(row UnbondingDelegationRow) error { entriesJSON, err := jsoniter.MarshalToString(row.Entries) if err != nil { - return fmt.Errorf("error JSON marshalling UnbondingDelegationRow.Entries for upsertion: %v: %w", err, rdb.ErrBuildSQLStmt) + return fmt.Errorf("error JSON marshalling UnbondingDelegationRow.Entries for insertion: %v: %w", err, rdb.ErrBuildSQLStmt) } sql, sqlArgs, err := view.rdb.StmtBuilder. @@ -77,52 +54,141 @@ func (view *UnbondingDelegationsView) Upsert(row UnbondingDelegationRow) error { "entries", ). Values( - row.Height, + fmt.Sprintf("[%v,)", row.Height), row.DelegatorAddress, row.ValidatorAddress, entriesJSON, ). - Suffix("ON CONFLICT(delegator_address, validator_address, height) DO UPDATE SET entries = EXCLUDED.entries"). ToSql() if err != nil { - return fmt.Errorf("error building UnbondingDelegation upsertion sql: %v: %w", err, rdb.ErrBuildSQLStmt) + return fmt.Errorf("error building UnbondingDelegation insertion sql: %v: %w", err, rdb.ErrBuildSQLStmt) } result, err := view.rdb.Exec(sql, sqlArgs...) if err != nil { - return fmt.Errorf("error upserting UnbondingDelegation into the table: %v: %w", err, rdb.ErrWrite) + return fmt.Errorf("error inserting UnbondingDelegation into the table: %v: %w", err, rdb.ErrWrite) } if result.RowsAffected() != 1 { - return fmt.Errorf("error upserting UnbondingDelegation into the table: no row upserted: %w", rdb.ErrWrite) + return fmt.Errorf("error inserting UnbondingDelegation into the table: no row upserted: %w", rdb.ErrWrite) } return nil } -func (view *UnbondingDelegationsView) Delete(row UnbondingDelegationRow) error { +func (view *UnbondingDelegationsView) Update(row UnbondingDelegationRow) error { + + // Check if there is an record's lower bound start with this height. + found, err := view.checkIfUnbondingDelegationRecordExistByHeightLowerBound(row) + if err != nil { + return fmt.Errorf("error in checking new UnbondingDelegation record existence at this height: %v", err) + } + + if found { + // If there is a record lower(height) == row.Height, then update the existed one + + entriesJSON, err := jsoniter.MarshalToString(row.Entries) + if err != nil { + return fmt.Errorf("error JSON marshalling UnbondingDelegationRow.Entries for upsertion: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + sql, sqlArgs, err := view.rdb.StmtBuilder. + Update( + "view_vd_unbonding_delegations", + ). + SetMap(map[string]interface{}{ + "entries": entriesJSON, + }). + Where( + "delegator_address = ? AND validator_address = ? AND height @> ?::int8", + row.DelegatorAddress, + row.ValidatorAddress, + row.Height, + ). + ToSql() + + if err != nil { + return fmt.Errorf("error building UnbondingDelegation update sql: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + result, err := view.rdb.Exec(sql, sqlArgs...) + if err != nil { + return fmt.Errorf("error updating UnbondingDelegation into the table: %v: %w", err, rdb.ErrWrite) + } + if result.RowsAffected() != 1 { + return fmt.Errorf("error updating UnbondingDelegation into the table: row updated: %v: %w", result.RowsAffected(), rdb.ErrWrite) + } + + } else { + // If there is not an existed record, then update the previous record's height range and insert a new record + + err := view.setUnbondingDelegationRecordHeightUpperBound(row) + if err != nil { + return fmt.Errorf("error updating UnbondingDelegation.Height upper bound: %v", err) + } + err = view.Insert(row) + if err != nil { + return fmt.Errorf("error inserting a new record for this UnbondingDelegation: %v", err) + } + + } + + return nil +} + +func (view *UnbondingDelegationsView) checkIfUnbondingDelegationRecordExistByHeightLowerBound(row UnbondingDelegationRow) (bool, error) { sql, sqlArgs, err := view.rdb.StmtBuilder. - Delete( - "view_vd_unbonding_delegations", + Select( + "COUNT(*)", ). + From("view_vd_unbonding_delegations"). Where( - "delegator_address = ? AND validator_address = ? AND height = ?", + "delegator_address = ? AND validator_address = ? AND lower(height) = ?", row.DelegatorAddress, row.ValidatorAddress, row.Height, ). ToSql() if err != nil { - return fmt.Errorf("error building UnbondingDelegation deletion sql: %v: %w", err, rdb.ErrBuildSQLStmt) + return false, fmt.Errorf("error building 'checking UnbondingDelegation at specific lower(height) sql: %v: %w", err, rdb.ErrPrepare) } - result, err := view.rdb.Exec(sql, sqlArgs...) - if err != nil { - return fmt.Errorf("error deleting UnbondingDelegation from the table: %v: %w", err, rdb.ErrWrite) + var count int64 + if err = view.rdb.QueryRow(sql, sqlArgs...).Scan( + &count, + ); err != nil { + return false, fmt.Errorf("error scanning count: %v: %w", err, rdb.ErrQuery) } - if result.RowsAffected() != 1 { - return fmt.Errorf("error deleting UnbondingDelegation from the table: no row deleted: %w", rdb.ErrWrite) + + return count == 1, nil +} + +func (view *UnbondingDelegationsView) Delete(row UnbondingDelegationRow) error { + + return view.setUnbondingDelegationRecordHeightUpperBound(row) +} + +func (view *UnbondingDelegationsView) setUnbondingDelegationRecordHeightUpperBound(row UnbondingDelegationRow) error { + + // Set the upper bound for record height: `[, row.Height)`. + sql, sqlErr := view.rdb.StmtBuilder.ReplacePlaceholders(` + UPDATE view_vd_unbonding_delegations + SET height = int8range(lower(height), ?, '[)') + WHERE delegator_address = ? AND validator_address = ? AND height @> ?::int8 + `) + if sqlErr != nil { + return fmt.Errorf("error building UnbondingDelegation upper(height) update sql: %v: %w", sqlErr, rdb.ErrBuildSQLStmt) + } + sqlArgs := []interface{}{ + row.Height, + row.DelegatorAddress, + row.ValidatorAddress, + row.Height, + } + + if _, execErr := view.rdb.Exec(sql, sqlArgs...); execErr != nil { + return fmt.Errorf("error executing UnbondingDelegation upper(height)update sql: %v: %w", execErr, rdb.ErrWrite) } return nil @@ -140,7 +206,7 @@ func (view *UnbondingDelegationsView) FindBy( ). From("view_vd_unbonding_delegations"). Where( - "delegator_address = ? AND validator_address = ? AND height = ?", + "delegator_address = ? AND validator_address = ? AND height @> ?::int8", delegatorAddress, validatorAddress, height, @@ -187,7 +253,7 @@ func (view *UnbondingDelegationsView) ListByValidator( "view_vd_unbonding_delegations", ). Where( - "validator_address = ? AND height = ?", + "validator_address = ? AND height @> ?::int8", validatorAddress, height, ). @@ -226,10 +292,70 @@ func (view *UnbondingDelegationsView) ListByValidator( return unbondingDelegations, nil } -// NOTES: -// - UNIQUE(delegatorAddress, validatorAddress, height) -// - INDEX(validatorAddress, height) -// - INDEX(delegatorAddress, height) +func (view *UnbondingDelegationsView) ListByValidatorWithPagination( + validatorAddress string, + height int64, + pagination *pagination_appinterface.Pagination, +) ([]UnbondingDelegationRow, *pagination_appinterface.PaginationResult, error) { + + stmtBuilder := view.rdb.StmtBuilder. + Select( + "delegator_address", + "entries", + ). + From( + "view_vd_unbonding_delegations", + ). + Where( + "validator_address = ? AND height @> ?::int8", + validatorAddress, + height, + ) + + rDbPagination := rdb.NewRDbPaginationBuilder( + pagination, + view.rdb, + ).BuildStmt(stmtBuilder) + sql, sqlArgs, err := rDbPagination.ToStmtBuilder().ToSql() + if err != nil { + return nil, nil, fmt.Errorf("error building UnbondingDelegation select by validator SQL: %v, %w", err, rdb.ErrBuildSQLStmt) + } + + rowsResult, err := view.rdb.Query(sql, sqlArgs...) + if err != nil { + return nil, nil, fmt.Errorf("error executing UnbondingDelegation select by validator SQL: %v: %w", err, rdb.ErrQuery) + } + defer rowsResult.Close() + + unbondingDelegations := make([]UnbondingDelegationRow, 0) + for rowsResult.Next() { + var unbondingDelegation UnbondingDelegationRow + unbondingDelegation.Height = height + unbondingDelegation.ValidatorAddress = validatorAddress + + var entriesJSON string + if err = rowsResult.Scan( + &unbondingDelegation.DelegatorAddress, + &entriesJSON, + ); err != nil { + return nil, nil, fmt.Errorf("error scanning UnbondingDelegation row: %v: %w", err, rdb.ErrQuery) + } + + if err = jsoniter.UnmarshalFromString(entriesJSON, &unbondingDelegation.Entries); err != nil { + return nil, nil, fmt.Errorf("error unmarshalling UnbondingDelegationRow.Entries JSON: %v: %w", err, rdb.ErrQuery) + } + + unbondingDelegations = append(unbondingDelegations, unbondingDelegation) + } + + paginationResult, err := rDbPagination.Result() + if err != nil { + return nil, nil, fmt.Errorf("error preparing pagination result: %v", err) + } + + return unbondingDelegations, paginationResult, nil +} + type UnbondingDelegationRow struct { Height int64 `json:"height"` DelegatorAddress string `json:"delegatorAddress"` @@ -245,6 +371,7 @@ func NewUnbondingDelegationRow( balance coin.Int, ) UnbondingDelegationRow { return UnbondingDelegationRow{ + Height: creationHeight, DelegatorAddress: delegatorAddress, ValidatorAddress: validatorAddress, Entries: []UnbondingDelegationEntry{ diff --git a/projection/validator_delegation/view/validators.go b/projection/validator_delegation/view/validators.go index 4077692e..43f07be8 100644 --- a/projection/validator_delegation/view/validators.go +++ b/projection/validator_delegation/view/validators.go @@ -12,7 +12,6 @@ import ( ) type Validators interface { - Clone(previousHeight int64, currentHeight int64) error Insert(row ValidatorRow) error Update(row ValidatorRow) error Delete(row ValidatorRow) error @@ -31,51 +30,6 @@ func NewValidatorsView(handle *rdb.Handle) Validators { } } -func (view *ValidatorsView) Clone(previousHeight, currentHeight int64) error { - - sql, sqlErr := view.rdb.StmtBuilder.ReplacePlaceholders(`INSERT INTO view_vd_validators( - height, - operator_address, - consensus_node_address, - tendermint_address, - status, - jailed, - power, - unbonding_height, - unbonding_time, - tokens, - shares, - min_self_delegation - ) SELECT - ?, - operator_address, - consensus_node_address, - tendermint_address, - status, - jailed, - power, - unbonding_height, - unbonding_time, - tokens, - shares, - min_self_delegation - FROM view_vd_validators WHERE height = ? - `) - if sqlErr != nil { - return fmt.Errorf("error building validator clone sql: %v: %w", sqlErr, rdb.ErrBuildSQLStmt) - } - sqlArgs := []interface{}{ - currentHeight, - previousHeight, - } - - if _, execErr := view.rdb.Exec(sql, sqlArgs...); execErr != nil { - return fmt.Errorf("error cloning validator into the table: %v: %w", execErr, rdb.ErrWrite) - } - - return nil -} - func (view *ValidatorsView) Insert(row ValidatorRow) error { sql, sqlArgs, err := view.rdb.StmtBuilder. @@ -97,7 +51,7 @@ func (view *ValidatorsView) Insert(row ValidatorRow) error { "min_self_delegation", ). Values( - row.Height, + fmt.Sprintf("[%v,)", row.Height), row.OperatorAddress, row.ConsensusNodeAddress, row.TendermintAddress, @@ -129,64 +83,116 @@ func (view *ValidatorsView) Insert(row ValidatorRow) error { func (view *ValidatorsView) Update(row ValidatorRow) error { - sql, sqlArgs, err := view.rdb.StmtBuilder. - Update( - "view_vd_validators", - ). - SetMap(map[string]interface{}{ - "status": row.Status, - "jailed": row.Jailed, - "power": row.Power, - "unbonding_height": row.UnbondingHeight, - "unbonding_time": view.rdb.Tton(&row.UnbondingTime), - "tokens": row.Tokens.String(), - "shares": row.Shares.String(), - "min_self_delegation": row.MinSelfDelegation.String(), - }). - Where( - "operator_address = ? AND height = ?", - row.OperatorAddress, - row.Height, - ). - ToSql() - + // Check if there is an record's lower bound start with this height. + found, err := view.checkIfValidatorRecordExistByHeightLowerBound(row) if err != nil { - return fmt.Errorf("error building validator update sql: %v: %w", err, rdb.ErrBuildSQLStmt) + return fmt.Errorf("error in checking new validator record existence at this height: %v", err) } - result, err := view.rdb.Exec(sql, sqlArgs...) - if err != nil { - return fmt.Errorf("error updating validator into the table: %v: %w", err, rdb.ErrWrite) - } - if result.RowsAffected() != 1 { - return fmt.Errorf("error updating validator into the table: row updated: %v: %w", result.RowsAffected(), rdb.ErrWrite) + if found { + // If there is a record lower(height) == row.Height, then update the existed one + + sql, sqlArgs, err := view.rdb.StmtBuilder. + Update( + "view_vd_validators", + ). + SetMap(map[string]interface{}{ + "status": row.Status, + "jailed": row.Jailed, + "power": row.Power, + "unbonding_height": row.UnbondingHeight, + "unbonding_time": view.rdb.Tton(&row.UnbondingTime), + "tokens": row.Tokens.String(), + "shares": row.Shares.String(), + "min_self_delegation": row.MinSelfDelegation.String(), + }). + Where( + "operator_address = ? AND height @> ?::int8", + row.OperatorAddress, + row.Height, + ). + ToSql() + + if err != nil { + return fmt.Errorf("error building validator update sql: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + result, err := view.rdb.Exec(sql, sqlArgs...) + if err != nil { + return fmt.Errorf("error updating validator into the table: %v: %w", err, rdb.ErrWrite) + } + if result.RowsAffected() != 1 { + return fmt.Errorf("error updating validator into the table: row updated: %v: %w", result.RowsAffected(), rdb.ErrWrite) + } + + } else { + // If there is not an existed record, then update the previous record's height range and insert a new record + + err := view.setValidatorRecordHeightUpperBound(row) + if err != nil { + return fmt.Errorf("error updating Validator.Height upper bound: %v", err) + } + err = view.Insert(row) + if err != nil { + return fmt.Errorf("error inserting a new record for this validator: %v", err) + } + } return nil } -func (view *ValidatorsView) Delete(row ValidatorRow) error { +func (view *ValidatorsView) checkIfValidatorRecordExistByHeightLowerBound(row ValidatorRow) (bool, error) { sql, sqlArgs, err := view.rdb.StmtBuilder. - Delete( - "view_vd_validators", + Select( + "COUNT(*)", ). + From("view_vd_validators"). Where( - "operator_address = ? AND height = ?", + "operator_address = ? AND lower(height) = ?", row.OperatorAddress, row.Height, ). ToSql() if err != nil { - return fmt.Errorf("error building validator deletion sql: %v: %w", err, rdb.ErrBuildSQLStmt) + return false, fmt.Errorf("error building 'checking validator at specific lower(height) sql: %v: %w", err, rdb.ErrPrepare) } - result, err := view.rdb.Exec(sql, sqlArgs...) - if err != nil { - return fmt.Errorf("error deleting validator from the table: %v: %w", err, rdb.ErrWrite) + var count int64 + if err = view.rdb.QueryRow(sql, sqlArgs...).Scan( + &count, + ); err != nil { + return false, fmt.Errorf("error scanning count: %v: %w", err, rdb.ErrQuery) } - if result.RowsAffected() != 1 { - return fmt.Errorf("error deleting validator into the table: row deleted: %v: %w", result.RowsAffected(), rdb.ErrWrite) + + return count == 1, nil +} + +func (view *ValidatorsView) Delete(row ValidatorRow) error { + + return view.setValidatorRecordHeightUpperBound(row) +} + +func (view *ValidatorsView) setValidatorRecordHeightUpperBound(row ValidatorRow) error { + + // Set the upper bound for record height: `[, row.Height)`. + sql, sqlErr := view.rdb.StmtBuilder.ReplacePlaceholders(` + UPDATE view_vd_validators + SET height = int8range(lower(height), ?, '[)') + WHERE operator_address = ? AND height @> ?::int8 + `) + if sqlErr != nil { + return fmt.Errorf("error building validator upper(height) update sql: %v: %w", sqlErr, rdb.ErrBuildSQLStmt) + } + sqlArgs := []interface{}{ + row.Height, + row.OperatorAddress, + row.Height, + } + + if _, execErr := view.rdb.Exec(sql, sqlArgs...); execErr != nil { + return fmt.Errorf("error executing validator upper(height)update sql: %v: %w", execErr, rdb.ErrWrite) } return nil @@ -236,13 +242,13 @@ func (view *ValidatorsView) findBy( if maybeOperatorAddress != nil { stmtBuilder = stmtBuilder.Where( - "operator_address = ? AND height = ?", + "operator_address = ? AND height @> ?::int8", *maybeOperatorAddress, height, ) } else if maybeConsensusNodeAddress != nil { stmtBuilder = stmtBuilder.Where( - "consensus_node_address = ? AND height = ?", + "consensus_node_address = ? AND height @> ?::int8", *maybeConsensusNodeAddress, height, ) @@ -334,7 +340,7 @@ func (view *ValidatorsView) List( "view_vd_validators", ). Where( - "height = ?", + "height @> ?::int8", height, ) @@ -419,11 +425,6 @@ func (view *ValidatorsView) List( // - power = 0: Validator.Status = Unbonding, UnbondingValidator entry created // - UnbondingValidator complete Unbonding period: Validator.Status = Unbonded -// NOTES: -// - UNIQUE(operatorAddress, height) -// - UNIQUE(consensusNodeAddress, height) -// - UNIQUE(tendermintAddress, height) -// - INDEX(height) type ValidatorRow struct { Height int64 `json:"height"` From 467494fc81ef2824032cc54bbcaf24c1406b711f Mon Sep 17 00:00:00 2001 From: Yang Song Date: Mon, 7 Feb 2022 13:37:51 +0800 Subject: [PATCH 15/24] Add what HTTP API for unbondingDelegations and redelegations. --- .../httpapi/handlers/validator_delegation.go | 86 ++++++++++++++++--- 1 file changed, 75 insertions(+), 11 deletions(-) diff --git a/infrastructure/httpapi/handlers/validator_delegation.go b/infrastructure/httpapi/handlers/validator_delegation.go index 63adf0f2..f0bf1cd0 100644 --- a/infrastructure/httpapi/handlers/validator_delegation.go +++ b/infrastructure/httpapi/handlers/validator_delegation.go @@ -21,8 +21,10 @@ type ValidatorDelegation struct { validatorAddressPrefix string consNodeAddressPrefix string - validatorsView validator_delegation_view.Validators - delegationsView validator_delegation_view.Delegations + validatorsView validator_delegation_view.Validators + delegationsView validator_delegation_view.Delegations + unbondingDelegationsView validator_delegation_view.UnbondingDelegations + redelegationsView validator_delegation_view.Redelegations } func NewValidatorDelegation( @@ -43,6 +45,8 @@ func NewValidatorDelegation( validator_delegation_view.NewValidatorsView(rdbHandle), validator_delegation_view.NewDelegationsView(rdbHandle), + validator_delegation_view.NewUnbondingDelegationsView(rdbHandle), + validator_delegation_view.NewRedelegationsView(rdbHandle), } } @@ -54,7 +58,7 @@ func (handler *ValidatorDelegation) FindValidatorByAddress(ctx *fasthttp.Request return } - address, ok := ctx.UserValue("address").(string) + validatorAddress, ok := ctx.UserValue("address").(string) if !ok { httpapi.BadRequest(ctx, errors.New("error parsing input address")) return @@ -63,9 +67,9 @@ func (handler *ValidatorDelegation) FindValidatorByAddress(ctx *fasthttp.Request var validator validator_delegation_view.ValidatorRow var found bool - if strings.HasPrefix(address, handler.consNodeAddressPrefix) { + if strings.HasPrefix(validatorAddress, handler.consNodeAddressPrefix) { - validator, found, err = handler.validatorsView.FindByConsensusNodeAddr(address, height) + validator, found, err = handler.validatorsView.FindByConsensusNodeAddr(validatorAddress, height) if err != nil { handler.logger.Errorf("error finding validator by ConsensusNodeAddress: %v", err) httpapi.InternalServerError(ctx) @@ -76,9 +80,9 @@ func (handler *ValidatorDelegation) FindValidatorByAddress(ctx *fasthttp.Request return } - } else if strings.HasPrefix(address, handler.validatorAddressPrefix) { + } else if strings.HasPrefix(validatorAddress, handler.validatorAddressPrefix) { - validator, found, err = handler.validatorsView.FindByOperatorAddr(address, height) + validator, found, err = handler.validatorsView.FindByOperatorAddr(validatorAddress, height) if err != nil { handler.logger.Errorf("error finding validaotr by OperatorAddress: %v", err) httpapi.InternalServerError(ctx) @@ -135,13 +139,13 @@ func (handler *ValidatorDelegation) ListDelegationByValidator(ctx *fasthttp.Requ return } - address, ok := ctx.UserValue("address").(string) + validatorAddress, ok := ctx.UserValue("address").(string) if !ok { httpapi.BadRequest(ctx, errors.New("error parsing input address")) return } - delegations, paginationResult, err := handler.delegationsView.ListByValidatorAddr(address, height, pagination) + delegations, paginationResult, err := handler.delegationsView.ListByValidatorAddr(validatorAddress, height, pagination) if err != nil { handler.logger.Errorf("error listing delegations by ValidatorAddress: %v", err) httpapi.InternalServerError(ctx) @@ -165,13 +169,13 @@ func (handler *ValidatorDelegation) ListDelegationByDelegator(ctx *fasthttp.Requ return } - address, ok := ctx.UserValue("address").(string) + delegatorAddress, ok := ctx.UserValue("address").(string) if !ok { httpapi.BadRequest(ctx, errors.New("error parsing input address")) return } - delegations, paginationResult, err := handler.delegationsView.ListByDelegatorAddr(address, height, pagination) + delegations, paginationResult, err := handler.delegationsView.ListByDelegatorAddr(delegatorAddress, height, pagination) if err != nil { handler.logger.Errorf("error listing delegations by DelegatorAddress: %v", err) httpapi.InternalServerError(ctx) @@ -181,6 +185,66 @@ func (handler *ValidatorDelegation) ListDelegationByDelegator(ctx *fasthttp.Requ httpapi.SuccessWithPagination(ctx, delegations, paginationResult) } +func (handler *ValidatorDelegation) ListUnbondingDelegationByValidator(ctx *fasthttp.RequestCtx) { + + pagination, err := httpapi.ParsePagination(ctx) + if err != nil { + ctx.SetStatusCode(fasthttp.StatusBadRequest) + return + } + + height, err := parseInputHeight(ctx) + if err != nil { + httpapi.BadRequest(ctx, fmt.Errorf("error parsing input height: %v", err)) + return + } + + validatorAddress, ok := ctx.UserValue("address").(string) + if !ok { + httpapi.BadRequest(ctx, errors.New("error parsing input address")) + return + } + + delegations, paginationResult, err := handler.unbondingDelegationsView.ListByValidatorWithPagination(validatorAddress, height, pagination) + if err != nil { + handler.logger.Errorf("error listing unbonding delegations by ValidatorAddress: %v", err) + httpapi.InternalServerError(ctx) + return + } + + httpapi.SuccessWithPagination(ctx, delegations, paginationResult) +} + +func (handler *ValidatorDelegation) ListRedelegationBySrcValidator(ctx *fasthttp.RequestCtx) { + + pagination, err := httpapi.ParsePagination(ctx) + if err != nil { + ctx.SetStatusCode(fasthttp.StatusBadRequest) + return + } + + height, err := parseInputHeight(ctx) + if err != nil { + httpapi.BadRequest(ctx, fmt.Errorf("error parsing input height: %v", err)) + return + } + + srcValidatorAddress, ok := ctx.UserValue("srcValAddress").(string) + if !ok { + httpapi.BadRequest(ctx, errors.New("error parsing input address")) + return + } + + delegations, paginationResult, err := handler.redelegationsView.ListBySrcValidatorWithPagination(srcValidatorAddress, height, pagination) + if err != nil { + handler.logger.Errorf("error listing redelegations by SrcValidatorAddress: %v", err) + httpapi.InternalServerError(ctx) + return + } + + httpapi.SuccessWithPagination(ctx, delegations, paginationResult) +} + func parseInputHeight(ctx *fasthttp.RequestCtx) (int64, error) { queryArgs := ctx.QueryArgs() From 5387cab8fbc5ded7a4a21b6e6e82aaa93eb33093 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Tue, 8 Feb 2022 16:43:20 +0800 Subject: [PATCH 16/24] Update index and constraints for the new projection --- .../20220117111937_create_view_vd_redelegations.down.sql | 2 ++ .../20220117111937_create_view_vd_redelegations.up.sql | 2 ++ ...17131200_create_view_vd_unbonding_delegations.down.sql | 2 ++ ...0117131200_create_view_vd_unbonding_delegations.up.sql | 2 ++ .../20220117133017_create_view_vd_validators.down.sql | 2 ++ .../20220117133017_create_view_vd_validators.up.sql | 8 ++++++-- 6 files changed, 16 insertions(+), 2 deletions(-) diff --git a/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.down.sql b/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.down.sql index f60bf6d8..e8cc696c 100644 --- a/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.down.sql +++ b/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.down.sql @@ -1 +1,3 @@ +DROP INDEX IF EXISTS view_vd_redelegations_validator_src_addr_index; + DROP TABLE IF EXISTS view_vd_redelegations; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.up.sql b/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.up.sql index e7fc1546..1356729e 100644 --- a/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.up.sql +++ b/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.up.sql @@ -15,3 +15,5 @@ CREATE TABLE view_vd_redelegations ( height WITH && ) ); + +CREATE INDEX view_vd_redelegations_validator_src_addr_index ON view_vd_redelegations USING gist (height, validator_src_address); diff --git a/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.down.sql b/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.down.sql index 8276bc82..a4d3175b 100644 --- a/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.down.sql +++ b/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.down.sql @@ -1 +1,3 @@ +DROP INDEX IF EXISTS view_vd_unbonding_delegations_validator_addr_height_index; + DROP TABLE IF EXISTS view_vd_unbonding_delegations; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.up.sql b/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.up.sql index 0cc98c3c..4696bd4a 100644 --- a/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.up.sql +++ b/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.up.sql @@ -9,3 +9,5 @@ CREATE TABLE view_vd_unbonding_delegations ( -- It prevents a delegation record appear twice at any given height. EXCLUDE USING gist (delegator_address WITH =, validator_address WITH =, height WITH &&) ); + +CREATE INDEX view_vd_unbonding_delegations_validator_addr_height_index ON view_vd_unbonding_delegations USING gist (height, validator_address); diff --git a/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.down.sql b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.down.sql index 1edb1c84..3d9e6dcf 100644 --- a/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.down.sql +++ b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.down.sql @@ -1 +1,3 @@ +DROP INDEX IF EXISTS view_vd_validators_height_index; + DROP TABLE IF EXISTS view_vd_validators; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql index 37f67f69..5361d41f 100644 --- a/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql +++ b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql @@ -14,11 +14,15 @@ CREATE TABLE view_vd_validators ( min_self_delegation VARCHAR NOT NULL, PRIMARY KEY (id), -- Below is a constraint and it is also an index. - -- It prevents a delegation record appear twice at any given height. + -- It prevents a delegation record appear twice at any given height. EXCLUDE USING gist ( operator_address WITH =, + height WITH && + ) + EXCLUDE USING gist ( consensus_node_address WITH =, - tendermint_address WITH =, height WITH && ) ); + +CREATE INDEX view_vd_validators_height_index ON view_vd_validators USING gist (height); From 541bf2ef9d3212154b6f5940b7faf31de903cd9d Mon Sep 17 00:00:00 2001 From: Yang Song Date: Tue, 8 Feb 2022 16:53:10 +0800 Subject: [PATCH 17/24] Fix migrations script --- .../migrations/20220117133017_create_view_vd_validators.up.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql index 5361d41f..c08d8b4c 100644 --- a/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql +++ b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql @@ -18,7 +18,7 @@ CREATE TABLE view_vd_validators ( EXCLUDE USING gist ( operator_address WITH =, height WITH && - ) + ), EXCLUDE USING gist ( consensus_node_address WITH =, height WITH && From 886dd283c1af2646e6c984982026690b0b2b8546 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Fri, 11 Feb 2022 10:10:14 +0800 Subject: [PATCH 18/24] Commit latest working code. Include the performance log related debug code. --- .../validator_delegation.go | 182 +++++++++++++++--- .../validator_delegation/view/delegations.go | 8 +- .../view/operation_performance_logs.go | 61 ++++++ .../view/redelegations.go | 8 +- .../view/unbonding_delegations.go | 8 +- .../validator_delegation/view/validators.go | 66 ++++++- 6 files changed, 286 insertions(+), 47 deletions(-) create mode 100644 projection/validator_delegation/view/operation_performance_logs.go diff --git a/projection/validator_delegation/validator_delegation.go b/projection/validator_delegation/validator_delegation.go index 4d026d2c..31a55298 100644 --- a/projection/validator_delegation/validator_delegation.go +++ b/projection/validator_delegation/validator_delegation.go @@ -110,6 +110,9 @@ var ( NewRedelegationQueue = view.NewRedelegationQueueView NewEvidences = view.NewEvidencesView UpdateLastHandledEventHeight = (*ValidatorDelegation).UpdateLastHandledEventHeight + + // DEBUG + NewOperationPerformanceLogs = view.NewOperationPerformanceLogsView ) type ValidatorDelegation struct { @@ -203,37 +206,6 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event } } - // Genesis block height is 0. - // - // If this is NOT a Genesis block, then always clone the following rows in previous height: - // - ValidatorRow - // - DelegationRow - // - UnbondingDelegationRow - // - RedelegationRow - // - // This is to keep track historical states in all height. - if height > 0 { - validatorsView := NewValidators(rdbTxHandle) - if err := validatorsView.Clone(height-1, height); err != nil { - return fmt.Errorf("error in cloning validator records in previous height: %v", err) - } - - delegationsView := NewDelegations(rdbTxHandle) - if err := delegationsView.Clone(height-1, height); err != nil { - return fmt.Errorf("error in cloning delegation records in previous height: %v", err) - } - - unbondingDelegationsView := NewUnbondingDelegations(rdbTxHandle) - if err := unbondingDelegationsView.Clone(height-1, height); err != nil { - return fmt.Errorf("error in cloning unbonding delegation records in previous height: %v", err) - } - - redelegationsView := NewRedelegations(rdbTxHandle) - if err := redelegationsView.Clone(height-1, height); err != nil { - return fmt.Errorf("error in cloning redelegation records in previous height: %v", err) - } - } - // Handle events in Genesis block for _, event := range events { if typedEvent, ok := event.(*event_usecase.CreateGenesisValidator); ok { @@ -253,6 +225,9 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event } } + // DEBUG + start := time.Now() + // Handle evidence. // // NOTES: Although Evidences are handled by CosmosSDK in BeginBlock, @@ -274,6 +249,19 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event } } + // DEBUG + end := time.Now() + performanceView := NewOperationPerformanceLogs(rdbTxHandle) + if err := performanceView.Insert( + view.OperationPerformanceRow{ + Height: height, + Action: "Evidence", + Duration: end.Sub(start), + }, + ); err != nil { + return fmt.Errorf("error in inserting performance log: %v", err) + } + start = end // Handle events in BeginBlock. for _, event := range events { @@ -371,6 +359,18 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event } } + // DEBUG + end = time.Now() + if err := performanceView.Insert( + view.OperationPerformanceRow{ + Height: height, + Action: "BeginBlock", + Duration: end.Sub(start), + }, + ); err != nil { + return fmt.Errorf("error in inserting performance log: %v", err) + } + start = end // Handle events and msgs in Tx for _, event := range events { @@ -387,6 +387,18 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event ); err != nil { return fmt.Errorf("error handleCreateNewValidator when MsgCreateValidator: %v", err) } + // DEBUG + end = time.Now() + if err := performanceView.Insert( + view.OperationPerformanceRow{ + Height: height, + Action: "MsgCreateValidator", + Duration: end.Sub(start), + }, + ); err != nil { + return fmt.Errorf("error in inserting performance log: %v", err) + } + start = end } else if typedEvent, ok := event.(*event_usecase.MsgEditValidator); ok { @@ -400,6 +412,18 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event ); err != nil { return fmt.Errorf("error handling MsgEditValidator: %v", err) } + // DEBUG + end = time.Now() + if err := performanceView.Insert( + view.OperationPerformanceRow{ + Height: height, + Action: "MsgEditValidator", + Duration: end.Sub(start), + }, + ); err != nil { + return fmt.Errorf("error in inserting performance log: %v", err) + } + start = end } @@ -414,6 +438,18 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event ); err != nil { return fmt.Errorf("error handling MsgDelegate: %v", err) } + // DEBUG + end = time.Now() + if err := performanceView.Insert( + view.OperationPerformanceRow{ + Height: height, + Action: "MsgDelegate", + Duration: end.Sub(start), + }, + ); err != nil { + return fmt.Errorf("error in inserting performance log: %v", err) + } + start = end } else if typedEvent, ok := event.(*event_usecase.MsgUndelegate); ok { @@ -430,6 +466,18 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event ); err != nil { return fmt.Errorf("error handling MsgUndelegate: %v", err) } + // DEBUG + end = time.Now() + if err := performanceView.Insert( + view.OperationPerformanceRow{ + Height: height, + Action: "MsgUndelegate", + Duration: end.Sub(start), + }, + ); err != nil { + return fmt.Errorf("error in inserting performance log: %v", err) + } + start = end } @@ -446,6 +494,18 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event ); err != nil { return fmt.Errorf("error handling MsgBeginRedelegate: %v", err) } + // DEBUG + end = time.Now() + if err := performanceView.Insert( + view.OperationPerformanceRow{ + Height: height, + Action: "MsgBeginRedelegate", + Duration: end.Sub(start), + }, + ); err != nil { + return fmt.Errorf("error in inserting performance log: %v", err) + } + start = end } else if typedEvent, ok := event.(*event_usecase.MsgUnjail); ok { @@ -456,6 +516,18 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event ); err != nil { return fmt.Errorf("error handling MsgUnjail: %v", err) } + // DEBUG + end = time.Now() + if err := performanceView.Insert( + view.OperationPerformanceRow{ + Height: height, + Action: "MsgUnjail", + Duration: end.Sub(start), + }, + ); err != nil { + return fmt.Errorf("error in inserting performance log: %v", err) + } + start = end } } @@ -478,6 +550,18 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event } } + // DEBUG + end = time.Now() + if err := performanceView.Insert( + view.OperationPerformanceRow{ + Height: height, + Action: "EndBlock", + Duration: end.Sub(start), + }, + ); err != nil { + return fmt.Errorf("error in inserting performance log: %v", err) + } + start = end if err := projection.handleMatureUnbondingValidators( rdbTxHandle, @@ -486,6 +570,18 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event ); err != nil { return fmt.Errorf("error handling mature unbonding validators: %v", err) } + // DEBUG + end = time.Now() + if err := performanceView.Insert( + view.OperationPerformanceRow{ + Height: height, + Action: "MatureUnbondingValidators", + Duration: end.Sub(start), + }, + ); err != nil { + return fmt.Errorf("error in inserting performance log: %v", err) + } + start = end if err := projection.handleMatureUnbondingDelegationQueueEntries( rdbTxHandle, @@ -494,6 +590,18 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event ); err != nil { return fmt.Errorf("error handling mature unbonding delegation queue entries: %v", err) } + // DEBUG + end = time.Now() + if err := performanceView.Insert( + view.OperationPerformanceRow{ + Height: height, + Action: "MatureUnbondingDelegations", + Duration: end.Sub(start), + }, + ); err != nil { + return fmt.Errorf("error in inserting performance log: %v", err) + } + start = end if err := projection.handleMatureRedelegationQueueEntries( rdbTxHandle, @@ -502,6 +610,18 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event ); err != nil { return fmt.Errorf("error handling mature redelegation queue entries(): %v", err) } + // DEBUG + end = time.Now() + if err := performanceView.Insert( + view.OperationPerformanceRow{ + Height: height, + Action: "MatureRedelegations", + Duration: end.Sub(start), + }, + ); err != nil { + return fmt.Errorf("error in inserting performance log: %v", err) + } + start = end if err := UpdateLastHandledEventHeight(projection, rdbTxHandle, height); err != nil { return fmt.Errorf("error updating last handled event height: %v", err) diff --git a/projection/validator_delegation/view/delegations.go b/projection/validator_delegation/view/delegations.go index 4e113d57..5e3b63cb 100644 --- a/projection/validator_delegation/view/delegations.go +++ b/projection/validator_delegation/view/delegations.go @@ -82,7 +82,7 @@ func (view *DelegationsView) Update(row DelegationRow) error { } if found { - // If there is a record lower(height) == row.Height, then update the existed one + // If there is a record that height = `[row.Height,)`, then update the existed one sql, sqlArgs, err := view.rdb.StmtBuilder. Update( @@ -136,14 +136,14 @@ func (view *DelegationsView) checkIfDelegationRecordExistByHeightLowerBound(row ). From("view_vd_delegations"). Where( - "validator_address = ? AND delegator_address = ? AND lower(height) = ?", + "validator_address = ? AND delegator_address = ? AND height = ?", row.ValidatorAddress, row.DelegatorAddress, - row.Height, + fmt.Sprintf("[%v,)", row.Height), ). ToSql() if err != nil { - return false, fmt.Errorf("error building 'checking delegation at specific lower(height) sql: %v: %w", err, rdb.ErrPrepare) + return false, fmt.Errorf("error building sql to check delegation at specific height: %v: %w", err, rdb.ErrPrepare) } var count int64 diff --git a/projection/validator_delegation/view/operation_performance_logs.go b/projection/validator_delegation/view/operation_performance_logs.go new file mode 100644 index 00000000..61d45ebb --- /dev/null +++ b/projection/validator_delegation/view/operation_performance_logs.go @@ -0,0 +1,61 @@ +package view + +import ( + "fmt" + "time" + + "github.com/crypto-com/chain-indexing/appinterface/rdb" +) + +type OperationPerformanceLogs interface { + Insert(row OperationPerformanceRow) error +} + +type OperationPerformanceLogsView struct { + rdb *rdb.Handle +} + +func NewOperationPerformanceLogsView(handle *rdb.Handle) OperationPerformanceLogs { + return &OperationPerformanceLogsView{ + handle, + } +} + +func (view *OperationPerformanceLogsView) Insert(row OperationPerformanceRow) error { + + sql, sqlArgs, err := view.rdb.StmtBuilder. + Insert( + "view_vd_operation_performance_log", + ). + Columns( + "height", + "action", + "duration", + ). + Values( + row.Height, + row.Action, + row.Duration.Milliseconds(), + ). + ToSql() + + if err != nil { + return fmt.Errorf("error building operation performance insertion sql: %v: %w", err, rdb.ErrBuildSQLStmt) + } + + result, err := view.rdb.Exec(sql, sqlArgs...) + if err != nil { + return fmt.Errorf("error inserting operation performance into the table: %v: %w", err, rdb.ErrWrite) + } + if result.RowsAffected() != 1 { + return fmt.Errorf("error inserting operation performance into the table: no rows inserted: %w", rdb.ErrWrite) + } + + return nil +} + +type OperationPerformanceRow struct { + Height int64 + Action string + Duration time.Duration +} diff --git a/projection/validator_delegation/view/redelegations.go b/projection/validator_delegation/view/redelegations.go index 6774882d..7a24691d 100644 --- a/projection/validator_delegation/view/redelegations.go +++ b/projection/validator_delegation/view/redelegations.go @@ -88,7 +88,7 @@ func (view *RedelegationsView) Update(row RedelegationRow) error { } if found { - // If there is a record lower(height) == row.Height, then update the existed one + // If there is a record that height = `[row.Height,)`, then update the existed one entriesJSON, err := jsoniter.MarshalToString(row.Entries) if err != nil { @@ -148,15 +148,15 @@ func (view *RedelegationsView) checkIfRedelegationRecordExistByHeightLowerBound( ). From("view_vd_redelegations"). Where( - "delegator_address = ? AND validator_src_address = ? AND validator_dst_address = ? AND lower(height) = ?", + "delegator_address = ? AND validator_src_address = ? AND validator_dst_address = ? AND height = ?", row.DelegatorAddress, row.ValidatorSrcAddress, row.ValidatorDstAddress, - row.Height, + fmt.Sprintf("[%v,)", row.Height), ). ToSql() if err != nil { - return false, fmt.Errorf("error building 'checking Redelegation at specific lower(height) sql: %v: %w", err, rdb.ErrPrepare) + return false, fmt.Errorf("error building sql to check redelegation at specific height: %v: %w", err, rdb.ErrPrepare) } var count int64 diff --git a/projection/validator_delegation/view/unbonding_delegations.go b/projection/validator_delegation/view/unbonding_delegations.go index 5e488ca6..6d849121 100644 --- a/projection/validator_delegation/view/unbonding_delegations.go +++ b/projection/validator_delegation/view/unbonding_delegations.go @@ -85,7 +85,7 @@ func (view *UnbondingDelegationsView) Update(row UnbondingDelegationRow) error { } if found { - // If there is a record lower(height) == row.Height, then update the existed one + // If there is a record that height = `[row.Height,)`, then update the existed one entriesJSON, err := jsoniter.MarshalToString(row.Entries) if err != nil { @@ -144,14 +144,14 @@ func (view *UnbondingDelegationsView) checkIfUnbondingDelegationRecordExistByHei ). From("view_vd_unbonding_delegations"). Where( - "delegator_address = ? AND validator_address = ? AND lower(height) = ?", + "delegator_address = ? AND validator_address = ? AND height = ?", row.DelegatorAddress, row.ValidatorAddress, - row.Height, + fmt.Sprintf("[%v,)", row.Height), ). ToSql() if err != nil { - return false, fmt.Errorf("error building 'checking UnbondingDelegation at specific lower(height) sql: %v: %w", err, rdb.ErrPrepare) + return false, fmt.Errorf("error building sql to check unbonding delegation at specific height: %v: %w", err, rdb.ErrPrepare) } var count int64 diff --git a/projection/validator_delegation/view/validators.go b/projection/validator_delegation/view/validators.go index 43f07be8..01ee65c8 100644 --- a/projection/validator_delegation/view/validators.go +++ b/projection/validator_delegation/view/validators.go @@ -3,6 +3,7 @@ package view import ( "errors" "fmt" + "time" "github.com/crypto-com/chain-indexing/appinterface/pagination" "github.com/crypto-com/chain-indexing/appinterface/rdb" @@ -83,14 +84,31 @@ func (view *ValidatorsView) Insert(row ValidatorRow) error { func (view *ValidatorsView) Update(row ValidatorRow) error { + // DEBUG + start := time.Now() + performanceView := NewOperationPerformanceLogsView(view.rdb) + // Check if there is an record's lower bound start with this height. found, err := view.checkIfValidatorRecordExistByHeightLowerBound(row) if err != nil { return fmt.Errorf("error in checking new validator record existence at this height: %v", err) } + // DEBUG + end := time.Now() + if err := performanceView.Insert( + OperationPerformanceRow{ + Height: row.Height, + Action: "UpdateValidator-CheckIfExist", + Duration: end.Sub(start), + }, + ); err != nil { + return fmt.Errorf("error in inserting performance log: %v", err) + } + start = end + if found { - // If there is a record lower(height) == row.Height, then update the existed one + // If there is a record that height = `[row.Height,)`, then update the existed one sql, sqlArgs, err := view.rdb.StmtBuilder. Update( @@ -125,6 +143,19 @@ func (view *ValidatorsView) Update(row ValidatorRow) error { return fmt.Errorf("error updating validator into the table: row updated: %v: %w", result.RowsAffected(), rdb.ErrWrite) } + // DEBUG + end = time.Now() + if err := performanceView.Insert( + OperationPerformanceRow{ + Height: row.Height, + Action: "UpdateValidator-UpdateExistedOne", + Duration: end.Sub(start), + }, + ); err != nil { + return fmt.Errorf("error in inserting performance log: %v", err) + } + start = end + } else { // If there is not an existed record, then update the previous record's height range and insert a new record @@ -132,11 +163,38 @@ func (view *ValidatorsView) Update(row ValidatorRow) error { if err != nil { return fmt.Errorf("error updating Validator.Height upper bound: %v", err) } + + // DEBUG + end = time.Now() + if err := performanceView.Insert( + OperationPerformanceRow{ + Height: row.Height, + Action: "UpdateValidator-UpdatePreviousOne", + Duration: end.Sub(start), + }, + ); err != nil { + return fmt.Errorf("error in inserting performance log: %v", err) + } + start = end + err = view.Insert(row) if err != nil { return fmt.Errorf("error inserting a new record for this validator: %v", err) } + // DEBUG + end = time.Now() + if err := performanceView.Insert( + OperationPerformanceRow{ + Height: row.Height, + Action: "UpdateValidator-Insert", + Duration: end.Sub(start), + }, + ); err != nil { + return fmt.Errorf("error in inserting performance log: %v", err) + } + start = end + } return nil @@ -150,13 +208,13 @@ func (view *ValidatorsView) checkIfValidatorRecordExistByHeightLowerBound(row Va ). From("view_vd_validators"). Where( - "operator_address = ? AND lower(height) = ?", + "operator_address = ? AND height = ?", row.OperatorAddress, - row.Height, + fmt.Sprintf("[%v,)", row.Height), ). ToSql() if err != nil { - return false, fmt.Errorf("error building 'checking validator at specific lower(height) sql: %v: %w", err, rdb.ErrPrepare) + return false, fmt.Errorf("error building sql to check validator at specific height: %v: %w", err, rdb.ErrPrepare) } var count int64 From 0081eebc049dd9b039a4d560d442843b68ef51f3 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Fri, 11 Feb 2022 11:07:10 +0800 Subject: [PATCH 19/24] Update example app --- example/Makefile | 4 +- example/app/example-app/config/bridgesapi.go | 60 +++++++++++++++++++ .../app/example-app/{ => config}/config.go | 3 +- example/app/example-app/cronjobs.go | 2 +- example/app/example-app/projections.go | 41 ++++++++++--- example/app/example-app/routes/routes.go | 46 +++++++++++++- example/app/example-app/run.go | 18 +++--- example/config/config.yaml | 6 ++ example/go.mod | 19 +++--- example/go.sum | 32 +++++++--- 10 files changed, 191 insertions(+), 40 deletions(-) create mode 100644 example/app/example-app/config/bridgesapi.go rename example/app/example-app/{ => config}/config.go (96%) diff --git a/example/Makefile b/example/Makefile index 51e9b741..4e861f3e 100644 --- a/example/Makefile +++ b/example/Makefile @@ -1,5 +1,5 @@ -build: chain-indexing-app -chain-indexing-app: +build: example-app +example-app: go build ./app/example-app/ clean: rm -i example-app diff --git a/example/app/example-app/config/bridgesapi.go b/example/app/example-app/config/bridgesapi.go new file mode 100644 index 00000000..f16ce225 --- /dev/null +++ b/example/app/example-app/config/bridgesapi.go @@ -0,0 +1,60 @@ +package config + +import ( + "github.com/crypto-com/chain-indexing/external/bridges/parsers" + "github.com/crypto-com/chain-indexing/external/bridges/parsers/cronos" + "github.com/crypto-com/chain-indexing/infrastructure/httpapi/handlers" +) + +type BridgesAPIConfig struct { + Networks []BridgeNetworkConfig `yaml:"networks"` + Chains []handlers.BridgeChainConfig `yaml:"chains"` +} + +type BridgeNetworkConfig struct { + ChainName string `yaml:"chain_name" mapstructure:"chain_name"` + // Chain network unique abbreviation, used in URL query params + Abbreviation handlers.NetworkAbbreviation `yaml:"abbreviation" mapstructure:"abbreviation"` + MaybeAddressHookKey *string `yaml:"maybe_address_hook_key"` + MaybeCronosAccountAddressPrefix *string `yaml:"maybe_cronos_account_address_prefix"` +} + +var BridgeAddressHooks = (func() map[string]func( + networkConfig *BridgeNetworkConfig, +) handlers.AddressHook { + hooks := make(map[string]func(config *BridgeNetworkConfig) handlers.AddressHook, 0) + + hooks["DefaultLowercaseAddressHook"] = func(_ *BridgeNetworkConfig) handlers.AddressHook { + return parsers.DefaultLowercaseAddressHook + } + hooks["DefaultCronosEVMAddressHookGenerator"] = func(config *BridgeNetworkConfig) handlers.AddressHook { + return cronos.DefaultCronosEVMAddressHookGenerator(*config.MaybeCronosAccountAddressPrefix) + } + + return hooks +})() + +func ParseBridgesConfig(rawConfig *BridgesAPIConfig) handlers.BridgesConfig { + config := handlers.BridgesConfig{ + Networks: make([]handlers.BridgeNetworkConfig, 0, len(rawConfig.Networks)), + Chains: rawConfig.Chains, + } + + for i, network := range rawConfig.Networks { + if network.MaybeAddressHookKey == nil { + config.Networks = append(config.Networks, handlers.BridgeNetworkConfig{ + ChainName: network.ChainName, + Abbreviation: network.Abbreviation, + }) + } else { + hook := BridgeAddressHooks[*network.MaybeAddressHookKey](&rawConfig.Networks[i]) + config.Networks = append(config.Networks, handlers.BridgeNetworkConfig{ + ChainName: network.ChainName, + Abbreviation: network.Abbreviation, + MaybeAddressHook: &hook, + }) + } + } + + return config +} diff --git a/example/app/example-app/config.go b/example/app/example-app/config/config.go similarity index 96% rename from example/app/example-app/config.go rename to example/app/example-app/config/config.go index 0deb7ebf..ec139dbf 100644 --- a/example/app/example-app/config.go +++ b/example/app/example-app/config/config.go @@ -1,4 +1,4 @@ -package main +package config import ( "github.com/crypto-com/chain-indexing/bootstrap/config" @@ -6,6 +6,7 @@ import ( type CustomConfig struct { ServerGithubAPI ServerGithubAPIConfig `yaml:"server_github_api"` + BridgeAPI BridgesAPIConfig `yaml:"bridges_api"` } type ServerGithubAPIConfig struct { diff --git a/example/app/example-app/cronjobs.go b/example/app/example-app/cronjobs.go index 20e4c9b0..5ff4d581 100644 --- a/example/app/example-app/cronjobs.go +++ b/example/app/example-app/cronjobs.go @@ -65,7 +65,7 @@ func InitCronJob(name string, params InitCronJobParams) projection_entity.CronJo params.Logger.Panicf(err.Error()) } - return bridge_activity_matcher.New(params.Logger, params.RdbConn, migrationHelper, config) + return bridge_activity_matcher.New(config, params.Logger, params.RdbConn, migrationHelper) // register more cronjobs here default: panic(fmt.Sprintf("Unrecognized cron job: %s", name)) diff --git a/example/app/example-app/projections.go b/example/app/example-app/projections.go index 287a7013..7e2e3558 100644 --- a/example/app/example-app/projections.go +++ b/example/app/example-app/projections.go @@ -30,13 +30,15 @@ import ( "github.com/crypto-com/chain-indexing/projection/validator" "github.com/crypto-com/chain-indexing/projection/validatorstats" "github.com/ettle/strcase" + + appconfig "github.com/crypto-com/chain-indexing/example/app/example-app/config" ) func initProjections( logger applogger.Logger, rdbConn rdb.Conn, config *configuration.Config, - customConfig *CustomConfig, + customConfig *appconfig.CustomConfig, ) []projection_entity.Projection { if !config.IndexService.Enable { return []projection_entity.Projection{} @@ -60,9 +62,10 @@ func initProjections( ExtraConfigs: config.IndexService.Projection.ExtraConfigs, - CosmosAppClient: cosmosAppClient, - AccountAddressPrefix: config.Blockchain.AccountAddressPrefix, - ConsNodeAddressPrefix: config.Blockchain.ConNodeAddressPrefix, + CosmosAppClient: cosmosAppClient, + AccountAddressPrefix: config.Blockchain.AccountAddressPrefix, + ValidatorAddressPrefix: config.Blockchain.ValidatorAddressPrefix, + ConsNodeAddressPrefix: config.Blockchain.ConNodeAddressPrefix, GithubAPIUser: config.IndexService.GithubAPI.Username, GithubAPIToken: config.IndexService.GithubAPI.Token, @@ -320,7 +323,28 @@ func InitProjection(name string, params InitProjectionParams) projection_entity. params.Logger.Panicf(err.Error()) } - return bridge_pending_activity.NewBridgePendingActivity(params.Logger, params.RdbConn, migrationHelper, config) + return bridge_pending_activity.New(config, params.Logger, params.RdbConn, migrationHelper) + // case "ValidatorDelegation": + // sourceURL := github_migrationhelper.GenerateDefaultSourceURL(name, githubMigrationHelperConfig) + // databaseURL := migrationhelper.GenerateDefaultDatabaseURL(name, connString) + // migrationHelper := github_migrationhelper.NewGithubMigrationHelper(sourceURL, databaseURL) + + // customConfig, err := validator_delegation.CustomConfigFromInterface(params.ExtraConfigs[name]) + // if err != nil { + // params.Logger.Panicf(err.Error()) + // } + + // config, err := validator_delegation.PrepareConfig( + // customConfig, + // params.AccountAddressPrefix, + // params.ValidatorAddressPrefix, + // params.ConsNodeAddressPrefix, + // ) + // if err != nil { + // params.Logger.Panicf(err.Error()) + // } + + // return validator_delegation.NewValidatorDelegation(params.Logger, params.RdbConn, config, migrationHelper) } return nil @@ -348,9 +372,10 @@ type InitProjectionParams struct { ExtraConfigs map[string]interface{} - CosmosAppClient cosmosapp.Client - AccountAddressPrefix string - ConsNodeAddressPrefix string + CosmosAppClient cosmosapp.Client + AccountAddressPrefix string + ValidatorAddressPrefix string + ConsNodeAddressPrefix string GithubAPIUser string GithubAPIToken string diff --git a/example/app/example-app/routes/routes.go b/example/app/example-app/routes/routes.go index 45a75823..aedd3b3f 100644 --- a/example/app/example-app/routes/routes.go +++ b/example/app/example-app/routes/routes.go @@ -6,17 +6,20 @@ import ( "github.com/crypto-com/chain-indexing/appinterface/tendermint" "github.com/crypto-com/chain-indexing/bootstrap" "github.com/crypto-com/chain-indexing/bootstrap/config" - custom_httpapi_handlers "github.com/crypto-com/chain-indexing/example/httpapi/handlers" applogger "github.com/crypto-com/chain-indexing/external/logger" cosmosapp_infrastructure "github.com/crypto-com/chain-indexing/infrastructure/cosmosapp" httpapi_handlers "github.com/crypto-com/chain-indexing/infrastructure/httpapi/handlers" tendermint_infrastructure "github.com/crypto-com/chain-indexing/infrastructure/tendermint" + + appconfig "github.com/crypto-com/chain-indexing/example/app/example-app/config" + custom_httpapi_handlers "github.com/crypto-com/chain-indexing/example/httpapi/handlers" ) func InitRouteRegistry( logger applogger.Logger, rdbConn rdb.Conn, config *config.Config, + customConfig *appconfig.CustomConfig, ) bootstrap.RouteRegistry { var cosmosAppClient cosmosapp.Client if config.CosmosApp.Insecure { @@ -335,6 +338,7 @@ func InitRouteRegistry( logger, rdbConn.ToHandle(), accountAddressPrefix, + appconfig.ParseBridgesConfig(&customConfig.BridgeAPI), ) routes = append(routes, Route{ @@ -366,5 +370,45 @@ func InitRouteRegistry( }, ) + // validatorDelegationHandler := httpapi_handlers.NewValidatorDelegation( + // logger, + // config.Blockchain.AccountAddressPrefix, + // config.Blockchain.ValidatorAddressPrefix, + // config.Blockchain.ConNodeAddressPrefix, + // rdbConn.ToHandle(), + // ) + // routes = append(routes, + // Route{ + // Method: GET, + // path: "api/test/validators", + // handler: validatorDelegationHandler.ListValidator, + // }, + // Route{ + // Method: GET, + // path: "api/test/validators/{address}", + // handler: validatorDelegationHandler.FindValidatorByAddress, + // }, + // Route{ + // Method: GET, + // path: "api/test/validators/{address}/delegations", + // handler: validatorDelegationHandler.ListDelegationByValidator, + // }, + // Route{ + // Method: GET, + // path: "api/test/validators/{address}/unbonding_delegations", + // handler: validatorDelegationHandler.ListUnbondingDelegationByValidator, + // }, + // Route{ + // Method: GET, + // path: "api/test/validators/{srcValAddress}/redelegations", + // handler: validatorDelegationHandler.ListRedelegationBySrcValidator, + // }, + // Route{ + // Method: GET, + // path: "api/test/delegators/{address}/delegations", + // handler: validatorDelegationHandler.ListDelegationByDelegator, + // }, + // ) + return &RouteRegistry{routes: routes} } diff --git a/example/app/example-app/run.go b/example/app/example-app/run.go index 3d128f74..f8d3ca08 100644 --- a/example/app/example-app/run.go +++ b/example/app/example-app/run.go @@ -5,15 +5,17 @@ import ( "os" "path/filepath" - "github.com/crypto-com/chain-indexing/bootstrap" - configuration "github.com/crypto-com/chain-indexing/bootstrap/config" - "github.com/crypto-com/chain-indexing/example/app/example-app/routes" - "github.com/crypto-com/chain-indexing/example/internal/filereader/yaml" "github.com/urfave/cli/v2" + "github.com/crypto-com/chain-indexing/bootstrap" + configuration "github.com/crypto-com/chain-indexing/bootstrap/config" applogger "github.com/crypto-com/chain-indexing/external/logger" "github.com/crypto-com/chain-indexing/external/primptr" "github.com/crypto-com/chain-indexing/infrastructure" + + appconfig "github.com/crypto-com/chain-indexing/example/app/example-app/config" + "github.com/crypto-com/chain-indexing/example/app/example-app/routes" + "github.com/crypto-com/chain-indexing/example/internal/filereader/yaml" ) func run(args []string) error { @@ -100,13 +102,13 @@ func run(args []string) error { return fmt.Errorf("error config from yaml: %v", err) } - var customConfig CustomConfig + var customConfig appconfig.CustomConfig err = yaml.FromYAMLFile(configPath, &customConfig) if err != nil { return fmt.Errorf("error custom config from yaml: %v", err) } - cliConfig := CLIConfig{ + cliConfig := appconfig.CLIConfig{ LogLevel: ctx.String("logLevel"), DatabaseHost: ctx.String("dbHost"), @@ -131,7 +133,7 @@ func run(args []string) error { cliConfig.DatabasePort = primptr.Int32(int32(ctx.Int("dbPort"))) } - OverrideByCLIConfig(&config, &cliConfig) + appconfig.OverrideByCLIConfig(&config, &cliConfig) // Create logger logLevel := parseLogLevel(config.Logger.Level) @@ -144,7 +146,7 @@ func run(args []string) error { initProjections(logger, app.GetRDbConn(), &config, &customConfig), initCronJobs(logger, app.GetRDbConn(), &config), ) - app.InitHTTPAPIServer(routes.InitRouteRegistry(logger, app.GetRDbConn(), &config)) + app.InitHTTPAPIServer(routes.InitRouteRegistry(logger, app.GetRDbConn(), &config, &customConfig)) app.Run() diff --git a/example/config/config.yaml b/example/config/config.yaml index 08629f4b..1b861b36 100644 --- a/example/config/config.yaml +++ b/example/config/config.yaml @@ -34,6 +34,7 @@ index_service: "IBCChannelMessage", "BridgePendingActivity", "Example", + # "ValidatorDelegation", ] extra_configs: BridgePendingActivity: @@ -42,6 +43,11 @@ index_service: counterparty_chain_name: "Cronos" channel_id: "channel-131" starting_height: 899374 + # ValidatorDelegation: + # unbonding_time: "2419200000000000ns" + # slash_fraction_double_sign: "0.050000000000000000" + # slash_fraction_downtime: "0.000000000000000000" + # default_power_reduction: "1000000" cronjob: enables: [ ] cosmos_version_enabled_height: diff --git a/example/go.mod b/example/go.mod index c3a910d1..7679f8bc 100644 --- a/example/go.mod +++ b/example/go.mod @@ -6,13 +6,10 @@ replace github.com/gogo/protobuf => github.com/regen-network/protobuf v1.3.2-alp replace github.com/rs/zerolog => github.com/rs/zerolog v1.23.0 -require ( - github.com/BurntSushi/toml v0.4.1 - github.com/urfave/cli/v2 v2.3.0 -) +require github.com/urfave/cli/v2 v2.3.0 require ( - github.com/crypto-com/chain-indexing v1.3.0 + github.com/crypto-com/chain-indexing v1.3.4 github.com/ettle/strcase v0.1.1 github.com/valyala/fasthttp v1.17.0 gopkg.in/yaml.v2 v2.4.0 @@ -38,9 +35,10 @@ require ( github.com/cespare/xxhash v1.1.0 // indirect github.com/cespare/xxhash/v2 v2.1.1 // indirect github.com/confio/ics23/go v0.6.6 // indirect - github.com/cosmos/cosmos-sdk v0.44.2 // indirect + github.com/cosmos/btcutil v1.0.4 // indirect + github.com/cosmos/cosmos-sdk v0.45.0 // indirect github.com/cosmos/go-bip39 v1.0.0 // indirect - github.com/cosmos/iavl v0.17.1 // indirect + github.com/cosmos/iavl v0.17.3 // indirect github.com/cosmos/ibc-go v1.2.1 // indirect github.com/cosmos/ledger-cosmos-go v0.11.1 // indirect github.com/cosmos/ledger-go v0.9.2 // indirect @@ -55,7 +53,6 @@ require ( github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/dustin/go-humanize v1.0.0 // indirect github.com/dvsekhvalnov/jose2go v0.0.0-20200901110807-248326c1351b // indirect - github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25 // indirect github.com/ethereum/go-ethereum v1.10.3 // indirect github.com/fasthttp/router v1.3.3 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect @@ -74,8 +71,10 @@ require ( github.com/google/uuid v1.3.0 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect + github.com/gravity-devs/liquidity v1.4.5 // indirect github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.0.1 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect github.com/gtank/merlin v0.1.1 // indirect github.com/gtank/ristretto255 v0.1.2 // indirect @@ -150,7 +149,7 @@ require ( github.com/tendermint/btcd v0.1.1 // indirect github.com/tendermint/crypto v0.0.0-20191022145703-50d29ede1e15 // indirect github.com/tendermint/go-amino v0.16.0 // indirect - github.com/tendermint/tendermint v0.34.13 // indirect + github.com/tendermint/tendermint v0.34.14 // indirect github.com/tendermint/tm-db v0.6.4 // indirect github.com/tharsis/ethermint v0.7.1 // indirect github.com/tklauser/go-sysconf v0.3.7 // indirect @@ -167,7 +166,7 @@ require ( golang.org/x/text v0.3.7 // indirect golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect google.golang.org/genproto v0.0.0-20211013025323-ce878158c4d4 // indirect - google.golang.org/grpc v1.41.0 // indirect + google.golang.org/grpc v1.42.0 // indirect google.golang.org/protobuf v1.27.1 // indirect gopkg.in/ini.v1 v1.63.2 // indirect gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce // indirect diff --git a/example/go.sum b/example/go.sum index 42de6b74..7e8d9e82 100644 --- a/example/go.sum +++ b/example/go.sum @@ -95,7 +95,6 @@ github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZ github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ChainSafe/go-schnorrkel v0.0.0-20200405005733-88cbf1b4c40d h1:nalkkPQcITbvhmL4+C4cKA87NW0tfm3Kl9VXRoPywFg= @@ -329,15 +328,19 @@ github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/cockroach-go/v2 v2.1.1/go.mod h1:7NtUnP6eK+l6k483WSYNrq3Kb23bWV10IRV1TyeSpwM= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/coinbase/rosetta-sdk-go v0.6.10 h1:rgHD/nHjxLh0lMEdfGDqpTtlvtSBwULqrrZ2qPdNaCM= github.com/coinbase/rosetta-sdk-go v0.6.10/go.mod h1:J/JFMsfcePrjJZkwQFLh+hJErkAmdm9Iyy3D5Y0LfXo= +github.com/coinbase/rosetta-sdk-go v0.7.0 h1:lmTO/JEpCvZgpbkOITL95rA80CPKb5CtMzLaqF2mCNg= +github.com/coinbase/rosetta-sdk-go v0.7.0/go.mod h1:7nD3oBPIiHqhRprqvMgPoGxe/nyq3yftRmpsy29coWE= github.com/confio/ics23/go v0.0.0-20200817220745-f173e6211efb/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= github.com/confio/ics23/go v0.6.3/go.mod h1:E45NqnlpxGnpfTWL/xauN7MRwEE28T4Dd4uraToOaKg= github.com/confio/ics23/go v0.6.6 h1:pkOy18YxxJ/r0XFDCnrl4Bjv6h4LkBSpLS6F38mrKL8= @@ -451,10 +454,13 @@ github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+ github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cosmos/btcutil v1.0.4 h1:n7C2ngKXo7UC9gNyMNLbzqz7Asuf+7Qv4gnX/rOdQ44= +github.com/cosmos/btcutil v1.0.4/go.mod h1:Ffqc8Hn6TJUdDgHBwIZLtrLQC1KdJ9jGJl/TvgUaxbU= github.com/cosmos/cosmos-sdk v0.43.0/go.mod h1:ctcrTEAhei9s8O3KSNvL0dxe+fVQGp07QyRb/7H9JYE= github.com/cosmos/cosmos-sdk v0.44.1/go.mod h1:fwQJdw+aECatpTvQTo1tSfHEsxACdZYU80QCZUPnHr4= -github.com/cosmos/cosmos-sdk v0.44.2 h1:EWoj9h9Q9t7uqS3LyqzZWWwnSEodUJlYDMloDoPBD3Y= github.com/cosmos/cosmos-sdk v0.44.2/go.mod h1:fwQJdw+aECatpTvQTo1tSfHEsxACdZYU80QCZUPnHr4= +github.com/cosmos/cosmos-sdk v0.45.0 h1:DHD+CIRZ+cYgiLXuTEUL/aprnfPsWSwaww/fIZEsZlk= +github.com/cosmos/cosmos-sdk v0.45.0/go.mod h1:XXS/asyCqWNWkx2rW6pSuen+EVcpAFxq6khrhnZgHaQ= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= @@ -462,8 +468,9 @@ github.com/cosmos/iavl v0.15.0-rc3.0.20201009144442-230e9bdf52cd/go.mod h1:3xOIa github.com/cosmos/iavl v0.15.0-rc5/go.mod h1:WqoPL9yPTQ85QBMT45OOUzPxG/U/JcJoN7uMjgxke/I= github.com/cosmos/iavl v0.15.3/go.mod h1:OLjQiAQ4fGD2KDZooyJG9yz+p2ao2IAYSbke8mVvSA4= github.com/cosmos/iavl v0.16.0/go.mod h1:2A8O/Jz9YwtjqXMO0CjnnbTYEEaovE8jWcwrakH3PoE= -github.com/cosmos/iavl v0.17.1 h1:b/Cl8h1PRMvsu24+TYNlKchIu7W6tmxIBGe6E9u2Ybw= github.com/cosmos/iavl v0.17.1/go.mod h1:7aisPZK8yCpQdy3PMvKeO+bhq1NwDjUwjzxwwROUxFk= +github.com/cosmos/iavl v0.17.3 h1:s2N819a2olOmiauVa0WAhoIJq9EhSXE9HDBAoR9k+8Y= +github.com/cosmos/iavl v0.17.3/go.mod h1:prJoErZFABYZGDHka1R6Oay4z9PrNeFFiMKHDAMOi4w= github.com/cosmos/ibc-go v1.0.0/go.mod h1:2wHKQUa+BLJMEyN635KrHfmTTwSNHBtXcqdY8JWGuXA= github.com/cosmos/ibc-go v1.0.1/go.mod h1:pfLnoW9yUdjSMw3rD0baIsqLBauVAlGFQ1zQ3HGK6J0= github.com/cosmos/ibc-go v1.2.1 h1:eWi8EzcgSwVipvhyQ7Rh1KfBe66C1ZdDSskeKMtIg0Q= @@ -480,8 +487,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/crypto-com/chain-indexing v1.2.1-0.20220111132225-b2712ba4fe23 h1:Pit1X4i8SXU/pUg60mo3tj/fKM+xYJ5j3TGtBK41D3k= -github.com/crypto-com/chain-indexing v1.2.1-0.20220111132225-b2712ba4fe23/go.mod h1:0KBBR7C2RZDavMpCBKlNtHkMZZ7tyndioZQRWUTD4YI= +github.com/crypto-com/chain-indexing v1.3.4 h1:voottjhjRDGnGFmC1g76v/yv7FYczChkgyGzii+j7Vs= +github.com/crypto-com/chain-indexing v1.3.4/go.mod h1:rBXfe6eRJmmkPL/tuw3fAClnp54N99sHisyi5rvVYaE= github.com/crypto-org-chain/chain-main/v3 v3.0.0-croeseid h1:YAffq+tYiSqYXgIb11Vc6dvBtgSvRsf2g1wPaMFkQUA= github.com/crypto-org-chain/chain-main/v3 v3.0.0-croeseid/go.mod h1:92Z70bDbsScrWzIHB496p7nXKydtq5am9rqa0fCpbM8= github.com/crypto-org-chain/cronos v0.6.0-testnet h1:iFLwra4QMZ6HgIEB1P0vMCa9pnQTeXjwSuYbH4glxqA= @@ -564,7 +571,6 @@ github.com/elastic/gosigar v0.14.1/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0 github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25 h1:2vLKys4RBU4pn2T/hjXMbvwTr1Cvy5THHrQkbeY9HRk= github.com/enigmampc/btcutil v1.0.3-0.20200723161021-e2fb6adb2a25/go.mod h1:hTr8+TLQmkUkgcuh3mcr5fjrT9c64ZzsBCdCEC6UppY= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -899,6 +905,8 @@ github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= github.com/graph-gophers/graphql-go v0.0.0-20191115155744-f33e81362277/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc= +github.com/gravity-devs/liquidity v1.4.5 h1:VhkcKima0HBztrrBdm4P0i1ey39KatyeB2u9AWJRCaI= +github.com/gravity-devs/liquidity v1.4.5/go.mod h1:TzUElAX4Wglt9x+8XWzPTMZGEwLrsTegXhk583Ht8RQ= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -915,6 +923,8 @@ github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqC github.com/grpc-ecosystem/grpc-gateway v1.14.7/go.mod h1:oYZKL012gGh6LMyg/xA7Q2yq6j8bu0wa+9w14EEthWU= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.0.1 h1:X2vfSnm1WC8HEo0MBHZg2TcuDUHJj6kd1TmEAQncnSA= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.0.1/go.mod h1:oVMjMN64nzEcepv1kdZKgx1qNYt4Ro0Gqefiq2JWdis= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= github.com/gtank/merlin v0.1.1-0.20191105220539-8318aed1a79f/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s= @@ -1709,8 +1719,9 @@ github.com/tendermint/tendermint v0.34.0/go.mod h1:Aj3PIipBFSNO21r+Lq3TtzQ+uKESx github.com/tendermint/tendermint v0.34.10/go.mod h1:aeHL7alPh4uTBIJQ8mgFEE8VwJLXI1VD3rVOmH2Mcy0= github.com/tendermint/tendermint v0.34.11/go.mod h1:aeHL7alPh4uTBIJQ8mgFEE8VwJLXI1VD3rVOmH2Mcy0= github.com/tendermint/tendermint v0.34.12/go.mod h1:aeHL7alPh4uTBIJQ8mgFEE8VwJLXI1VD3rVOmH2Mcy0= -github.com/tendermint/tendermint v0.34.13 h1:fu+tsHudbOr5PvepjH0q47Jae59hQAvn3IqAHv2EbC8= github.com/tendermint/tendermint v0.34.13/go.mod h1:6RVVRBqwtKhA+H59APKumO+B7Nye4QXSFc6+TYxAxCI= +github.com/tendermint/tendermint v0.34.14 h1:GCXmlS8Bqd2Ix3TQCpwYLUNHe+Y+QyJsm5YE+S/FkPo= +github.com/tendermint/tendermint v0.34.14/go.mod h1:FrwVm3TvsVicI9Z7FlucHV6Znfd5KBc/Lpp69cCwtk0= github.com/tendermint/tm-db v0.6.2/go.mod h1:GYtQ67SUvATOcoY8/+x6ylk8Qo02BQyLrAs+yAcLvGI= github.com/tendermint/tm-db v0.6.3/go.mod h1:lfA1dL9/Y/Y8wwyPp2NMLyn5P5Ptr/gvDFNWtrCWSf8= github.com/tendermint/tm-db v0.6.4 h1:3N2jlnYQkXNQclQwd/eKV/NzlqPlfK21cpRRIx80XXQ= @@ -2418,6 +2429,7 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D 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-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201111145450-ac7456db90a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -2486,8 +2498,10 @@ google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.41.0 h1:f+PlOh7QV4iIJkPrx5NQ7qaNGFQ3OTse67yaDHfju4E= google.golang.org/grpc v1.41.0/go.mod h1:U3l9uK9J0sini8mHphKoXyaqDA/8VyGnDee1zzIUK6k= +google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A= +google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= +google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.0.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.0.1/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= From 0e0c234a6a0f49523979348a7cbb26c7ea6d2394 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Fri, 11 Feb 2022 13:17:58 +0800 Subject: [PATCH 20/24] Removed performance trace related code --- ...view_vd_operation_performance_log.down.sql | 3 - ...e_view_vd_operation_performance_log.up.sql | 9 -- .../validator_delegation.go | 151 ------------------ .../view/operation_performance_logs.go | 61 ------- .../validator_delegation/view/validators.go | 57 ------- 5 files changed, 281 deletions(-) delete mode 100644 projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.down.sql delete mode 100644 projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.up.sql delete mode 100644 projection/validator_delegation/view/operation_performance_logs.go diff --git a/projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.down.sql b/projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.down.sql deleted file mode 100644 index 453594fe..00000000 --- a/projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.down.sql +++ /dev/null @@ -1,3 +0,0 @@ -DROP INDEX IF EXISTS view_vd_operation_performance_log_height_index; - -DROP TABLE IF EXISTS view_vd_operation_performance_log; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.up.sql b/projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.up.sql deleted file mode 100644 index 7441734a..00000000 --- a/projection/validator_delegation/migrations/20220124102425_create_view_vd_operation_performance_log.up.sql +++ /dev/null @@ -1,9 +0,0 @@ -CREATE TABLE view_vd_operation_performance_log ( - id BIGSERIAL, - height BIGINT NOT NULL, - action VARCHAR NOT NULL, - duration BIGINT NOT NULL, - PRIMARY KEY (id) -); - -CREATE INDEX view_vd_operation_performance_log_height_index ON view_vd_operation_performance_log USING btree (height); diff --git a/projection/validator_delegation/validator_delegation.go b/projection/validator_delegation/validator_delegation.go index 31a55298..ea479b21 100644 --- a/projection/validator_delegation/validator_delegation.go +++ b/projection/validator_delegation/validator_delegation.go @@ -110,9 +110,6 @@ var ( NewRedelegationQueue = view.NewRedelegationQueueView NewEvidences = view.NewEvidencesView UpdateLastHandledEventHeight = (*ValidatorDelegation).UpdateLastHandledEventHeight - - // DEBUG - NewOperationPerformanceLogs = view.NewOperationPerformanceLogsView ) type ValidatorDelegation struct { @@ -225,9 +222,6 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event } } - // DEBUG - start := time.Now() - // Handle evidence. // // NOTES: Although Evidences are handled by CosmosSDK in BeginBlock, @@ -249,19 +243,6 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event } } - // DEBUG - end := time.Now() - performanceView := NewOperationPerformanceLogs(rdbTxHandle) - if err := performanceView.Insert( - view.OperationPerformanceRow{ - Height: height, - Action: "Evidence", - Duration: end.Sub(start), - }, - ); err != nil { - return fmt.Errorf("error in inserting performance log: %v", err) - } - start = end // Handle events in BeginBlock. for _, event := range events { @@ -359,18 +340,6 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event } } - // DEBUG - end = time.Now() - if err := performanceView.Insert( - view.OperationPerformanceRow{ - Height: height, - Action: "BeginBlock", - Duration: end.Sub(start), - }, - ); err != nil { - return fmt.Errorf("error in inserting performance log: %v", err) - } - start = end // Handle events and msgs in Tx for _, event := range events { @@ -387,18 +356,6 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event ); err != nil { return fmt.Errorf("error handleCreateNewValidator when MsgCreateValidator: %v", err) } - // DEBUG - end = time.Now() - if err := performanceView.Insert( - view.OperationPerformanceRow{ - Height: height, - Action: "MsgCreateValidator", - Duration: end.Sub(start), - }, - ); err != nil { - return fmt.Errorf("error in inserting performance log: %v", err) - } - start = end } else if typedEvent, ok := event.(*event_usecase.MsgEditValidator); ok { @@ -412,18 +369,6 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event ); err != nil { return fmt.Errorf("error handling MsgEditValidator: %v", err) } - // DEBUG - end = time.Now() - if err := performanceView.Insert( - view.OperationPerformanceRow{ - Height: height, - Action: "MsgEditValidator", - Duration: end.Sub(start), - }, - ); err != nil { - return fmt.Errorf("error in inserting performance log: %v", err) - } - start = end } @@ -438,18 +383,6 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event ); err != nil { return fmt.Errorf("error handling MsgDelegate: %v", err) } - // DEBUG - end = time.Now() - if err := performanceView.Insert( - view.OperationPerformanceRow{ - Height: height, - Action: "MsgDelegate", - Duration: end.Sub(start), - }, - ); err != nil { - return fmt.Errorf("error in inserting performance log: %v", err) - } - start = end } else if typedEvent, ok := event.(*event_usecase.MsgUndelegate); ok { @@ -466,18 +399,6 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event ); err != nil { return fmt.Errorf("error handling MsgUndelegate: %v", err) } - // DEBUG - end = time.Now() - if err := performanceView.Insert( - view.OperationPerformanceRow{ - Height: height, - Action: "MsgUndelegate", - Duration: end.Sub(start), - }, - ); err != nil { - return fmt.Errorf("error in inserting performance log: %v", err) - } - start = end } @@ -494,18 +415,6 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event ); err != nil { return fmt.Errorf("error handling MsgBeginRedelegate: %v", err) } - // DEBUG - end = time.Now() - if err := performanceView.Insert( - view.OperationPerformanceRow{ - Height: height, - Action: "MsgBeginRedelegate", - Duration: end.Sub(start), - }, - ); err != nil { - return fmt.Errorf("error in inserting performance log: %v", err) - } - start = end } else if typedEvent, ok := event.(*event_usecase.MsgUnjail); ok { @@ -516,18 +425,6 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event ); err != nil { return fmt.Errorf("error handling MsgUnjail: %v", err) } - // DEBUG - end = time.Now() - if err := performanceView.Insert( - view.OperationPerformanceRow{ - Height: height, - Action: "MsgUnjail", - Duration: end.Sub(start), - }, - ); err != nil { - return fmt.Errorf("error in inserting performance log: %v", err) - } - start = end } } @@ -550,18 +447,6 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event } } - // DEBUG - end = time.Now() - if err := performanceView.Insert( - view.OperationPerformanceRow{ - Height: height, - Action: "EndBlock", - Duration: end.Sub(start), - }, - ); err != nil { - return fmt.Errorf("error in inserting performance log: %v", err) - } - start = end if err := projection.handleMatureUnbondingValidators( rdbTxHandle, @@ -570,18 +455,6 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event ); err != nil { return fmt.Errorf("error handling mature unbonding validators: %v", err) } - // DEBUG - end = time.Now() - if err := performanceView.Insert( - view.OperationPerformanceRow{ - Height: height, - Action: "MatureUnbondingValidators", - Duration: end.Sub(start), - }, - ); err != nil { - return fmt.Errorf("error in inserting performance log: %v", err) - } - start = end if err := projection.handleMatureUnbondingDelegationQueueEntries( rdbTxHandle, @@ -590,18 +463,6 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event ); err != nil { return fmt.Errorf("error handling mature unbonding delegation queue entries: %v", err) } - // DEBUG - end = time.Now() - if err := performanceView.Insert( - view.OperationPerformanceRow{ - Height: height, - Action: "MatureUnbondingDelegations", - Duration: end.Sub(start), - }, - ); err != nil { - return fmt.Errorf("error in inserting performance log: %v", err) - } - start = end if err := projection.handleMatureRedelegationQueueEntries( rdbTxHandle, @@ -610,18 +471,6 @@ func (projection *ValidatorDelegation) HandleEvents(height int64, events []event ); err != nil { return fmt.Errorf("error handling mature redelegation queue entries(): %v", err) } - // DEBUG - end = time.Now() - if err := performanceView.Insert( - view.OperationPerformanceRow{ - Height: height, - Action: "MatureRedelegations", - Duration: end.Sub(start), - }, - ); err != nil { - return fmt.Errorf("error in inserting performance log: %v", err) - } - start = end if err := UpdateLastHandledEventHeight(projection, rdbTxHandle, height); err != nil { return fmt.Errorf("error updating last handled event height: %v", err) diff --git a/projection/validator_delegation/view/operation_performance_logs.go b/projection/validator_delegation/view/operation_performance_logs.go deleted file mode 100644 index 61d45ebb..00000000 --- a/projection/validator_delegation/view/operation_performance_logs.go +++ /dev/null @@ -1,61 +0,0 @@ -package view - -import ( - "fmt" - "time" - - "github.com/crypto-com/chain-indexing/appinterface/rdb" -) - -type OperationPerformanceLogs interface { - Insert(row OperationPerformanceRow) error -} - -type OperationPerformanceLogsView struct { - rdb *rdb.Handle -} - -func NewOperationPerformanceLogsView(handle *rdb.Handle) OperationPerformanceLogs { - return &OperationPerformanceLogsView{ - handle, - } -} - -func (view *OperationPerformanceLogsView) Insert(row OperationPerformanceRow) error { - - sql, sqlArgs, err := view.rdb.StmtBuilder. - Insert( - "view_vd_operation_performance_log", - ). - Columns( - "height", - "action", - "duration", - ). - Values( - row.Height, - row.Action, - row.Duration.Milliseconds(), - ). - ToSql() - - if err != nil { - return fmt.Errorf("error building operation performance insertion sql: %v: %w", err, rdb.ErrBuildSQLStmt) - } - - result, err := view.rdb.Exec(sql, sqlArgs...) - if err != nil { - return fmt.Errorf("error inserting operation performance into the table: %v: %w", err, rdb.ErrWrite) - } - if result.RowsAffected() != 1 { - return fmt.Errorf("error inserting operation performance into the table: no rows inserted: %w", rdb.ErrWrite) - } - - return nil -} - -type OperationPerformanceRow struct { - Height int64 - Action string - Duration time.Duration -} diff --git a/projection/validator_delegation/view/validators.go b/projection/validator_delegation/view/validators.go index 01ee65c8..777c0add 100644 --- a/projection/validator_delegation/view/validators.go +++ b/projection/validator_delegation/view/validators.go @@ -3,7 +3,6 @@ package view import ( "errors" "fmt" - "time" "github.com/crypto-com/chain-indexing/appinterface/pagination" "github.com/crypto-com/chain-indexing/appinterface/rdb" @@ -84,29 +83,12 @@ func (view *ValidatorsView) Insert(row ValidatorRow) error { func (view *ValidatorsView) Update(row ValidatorRow) error { - // DEBUG - start := time.Now() - performanceView := NewOperationPerformanceLogsView(view.rdb) - // Check if there is an record's lower bound start with this height. found, err := view.checkIfValidatorRecordExistByHeightLowerBound(row) if err != nil { return fmt.Errorf("error in checking new validator record existence at this height: %v", err) } - // DEBUG - end := time.Now() - if err := performanceView.Insert( - OperationPerformanceRow{ - Height: row.Height, - Action: "UpdateValidator-CheckIfExist", - Duration: end.Sub(start), - }, - ); err != nil { - return fmt.Errorf("error in inserting performance log: %v", err) - } - start = end - if found { // If there is a record that height = `[row.Height,)`, then update the existed one @@ -143,19 +125,6 @@ func (view *ValidatorsView) Update(row ValidatorRow) error { return fmt.Errorf("error updating validator into the table: row updated: %v: %w", result.RowsAffected(), rdb.ErrWrite) } - // DEBUG - end = time.Now() - if err := performanceView.Insert( - OperationPerformanceRow{ - Height: row.Height, - Action: "UpdateValidator-UpdateExistedOne", - Duration: end.Sub(start), - }, - ); err != nil { - return fmt.Errorf("error in inserting performance log: %v", err) - } - start = end - } else { // If there is not an existed record, then update the previous record's height range and insert a new record @@ -164,37 +133,11 @@ func (view *ValidatorsView) Update(row ValidatorRow) error { return fmt.Errorf("error updating Validator.Height upper bound: %v", err) } - // DEBUG - end = time.Now() - if err := performanceView.Insert( - OperationPerformanceRow{ - Height: row.Height, - Action: "UpdateValidator-UpdatePreviousOne", - Duration: end.Sub(start), - }, - ); err != nil { - return fmt.Errorf("error in inserting performance log: %v", err) - } - start = end - err = view.Insert(row) if err != nil { return fmt.Errorf("error inserting a new record for this validator: %v", err) } - // DEBUG - end = time.Now() - if err := performanceView.Insert( - OperationPerformanceRow{ - Height: row.Height, - Action: "UpdateValidator-Insert", - Duration: end.Sub(start), - }, - ); err != nil { - return fmt.Errorf("error in inserting performance log: %v", err) - } - start = end - } return nil From f5211d12372e6fc6a89aca3ab6649a70b5f9abb8 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Fri, 11 Feb 2022 13:34:53 +0800 Subject: [PATCH 21/24] Updated example --- example/app/example-app/projections.go | 43 ++++++------- example/app/example-app/routes/routes.go | 78 ++++++++++++------------ example/config/config.yaml | 35 +++++------ example/go.mod | 2 +- example/go.sum | 4 +- 5 files changed, 82 insertions(+), 80 deletions(-) diff --git a/example/app/example-app/projections.go b/example/app/example-app/projections.go index 7e2e3558..a6df0c76 100644 --- a/example/app/example-app/projections.go +++ b/example/app/example-app/projections.go @@ -28,6 +28,7 @@ import ( "github.com/crypto-com/chain-indexing/projection/proposal" "github.com/crypto-com/chain-indexing/projection/transaction" "github.com/crypto-com/chain-indexing/projection/validator" + "github.com/crypto-com/chain-indexing/projection/validator_delegation" "github.com/crypto-com/chain-indexing/projection/validatorstats" "github.com/ettle/strcase" @@ -324,27 +325,27 @@ func InitProjection(name string, params InitProjectionParams) projection_entity. } return bridge_pending_activity.New(config, params.Logger, params.RdbConn, migrationHelper) - // case "ValidatorDelegation": - // sourceURL := github_migrationhelper.GenerateDefaultSourceURL(name, githubMigrationHelperConfig) - // databaseURL := migrationhelper.GenerateDefaultDatabaseURL(name, connString) - // migrationHelper := github_migrationhelper.NewGithubMigrationHelper(sourceURL, databaseURL) - - // customConfig, err := validator_delegation.CustomConfigFromInterface(params.ExtraConfigs[name]) - // if err != nil { - // params.Logger.Panicf(err.Error()) - // } - - // config, err := validator_delegation.PrepareConfig( - // customConfig, - // params.AccountAddressPrefix, - // params.ValidatorAddressPrefix, - // params.ConsNodeAddressPrefix, - // ) - // if err != nil { - // params.Logger.Panicf(err.Error()) - // } - - // return validator_delegation.NewValidatorDelegation(params.Logger, params.RdbConn, config, migrationHelper) + case "ValidatorDelegation": + sourceURL := github_migrationhelper.GenerateDefaultSourceURL(name, githubMigrationHelperConfig) + databaseURL := migrationhelper.GenerateDefaultDatabaseURL(name, connString) + migrationHelper := github_migrationhelper.NewGithubMigrationHelper(sourceURL, databaseURL) + + customConfig, err := validator_delegation.CustomConfigFromInterface(params.ExtraConfigs[name]) + if err != nil { + params.Logger.Panicf(err.Error()) + } + + config, err := validator_delegation.PrepareConfig( + customConfig, + params.AccountAddressPrefix, + params.ValidatorAddressPrefix, + params.ConsNodeAddressPrefix, + ) + if err != nil { + params.Logger.Panicf(err.Error()) + } + + return validator_delegation.NewValidatorDelegation(params.Logger, params.RdbConn, config, migrationHelper) } return nil diff --git a/example/app/example-app/routes/routes.go b/example/app/example-app/routes/routes.go index aedd3b3f..87aeaec2 100644 --- a/example/app/example-app/routes/routes.go +++ b/example/app/example-app/routes/routes.go @@ -370,45 +370,45 @@ func InitRouteRegistry( }, ) - // validatorDelegationHandler := httpapi_handlers.NewValidatorDelegation( - // logger, - // config.Blockchain.AccountAddressPrefix, - // config.Blockchain.ValidatorAddressPrefix, - // config.Blockchain.ConNodeAddressPrefix, - // rdbConn.ToHandle(), - // ) - // routes = append(routes, - // Route{ - // Method: GET, - // path: "api/test/validators", - // handler: validatorDelegationHandler.ListValidator, - // }, - // Route{ - // Method: GET, - // path: "api/test/validators/{address}", - // handler: validatorDelegationHandler.FindValidatorByAddress, - // }, - // Route{ - // Method: GET, - // path: "api/test/validators/{address}/delegations", - // handler: validatorDelegationHandler.ListDelegationByValidator, - // }, - // Route{ - // Method: GET, - // path: "api/test/validators/{address}/unbonding_delegations", - // handler: validatorDelegationHandler.ListUnbondingDelegationByValidator, - // }, - // Route{ - // Method: GET, - // path: "api/test/validators/{srcValAddress}/redelegations", - // handler: validatorDelegationHandler.ListRedelegationBySrcValidator, - // }, - // Route{ - // Method: GET, - // path: "api/test/delegators/{address}/delegations", - // handler: validatorDelegationHandler.ListDelegationByDelegator, - // }, - // ) + validatorDelegationHandler := httpapi_handlers.NewValidatorDelegation( + logger, + config.Blockchain.AccountAddressPrefix, + config.Blockchain.ValidatorAddressPrefix, + config.Blockchain.ConNodeAddressPrefix, + rdbConn.ToHandle(), + ) + routes = append(routes, + Route{ + Method: GET, + path: "api/test/validators", + handler: validatorDelegationHandler.ListValidator, + }, + Route{ + Method: GET, + path: "api/test/validators/{address}", + handler: validatorDelegationHandler.FindValidatorByAddress, + }, + Route{ + Method: GET, + path: "api/test/validators/{address}/delegations", + handler: validatorDelegationHandler.ListDelegationByValidator, + }, + Route{ + Method: GET, + path: "api/test/validators/{address}/unbonding_delegations", + handler: validatorDelegationHandler.ListUnbondingDelegationByValidator, + }, + Route{ + Method: GET, + path: "api/test/validators/{srcValAddress}/redelegations", + handler: validatorDelegationHandler.ListRedelegationBySrcValidator, + }, + Route{ + Method: GET, + path: "api/test/delegators/{address}/delegations", + handler: validatorDelegationHandler.ListDelegationByDelegator, + }, + ) return &RouteRegistry{routes: routes} } diff --git a/example/config/config.yaml b/example/config/config.yaml index 1b861b36..178e0367 100644 --- a/example/config/config.yaml +++ b/example/config/config.yaml @@ -28,14 +28,14 @@ index_service: "Validator", "ValidatorStats", "NFT", - # "CryptoComNFT", + # "CryptoComNFT", "IBCChannel", - # "IBCChannelTxMsgTrace", + # "IBCChannelTxMsgTrace", "IBCChannelMessage", "BridgePendingActivity", "Example", - # "ValidatorDelegation", - ] + "ValidatorDelegation", + ] extra_configs: BridgePendingActivity: this_chain_id: "testnet-croeseid-4" @@ -43,20 +43,20 @@ index_service: counterparty_chain_name: "Cronos" channel_id: "channel-131" starting_height: 899374 - # ValidatorDelegation: - # unbonding_time: "2419200000000000ns" - # slash_fraction_double_sign: "0.050000000000000000" - # slash_fraction_downtime: "0.000000000000000000" - # default_power_reduction: "1000000" + ValidatorDelegation: + unbonding_time: "2419200000000000ns" + slash_fraction_double_sign: "0.050000000000000000" + slash_fraction_downtime: "0.000000000000000000" + default_power_reduction: "1000000" cronjob: - enables: [ ] + enables: [] cosmos_version_enabled_height: v0_42_7: 0 github_api: # For `username` and `token`, please generate your own `Personal access tokens` in Github. username: "public" token: "token" - migration_repo_ref: "" + migration_repo_ref: "feature/652-part-2" http_service: enable: true @@ -65,9 +65,10 @@ http_service: # A list of origins a cross-domain request is allowed to be requested from # Default value '[]' disables CORS support # Use '["*"]' to allow request from any origin - cors_allowed_origins: [ ] - cors_allowed_methods: [ "HEAD", "GET" ] - cors_allowed_headers: [ "Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time" ] + cors_allowed_origins: [] + cors_allowed_methods: ["HEAD", "GET"] + cors_allowed_headers: + ["Origin", "Accept", "Content-Type", "X-Requested-With", "X-Server-Time"] tendermint_app: http_rpc_url: "https://testnet-croeseid-4.crypto.org:26657" @@ -90,7 +91,7 @@ postgres: username: "postgres" # password can only be provided through CLI or Environment variable `DB_PASSWORD` # password: "postgres" - name: "postgres" + name: "testnet-no-trace" schema: "public" ssl: true pool_max_conns: 100 @@ -101,7 +102,7 @@ postgres: logger: # Comma separated log levels. possible values: debug,info,error,panic - level: "debug" + level: "error" color: false prometheus: @@ -111,4 +112,4 @@ prometheus: # Custom config for example server_github_api: - migration_repo_ref: "" \ No newline at end of file + migration_repo_ref: "" diff --git a/example/go.mod b/example/go.mod index 7679f8bc..8321bcb1 100644 --- a/example/go.mod +++ b/example/go.mod @@ -9,7 +9,7 @@ replace github.com/rs/zerolog => github.com/rs/zerolog v1.23.0 require github.com/urfave/cli/v2 v2.3.0 require ( - github.com/crypto-com/chain-indexing v1.3.4 + github.com/crypto-com/chain-indexing v1.3.5-0.20220211051758-0e0c234a6a0f github.com/ettle/strcase v0.1.1 github.com/valyala/fasthttp v1.17.0 gopkg.in/yaml.v2 v2.4.0 diff --git a/example/go.sum b/example/go.sum index 7e8d9e82..04298995 100644 --- a/example/go.sum +++ b/example/go.sum @@ -487,8 +487,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/crypto-com/chain-indexing v1.3.4 h1:voottjhjRDGnGFmC1g76v/yv7FYczChkgyGzii+j7Vs= -github.com/crypto-com/chain-indexing v1.3.4/go.mod h1:rBXfe6eRJmmkPL/tuw3fAClnp54N99sHisyi5rvVYaE= +github.com/crypto-com/chain-indexing v1.3.5-0.20220211051758-0e0c234a6a0f h1:64MVP1S/XHyTyENTSmchtPPuT7fTjHyFQN6w2TcQTT4= +github.com/crypto-com/chain-indexing v1.3.5-0.20220211051758-0e0c234a6a0f/go.mod h1:rBXfe6eRJmmkPL/tuw3fAClnp54N99sHisyi5rvVYaE= github.com/crypto-org-chain/chain-main/v3 v3.0.0-croeseid h1:YAffq+tYiSqYXgIb11Vc6dvBtgSvRsf2g1wPaMFkQUA= github.com/crypto-org-chain/chain-main/v3 v3.0.0-croeseid/go.mod h1:92Z70bDbsScrWzIHB496p7nXKydtq5am9rqa0fCpbM8= github.com/crypto-org-chain/cronos v0.6.0-testnet h1:iFLwra4QMZ6HgIEB1P0vMCa9pnQTeXjwSuYbH4glxqA= From 720b1da192330272f3f345d8779cba62f880b565 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Fri, 11 Feb 2022 18:32:00 +0800 Subject: [PATCH 22/24] Changed back a example config --- example/config/config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/config/config.yaml b/example/config/config.yaml index 178e0367..16b62e07 100644 --- a/example/config/config.yaml +++ b/example/config/config.yaml @@ -91,7 +91,7 @@ postgres: username: "postgres" # password can only be provided through CLI or Environment variable `DB_PASSWORD` # password: "postgres" - name: "testnet-no-trace" + name: "postgres" schema: "public" ssl: true pool_max_conns: 100 From 38ae3fe094d6d76d15f80c2f7ce63e4782b3c03e Mon Sep 17 00:00:00 2001 From: Yang Song Date: Mon, 21 Feb 2022 10:44:25 +0800 Subject: [PATCH 23/24] Updated the PR according to comments. --- ...104331_create_view_vd_delegations.down.sql | 2 +- ...17104331_create_view_vd_delegations.up.sql | 2 +- ...17110519_create_view_vd_evidences.down.sql | 2 +- ...0117110519_create_view_vd_evidences.up.sql | 2 +- ...create_view_vd_redelegation_queue.down.sql | 2 +- ...5_create_view_vd_redelegation_queue.up.sql | 3 +- ...1937_create_view_vd_redelegations.down.sql | 4 +- ...111937_create_view_vd_redelegations.up.sql | 4 +- ...iew_vd_unbonding_delegation_queue.down.sql | 2 +- ..._view_vd_unbonding_delegation_queue.up.sql | 3 +- ...ate_view_vd_unbonding_delegations.down.sql | 4 +- ...reate_view_vd_unbonding_delegations.up.sql | 4 +- ...eate_view_vd_unbonding_validators.down.sql | 2 +- ...create_view_vd_unbonding_validators.up.sql | 2 +- ...7133017_create_view_vd_validators.down.sql | 4 +- ...117133017_create_view_vd_validators.up.sql | 4 +- .../validator_delegation/view/delegations.go | 30 ++++++------- .../validator_delegation/view/evidences.go | 4 +- .../view/redelegation_queue.go | 8 ++-- .../view/redelegations.go | 42 ++++++++++++------- .../view/unbonding_delegation_queue.go | 8 ++-- .../view/unbonding_delegations.go | 34 ++++++++------- .../view/unbonding_validators.go | 8 ++-- .../validator_delegation/view/validators.go | 26 ++++++------ 24 files changed, 111 insertions(+), 95 deletions(-) diff --git a/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.down.sql b/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.down.sql index 87cfa3ed..b880b04c 100644 --- a/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.down.sql +++ b/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.down.sql @@ -1,3 +1,3 @@ -DROP TABLE IF EXISTS view_vd_delegations; +DROP TABLE IF EXISTS view_validator_delegation_delegations; DROP EXTENSION IF EXISTS btree_gist; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.up.sql b/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.up.sql index 0ebe3f0b..4112ce1b 100644 --- a/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.up.sql +++ b/projection/validator_delegation/migrations/20220117104331_create_view_vd_delegations.up.sql @@ -1,6 +1,6 @@ CREATE EXTENSION btree_gist; -CREATE TABLE view_vd_delegations ( +CREATE TABLE view_validator_delegation_delegations ( id BIGSERIAL, height INT8RANGE NOT NULL, validator_address VARCHAR NOT NULL, diff --git a/projection/validator_delegation/migrations/20220117110519_create_view_vd_evidences.down.sql b/projection/validator_delegation/migrations/20220117110519_create_view_vd_evidences.down.sql index f1997639..889ceef3 100644 --- a/projection/validator_delegation/migrations/20220117110519_create_view_vd_evidences.down.sql +++ b/projection/validator_delegation/migrations/20220117110519_create_view_vd_evidences.down.sql @@ -1 +1 @@ -DROP TABLE IF EXISTS view_vd_evidences; \ No newline at end of file +DROP TABLE IF EXISTS view_validator_delegation_evidences; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117110519_create_view_vd_evidences.up.sql b/projection/validator_delegation/migrations/20220117110519_create_view_vd_evidences.up.sql index e8f3071f..e40b9c4a 100644 --- a/projection/validator_delegation/migrations/20220117110519_create_view_vd_evidences.up.sql +++ b/projection/validator_delegation/migrations/20220117110519_create_view_vd_evidences.up.sql @@ -1,4 +1,4 @@ -CREATE TABLE view_vd_evidences ( +CREATE TABLE view_validator_delegation_evidences ( id BIGSERIAL, height BIGINT NOT NULL, tendermint_address VARCHAR NOT NULL, diff --git a/projection/validator_delegation/migrations/20220117111405_create_view_vd_redelegation_queue.down.sql b/projection/validator_delegation/migrations/20220117111405_create_view_vd_redelegation_queue.down.sql index 21791710..1bfc4387 100644 --- a/projection/validator_delegation/migrations/20220117111405_create_view_vd_redelegation_queue.down.sql +++ b/projection/validator_delegation/migrations/20220117111405_create_view_vd_redelegation_queue.down.sql @@ -1 +1 @@ -DROP TABLE IF EXISTS view_vd_redelegation_queue; \ No newline at end of file +DROP TABLE IF EXISTS view_validator_delegation_redelegation_queue; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117111405_create_view_vd_redelegation_queue.up.sql b/projection/validator_delegation/migrations/20220117111405_create_view_vd_redelegation_queue.up.sql index 89cc4bb8..3206eddd 100644 --- a/projection/validator_delegation/migrations/20220117111405_create_view_vd_redelegation_queue.up.sql +++ b/projection/validator_delegation/migrations/20220117111405_create_view_vd_redelegation_queue.up.sql @@ -1,6 +1,7 @@ -CREATE TABLE view_vd_redelegation_queue ( +CREATE TABLE view_validator_delegation_redelegation_queue ( id BIGSERIAL, completion_time BIGINT NOT NULL UNIQUE, + -- dvv_triplets is a list of (delegator_addr, src_validator_addr, dst_validator_addr) triplet dvv_triplets JSONB NOT NULL, PRIMARY KEY (id) ); diff --git a/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.down.sql b/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.down.sql index e8cc696c..b251e9e8 100644 --- a/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.down.sql +++ b/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.down.sql @@ -1,3 +1,3 @@ -DROP INDEX IF EXISTS view_vd_redelegations_validator_src_addr_index; +DROP INDEX IF EXISTS view_validator_delegation_redelegations_validator_src_addr_index; -DROP TABLE IF EXISTS view_vd_redelegations; \ No newline at end of file +DROP TABLE IF EXISTS view_validator_delegation_redelegations; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.up.sql b/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.up.sql index 1356729e..366a764e 100644 --- a/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.up.sql +++ b/projection/validator_delegation/migrations/20220117111937_create_view_vd_redelegations.up.sql @@ -1,4 +1,4 @@ -CREATE TABLE view_vd_redelegations ( +CREATE TABLE view_validator_delegation_redelegations ( id BIGSERIAL, height INT8RANGE NOT NULL, delegator_address VARCHAR NOT NULL, @@ -16,4 +16,4 @@ CREATE TABLE view_vd_redelegations ( ) ); -CREATE INDEX view_vd_redelegations_validator_src_addr_index ON view_vd_redelegations USING gist (height, validator_src_address); +CREATE INDEX view_validator_delegation_redelegations_validator_src_addr_index ON view_validator_delegation_redelegations USING gist (height, validator_src_address); diff --git a/projection/validator_delegation/migrations/20220117130920_create_view_vd_unbonding_delegation_queue.down.sql b/projection/validator_delegation/migrations/20220117130920_create_view_vd_unbonding_delegation_queue.down.sql index c2b0d4a1..3479d3aa 100644 --- a/projection/validator_delegation/migrations/20220117130920_create_view_vd_unbonding_delegation_queue.down.sql +++ b/projection/validator_delegation/migrations/20220117130920_create_view_vd_unbonding_delegation_queue.down.sql @@ -1 +1 @@ -DROP TABLE IF EXISTS view_vd_unbonding_delegation_queue; \ No newline at end of file +DROP TABLE IF EXISTS view_validator_delegation_unbonding_delegation_queue; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117130920_create_view_vd_unbonding_delegation_queue.up.sql b/projection/validator_delegation/migrations/20220117130920_create_view_vd_unbonding_delegation_queue.up.sql index 4638701b..9d6fe925 100644 --- a/projection/validator_delegation/migrations/20220117130920_create_view_vd_unbonding_delegation_queue.up.sql +++ b/projection/validator_delegation/migrations/20220117130920_create_view_vd_unbonding_delegation_queue.up.sql @@ -1,6 +1,7 @@ -CREATE TABLE view_vd_unbonding_delegation_queue ( +CREATE TABLE view_validator_delegation_unbonding_delegation_queue ( id BIGSERIAL, completion_time BIGINT NOT NULL UNIQUE, + -- dv_pairs is a list of (delegator_addr, validator_addr) pair dv_pairs JSONB NOT NULL, PRIMARY KEY (id) ); diff --git a/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.down.sql b/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.down.sql index a4d3175b..3f15922a 100644 --- a/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.down.sql +++ b/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.down.sql @@ -1,3 +1,3 @@ -DROP INDEX IF EXISTS view_vd_unbonding_delegations_validator_addr_height_index; +DROP INDEX IF EXISTS view_validator_delegation_unbonding_delegations_validator_addr_height_index; -DROP TABLE IF EXISTS view_vd_unbonding_delegations; \ No newline at end of file +DROP TABLE IF EXISTS view_validator_delegation_unbonding_delegations; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.up.sql b/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.up.sql index 4696bd4a..fb07ba59 100644 --- a/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.up.sql +++ b/projection/validator_delegation/migrations/20220117131200_create_view_vd_unbonding_delegations.up.sql @@ -1,4 +1,4 @@ -CREATE TABLE view_vd_unbonding_delegations ( +CREATE TABLE view_validator_delegation_unbonding_delegations ( id BIGSERIAL, height INT8RANGE NOT NULL, delegator_address VARCHAR NOT NULL, @@ -10,4 +10,4 @@ CREATE TABLE view_vd_unbonding_delegations ( EXCLUDE USING gist (delegator_address WITH =, validator_address WITH =, height WITH &&) ); -CREATE INDEX view_vd_unbonding_delegations_validator_addr_height_index ON view_vd_unbonding_delegations USING gist (height, validator_address); +CREATE INDEX view_validator_delegation_unbonding_delegations_validator_addr_height_index ON view_validator_delegation_unbonding_delegations USING gist (height, validator_address); diff --git a/projection/validator_delegation/migrations/20220117132223_create_view_vd_unbonding_validators.down.sql b/projection/validator_delegation/migrations/20220117132223_create_view_vd_unbonding_validators.down.sql index 85f88a62..63e4242e 100644 --- a/projection/validator_delegation/migrations/20220117132223_create_view_vd_unbonding_validators.down.sql +++ b/projection/validator_delegation/migrations/20220117132223_create_view_vd_unbonding_validators.down.sql @@ -1 +1 @@ -DROP TABLE IF EXISTS view_vd_unbonding_validators; \ No newline at end of file +DROP TABLE IF EXISTS view_validator_delegation_unbonding_validators; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117132223_create_view_vd_unbonding_validators.up.sql b/projection/validator_delegation/migrations/20220117132223_create_view_vd_unbonding_validators.up.sql index 553eb5c2..eb57e666 100644 --- a/projection/validator_delegation/migrations/20220117132223_create_view_vd_unbonding_validators.up.sql +++ b/projection/validator_delegation/migrations/20220117132223_create_view_vd_unbonding_validators.up.sql @@ -1,4 +1,4 @@ -CREATE TABLE view_vd_unbonding_validators ( +CREATE TABLE view_validator_delegation_unbonding_validators ( id BIGSERIAL, operator_address VARCHAR NOT NULL UNIQUE, unbonding_time BIGINT NOT NULL, diff --git a/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.down.sql b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.down.sql index 3d9e6dcf..72e4060f 100644 --- a/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.down.sql +++ b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.down.sql @@ -1,3 +1,3 @@ -DROP INDEX IF EXISTS view_vd_validators_height_index; +DROP INDEX IF EXISTS view_validator_delegation_validators_height_index; -DROP TABLE IF EXISTS view_vd_validators; \ No newline at end of file +DROP TABLE IF EXISTS view_validator_delegation_validators; \ No newline at end of file diff --git a/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql index c08d8b4c..700b97ce 100644 --- a/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql +++ b/projection/validator_delegation/migrations/20220117133017_create_view_vd_validators.up.sql @@ -1,4 +1,4 @@ -CREATE TABLE view_vd_validators ( +CREATE TABLE view_validator_delegation_validators ( id BIGSERIAL, height INT8RANGE NOT NULL, operator_address VARCHAR NOT NULL, @@ -25,4 +25,4 @@ CREATE TABLE view_vd_validators ( ) ); -CREATE INDEX view_vd_validators_height_index ON view_vd_validators USING gist (height); +CREATE INDEX view_validator_delegation_validators_height_index ON view_validator_delegation_validators USING gist (height); diff --git a/projection/validator_delegation/view/delegations.go b/projection/validator_delegation/view/delegations.go index 5e3b63cb..8fffb36f 100644 --- a/projection/validator_delegation/view/delegations.go +++ b/projection/validator_delegation/view/delegations.go @@ -42,7 +42,7 @@ func (view *DelegationsView) Insert(row DelegationRow) error { sql, sqlArgs, err := view.rdb.StmtBuilder. Insert( - "view_vd_delegations", + "view_validator_delegation_delegations", ). Columns( "height", @@ -76,7 +76,7 @@ func (view *DelegationsView) Insert(row DelegationRow) error { func (view *DelegationsView) Update(row DelegationRow) error { // Check if there is an record's lower bound start with this height. - found, err := view.checkIfDelegationRecordExistByHeightLowerBound(row) + found, err := view.isExistedByLowerBoundHeight(row.ValidatorAddress, row.DelegatorAddress, row.Height) if err != nil { return fmt.Errorf("error in checking new delegation record existence at this height: %v", err) } @@ -86,7 +86,7 @@ func (view *DelegationsView) Update(row DelegationRow) error { sql, sqlArgs, err := view.rdb.StmtBuilder. Update( - "view_vd_delegations", + "view_validator_delegation_delegations", ). SetMap(map[string]interface{}{ "shares": row.Shares.String(), @@ -114,7 +114,7 @@ func (view *DelegationsView) Update(row DelegationRow) error { } else { // Else, update the previous record's height range, then insert a new record - err := view.setDelegationRecordHeightUpperBound(row) + err := view.updateUpperBoundHeight(row) if err != nil { return fmt.Errorf("error updating delegation.Height upper bound: %v", err) } @@ -128,18 +128,18 @@ func (view *DelegationsView) Update(row DelegationRow) error { return nil } -func (view *DelegationsView) checkIfDelegationRecordExistByHeightLowerBound(row DelegationRow) (bool, error) { +func (view *DelegationsView) isExistedByLowerBoundHeight(validatorAddress, delegatorAddress string, height int64) (bool, error) { sql, sqlArgs, err := view.rdb.StmtBuilder. Select( "COUNT(*)", ). - From("view_vd_delegations"). + From("view_validator_delegation_delegations"). Where( "validator_address = ? AND delegator_address = ? AND height = ?", - row.ValidatorAddress, - row.DelegatorAddress, - fmt.Sprintf("[%v,)", row.Height), + validatorAddress, + delegatorAddress, + fmt.Sprintf("[%v,)", height), ). ToSql() if err != nil { @@ -158,14 +158,14 @@ func (view *DelegationsView) checkIfDelegationRecordExistByHeightLowerBound(row func (view *DelegationsView) Delete(row DelegationRow) error { - return view.setDelegationRecordHeightUpperBound(row) + return view.updateUpperBoundHeight(row) } -func (view *DelegationsView) setDelegationRecordHeightUpperBound(row DelegationRow) error { +func (view *DelegationsView) updateUpperBoundHeight(row DelegationRow) error { // Set the upper bound for record height: `[, row.Height)`. sql, sqlErr := view.rdb.StmtBuilder.ReplacePlaceholders(` - UPDATE view_vd_delegations + UPDATE view_validator_delegation_delegations SET height = int8range(lower(height), ?, '[)') WHERE validator_address = ? AND delegator_address = ? AND height @> ?::int8 `) @@ -196,7 +196,7 @@ func (view *DelegationsView) FindBy( Select( "shares", ). - From("view_vd_delegations"). + From("view_validator_delegation_delegations"). Where( "validator_address = ? AND delegator_address = ? AND height @> ?::int8", validatorAddress, @@ -244,7 +244,7 @@ func (view *DelegationsView) ListByValidatorAddr( "shares", ). From( - "view_vd_delegations", + "view_validator_delegation_delegations", ). Where( "validator_address = ? AND height @> ?::int8", @@ -309,7 +309,7 @@ func (view *DelegationsView) ListByDelegatorAddr( "shares", ). From( - "view_vd_delegations", + "view_validator_delegation_delegations", ). Where( "delegator_address = ? AND height @> ?::int8", diff --git a/projection/validator_delegation/view/evidences.go b/projection/validator_delegation/view/evidences.go index 6618cc8c..818b45f3 100644 --- a/projection/validator_delegation/view/evidences.go +++ b/projection/validator_delegation/view/evidences.go @@ -32,7 +32,7 @@ func (view *EvidencesView) Insert(row EvidenceRow) error { sql, sqlArgs, err := view.rdb.StmtBuilder. Insert( - "view_vd_evidences", + "view_validator_delegation_evidences", ). Columns( "height", @@ -70,7 +70,7 @@ func (view *EvidencesView) FindBy(height int64, tendermintAddress string) (Evide "infraction_height", "raw_evidence", ). - From("view_vd_evidences"). + From("view_validator_delegation_evidences"). Where( "tendermint_address = ? AND height = ?", tendermintAddress, diff --git a/projection/validator_delegation/view/redelegation_queue.go b/projection/validator_delegation/view/redelegation_queue.go index 1b161372..33e60116 100644 --- a/projection/validator_delegation/view/redelegation_queue.go +++ b/projection/validator_delegation/view/redelegation_queue.go @@ -34,7 +34,7 @@ func (view *RedelegationQueueView) Upsert(row RedelegationQueueRow) error { sql, sqlArgs, err := view.rdb.StmtBuilder. Insert( - "view_vd_redelegation_queue", + "view_validator_delegation_redelegation_queue", ). Columns( "completion_time", @@ -68,7 +68,7 @@ func (view *RedelegationQueueView) FindBy(completionTime utctime.UTCTime) (Redel Select( "dvv_triplets", ). - From("view_vd_redelegation_queue"). + From("view_validator_delegation_redelegation_queue"). Where( "completion_time = ?", view.rdb.Tton(&completionTime), @@ -108,7 +108,7 @@ func (view *RedelegationQueueView) DequeueAllMatureRedelegationQueue(blockTime u "dvv_triplets", ). From( - "view_vd_redelegation_queue", + "view_validator_delegation_redelegation_queue", ). Where( "completion_time <= ?", @@ -150,7 +150,7 @@ func (view *RedelegationQueueView) DequeueAllMatureRedelegationQueue(blockTime u sql, sqlArgs, err = view.rdb.StmtBuilder. Delete( - "view_vd_redelegation_queue", + "view_validator_delegation_redelegation_queue", ). Where( "completion_time <= ?", diff --git a/projection/validator_delegation/view/redelegations.go b/projection/validator_delegation/view/redelegations.go index 7a24691d..8a6896b4 100644 --- a/projection/validator_delegation/view/redelegations.go +++ b/projection/validator_delegation/view/redelegations.go @@ -46,7 +46,7 @@ func (view *RedelegationsView) Insert(row RedelegationRow) error { sql, sqlArgs, err := view.rdb.StmtBuilder. Insert( - "view_vd_redelegations", + "view_validator_delegation_redelegations", ). Columns( "height", @@ -82,7 +82,12 @@ func (view *RedelegationsView) Insert(row RedelegationRow) error { func (view *RedelegationsView) Update(row RedelegationRow) error { // Check if there is an record's lower bound start with this height. - found, err := view.checkIfRedelegationRecordExistByHeightLowerBound(row) + found, err := view.isExistedByLowerBoundHeight( + row.DelegatorAddress, + row.ValidatorSrcAddress, + row.ValidatorDstAddress, + row.Height, + ) if err != nil { return fmt.Errorf("error in checking new Redelegation record existence at this height: %v", err) } @@ -97,7 +102,7 @@ func (view *RedelegationsView) Update(row RedelegationRow) error { sql, sqlArgs, err := view.rdb.StmtBuilder. Update( - "view_vd_redelegations", + "view_validator_delegation_redelegations", ). SetMap(map[string]interface{}{ "entries": entriesJSON, @@ -126,7 +131,7 @@ func (view *RedelegationsView) Update(row RedelegationRow) error { } else { // If there is not an existed record, then update the previous record's height range and insert a new record - err := view.setRedelegationRecordHeightUpperBound(row) + err := view.updateUpperBoundHeight(row) if err != nil { return fmt.Errorf("error updating Redelegation.Height upper bound: %v", err) } @@ -140,19 +145,24 @@ func (view *RedelegationsView) Update(row RedelegationRow) error { return nil } -func (view *RedelegationsView) checkIfRedelegationRecordExistByHeightLowerBound(row RedelegationRow) (bool, error) { +func (view *RedelegationsView) isExistedByLowerBoundHeight( + delegatorAddress string, + validatorSrcAddress string, + validatorDstAddress string, + height int64, +) (bool, error) { sql, sqlArgs, err := view.rdb.StmtBuilder. Select( "COUNT(*)", ). - From("view_vd_redelegations"). + From("view_validator_delegation_redelegations"). Where( "delegator_address = ? AND validator_src_address = ? AND validator_dst_address = ? AND height = ?", - row.DelegatorAddress, - row.ValidatorSrcAddress, - row.ValidatorDstAddress, - fmt.Sprintf("[%v,)", row.Height), + delegatorAddress, + validatorSrcAddress, + validatorDstAddress, + fmt.Sprintf("[%v,)", height), ). ToSql() if err != nil { @@ -171,14 +181,14 @@ func (view *RedelegationsView) checkIfRedelegationRecordExistByHeightLowerBound( func (view *RedelegationsView) Delete(row RedelegationRow) error { - return view.setRedelegationRecordHeightUpperBound(row) + return view.updateUpperBoundHeight(row) } -func (view *RedelegationsView) setRedelegationRecordHeightUpperBound(row RedelegationRow) error { +func (view *RedelegationsView) updateUpperBoundHeight(row RedelegationRow) error { // Set the upper bound for record height: `[, row.Height)`. sql, sqlErr := view.rdb.StmtBuilder.ReplacePlaceholders(` - UPDATE view_vd_redelegations + UPDATE view_validator_delegation_redelegations SET height = int8range(lower(height), ?, '[)') WHERE delegator_address = ? AND validator_src_address = ? AND validator_dst_address = ? AND height @> ?::int8 `) @@ -211,7 +221,7 @@ func (view *RedelegationsView) FindBy( Select( "entries", ). - From("view_vd_redelegations"). + From("view_validator_delegation_redelegations"). Where( "delegator_address = ? AND validator_src_address = ? AND validator_dst_address = ? AND height @> ?::int8", delegatorAddress, @@ -260,7 +270,7 @@ func (view *RedelegationsView) ListBySrcValidator( "entries", ). From( - "view_vd_redelegations", + "view_validator_delegation_redelegations", ). Where( "validator_src_address = ? AND height @> ?::int8", @@ -316,7 +326,7 @@ func (view *RedelegationsView) ListBySrcValidatorWithPagination( "entries", ). From( - "view_vd_redelegations", + "view_validator_delegation_redelegations", ). Where( "validator_src_address = ? AND height @> ?::int8", diff --git a/projection/validator_delegation/view/unbonding_delegation_queue.go b/projection/validator_delegation/view/unbonding_delegation_queue.go index 10d686ac..afa3c131 100644 --- a/projection/validator_delegation/view/unbonding_delegation_queue.go +++ b/projection/validator_delegation/view/unbonding_delegation_queue.go @@ -34,7 +34,7 @@ func (view *UnbondingDelegationQueueView) Upsert(row UnbondingDelegationQueueRow sql, sqlArgs, err := view.rdb.StmtBuilder. Insert( - "view_vd_unbonding_delegation_queue", + "view_validator_delegation_unbonding_delegation_queue", ). Columns( "completion_time", @@ -68,7 +68,7 @@ func (view *UnbondingDelegationQueueView) FindBy(completionTime utctime.UTCTime) Select( "dv_pairs", ). - From("view_vd_unbonding_delegation_queue"). + From("view_validator_delegation_unbonding_delegation_queue"). Where( "completion_time = ?", view.rdb.Tton(&completionTime), @@ -108,7 +108,7 @@ func (view *UnbondingDelegationQueueView) DequeueAllMatureUnbondingDelegationQue "dv_pairs", ). From( - "view_vd_unbonding_delegation_queue", + "view_validator_delegation_unbonding_delegation_queue", ). Where( "completion_time <= ?", @@ -150,7 +150,7 @@ func (view *UnbondingDelegationQueueView) DequeueAllMatureUnbondingDelegationQue sql, sqlArgs, err = view.rdb.StmtBuilder. Delete( - "view_vd_unbonding_delegation_queue", + "view_validator_delegation_unbonding_delegation_queue", ). Where( "completion_time <= ?", diff --git a/projection/validator_delegation/view/unbonding_delegations.go b/projection/validator_delegation/view/unbonding_delegations.go index 6d849121..fb8a51b6 100644 --- a/projection/validator_delegation/view/unbonding_delegations.go +++ b/projection/validator_delegation/view/unbonding_delegations.go @@ -45,7 +45,7 @@ func (view *UnbondingDelegationsView) Insert(row UnbondingDelegationRow) error { sql, sqlArgs, err := view.rdb.StmtBuilder. Insert( - "view_vd_unbonding_delegations", + "view_validator_delegation_unbonding_delegations", ). Columns( "height", @@ -79,7 +79,7 @@ func (view *UnbondingDelegationsView) Insert(row UnbondingDelegationRow) error { func (view *UnbondingDelegationsView) Update(row UnbondingDelegationRow) error { // Check if there is an record's lower bound start with this height. - found, err := view.checkIfUnbondingDelegationRecordExistByHeightLowerBound(row) + found, err := view.isExistedByLowerBoundHeight(row.DelegatorAddress, row.ValidatorAddress, row.Height) if err != nil { return fmt.Errorf("error in checking new UnbondingDelegation record existence at this height: %v", err) } @@ -94,7 +94,7 @@ func (view *UnbondingDelegationsView) Update(row UnbondingDelegationRow) error { sql, sqlArgs, err := view.rdb.StmtBuilder. Update( - "view_vd_unbonding_delegations", + "view_validator_delegation_unbonding_delegations", ). SetMap(map[string]interface{}{ "entries": entriesJSON, @@ -122,7 +122,7 @@ func (view *UnbondingDelegationsView) Update(row UnbondingDelegationRow) error { } else { // If there is not an existed record, then update the previous record's height range and insert a new record - err := view.setUnbondingDelegationRecordHeightUpperBound(row) + err := view.updateUpperBoundHeight(row) if err != nil { return fmt.Errorf("error updating UnbondingDelegation.Height upper bound: %v", err) } @@ -136,18 +136,22 @@ func (view *UnbondingDelegationsView) Update(row UnbondingDelegationRow) error { return nil } -func (view *UnbondingDelegationsView) checkIfUnbondingDelegationRecordExistByHeightLowerBound(row UnbondingDelegationRow) (bool, error) { +func (view *UnbondingDelegationsView) isExistedByLowerBoundHeight( + delegatorAddress string, + validatorAddress string, + height int64, +) (bool, error) { sql, sqlArgs, err := view.rdb.StmtBuilder. Select( "COUNT(*)", ). - From("view_vd_unbonding_delegations"). + From("view_validator_delegation_unbonding_delegations"). Where( "delegator_address = ? AND validator_address = ? AND height = ?", - row.DelegatorAddress, - row.ValidatorAddress, - fmt.Sprintf("[%v,)", row.Height), + delegatorAddress, + validatorAddress, + fmt.Sprintf("[%v,)", height), ). ToSql() if err != nil { @@ -166,14 +170,14 @@ func (view *UnbondingDelegationsView) checkIfUnbondingDelegationRecordExistByHei func (view *UnbondingDelegationsView) Delete(row UnbondingDelegationRow) error { - return view.setUnbondingDelegationRecordHeightUpperBound(row) + return view.updateUpperBoundHeight(row) } -func (view *UnbondingDelegationsView) setUnbondingDelegationRecordHeightUpperBound(row UnbondingDelegationRow) error { +func (view *UnbondingDelegationsView) updateUpperBoundHeight(row UnbondingDelegationRow) error { // Set the upper bound for record height: `[, row.Height)`. sql, sqlErr := view.rdb.StmtBuilder.ReplacePlaceholders(` - UPDATE view_vd_unbonding_delegations + UPDATE view_validator_delegation_unbonding_delegations SET height = int8range(lower(height), ?, '[)') WHERE delegator_address = ? AND validator_address = ? AND height @> ?::int8 `) @@ -204,7 +208,7 @@ func (view *UnbondingDelegationsView) FindBy( Select( "entries", ). - From("view_vd_unbonding_delegations"). + From("view_validator_delegation_unbonding_delegations"). Where( "delegator_address = ? AND validator_address = ? AND height @> ?::int8", delegatorAddress, @@ -250,7 +254,7 @@ func (view *UnbondingDelegationsView) ListByValidator( "entries", ). From( - "view_vd_unbonding_delegations", + "view_validator_delegation_unbonding_delegations", ). Where( "validator_address = ? AND height @> ?::int8", @@ -304,7 +308,7 @@ func (view *UnbondingDelegationsView) ListByValidatorWithPagination( "entries", ). From( - "view_vd_unbonding_delegations", + "view_validator_delegation_unbonding_delegations", ). Where( "validator_address = ? AND height @> ?::int8", diff --git a/projection/validator_delegation/view/unbonding_validators.go b/projection/validator_delegation/view/unbonding_validators.go index 868ed004..d3d234f6 100644 --- a/projection/validator_delegation/view/unbonding_validators.go +++ b/projection/validator_delegation/view/unbonding_validators.go @@ -28,7 +28,7 @@ func (view *UnbondingValidatorsView) Insert(operatorAddress string, unbondingTim sql, sqlArgs, err := view.rdb.StmtBuilder. Insert( - "view_vd_unbonding_validators", + "view_validator_delegation_unbonding_validators", ). Columns( "operator_address", @@ -59,7 +59,7 @@ func (view *UnbondingValidatorsView) RemoveIfExist(operatorAddress string) error sql, sqlArgs, err := view.rdb.StmtBuilder. Delete( - "view_vd_unbonding_validators", + "view_validator_delegation_unbonding_validators", ). Where( "operator_address = ?", @@ -87,7 +87,7 @@ func (view *UnbondingValidatorsView) GetMatureEntries(blockTime utctime.UTCTime) "unbonding_time", ). From( - "view_vd_unbonding_validators", + "view_validator_delegation_unbonding_validators", ). Where( "unbonding_time <= ?", @@ -133,7 +133,7 @@ func (view *UnbondingValidatorsView) DeleteMatureEntries(blockTime utctime.UTCTi sql, sqlArgs, err := view.rdb.StmtBuilder. Delete( - "view_vd_unbonding_validators", + "view_validator_delegation_unbonding_validators", ). Where( "unbonding_time <= ?", diff --git a/projection/validator_delegation/view/validators.go b/projection/validator_delegation/view/validators.go index 777c0add..4649a40c 100644 --- a/projection/validator_delegation/view/validators.go +++ b/projection/validator_delegation/view/validators.go @@ -34,7 +34,7 @@ func (view *ValidatorsView) Insert(row ValidatorRow) error { sql, sqlArgs, err := view.rdb.StmtBuilder. Insert( - "view_vd_validators", + "view_validator_delegation_validators", ). Columns( "height", @@ -84,7 +84,7 @@ func (view *ValidatorsView) Insert(row ValidatorRow) error { func (view *ValidatorsView) Update(row ValidatorRow) error { // Check if there is an record's lower bound start with this height. - found, err := view.checkIfValidatorRecordExistByHeightLowerBound(row) + found, err := view.isExistedByLowerBoundHeight(row.OperatorAddress, row.Height) if err != nil { return fmt.Errorf("error in checking new validator record existence at this height: %v", err) } @@ -94,7 +94,7 @@ func (view *ValidatorsView) Update(row ValidatorRow) error { sql, sqlArgs, err := view.rdb.StmtBuilder. Update( - "view_vd_validators", + "view_validator_delegation_validators", ). SetMap(map[string]interface{}{ "status": row.Status, @@ -128,7 +128,7 @@ func (view *ValidatorsView) Update(row ValidatorRow) error { } else { // If there is not an existed record, then update the previous record's height range and insert a new record - err := view.setValidatorRecordHeightUpperBound(row) + err := view.updateUpperBoundHeight(row) if err != nil { return fmt.Errorf("error updating Validator.Height upper bound: %v", err) } @@ -143,17 +143,17 @@ func (view *ValidatorsView) Update(row ValidatorRow) error { return nil } -func (view *ValidatorsView) checkIfValidatorRecordExistByHeightLowerBound(row ValidatorRow) (bool, error) { +func (view *ValidatorsView) isExistedByLowerBoundHeight(operatorAddress string, height int64) (bool, error) { sql, sqlArgs, err := view.rdb.StmtBuilder. Select( "COUNT(*)", ). - From("view_vd_validators"). + From("view_validator_delegation_validators"). Where( "operator_address = ? AND height = ?", - row.OperatorAddress, - fmt.Sprintf("[%v,)", row.Height), + operatorAddress, + fmt.Sprintf("[%v,)", height), ). ToSql() if err != nil { @@ -172,14 +172,14 @@ func (view *ValidatorsView) checkIfValidatorRecordExistByHeightLowerBound(row Va func (view *ValidatorsView) Delete(row ValidatorRow) error { - return view.setValidatorRecordHeightUpperBound(row) + return view.updateUpperBoundHeight(row) } -func (view *ValidatorsView) setValidatorRecordHeightUpperBound(row ValidatorRow) error { +func (view *ValidatorsView) updateUpperBoundHeight(row ValidatorRow) error { // Set the upper bound for record height: `[, row.Height)`. sql, sqlErr := view.rdb.StmtBuilder.ReplacePlaceholders(` - UPDATE view_vd_validators + UPDATE view_validator_delegation_validators SET height = int8range(lower(height), ?, '[)') WHERE operator_address = ? AND height @> ?::int8 `) @@ -239,7 +239,7 @@ func (view *ValidatorsView) findBy( "shares", "min_self_delegation", ). - From("view_vd_validators") + From("view_validator_delegation_validators") if maybeOperatorAddress != nil { stmtBuilder = stmtBuilder.Where( @@ -338,7 +338,7 @@ func (view *ValidatorsView) List( "min_self_delegation", ). From( - "view_vd_validators", + "view_validator_delegation_validators", ). Where( "height @> ?::int8", From d80fba5698f1f772612e90342f090b9d14471b79 Mon Sep 17 00:00:00 2001 From: Yang Song Date: Mon, 21 Feb 2022 16:26:00 +0800 Subject: [PATCH 24/24] Updated example accordingly --- example/config/config.yaml | 6 +++--- example/go.mod | 2 +- example/go.sum | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/example/config/config.yaml b/example/config/config.yaml index 16b62e07..5086aa57 100644 --- a/example/config/config.yaml +++ b/example/config/config.yaml @@ -34,7 +34,7 @@ index_service: "IBCChannelMessage", "BridgePendingActivity", "Example", - "ValidatorDelegation", + # "ValidatorDelegation", ] extra_configs: BridgePendingActivity: @@ -56,7 +56,7 @@ index_service: # For `username` and `token`, please generate your own `Personal access tokens` in Github. username: "public" token: "token" - migration_repo_ref: "feature/652-part-2" + migration_repo_ref: "" http_service: enable: true @@ -102,7 +102,7 @@ postgres: logger: # Comma separated log levels. possible values: debug,info,error,panic - level: "error" + level: "debug" color: false prometheus: diff --git a/example/go.mod b/example/go.mod index 8321bcb1..c5c8a147 100644 --- a/example/go.mod +++ b/example/go.mod @@ -9,7 +9,7 @@ replace github.com/rs/zerolog => github.com/rs/zerolog v1.23.0 require github.com/urfave/cli/v2 v2.3.0 require ( - github.com/crypto-com/chain-indexing v1.3.5-0.20220211051758-0e0c234a6a0f + github.com/crypto-com/chain-indexing v1.3.5-0.20220221024425-38ae3fe094d6 github.com/ettle/strcase v0.1.1 github.com/valyala/fasthttp v1.17.0 gopkg.in/yaml.v2 v2.4.0 diff --git a/example/go.sum b/example/go.sum index 04298995..18d32b65 100644 --- a/example/go.sum +++ b/example/go.sum @@ -487,8 +487,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsr github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/crypto-com/chain-indexing v1.3.5-0.20220211051758-0e0c234a6a0f h1:64MVP1S/XHyTyENTSmchtPPuT7fTjHyFQN6w2TcQTT4= -github.com/crypto-com/chain-indexing v1.3.5-0.20220211051758-0e0c234a6a0f/go.mod h1:rBXfe6eRJmmkPL/tuw3fAClnp54N99sHisyi5rvVYaE= +github.com/crypto-com/chain-indexing v1.3.5-0.20220221024425-38ae3fe094d6 h1:qbOH3UOYef6faMg2OGjw6j/lZTM4ZkjA79ojPZ3RIWE= +github.com/crypto-com/chain-indexing v1.3.5-0.20220221024425-38ae3fe094d6/go.mod h1:rBXfe6eRJmmkPL/tuw3fAClnp54N99sHisyi5rvVYaE= github.com/crypto-org-chain/chain-main/v3 v3.0.0-croeseid h1:YAffq+tYiSqYXgIb11Vc6dvBtgSvRsf2g1wPaMFkQUA= github.com/crypto-org-chain/chain-main/v3 v3.0.0-croeseid/go.mod h1:92Z70bDbsScrWzIHB496p7nXKydtq5am9rqa0fCpbM8= github.com/crypto-org-chain/cronos v0.6.0-testnet h1:iFLwra4QMZ6HgIEB1P0vMCa9pnQTeXjwSuYbH4glxqA=