Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(indexer) API Observability for Bridge Supplies #7680

Merged
merged 5 commits into from
Nov 8, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions indexer/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ const (
HealthPath = "/healthz"
DepositsPath = "/api/v0/deposits/"
WithdrawalsPath = "/api/v0/withdrawals/"

SupplyPath = "/api/v0/supply"
)

// chiMetricsMiddleware ... Injects a metrics recorder into request processing middleware
Expand Down Expand Up @@ -70,6 +72,8 @@ func NewApi(logger log.Logger, bv database.BridgeTransfersView, serverConfig con
apiRouter.Get(fmt.Sprintf(DepositsPath+addressParam, ethereumAddressRegex), h.L1DepositsHandler)
apiRouter.Get(fmt.Sprintf(WithdrawalsPath+addressParam, ethereumAddressRegex), h.L2WithdrawalsHandler)

apiRouter.Get(SupplyPath, h.SupplyView)

return &API{log: logger, router: apiRouter, metricsRegistry: mr, serverConfig: serverConfig, metricsConfig: metricsConfig}
}

Expand Down
5 changes: 5 additions & 0 deletions indexer/api/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,11 @@ func (mbv *MockBridgeTransfersView) L2BridgeWithdrawalsByAddress(address common.
},
}, nil
}

func (mbv *MockBridgeTransfersView) L1BridgeDepositSum() (float64, error) {
return 69, nil
}

func TestHealthz(t *testing.T) {
logger := testlog.Logger(t, log.LvlInfo)
api := NewApi(logger, &MockBridgeTransfersView{}, apiConfig, metricsConfig)
Expand Down
4 changes: 4 additions & 0 deletions indexer/api/models/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,7 @@ type WithdrawalResponse struct {
HasNextPage bool `json:"hasNextPage"`
Items []WithdrawalItem `json:"items"`
}

type BridgeSupplyView struct {
L1DepositSum float64 `json:"l1DepositSum"`
}
25 changes: 25 additions & 0 deletions indexer/api/routes/deposits.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,28 @@ func (h Routes) L1DepositsHandler(w http.ResponseWriter, r *http.Request) {
h.logger.Error("Error writing response", "err", err)
}
}

// SupplyView ... Handles /api/v0/supply GET requests
func (h Routes) SupplyView(w http.ResponseWriter, r *http.Request) {
sum, err := h.view.L1BridgeDepositSum()
if err != nil {
http.Error(w, "Internal server error reading deposits", http.StatusInternalServerError)
h.logger.Error("Unable to read deposits from DB", "err", err.Error())
return
}

view := models.BridgeSupplyView{
L1DepositSum: sum,
}

// TODO - Add support for:
// - L2DepositSum
// - L1WithdrawalProvenSum
// - L1WithdrawalFinalizedSum
// - L2WithdrawalInitiatedSum

err = jsonResponse(w, view, http.StatusOK)
if err != nil {
h.logger.Error("Error writing response", "err", err)
}
}
20 changes: 20 additions & 0 deletions indexer/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const (
healthz = "get_health"
deposits = "get_deposits"
withdrawals = "get_withdrawals"
sum = "get_sum"
)

// Option ... Provides configuration through callback injection
Expand Down Expand Up @@ -164,6 +165,25 @@ func (c *Client) GetAllDepositsByAddress(l1Address common.Address) ([]models.Dep

}

// GetSupplyAssessment ... Returns an assessment of the current supply
// on both L1 and L2. This includes the individual sums of
// (L1/L2) deposits and withdrawals
func (c *Client) GetSupplyAssessment() (*models.BridgeSupplyView, error) {
url := c.cfg.BaseURL + api.SupplyPath

resp, err := c.doRecordRequest(sum, url)
if err != nil {
return nil, err
}

var bsv *models.BridgeSupplyView
if err := json.Unmarshal(resp, &bsv); err != nil {
return nil, err
}

return bsv, nil
}

// GetAllWithdrawalsByAddress ... Gets all withdrawals provided a L2 address
func (c *Client) GetAllWithdrawalsByAddress(l2Address common.Address) ([]models.WithdrawalItem, error) {
var withdrawals []models.WithdrawalItem
Expand Down
13 changes: 13 additions & 0 deletions indexer/database/bridge_transfers.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ type L2BridgeWithdrawalWithTransactionHashes struct {

type BridgeTransfersView interface {
L1BridgeDeposit(common.Hash) (*L1BridgeDeposit, error)
L1BridgeDepositSum() (float64, error)
L1BridgeDepositWithFilter(BridgeTransfer) (*L1BridgeDeposit, error)
L1BridgeDepositsByAddress(common.Address, string, int) (*L1BridgeDepositsResponse, error)

Expand Down Expand Up @@ -128,6 +129,18 @@ type L1BridgeDepositsResponse struct {
HasNextPage bool
}

// L1BridgeDepositSum ... returns the sum of all l1 bridge deposit mints in gwei
func (db *bridgeTransfersDB) L1BridgeDepositSum() (float64, error) {
// (1) Fetch the sum of all deposits in gwei
var sum float64
result := db.gorm.Model(&L1TransactionDeposit{}).Select("sum(amount)").Scan(&sum)
if result.Error != nil {
return 0, result.Error
}

return sum, nil
}

// L1BridgeDepositsByAddress retrieves a list of deposits initiated by the specified address,
// coupled with the L1/L2 transaction hashes that complete the bridge transaction.
func (db *bridgeTransfersDB) L1BridgeDepositsByAddress(address common.Address, cursor string, limit int) (*L1BridgeDepositsResponse, error) {
Expand Down
19 changes: 18 additions & 1 deletion indexer/e2e_tests/bridge_transfers_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"testing"
"time"

"github.com/ethereum-optimism/optimism/indexer/bigint"
e2etest_utils "github.com/ethereum-optimism/optimism/indexer/e2e_tests/utils"
op_e2e "github.com/ethereum-optimism/optimism/op-e2e"
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/transactions"
Expand Down Expand Up @@ -447,7 +448,7 @@ func TestE2EBridgeTransfersCursoredWithdrawals(t *testing.T) {
}
}

func TestClientGetWithdrawals(t *testing.T) {
func TestClientBridgeFunctions(t *testing.T) {
testSuite := createE2ETestSuite(t)

// (1) Generate contract bindings for the L1 and L2 standard bridges
Expand All @@ -459,12 +460,14 @@ func TestClientGetWithdrawals(t *testing.T) {
// (2) Create test actors that will deposit and withdraw using the standard bridge
aliceAddr := testSuite.OpCfg.Secrets.Addresses().Alice
bobAddr := testSuite.OpCfg.Secrets.Addresses().Bob
malAddr := testSuite.OpCfg.Secrets.Addresses().Mallory

type actor struct {
addr common.Address
priv *ecdsa.PrivateKey
}

mintSum := bigint.Zero
actors := []actor{
{
addr: aliceAddr,
Expand All @@ -474,6 +477,10 @@ func TestClientGetWithdrawals(t *testing.T) {
addr: bobAddr,
priv: testSuite.OpCfg.Secrets.Bob,
},
{
addr: malAddr,
priv: testSuite.OpCfg.Secrets.Mallory,
},
}

// (3) Iterate over each actor and deposit / withdraw
Expand All @@ -491,6 +498,8 @@ func TestClientGetWithdrawals(t *testing.T) {
_, err = wait.ForReceiptOK(context.Background(), testSuite.L1Client, depositTx.Hash())
require.NoError(t, err)

mintSum = new(big.Int).Add(mintSum, depositTx.Value())

// (3.b) Initiate withdrawal transaction via L2ToL1MessagePasser contract
l2ToL1MessagePasserWithdrawTx, err := l2ToL1MessagePasser.Receive(l2Opts)
require.NoError(t, err)
Expand All @@ -513,6 +522,14 @@ func TestClientGetWithdrawals(t *testing.T) {
require.NoError(t, err)
require.Len(t, withdrawals, 1)
require.Equal(t, l2ToL1MessagePasserWithdrawTx.Hash().String(), withdrawals[0].TransactionHash)

}

// (4) Ensure that supply assessment is correct
assessment, err := testSuite.Client.GetSupplyAssessment()
require.NoError(t, err)

asFloat, _ := mintSum.Float64()
require.Equal(t, asFloat, assessment.L1DepositSum)

}
2 changes: 1 addition & 1 deletion indexer/migrations/20230523_create_schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ CREATE TABLE IF NOT EXISTS l1_transaction_deposits (

-- transaction data. NOTE: `to_address` is the recipient of funds transferred in value field of the
-- L2 deposit transaction and not the amount minted on L1 from the source address. Hence the `amount`
-- column in this table does NOT indiciate the amount transferred to the recipient but instead funds
-- column in this table does NOT indicate the amount transferred to the recipient but instead funds
-- bridged from L1 into `from_address`.
epociask marked this conversation as resolved.
Show resolved Hide resolved
from_address VARCHAR NOT NULL,
to_address VARCHAR NOT NULL,
Expand Down