From 9f1aa7f63b83ac31bb01a33316e08a28e0b6780a Mon Sep 17 00:00:00 2001 From: spletka Date: Wed, 11 Oct 2023 14:58:42 +0200 Subject: [PATCH 1/5] (BIDS-2548) Only allow exact matches for the deposits searches --- db/db.go | 254 ++++++++++++++++++++++------------------- handlers/validators.go | 4 +- utils/utils.go | 11 +- 3 files changed, 148 insertions(+), 121 deletions(-) diff --git a/db/db.go b/db/db.go index 4ab78e2b21..d45f091984 100644 --- a/db/db.go +++ b/db/db.go @@ -54,9 +54,6 @@ const WithdrawalsQueryLimit = 10000 const BlsChangeQueryLimit = 10000 const MaxSqlInteger = 2147483647 -var addressRE = regexp.MustCompile(`^(0x)?[0-9a-fA-F]{40}$`) -var blsRE = regexp.MustCompile(`^(0x)?[0-9a-fA-F]{96}$`) - var ErrNoStats = errors.New("no stats available") func dbTestConnection(dbConn *sqlx.DB, dataBaseName string) { @@ -185,8 +182,6 @@ func GetEth1Deposits(address string, length, start uint64) ([]*types.EthOneDepos return deposits, nil } -var searchLikeHash = regexp.MustCompile(`^(0x)?[0-9a-fA-F]{2,96}`) // only search for pubkeys if string consists of 96 hex-chars - func GetEth1DepositsJoinEth2Deposits(query string, length, start uint64, orderBy, orderDir string, latestEpoch, validatorOnlineThresholdSlot uint64) ([]*types.EthOneDepositsData, uint64, error) { deposits := []*types.EthOneDepositsData{} @@ -208,38 +203,51 @@ func GetEth1DepositsJoinEth2Deposits(query string, length, start uint64, orderBy var totalCount uint64 var err error - query = strings.Replace(query, "0x", "", -1) + deposistsCountQuery := ` + SELECT COUNT(*) FROM eth1_deposits as eth1 + %s` - if searchLikeHash.MatchString(query) { - if query != "" { - err = ReaderDb.Get(&totalCount, ` - SELECT COUNT(*) FROM eth1_deposits as eth1 - WHERE - ENCODE(eth1.publickey, 'hex') LIKE LOWER($1) - OR ENCODE(eth1.withdrawal_credentials, 'hex') LIKE LOWER($1) - OR ENCODE(eth1.from_address, 'hex') LIKE LOWER($1) - OR ENCODE(tx_hash, 'hex') LIKE LOWER($1) - OR CAST(eth1.block_number AS text) LIKE LOWER($1)`, query+"%") - } - } else { - if query != "" { - err = ReaderDb.Get(&totalCount, ` - SELECT COUNT(*) FROM eth1_deposits as eth1 - WHERE - CAST(eth1.block_number AS text) LIKE LOWER($1)`, query+"%") + trimmedQuery := strings.ToLower(strings.TrimPrefix(query, "0x")) + var hash []byte + if len(trimmedQuery)%2 == 0 && utils.HashLikeRegex.MatchString(trimmedQuery) { + hash, err = hex.DecodeString(trimmedQuery) + if err != nil { + return nil, 0, err } } - if query == "" { - err = ReaderDb.Get(&totalCount, "SELECT COUNT(*) FROM eth1_deposits") + if trimmedQuery != "" { + if utils.IsHash(trimmedQuery) { + searchQuery := `WHERE eth1.publickey = $1` + err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, searchQuery), hash) + } else if utils.IsEth1Tx(trimmedQuery) { + // Withdrawal credentials have the same length as a tx hash + searchQuery := "" + if utils.IsValidWithdrawalCredentials(trimmedQuery) { + searchQuery = ` + WHERE + eth1.tx_hash = $1 + OR eth1.withdrawal_credentials = $1` + } else { + searchQuery = `WHERE eth1.tx_hash = $1` + } + err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, searchQuery), hash) + } else if utils.IsEth1Address(trimmedQuery) { + searchQuery := `WHERE eth1.from_address = $1` + err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, searchQuery), hash) + } else if uiQuery, parseErr := strconv.ParseUint(query, 10, 64); parseErr == nil { + searchQuery := `WHERE eth1.block_number = $1` + err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, searchQuery), uiQuery) + } + } else { + err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, "")) } - if err != nil && err != sql.ErrNoRows { + if err != nil { return nil, 0, err } - if query != "" { - wholeQuery := fmt.Sprintf(` + deposistsQuery := ` SELECT eth1.tx_hash as tx_hash, eth1.tx_input as tx_input, @@ -263,45 +271,38 @@ func GetEth1DepositsJoinEth2Deposits(query string, length, start uint64, orderBy ) as v ON v.pubkey = eth1.publickey - WHERE - ENCODE(eth1.publickey, 'hex') LIKE LOWER($3) - OR ENCODE(eth1.withdrawal_credentials, 'hex') LIKE LOWER($3) - OR ENCODE(eth1.from_address, 'hex') LIKE LOWER($3) - OR ENCODE(tx_hash, 'hex') LIKE LOWER($3) - OR CAST(eth1.block_number AS text) LIKE LOWER($3) + %s ORDER BY %s %s LIMIT $1 - OFFSET $2`, orderBy, orderDir) - err = ReaderDb.Select(&deposits, wholeQuery, length, start, query+"%") + OFFSET $2` + + if trimmedQuery != "" { + if utils.IsHash(trimmedQuery) { + searchQuery := `WHERE eth1.publickey = $3` + err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, hash) + } else if utils.IsEth1Tx(trimmedQuery) { + // Withdrawal credentials have the same length as a tx hash + searchQuery := "" + if utils.IsValidWithdrawalCredentials(trimmedQuery) { + searchQuery = ` + WHERE + eth1.tx_hash = $3 + OR eth1.withdrawal_credentials = $3` + } else { + searchQuery = `WHERE eth1.tx_hash = $3` + } + err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, hash) + } else if utils.IsEth1Address(trimmedQuery) { + searchQuery := `WHERE eth1.from_address = $3` + err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, hash) + } else if uiQuery, parseErr := strconv.ParseUint(query, 10, 64); parseErr == nil { + searchQuery := `WHERE eth1.block_number = $3` + err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, uiQuery) + } } else { - err = ReaderDb.Select(&deposits, fmt.Sprintf(` - SELECT - eth1.tx_hash as tx_hash, - eth1.tx_input as tx_input, - eth1.tx_index as tx_index, - eth1.block_number as block_number, - eth1.block_ts as block_ts, - eth1.from_address as from_address, - eth1.publickey as publickey, - eth1.withdrawal_credentials as withdrawal_credentials, - eth1.amount as amount, - eth1.signature as signature, - eth1.merkletree_index as merkletree_index, - eth1.valid_signature as valid_signature, - COALESCE(v.state, 'deposited') as state - FROM - eth1_deposits as eth1 - LEFT JOIN - ( - SELECT pubkey, status AS state - FROM validators - ) as v - ON - v.pubkey = eth1.publickey - ORDER BY %s %s - LIMIT $1 - OFFSET $2`, orderBy, orderDir), length, start) + err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, "", orderBy, orderDir), length, start) } + if err != nil && err != sql.ErrNoRows { return nil, 0, err } @@ -309,15 +310,6 @@ func GetEth1DepositsJoinEth2Deposits(query string, length, start uint64, orderBy return deposits, totalCount, nil } -func GetEth1DepositsCount() (uint64, error) { - deposits := uint64(0) - err := ReaderDb.Get(&deposits, `SELECT COUNT(*) FROM eth1_deposits`) - if err != nil { - return 0, err - } - return deposits, nil -} - func GetEth1DepositsLeaderboard(query string, length, start uint64, orderBy, orderDir string) ([]*types.EthOneDepositLeaderboardData, uint64, error) { deposits := []*types.EthOneDepositLeaderboardData{} @@ -398,8 +390,9 @@ func GetEth2Deposits(query string, length, start uint64, orderBy, orderDir strin orderBy = "block_slot" } - if query != "" { - err := ReaderDb.Select(&deposits, fmt.Sprintf(` + var err error + + deposistsQuery := ` SELECT blocks_deposits.block_slot, blocks_deposits.block_index, @@ -410,65 +403,92 @@ func GetEth2Deposits(query string, length, start uint64, orderBy, orderDir strin blocks_deposits.signature FROM blocks_deposits INNER JOIN blocks ON blocks_deposits.block_root = blocks.blockroot AND blocks.status = '1' - LEFT JOIN eth1_deposits ON blocks_deposits.publickey = eth1_deposits.publickey - WHERE ENCODE(blocks_deposits.publickey, 'hex') LIKE LOWER($3) - OR ENCODE(blocks_deposits.withdrawalcredentials, 'hex') LIKE LOWER($3) - OR CAST(blocks_deposits.block_slot as varchar) LIKE LOWER($3) - OR ENCODE(eth1_deposits.from_address, 'hex') LIKE LOWER($3) + %s ORDER BY %s %s LIMIT $1 - OFFSET $2`, orderBy, orderDir), length, start, query+"%") + OFFSET $2` + + trimmedQuery := strings.ToLower(strings.TrimPrefix(query, "0x")) + var hash []byte + if len(trimmedQuery)%2 == 0 && utils.HashLikeRegex.MatchString(trimmedQuery) { + hash, err = hex.DecodeString(trimmedQuery) if err != nil { return nil, err } - } else { - err := ReaderDb.Select(&deposits, fmt.Sprintf(` - SELECT - blocks_deposits.block_slot, - blocks_deposits.block_index, - blocks_deposits.proof, - blocks_deposits.publickey, - blocks_deposits.withdrawalcredentials, - blocks_deposits.amount, - blocks_deposits.signature - FROM blocks_deposits - INNER JOIN blocks ON blocks_deposits.block_root = blocks.blockroot AND blocks.status = '1' - ORDER BY %s %s - LIMIT $1 - OFFSET $2`, orderBy, orderDir), length, start) - if err != nil { - return nil, err + } + + if trimmedQuery != "" { + if utils.IsHash(trimmedQuery) { + searchQuery := `WHERE blocks_deposits.publickey = $3` + err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, hash) + } else if utils.IsValidWithdrawalCredentials(trimmedQuery) { + searchQuery := `WHERE blocks_deposits.withdrawalcredentials = $3` + err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, hash) + } else if utils.IsEth1Address(trimmedQuery) { + searchQuery := ` + LEFT JOIN eth1_deposits ON blocks_deposits.publickey = eth1_deposits.publickey + WHERE eth1_deposits.from_address = $3` + err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, hash) + } else if uiQuery, parseErr := strconv.ParseUint(query, 10, 64); parseErr == nil { + searchQuery := `WHERE blocks_deposits.block_slot = $3` + err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, uiQuery) } + } else { + err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, "", orderBy, orderDir), length, start) + } + + if err != nil && err != sql.ErrNoRows { + return nil, err } return deposits, nil } -func GetEth2DepositsCount(search string) (uint64, error) { - deposits := uint64(0) +func GetEth2DepositsCount(query string) (uint64, error) { + totalCount := uint64(0) + var err error - if search == "" { - err = ReaderDb.Get(&deposits, ` - SELECT COUNT(*) - FROM blocks_deposits - INNER JOIN blocks ON blocks_deposits.block_root = blocks.blockroot AND blocks.status = '1'`) - } else { - err = ReaderDb.Get(&deposits, ` + + deposistsCountQuery := ` SELECT COUNT(*) FROM blocks_deposits INNER JOIN blocks ON blocks_deposits.block_root = blocks.blockroot AND blocks.status = '1' - LEFT JOIN eth1_deposits ON blocks_deposits.publickey = eth1_deposits.publickey - WHERE ENCODE(blocks_deposits.publickey, 'hex') LIKE LOWER($1) - OR ENCODE(blocks_deposits.withdrawalcredentials, 'hex') LIKE LOWER($1) - OR CAST(blocks_deposits.block_slot as varchar) LIKE LOWER($1) - OR ENCODE(eth1_deposits.from_address, 'hex') LIKE LOWER($1) - `, search+"%") + %s` + + trimmedQuery := strings.ToLower(strings.TrimPrefix(query, "0x")) + var hash []byte + if len(trimmedQuery)%2 == 0 && utils.HashLikeRegex.MatchString(trimmedQuery) { + hash, err = hex.DecodeString(trimmedQuery) + if err != nil { + return 0, err + } } + + if trimmedQuery != "" { + if utils.IsHash(trimmedQuery) { + searchQuery := `WHERE blocks_deposits.publickey = $1` + err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, searchQuery), hash) + } else if utils.IsValidWithdrawalCredentials(trimmedQuery) { + searchQuery := `WHERE blocks_deposits.withdrawalcredentials = $1` + err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, searchQuery), hash) + } else if utils.IsEth1Address(trimmedQuery) { + searchQuery := ` + LEFT JOIN eth1_deposits ON blocks_deposits.publickey = eth1_deposits.publickey + WHERE eth1_deposits.from_address = $1` + err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, searchQuery), hash) + } else if uiQuery, parseErr := strconv.ParseUint(query, 10, 64); parseErr == nil { + searchQuery := `WHERE blocks_deposits.block_slot = $1` + err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, searchQuery), uiQuery) + } + } else { + err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, "")) + } + if err != nil { return 0, err } - return deposits, nil + return totalCount, nil } func GetSlashingCount() (uint64, error) { slashings := uint64(0) @@ -2279,7 +2299,7 @@ func GetWithdrawalsCountForQuery(query string) (uint64, error) { var err error = nil trimmedQuery := strings.ToLower(strings.TrimPrefix(query, "0x")) - if addressRE.MatchString(query) { + if utils.IsEth1Address(query) { searchQuery := `WHERE w.address = $1` addr, decErr := hex.DecodeString(trimmedQuery) if err != nil { @@ -2344,7 +2364,7 @@ func GetWithdrawals(query string, length, start uint64, orderBy, orderDir string trimmedQuery := strings.ToLower(strings.TrimPrefix(query, "0x")) if trimmedQuery != "" { - if addressRE.MatchString(query) { + if utils.IsEth1Address(query) { searchQuery := `WHERE w.address = $3` addr, decErr := hex.DecodeString(trimmedQuery) if decErr != nil { @@ -2944,7 +2964,7 @@ func GetBLSChangesCountForQuery(query string) (uint64, error) { trimmedQuery := strings.ToLower(strings.TrimPrefix(query, "0x")) var err error = nil - if blsRE.MatchString(query) { + if utils.IsHash(query) { searchQuery := `WHERE bls.pubkey = $1` pubkey, decErr := hex.DecodeString(trimmedQuery) if decErr != nil { @@ -3004,7 +3024,7 @@ func GetBLSChanges(query string, length, start uint64, orderBy, orderDir string) var err error = nil if trimmedQuery != "" { - if blsRE.MatchString(query) { + if utils.IsHash(query) { searchQuery := `WHERE bls.pubkey = $3` pubkey, decErr := hex.DecodeString(trimmedQuery) if decErr != nil { diff --git a/handlers/validators.go b/handlers/validators.go index fcaa03868e..6cb32d3b1b 100644 --- a/handlers/validators.go +++ b/handlers/validators.go @@ -95,8 +95,8 @@ type ValidatorsDataQueryParams struct { StateFilter string } -var searchPubkeyExactRE = regexp.MustCompile(`^(0x)?[0-9a-fA-F]{96}`) // only search for pubkeys if string consists of 96 hex-chars -var searchPubkeyLikeRE = regexp.MustCompile(`^(0x)?[0-9a-fA-F]{2,96}`) // only search for pubkeys if string consists of 96 hex-chars +var searchPubkeyExactRE = regexp.MustCompile(`^(0x)?[0-9a-fA-F]{96}`) // only search for pubkeys if string consists of 96 hex-chars +var searchPubkeyLikeRE = regexp.MustCompile(`^(0x)?[0-9a-fA-F]{2,96}`) func parseValidatorsDataQueryParams(r *http.Request) (*ValidatorsDataQueryParams, error) { q := r.URL.Query() diff --git a/utils/utils.go b/utils/utils.go index e64c80d8bf..3b53eab144 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -741,7 +741,8 @@ func IsValidEth1Address(s string) bool { return !zeroHashRE.MatchString(s) && eth1AddressRE.MatchString(s) } -// IsEth1Address verifies whether a string represents an eth1-address. In contrast to IsValidEth1Address, this also returns true for the 0x0 address +// IsEth1Address verifies whether a string represents an eth1-address. +// In contrast to IsValidEth1Address, this also returns true for the 0x0 address func IsEth1Address(s string) bool { return eth1AddressRE.MatchString(s) } @@ -751,7 +752,13 @@ func IsValidEth1Tx(s string) bool { return !zeroHashRE.MatchString(s) && eth1TxRE.MatchString(s) } -// IsValidEth1Tx verifies whether a string represents a valid eth1-tx-hash. +// IsEth1Tx verifies whether a string represents an eth1-tx-hash. +// In contrast to IsValidEth1Tx, this also returns true for the 0x0 address +func IsEth1Tx(s string) bool { + return eth1TxRE.MatchString(s) +} + +// IsHash verifies whether a string represents an eth1-hash. func IsHash(s string) bool { return hashRE.MatchString(s) } From bd504c9cd5cfc22041484ab5d9fdac1e02095392 Mon Sep 17 00:00:00 2001 From: spletka Date: Mon, 16 Oct 2023 16:25:13 +0200 Subject: [PATCH 2/5] (BIDS-2548) Refactored search query code --- db/db.go | 166 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 86 insertions(+), 80 deletions(-) diff --git a/db/db.go b/db/db.go index d45f091984..29fe5a39a4 100644 --- a/db/db.go +++ b/db/db.go @@ -201,52 +201,15 @@ func GetEth1DepositsJoinEth2Deposits(query string, length, start uint64, orderBy } var totalCount uint64 + var param interface{} + var searchQuery string + shouldSearch := true var err error deposistsCountQuery := ` SELECT COUNT(*) FROM eth1_deposits as eth1 %s` - trimmedQuery := strings.ToLower(strings.TrimPrefix(query, "0x")) - var hash []byte - if len(trimmedQuery)%2 == 0 && utils.HashLikeRegex.MatchString(trimmedQuery) { - hash, err = hex.DecodeString(trimmedQuery) - if err != nil { - return nil, 0, err - } - } - - if trimmedQuery != "" { - if utils.IsHash(trimmedQuery) { - searchQuery := `WHERE eth1.publickey = $1` - err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, searchQuery), hash) - } else if utils.IsEth1Tx(trimmedQuery) { - // Withdrawal credentials have the same length as a tx hash - searchQuery := "" - if utils.IsValidWithdrawalCredentials(trimmedQuery) { - searchQuery = ` - WHERE - eth1.tx_hash = $1 - OR eth1.withdrawal_credentials = $1` - } else { - searchQuery = `WHERE eth1.tx_hash = $1` - } - err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, searchQuery), hash) - } else if utils.IsEth1Address(trimmedQuery) { - searchQuery := `WHERE eth1.from_address = $1` - err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, searchQuery), hash) - } else if uiQuery, parseErr := strconv.ParseUint(query, 10, 64); parseErr == nil { - searchQuery := `WHERE eth1.block_number = $1` - err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, searchQuery), uiQuery) - } - } else { - err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, "")) - } - - if err != nil { - return nil, 0, err - } - deposistsQuery := ` SELECT eth1.tx_hash as tx_hash, @@ -276,13 +239,21 @@ func GetEth1DepositsJoinEth2Deposits(query string, length, start uint64, orderBy LIMIT $1 OFFSET $2` + trimmedQuery := strings.ToLower(strings.TrimPrefix(query, "0x")) + var hash []byte + if len(trimmedQuery)%2 == 0 && utils.HashLikeRegex.MatchString(trimmedQuery) { + hash, err = hex.DecodeString(trimmedQuery) + if err != nil { + return nil, 0, err + } + } + if trimmedQuery != "" { + param = hash if utils.IsHash(trimmedQuery) { - searchQuery := `WHERE eth1.publickey = $3` - err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, hash) + searchQuery = `WHERE eth1.publickey = $3` } else if utils.IsEth1Tx(trimmedQuery) { // Withdrawal credentials have the same length as a tx hash - searchQuery := "" if utils.IsValidWithdrawalCredentials(trimmedQuery) { searchQuery = ` WHERE @@ -291,20 +262,38 @@ func GetEth1DepositsJoinEth2Deposits(query string, length, start uint64, orderBy } else { searchQuery = `WHERE eth1.tx_hash = $3` } - err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, hash) } else if utils.IsEth1Address(trimmedQuery) { - searchQuery := `WHERE eth1.from_address = $3` - err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, hash) - } else if uiQuery, parseErr := strconv.ParseUint(query, 10, 64); parseErr == nil { - searchQuery := `WHERE eth1.block_number = $3` - err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, uiQuery) + searchQuery = `WHERE eth1.from_address = $3` + } else if uiQuery, parseErr := strconv.ParseUint(query, 10, 31); parseErr == nil { // Limit to 31 bits to stay within math.MaxInt32 + param = uiQuery + searchQuery = `WHERE eth1.block_number = $3` + } else { + // The query does not fulfill any of the requirements for a search + shouldSearch = false } - } else { - err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, "", orderBy, orderDir), length, start) } - if err != nil && err != sql.ErrNoRows { - return nil, 0, err + if shouldSearch { + // The deposits count query only has one parameter for the search + countSearchQuery := strings.ReplaceAll(searchQuery, "$3", "$1") + + if param != nil { + err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, countSearchQuery), param) + } else { + err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, countSearchQuery)) + } + if err != nil { + return nil, 0, err + } + + if param != nil { + err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, param) + } else { + err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start) + } + if err != nil && err != sql.ErrNoRows { + return nil, 0, err + } } return deposits, totalCount, nil @@ -390,6 +379,9 @@ func GetEth2Deposits(query string, length, start uint64, orderBy, orderDir strin orderBy = "block_slot" } + var param interface{} + var searchQuery string + shouldSearch := true var err error deposistsQuery := ` @@ -418,27 +410,33 @@ func GetEth2Deposits(query string, length, start uint64, orderBy, orderDir strin } if trimmedQuery != "" { + param = hash if utils.IsHash(trimmedQuery) { - searchQuery := `WHERE blocks_deposits.publickey = $3` - err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, hash) + searchQuery = `WHERE blocks_deposits.publickey = $3` } else if utils.IsValidWithdrawalCredentials(trimmedQuery) { - searchQuery := `WHERE blocks_deposits.withdrawalcredentials = $3` - err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, hash) + searchQuery = `WHERE blocks_deposits.withdrawalcredentials = $3` } else if utils.IsEth1Address(trimmedQuery) { - searchQuery := ` + searchQuery = ` LEFT JOIN eth1_deposits ON blocks_deposits.publickey = eth1_deposits.publickey WHERE eth1_deposits.from_address = $3` - err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, hash) - } else if uiQuery, parseErr := strconv.ParseUint(query, 10, 64); parseErr == nil { - searchQuery := `WHERE blocks_deposits.block_slot = $3` - err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, uiQuery) + } else if uiQuery, parseErr := strconv.ParseUint(query, 10, 31); parseErr == nil { // Limit to 31 bits to stay within math.MaxInt32 + param = uiQuery + searchQuery = `WHERE blocks_deposits.block_slot = $3` + } else { + // The query does not fulfill any of the requirements for a search + shouldSearch = false } - } else { - err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, "", orderBy, orderDir), length, start) } - if err != nil && err != sql.ErrNoRows { - return nil, err + if shouldSearch { + if param != nil { + err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, param) + } else { + err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start) + } + if err != nil && err != sql.ErrNoRows { + return nil, err + } } return deposits, nil @@ -446,7 +444,9 @@ func GetEth2Deposits(query string, length, start uint64, orderBy, orderDir strin func GetEth2DepositsCount(query string) (uint64, error) { totalCount := uint64(0) - + var param interface{} + var searchQuery string + shouldSearch := true var err error deposistsCountQuery := ` @@ -465,27 +465,33 @@ func GetEth2DepositsCount(query string) (uint64, error) { } if trimmedQuery != "" { + param = hash if utils.IsHash(trimmedQuery) { - searchQuery := `WHERE blocks_deposits.publickey = $1` - err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, searchQuery), hash) + searchQuery = `WHERE blocks_deposits.publickey = $1` } else if utils.IsValidWithdrawalCredentials(trimmedQuery) { - searchQuery := `WHERE blocks_deposits.withdrawalcredentials = $1` - err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, searchQuery), hash) + searchQuery = `WHERE blocks_deposits.withdrawalcredentials = $1` } else if utils.IsEth1Address(trimmedQuery) { - searchQuery := ` + searchQuery = ` LEFT JOIN eth1_deposits ON blocks_deposits.publickey = eth1_deposits.publickey WHERE eth1_deposits.from_address = $1` - err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, searchQuery), hash) - } else if uiQuery, parseErr := strconv.ParseUint(query, 10, 64); parseErr == nil { - searchQuery := `WHERE blocks_deposits.block_slot = $1` - err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, searchQuery), uiQuery) + } else if uiQuery, parseErr := strconv.ParseUint(query, 10, 31); parseErr == nil { // Limit to 31 bits to stay within math.MaxInt32 + param = uiQuery + searchQuery = `WHERE blocks_deposits.block_slot = $1` + } else { + // The query does not fulfill any of the requirements for a search + shouldSearch = false } - } else { - err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, "")) } - if err != nil { - return 0, err + if shouldSearch { + if param != nil { + err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, searchQuery), param) + } else { + err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, searchQuery)) + } + if err != nil { + return 0, err + } } return totalCount, nil From fa267e73614c9b067bcb97504530a0a0ca51eb36 Mon Sep 17 00:00:00 2001 From: spletka Date: Tue, 17 Oct 2023 11:58:25 +0200 Subject: [PATCH 3/5] (BIDS-2548) Refactor search query usage --- db/db.go | 105 +++++++++++++++------------------------ handlers/eth2Deposits.go | 11 +--- 2 files changed, 41 insertions(+), 75 deletions(-) diff --git a/db/db.go b/db/db.go index 29fe5a39a4..3d160a1a1c 100644 --- a/db/db.go +++ b/db/db.go @@ -183,7 +183,9 @@ func GetEth1Deposits(address string, length, start uint64) ([]*types.EthOneDepos } func GetEth1DepositsJoinEth2Deposits(query string, length, start uint64, orderBy, orderDir string, latestEpoch, validatorOnlineThresholdSlot uint64) ([]*types.EthOneDepositsData, uint64, error) { + // Initialize the return values deposits := []*types.EthOneDepositsData{} + totalCount := uint64(0) if orderDir != "desc" && orderDir != "asc" { orderDir = "desc" @@ -200,12 +202,12 @@ func GetEth1DepositsJoinEth2Deposits(query string, length, start uint64, orderBy orderBy = "block_ts" } - var totalCount uint64 var param interface{} - var searchQuery string shouldSearch := true + var searchQuery string var err error + // Define the base queries deposistsCountQuery := ` SELECT COUNT(*) FROM eth1_deposits as eth1 %s` @@ -239,6 +241,7 @@ func GetEth1DepositsJoinEth2Deposits(query string, length, start uint64, orderBy LIMIT $1 OFFSET $2` + // Get the search query and parameter for it trimmedQuery := strings.ToLower(strings.TrimPrefix(query, "0x")) var hash []byte if len(trimmedQuery)%2 == 0 && utils.HashLikeRegex.MatchString(trimmedQuery) { @@ -247,7 +250,6 @@ func GetEth1DepositsJoinEth2Deposits(query string, length, start uint64, orderBy return nil, 0, err } } - if trimmedQuery != "" { param = hash if utils.IsHash(trimmedQuery) { @@ -273,10 +275,11 @@ func GetEth1DepositsJoinEth2Deposits(query string, length, start uint64, orderBy } } - if shouldSearch { - // The deposits count query only has one parameter for the search - countSearchQuery := strings.ReplaceAll(searchQuery, "$3", "$1") + // The deposits count query only has one parameter for the search + countSearchQuery := strings.ReplaceAll(searchQuery, "$3", "$1") + // Get the deposits and the total count + if shouldSearch { if param != nil { err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, countSearchQuery), param) } else { @@ -361,9 +364,11 @@ func GetEth1DepositsLeaderboard(query string, length, start uint64, orderBy, ord return deposits, totalCount, nil } -func GetEth2Deposits(query string, length, start uint64, orderBy, orderDir string) ([]*types.EthTwoDepositData, error) { +func GetEth2Deposits(query string, length, start uint64, orderBy, orderDir string) ([]*types.EthTwoDepositData, uint64, error) { + // Initialize the return values deposits := []*types.EthTwoDepositData{} - // ENCODE(publickey, 'hex') LIKE $3 OR ENCODE(withdrawalcredentials, 'hex') LIKE $3 OR + totalCount := uint64(0) + if orderDir != "desc" && orderDir != "asc" { orderDir = "desc" } @@ -380,10 +385,17 @@ func GetEth2Deposits(query string, length, start uint64, orderBy, orderDir strin } var param interface{} - var searchQuery string shouldSearch := true + var searchQuery string var err error + // Define the base queries + deposistsCountQuery := ` + SELECT COUNT(*) + FROM blocks_deposits + INNER JOIN blocks ON blocks_deposits.block_root = blocks.blockroot AND blocks.status = '1' + %s` + deposistsQuery := ` SELECT blocks_deposits.block_slot, @@ -400,22 +412,24 @@ func GetEth2Deposits(query string, length, start uint64, orderBy, orderDir strin LIMIT $1 OFFSET $2` + // Get the search query and parameter for it trimmedQuery := strings.ToLower(strings.TrimPrefix(query, "0x")) var hash []byte if len(trimmedQuery)%2 == 0 && utils.HashLikeRegex.MatchString(trimmedQuery) { hash, err = hex.DecodeString(trimmedQuery) if err != nil { - return nil, err + return nil, 0, err } } - if trimmedQuery != "" { - param = hash if utils.IsHash(trimmedQuery) { + param = hash searchQuery = `WHERE blocks_deposits.publickey = $3` } else if utils.IsValidWithdrawalCredentials(trimmedQuery) { + param = hash searchQuery = `WHERE blocks_deposits.withdrawalcredentials = $3` } else if utils.IsEth1Address(trimmedQuery) { + param = hash searchQuery = ` LEFT JOIN eth1_deposits ON blocks_deposits.publickey = eth1_deposits.publickey WHERE eth1_deposits.from_address = $3` @@ -428,74 +442,33 @@ func GetEth2Deposits(query string, length, start uint64, orderBy, orderDir strin } } + // The deposits count query only has one parameter for the search + countSearchQuery := strings.ReplaceAll(searchQuery, "$3", "$1") + + // Get the deposits and the total count if shouldSearch { if param != nil { - err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, param) + err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, countSearchQuery), param) } else { - err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start) - } - if err != nil && err != sql.ErrNoRows { - return nil, err + err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, countSearchQuery)) } - } - - return deposits, nil -} - -func GetEth2DepositsCount(query string) (uint64, error) { - totalCount := uint64(0) - var param interface{} - var searchQuery string - shouldSearch := true - var err error - - deposistsCountQuery := ` - SELECT COUNT(*) - FROM blocks_deposits - INNER JOIN blocks ON blocks_deposits.block_root = blocks.blockroot AND blocks.status = '1' - %s` - - trimmedQuery := strings.ToLower(strings.TrimPrefix(query, "0x")) - var hash []byte - if len(trimmedQuery)%2 == 0 && utils.HashLikeRegex.MatchString(trimmedQuery) { - hash, err = hex.DecodeString(trimmedQuery) if err != nil { - return 0, err - } - } - - if trimmedQuery != "" { - param = hash - if utils.IsHash(trimmedQuery) { - searchQuery = `WHERE blocks_deposits.publickey = $1` - } else if utils.IsValidWithdrawalCredentials(trimmedQuery) { - searchQuery = `WHERE blocks_deposits.withdrawalcredentials = $1` - } else if utils.IsEth1Address(trimmedQuery) { - searchQuery = ` - LEFT JOIN eth1_deposits ON blocks_deposits.publickey = eth1_deposits.publickey - WHERE eth1_deposits.from_address = $1` - } else if uiQuery, parseErr := strconv.ParseUint(query, 10, 31); parseErr == nil { // Limit to 31 bits to stay within math.MaxInt32 - param = uiQuery - searchQuery = `WHERE blocks_deposits.block_slot = $1` - } else { - // The query does not fulfill any of the requirements for a search - shouldSearch = false + return nil, 0, err } - } - if shouldSearch { if param != nil { - err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, searchQuery), param) + err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, param) } else { - err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, searchQuery)) + err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start) } - if err != nil { - return 0, err + if err != nil && err != sql.ErrNoRows { + return nil, 0, err } } - return totalCount, nil + return deposits, totalCount, nil } + func GetSlashingCount() (uint64, error) { slashings := uint64(0) diff --git a/handlers/eth2Deposits.go b/handlers/eth2Deposits.go index 032b1deb14..263a409db8 100644 --- a/handlers/eth2Deposits.go +++ b/handlers/eth2Deposits.go @@ -63,16 +63,9 @@ func Eth2DepositsData(w http.ResponseWriter, r *http.Request) { orderDir := q.Get("order[0][dir]") - depositCount, err := db.GetEth2DepositsCount(search) + deposits, depositCount, err := db.GetEth2Deposits(search, length, start, orderBy, orderDir) if err != nil { - logger.Errorf("error retrieving eth2_deposit count: %v", err) - http.Error(w, "Internal server error", http.StatusServiceUnavailable) - return - } - - deposits, err := db.GetEth2Deposits(search, length, start, orderBy, orderDir) - if err != nil { - logger.Errorf("error retrieving eth2_deposit data: %v", err) + logger.Errorf("error retrieving eth2_deposit data or count: %v", err) http.Error(w, "Internal server error", http.StatusServiceUnavailable) return } From 94f06981b9863231ec91a82eb908dfe85bf1cfc2 Mon Sep 17 00:00:00 2001 From: spletka Date: Tue, 17 Oct 2023 13:34:57 +0200 Subject: [PATCH 4/5] (BIDS-2548) Refactor query call placement --- db/db.go | 62 +++++++++++++++++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 28 deletions(-) diff --git a/db/db.go b/db/db.go index 3886b72f9d..4a4abbf436 100644 --- a/db/db.go +++ b/db/db.go @@ -239,27 +239,30 @@ func GetEth1DepositsJoinEth2Deposits(query string, length, start uint64, orderBy // The query does not fulfill any of the requirements for a search shouldSearch = false } - } + } else { + err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, "")) + if err != nil { + return nil, 0, err + } - // The deposits count query only has one parameter for the search - countSearchQuery := strings.ReplaceAll(searchQuery, "$3", "$1") + err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, "", orderBy, orderDir), length, start) + if err != nil && err != sql.ErrNoRows { + return nil, 0, err + } + + return deposits, totalCount, nil + } - // Get the deposits and the total count if shouldSearch { - if param != nil { - err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, countSearchQuery), param) - } else { - err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, countSearchQuery)) - } + // The deposits count query only has one parameter for the search + countSearchQuery := strings.ReplaceAll(searchQuery, "$3", "$1") + + err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, countSearchQuery), param) if err != nil { return nil, 0, err } - if param != nil { - err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, param) - } else { - err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start) - } + err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, param) if err != nil && err != sql.ErrNoRows { return nil, 0, err } @@ -406,27 +409,30 @@ func GetEth2Deposits(query string, length, start uint64, orderBy, orderDir strin // The query does not fulfill any of the requirements for a search shouldSearch = false } - } + } else { + err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, "")) + if err != nil { + return nil, 0, err + } - // The deposits count query only has one parameter for the search - countSearchQuery := strings.ReplaceAll(searchQuery, "$3", "$1") + err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, "", orderBy, orderDir), length, start) + if err != nil && err != sql.ErrNoRows { + return nil, 0, err + } + + return deposits, totalCount, nil + } - // Get the deposits and the total count if shouldSearch { - if param != nil { - err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, countSearchQuery), param) - } else { - err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, countSearchQuery)) - } + // The deposits count query only has one parameter for the search + countSearchQuery := strings.ReplaceAll(searchQuery, "$3", "$1") + + err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, countSearchQuery), param) if err != nil { return nil, 0, err } - if param != nil { - err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, param) - } else { - err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start) - } + err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, param) if err != nil && err != sql.ErrNoRows { return nil, 0, err } From 8e9f0da2981f52d9205de9ab96a595bc131a748d Mon Sep 17 00:00:00 2001 From: spletka Date: Wed, 18 Oct 2023 12:19:55 +0200 Subject: [PATCH 5/5] (BIDS-2548) Refactor code --- db/db.go | 130 ++++++++++++++++++++++++++----------------------------- 1 file changed, 62 insertions(+), 68 deletions(-) diff --git a/db/db.go b/db/db.go index 4a4abbf436..702dbe0be3 100644 --- a/db/db.go +++ b/db/db.go @@ -169,7 +169,6 @@ func GetEth1DepositsJoinEth2Deposits(query string, length, start uint64, orderBy } var param interface{} - shouldSearch := true var searchQuery string var err error @@ -216,30 +215,7 @@ func GetEth1DepositsJoinEth2Deposits(query string, length, start uint64, orderBy return nil, 0, err } } - if trimmedQuery != "" { - param = hash - if utils.IsHash(trimmedQuery) { - searchQuery = `WHERE eth1.publickey = $3` - } else if utils.IsEth1Tx(trimmedQuery) { - // Withdrawal credentials have the same length as a tx hash - if utils.IsValidWithdrawalCredentials(trimmedQuery) { - searchQuery = ` - WHERE - eth1.tx_hash = $3 - OR eth1.withdrawal_credentials = $3` - } else { - searchQuery = `WHERE eth1.tx_hash = $3` - } - } else if utils.IsEth1Address(trimmedQuery) { - searchQuery = `WHERE eth1.from_address = $3` - } else if uiQuery, parseErr := strconv.ParseUint(query, 10, 31); parseErr == nil { // Limit to 31 bits to stay within math.MaxInt32 - param = uiQuery - searchQuery = `WHERE eth1.block_number = $3` - } else { - // The query does not fulfill any of the requirements for a search - shouldSearch = false - } - } else { + if trimmedQuery == "" { err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, "")) if err != nil { return nil, 0, err @@ -253,19 +229,40 @@ func GetEth1DepositsJoinEth2Deposits(query string, length, start uint64, orderBy return deposits, totalCount, nil } - if shouldSearch { - // The deposits count query only has one parameter for the search - countSearchQuery := strings.ReplaceAll(searchQuery, "$3", "$1") - - err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, countSearchQuery), param) - if err != nil { - return nil, 0, err + param = hash + if utils.IsHash(trimmedQuery) { + searchQuery = `WHERE eth1.publickey = $3` + } else if utils.IsEth1Tx(trimmedQuery) { + // Withdrawal credentials have the same length as a tx hash + if utils.IsValidWithdrawalCredentials(trimmedQuery) { + searchQuery = ` + WHERE + eth1.tx_hash = $3 + OR eth1.withdrawal_credentials = $3` + } else { + searchQuery = `WHERE eth1.tx_hash = $3` } + } else if utils.IsEth1Address(trimmedQuery) { + searchQuery = `WHERE eth1.from_address = $3` + } else if uiQuery, parseErr := strconv.ParseUint(query, 10, 31); parseErr == nil { // Limit to 31 bits to stay within math.MaxInt32 + param = uiQuery + searchQuery = `WHERE eth1.block_number = $3` + } else { + // The query does not fulfill any of the requirements for a search + return deposits, totalCount, nil + } - err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, param) - if err != nil && err != sql.ErrNoRows { - return nil, 0, err - } + // The deposits count query only has one parameter for the search + countSearchQuery := strings.ReplaceAll(searchQuery, "$3", "$1") + + err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, countSearchQuery), param) + if err != nil { + return nil, 0, err + } + + err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, param) + if err != nil && err != sql.ErrNoRows { + return nil, 0, err } return deposits, totalCount, nil @@ -354,7 +351,6 @@ func GetEth2Deposits(query string, length, start uint64, orderBy, orderDir strin } var param interface{} - shouldSearch := true var searchQuery string var err error @@ -390,26 +386,7 @@ func GetEth2Deposits(query string, length, start uint64, orderBy, orderDir strin return nil, 0, err } } - if trimmedQuery != "" { - if utils.IsHash(trimmedQuery) { - param = hash - searchQuery = `WHERE blocks_deposits.publickey = $3` - } else if utils.IsValidWithdrawalCredentials(trimmedQuery) { - param = hash - searchQuery = `WHERE blocks_deposits.withdrawalcredentials = $3` - } else if utils.IsEth1Address(trimmedQuery) { - param = hash - searchQuery = ` - LEFT JOIN eth1_deposits ON blocks_deposits.publickey = eth1_deposits.publickey - WHERE eth1_deposits.from_address = $3` - } else if uiQuery, parseErr := strconv.ParseUint(query, 10, 31); parseErr == nil { // Limit to 31 bits to stay within math.MaxInt32 - param = uiQuery - searchQuery = `WHERE blocks_deposits.block_slot = $3` - } else { - // The query does not fulfill any of the requirements for a search - shouldSearch = false - } - } else { + if trimmedQuery == "" { err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, "")) if err != nil { return nil, 0, err @@ -423,19 +400,36 @@ func GetEth2Deposits(query string, length, start uint64, orderBy, orderDir strin return deposits, totalCount, nil } - if shouldSearch { - // The deposits count query only has one parameter for the search - countSearchQuery := strings.ReplaceAll(searchQuery, "$3", "$1") + if utils.IsHash(trimmedQuery) { + param = hash + searchQuery = `WHERE blocks_deposits.publickey = $3` + } else if utils.IsValidWithdrawalCredentials(trimmedQuery) { + param = hash + searchQuery = `WHERE blocks_deposits.withdrawalcredentials = $3` + } else if utils.IsEth1Address(trimmedQuery) { + param = hash + searchQuery = ` + LEFT JOIN eth1_deposits ON blocks_deposits.publickey = eth1_deposits.publickey + WHERE eth1_deposits.from_address = $3` + } else if uiQuery, parseErr := strconv.ParseUint(query, 10, 31); parseErr == nil { // Limit to 31 bits to stay within math.MaxInt32 + param = uiQuery + searchQuery = `WHERE blocks_deposits.block_slot = $3` + } else { + // The query does not fulfill any of the requirements for a search + return deposits, totalCount, nil + } - err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, countSearchQuery), param) - if err != nil { - return nil, 0, err - } + // The deposits count query only has one parameter for the search + countSearchQuery := strings.ReplaceAll(searchQuery, "$3", "$1") - err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, param) - if err != nil && err != sql.ErrNoRows { - return nil, 0, err - } + err = ReaderDb.Get(&totalCount, fmt.Sprintf(deposistsCountQuery, countSearchQuery), param) + if err != nil { + return nil, 0, err + } + + err = ReaderDb.Select(&deposits, fmt.Sprintf(deposistsQuery, searchQuery, orderBy, orderDir), length, start, param) + if err != nil && err != sql.ErrNoRows { + return nil, 0, err } return deposits, totalCount, nil