Commit adbb3f85 authored by Ethen Pociask's avatar Ethen Pociask

[indexer.withdrawal_type_supplies] updated models & and tests

parent b4fa4c75
package models package models
import "github.com/ethereum/go-ethereum/common" import (
"github.com/ethereum/go-ethereum/common"
)
// Params ... Query params // Params ... Query params
type Params struct { type Params struct {
......
...@@ -7,9 +7,6 @@ import ( ...@@ -7,9 +7,6 @@ import (
const ( const (
InternalServerError = "Internal server error" InternalServerError = "Internal server error"
// defaultPageLimit ... Default page limit for pagination
defaultPageLimit = 100
) )
// jsonResponse ... Marshals and writes a JSON response provided arbitrary data // jsonResponse ... Marshals and writes a JSON response provided arbitrary data
......
package service package service
import ( import (
"strconv"
"errors" "errors"
"strconv"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
) )
...@@ -11,25 +10,6 @@ import ( ...@@ -11,25 +10,6 @@ import (
// Validator ... Validates API user request parameters // Validator ... Validates API user request parameters
type Validator struct{} type Validator struct{}
// ParseValidateLimit ... Validates and parses the limit query parameters
func (v *Validator) ParseValidateLimit(limit string) (int, error) {
if limit == "" {
return 100, nil
}
val, err := strconv.Atoi(limit)
if err != nil {
return 0, errors.New("limit must be an integer value")
}
if val <= 0 {
return 0, errors.New("limit must be greater than 0")
}
// TODO - Add a check against a max limit value
return val, nil
}
// ParseValidateAddress ... Validates and parses the address query parameter // ParseValidateAddress ... Validates and parses the address query parameter
func (v *Validator) ParseValidateAddress(addr string) (common.Address, error) { func (v *Validator) ParseValidateAddress(addr string) (common.Address, error) {
if !common.IsHexAddress(addr) { if !common.IsHexAddress(addr) {
...@@ -60,3 +40,22 @@ func (v *Validator) ValidateCursor(cursor string) error { ...@@ -60,3 +40,22 @@ func (v *Validator) ValidateCursor(cursor string) error {
return nil return nil
} }
// ParseValidateLimit ... Validates and parses the limit query parameters
func (v *Validator) ParseValidateLimit(limit string) (int, error) {
if limit == "" {
return 100, nil
}
val, err := strconv.Atoi(limit)
if err != nil {
return 0, errors.New("limit must be an integer value")
}
if val <= 0 {
return 0, errors.New("limit must be greater than 0")
}
// TODO - Add a check against a max limit value
return val, nil
}
...@@ -3,6 +3,7 @@ package database ...@@ -3,6 +3,7 @@ package database
import ( import (
"errors" "errors"
"fmt" "fmt"
"strings"
"gorm.io/gorm" "gorm.io/gorm"
"gorm.io/gorm/clause" "gorm.io/gorm/clause"
...@@ -255,22 +256,28 @@ func (db *bridgeTransfersDB) L2BridgeWithdrawalSum(filter models.WithdrawFilter) ...@@ -255,22 +256,28 @@ func (db *bridgeTransfersDB) L2BridgeWithdrawalSum(filter models.WithdrawFilter)
clause = "" clause = ""
case models.Finalized: case models.Finalized:
clause = "finalized_l1_transaction_hash IS NOT NULL" clause = "finalized_l1_event_guid IS NOT NULL"
case models.Proven: case models.Proven:
clause = "proven_l1_transaction_hash IS NOT NULL" clause = "proven_l1_event_guid IS NOT NULL"
default: default:
return 0, fmt.Errorf("unknown filter argument: %d", filter) return 0, fmt.Errorf("unknown filter argument: %d", filter)
} }
// NOTE - Scanning to float64 reduces precision versus scanning to big.Int since amount is a uint256
// This is ok though given all bridges will never exceed max float64 (10^308 || 1.7E+308) in wei value locked
// since that would require 10^308 / 10^18 = 10^290 ETH locked in the bridge
var sum float64 var sum float64
result := db.gorm.Model(&L2TransactionWithdrawal{}).Select("sum(amount)").Scan(&sum).Where(clause) result := db.gorm.Model(&L2TransactionWithdrawal{}).Where(clause).Select("sum(amount)").Scan(&sum)
if result.Error != nil { if result.Error != nil && strings.Contains(result.Error.Error(), "converting NULL to float64 is unsupported") {
// no rows found
return 0, nil
} else if result.Error != nil {
return 0, result.Error return 0, result.Error
} else {
return sum, nil
} }
return sum, nil
} }
// L2BridgeWithdrawalWithFilter queries for a bridge withdrawal with set fields in the `BridgeTransfer` filter // L2BridgeWithdrawalWithFilter queries for a bridge withdrawal with set fields in the `BridgeTransfer` filter
......
...@@ -460,13 +460,13 @@ func TestClientBridgeFunctions(t *testing.T) { ...@@ -460,13 +460,13 @@ func TestClientBridgeFunctions(t *testing.T) {
// (2) Create test actors that will deposit and withdraw using the standard bridge // (2) Create test actors that will deposit and withdraw using the standard bridge
aliceAddr := testSuite.OpCfg.Secrets.Addresses().Alice aliceAddr := testSuite.OpCfg.Secrets.Addresses().Alice
bobAddr := testSuite.OpCfg.Secrets.Addresses().Bob bobAddr := testSuite.OpCfg.Secrets.Addresses().Bob
malAddr := testSuite.OpCfg.Secrets.Addresses().Mallory // malAddr := testSuite.OpCfg.Secrets.Addresses().Mallory
type actor struct { type actor struct {
addr common.Address addr common.Address
priv *ecdsa.PrivateKey priv *ecdsa.PrivateKey
amt *big.Int amt *big.Int
receipt types.Receipt receipt *types.Receipt
} }
mintSum := bigint.Zero mintSum := bigint.Zero
...@@ -482,11 +482,11 @@ func TestClientBridgeFunctions(t *testing.T) { ...@@ -482,11 +482,11 @@ func TestClientBridgeFunctions(t *testing.T) {
priv: testSuite.OpCfg.Secrets.Bob, priv: testSuite.OpCfg.Secrets.Bob,
amt: big.NewInt(0), amt: big.NewInt(0),
}, },
{ // {
addr: malAddr, // addr: malAddr,
priv: testSuite.OpCfg.Secrets.Mallory, // priv: testSuite.OpCfg.Secrets.Mallory,
amt: big.NewInt(0), // amt: big.NewInt(0),
}, // },
} }
type supplies struct { type supplies struct {
...@@ -502,8 +502,8 @@ func TestClientBridgeFunctions(t *testing.T) { ...@@ -502,8 +502,8 @@ func TestClientBridgeFunctions(t *testing.T) {
} }
// (3) Iterate over each actor and deposit / withdraw // (3) Iterate over each actor and deposit / withdraw
for _, actor := range actors { for i, actor := range actors {
t.Logf("simulating deposit/withdrawal flow for %s", actor.addr.String()) t.Logf("%d - simulating deposit/withdrawal flow for %s", i, actor.addr.String())
l2Opts, err := bind.NewKeyedTransactorWithChainID(actor.priv, testSuite.OpCfg.L2ChainIDBig()) l2Opts, err := bind.NewKeyedTransactorWithChainID(actor.priv, testSuite.OpCfg.L2ChainIDBig())
require.NoError(t, err) require.NoError(t, err)
...@@ -536,8 +536,8 @@ func TestClientBridgeFunctions(t *testing.T) { ...@@ -536,8 +536,8 @@ func TestClientBridgeFunctions(t *testing.T) {
})) }))
s.all = new(big.Int).Add(s.all, l2ToL1MessagePasserWithdrawTx.Value()) s.all = new(big.Int).Add(s.all, l2ToL1MessagePasserWithdrawTx.Value())
actor.receipt = *l2ToL1WithdrawReceipt actors[i].receipt = l2ToL1WithdrawReceipt
actor.amt = l2ToL1MessagePasserWithdrawTx.Value() actors[i].amt = l2ToL1MessagePasserWithdrawTx.Value()
// (3.d) Ensure that withdrawal and deposit txs are retrievable via API // (3.d) Ensure that withdrawal and deposit txs are retrievable via API
deposits, err := testSuite.Client.GetAllDepositsByAddress(actor.addr) deposits, err := testSuite.Client.GetAllDepositsByAddress(actor.addr)
...@@ -560,26 +560,38 @@ func TestClientBridgeFunctions(t *testing.T) { ...@@ -560,26 +560,38 @@ func TestClientBridgeFunctions(t *testing.T) {
require.Equal(t, mintFloat, assessment.L1DepositSum) require.Equal(t, mintFloat, assessment.L1DepositSum)
withdrawFloat, _ := s.all.Float64() withdrawFloat, _ := s.all.Float64()
require.Equal(t, withdrawFloat, assessment.FinalizedWithdrawSum) require.Equal(t, withdrawFloat, assessment.InitWithdrawalSum)
// (5) Prove withdrawal for two actors and verify supplies require.Equal(t, assessment.ProvenWithdrawSum, float64(0))
require.Equal(t, assessment.FinalizedWithdrawSum, float64(0))
for i := 0; i < 2; i++ { // (5) Prove & finalize withdrawals on L1
_, proveReceipt := op_e2e.ProveWithdrawal(t, *testSuite.OpCfg, testSuite.L1Client, testSuite.OpSys.EthInstances["sequencer"], actors[i].priv, &actors[i].receipt) for _, actor := range actors {
params, proveReceipt := op_e2e.ProveWithdrawal(t, *testSuite.OpCfg, testSuite.L1Client, testSuite.OpSys.EthInstances["sequencer"], actor.priv, actor.receipt)
require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) { require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.BridgeProcessor.LastL1Header l1Header := testSuite.Indexer.BridgeProcessor.LastL1Header
seen := l1Header != nil && l1Header.Number.Uint64() >= proveReceipt.BlockNumber.Uint64() seen := l1Header != nil && l1Header.Number.Uint64() >= proveReceipt.BlockNumber.Uint64()
return seen, nil return seen, nil
})) }))
s.proven = new(big.Int).Add(s.proven, actors[i].amt) s.proven = new(big.Int).Add(s.proven, actor.amt)
finalReceipt := op_e2e.FinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.L1Client, actor.priv, proveReceipt, params)
require.NoError(t, wait.For(context.Background(), 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.BridgeProcessor.LastFinalizedL1Header
seen := l1Header != nil && l1Header.Number.Uint64() >= finalReceipt.BlockNumber.Uint64()
return seen, nil
}))
s.finalized = new(big.Int).Add(s.finalized, actor.amt)
} }
// (6) Validate assessment for proven & finalized withdrawals
assessment, err = testSuite.Client.GetSupplyAssessment() assessment, err = testSuite.Client.GetSupplyAssessment()
require.NoError(t, err) require.NoError(t, err)
provenFloat, _ := s.proven.Float64() provenFloat, _ := s.proven.Float64()
require.Equal(t, provenFloat, assessment.FinalizedWithdrawSum) require.Equal(t, provenFloat, assessment.ProvenWithdrawSum)
// (6) Finalize withdrawal for one actor and verify supplies finalFloat, _ := s.finalized.Float64()
require.Equal(t, finalFloat, assessment.FinalizedWithdrawSum)
} }
...@@ -106,7 +106,7 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite { ...@@ -106,7 +106,7 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite {
// the system is running, mark this test for Parallel execution // the system is running, mark this test for Parallel execution
t.Parallel() t.Parallel()
indexerLog := testlog.Logger(t, log.LvlInfo).New("role", "indexer") indexerLog := testlog.Logger(t, log.LvlDebug).New("role", "indexer")
ix, err := indexer.NewIndexer(context.Background(), indexerLog, indexerCfg, func(cause error) { ix, err := indexer.NewIndexer(context.Background(), indexerLog, indexerCfg, func(cause error) {
if cause != nil { if cause != nil {
t.Fatalf("indexer shut down with critical error: %v", cause) t.Fatalf("indexer shut down with critical error: %v", cause)
...@@ -120,7 +120,7 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite { ...@@ -120,7 +120,7 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite {
require.NoError(t, ix.Stop(context.Background()), "cleanly shut down indexer") require.NoError(t, ix.Stop(context.Background()), "cleanly shut down indexer")
}) })
apiLog := testlog.Logger(t, log.LvlInfo).New("role", "indexer_api") apiLog := testlog.Logger(t, log.LvlDebug).New("role", "indexer_api")
apiCfg := &api.Config{ apiCfg := &api.Config{
DB: &api.TestDBConnector{BridgeTransfers: ix.DB.BridgeTransfers}, // reuse the same DB DB: &api.TestDBConnector{BridgeTransfers: ix.DB.BridgeTransfers}, // reuse the same DB
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment