Skip to content

Commit

Permalink
Fully test M1 and M1 --> M2 migration
Browse files Browse the repository at this point in the history
  • Loading branch information
seanmcgary committed Sep 10, 2024
1 parent f85e5d8 commit 4790cd9
Show file tree
Hide file tree
Showing 6 changed files with 544 additions and 24 deletions.
134 changes: 134 additions & 0 deletions cmd/debugger/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package main

import (
"context"
"fmt"
"github.com/Layr-Labs/go-sidecar/internal/clients/ethereum"
"github.com/Layr-Labs/go-sidecar/internal/clients/etherscan"
"github.com/Layr-Labs/go-sidecar/internal/config"
"github.com/Layr-Labs/go-sidecar/internal/contractManager"
"github.com/Layr-Labs/go-sidecar/internal/contractStore/sqliteContractStore"
"github.com/Layr-Labs/go-sidecar/internal/eigenState/avsOperators"
"github.com/Layr-Labs/go-sidecar/internal/eigenState/operatorShares"
"github.com/Layr-Labs/go-sidecar/internal/eigenState/stakerDelegations"
"github.com/Layr-Labs/go-sidecar/internal/eigenState/stakerShares"
"github.com/Layr-Labs/go-sidecar/internal/eigenState/stateManager"
"github.com/Layr-Labs/go-sidecar/internal/fetcher"
"github.com/Layr-Labs/go-sidecar/internal/indexer"
"github.com/Layr-Labs/go-sidecar/internal/logger"
"github.com/Layr-Labs/go-sidecar/internal/metrics"
"github.com/Layr-Labs/go-sidecar/internal/pipeline"
"github.com/Layr-Labs/go-sidecar/internal/sidecar"
"github.com/Layr-Labs/go-sidecar/internal/sqlite"
"github.com/Layr-Labs/go-sidecar/internal/sqlite/migrations"
sqliteBlockStore "github.com/Layr-Labs/go-sidecar/internal/storage/sqlite"
"go.uber.org/zap"
"log"
)

func main() {
ctx := context.Background()
cfg := config.NewConfig()

fmt.Printf("Config: %+v\n", cfg)

l, _ := logger.NewLogger(&logger.LoggerConfig{Debug: cfg.Debug})

sdc, err := metrics.InitStatsdClient(cfg.StatsdUrl)
if err != nil {
l.Sugar().Fatal("Failed to setup statsd client", zap.Error(err))
}

etherscanClient := etherscan.NewEtherscanClient(cfg, l)
client := ethereum.NewClient(cfg.EthereumRpcConfig.BaseUrl, l)

db := sqlite.NewSqlite(cfg.SqliteConfig.GetSqlitePath())

grm, err := sqlite.NewGormSqliteFromSqlite(db)
if err != nil {
l.Error("Failed to create gorm instance", zap.Error(err))
panic(err)
}

migrator := migrations.NewSqliteMigrator(grm, l)
if err = migrator.MigrateAll(); err != nil {
log.Fatalf("Failed to migrate: %v", err)
}

contractStore := sqliteContractStore.NewSqliteContractStore(grm, l, cfg)
if err := contractStore.InitializeCoreContracts(); err != nil {
log.Fatalf("Failed to initialize core contracts: %v", err)
}

cm := contractManager.NewContractManager(contractStore, etherscanClient, client, sdc, l)

mds := sqliteBlockStore.NewSqliteBlockStore(grm, l, cfg)
if err != nil {
log.Fatalln(err)
}

sm := stateManager.NewEigenStateManager(l, grm)

if _, err := avsOperators.NewAvsOperators(sm, grm, cfg.Network, cfg.Environment, l, cfg); err != nil {
l.Sugar().Fatalw("Failed to create AvsOperatorsModel", zap.Error(err))
}
if _, err := operatorShares.NewOperatorSharesModel(sm, grm, cfg.Network, cfg.Environment, l, cfg); err != nil {
l.Sugar().Fatalw("Failed to create OperatorSharesModel", zap.Error(err))
}
if _, err := stakerDelegations.NewStakerDelegationsModel(sm, grm, cfg.Network, cfg.Environment, l, cfg); err != nil {
l.Sugar().Fatalw("Failed to create StakerDelegationsModel", zap.Error(err))
}
if _, err := stakerShares.NewStakerSharesModel(sm, grm, cfg.Network, cfg.Environment, l, cfg); err != nil {
l.Sugar().Fatalw("Failed to create StakerSharesModel", zap.Error(err))
}

fetchr := fetcher.NewFetcher(client, cfg, l)

idxr := indexer.NewIndexer(mds, contractStore, etherscanClient, cm, client, fetchr, l, cfg)

p := pipeline.NewPipeline(fetchr, idxr, mds, sm, l)

// Create new sidecar instance
sidecar := sidecar.NewSidecar(&sidecar.SidecarConfig{
GenesisBlockNumber: cfg.GetGenesisBlockNumber(),
}, cfg, mds, p, sm, l, client)

// RPC channel to notify the RPC server to shutdown gracefully
rpcChannel := make(chan bool)
err = sidecar.WithRpcServer(ctx, mds, sm, rpcChannel)
if err != nil {
l.Sugar().Fatalw("Failed to start RPC server", zap.Error(err))
}

block, err := fetchr.FetchBlock(ctx, 1215893)
if err != nil {
l.Sugar().Fatalw("Failed to fetch block", zap.Error(err))
}

transactionHash := "0xf6775c38af1d2802bcbc2b7c8959c0d5b48c63a14bfeda0261ba29d76c68c423"
transaction := &ethereum.EthereumTransaction{}

for _, tx := range block.Block.Transactions {
if tx.Hash.Value() == transactionHash {
transaction = tx
break
}
}

logIndex := 4
receipt := block.TxReceipts[transaction.Hash.Value()]
var interestingLog *ethereum.EthereumEventLog

for _, log := range receipt.Logs {
if log.LogIndex.Value() == uint64(logIndex) {
fmt.Printf("Log: %+v\n", log)
interestingLog = log
}
}

decodedLog, err := idxr.DecodeLogWithAbi(nil, receipt, interestingLog)
if err != nil {
l.Sugar().Fatalw("Failed to decode log", zap.Error(err))
}
l.Sugar().Infof("Decoded log: %+v", decodedLog)
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ require (
github.com/klauspost/compress v1.17.9 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-sqlite3 v1.14.22 // indirect
github.com/mattn/go-sqlite3 v1.14.23 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mmcloughlin/addchain v0.4.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mattn/go-sqlite3 v1.14.23 h1:gbShiuAP1W5j9UOksQ06aiiqPMxYecovVGwmTxWtuw0=
github.com/mattn/go-sqlite3 v1.14.23/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
Expand Down
107 changes: 88 additions & 19 deletions internal/eigenState/stakerShares/stakerShares.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ type AccumulatedStateChange struct {
Strategy string
Shares *big.Int
BlockNumber uint64
IsNegative bool
}

type StakerSharesDiff struct {
Expand Down Expand Up @@ -221,20 +220,92 @@ func (ss *StakerSharesModel) handleM1StakerWithdrawals(log *storage.TransactionL
return &AccumulatedStateChange{
Staker: stakerAddress,
Strategy: outputData.Strategy,
Shares: shares,
Shares: shares.Mul(shares, big.NewInt(-1)),
BlockNumber: log.BlockNumber,
IsNegative: true,
}, nil
}

type m2MigrationOutputData struct {
OldWithdrawalRoot []byte `json:"oldWithdrawalRoot"`
OldWithdrawalRootString string
}

func parseLogOutputForM2MigrationEvent(outputDataStr string) (*m2MigrationOutputData, error) {
outputData := &m2MigrationOutputData{}
decoder := json.NewDecoder(strings.NewReader(outputDataStr))
decoder.UseNumber()

err := decoder.Decode(&outputData)
if err != nil {
return nil, err
}
outputData.OldWithdrawalRootString = hex.EncodeToString(outputData.OldWithdrawalRoot)
return outputData, err
}

// handleMigratedM2StakerWithdrawals handles the WithdrawalMigrated event from the DelegationManager contract
//
// Since we have already counted M1 withdrawals due to processing events block-by-block, we need to handle not double subtracting.
// Assuming that M2 WithdrawalQueued events always result in a subtraction, if we encounter a migration event, we need
// to add the amount back to the shares to get the correct final state.
func (ss *StakerSharesModel) handleMigratedM2StakerWithdrawals(log *storage.TransactionLog) (*AccumulatedStateChange, error) {
// TODO(seanmcgary): come back to this...
return nil, nil
func (ss *StakerSharesModel) handleMigratedM2StakerWithdrawals(log *storage.TransactionLog) ([]*AccumulatedStateChange, error) {
outputData, err := parseLogOutputForM2MigrationEvent(log.OutputData)
if err != nil {
return nil, err
}
query := `
with migration as (
select
json_extract(tl.output_data, '$.nonce') as nonce,
coalesce(json_extract(tl.output_data, '$.depositor'), json_extract(tl.output_data, '$.staker')) as staker
from transaction_logs tl
where
tl.address = @strategyManagerAddress
and tl.block_number <= @logBlockNumber
and tl.event_name = 'WithdrawalQueued'
and bytes_to_hex(json_extract(tl.output_data, '$.withdrawalRoot')) = @oldWithdrawalRoot
),
share_withdrawal_queued as (
select
tl.*,
json_extract(tl.output_data, '$.nonce') as nonce,
coalesce(json_extract(tl.output_data, '$.depositor'), json_extract(tl.output_data, '$.staker')) as staker
from transaction_logs as tl
where
tl.address = @strategyManagerAddress
and tl.event_name = 'ShareWithdrawalQueued'
)
select
*
from share_withdrawal_queued
where
nonce = (select nonce from migration)
and staker = (select staker from migration)
`
logs := make([]storage.TransactionLog, 0)
res := ss.Db.
Raw(query,
sql.Named("strategyManagerAddress", ss.globalConfig.GetContractsMapForEnvAndNetwork().StrategyManager),
sql.Named("logBlockNumber", log.BlockNumber),
sql.Named("oldWithdrawalRoot", outputData.OldWithdrawalRootString),
).
Scan(&logs)

if res.Error != nil {
ss.logger.Sugar().Errorw("Failed to fetch share withdrawal queued logs", zap.Error(res.Error))
return nil, res.Error
}

changes := make([]*AccumulatedStateChange, 0)
for _, l := range logs {
c, err := ss.handleStakerDepositEvent(&l)
if err != nil {
return nil, err
}
changes = append(changes, c)
}

return changes, nil
}

type m2WithdrawalOutputData struct {
Expand Down Expand Up @@ -280,9 +351,8 @@ func (ss *StakerSharesModel) handleM2QueuedWithdrawal(log *storage.TransactionLo
r := &AccumulatedStateChange{
Staker: outputData.Withdrawal.Staker,
Strategy: strategy,
Shares: shares,
Shares: shares.Mul(shares, big.NewInt(-1)),
BlockNumber: log.BlockNumber,
IsNegative: true,
}
records = append(records, r)
}
Expand Down Expand Up @@ -319,13 +389,13 @@ func (ss *StakerSharesModel) GetStateTransitions() (types.StateTransitions[Accum
if err == nil {
parsedRecords = append(parsedRecords, record)
}
} else if log.Address == contractAddresses.DelegationManager && log.EventName == "WithdrawalMigrated" {
record, err := ss.handleMigratedM2StakerWithdrawals(log)
if err == nil {
parsedRecords = append(parsedRecords, record)
}
} else if log.Address == contractAddresses.DelegationManager && log.EventName == "WithdrawalQueued" {
records, err := ss.handleM2QueuedWithdrawal(log)
if err == nil && records != nil {
parsedRecords = append(parsedRecords, records...)
}
} else if log.Address == contractAddresses.DelegationManager && log.EventName == "WithdrawalMigrated" {
records, err := ss.handleMigratedM2StakerWithdrawals(log)
if err == nil {
parsedRecords = append(parsedRecords, records...)
}
Expand All @@ -348,17 +418,16 @@ func (ss *StakerSharesModel) GetStateTransitions() (types.StateTransitions[Accum
}

for _, parsedRecord := range parsedRecords {
if parsedRecord == nil {
continue
}
slotId := NewSlotId(parsedRecord.Staker, parsedRecord.Strategy)
record, ok := ss.stateAccumulator[log.BlockNumber][slotId]
if !ok {
record = parsedRecord
ss.stateAccumulator[log.BlockNumber][slotId] = record
} else {
if record.IsNegative {
record.Shares = record.Shares.Sub(record.Shares, parsedRecord.Shares)
} else {
record.Shares = record.Shares.Add(record.Shares, parsedRecord.Shares)
}
record.Shares = record.Shares.Add(record.Shares, parsedRecord.Shares)
}
}

Expand Down Expand Up @@ -417,7 +486,7 @@ func (ss *StakerSharesModel) HandleStateChange(log *storage.TransactionLog) (int
return nil, err
}
if change == nil {
return nil, xerrors.Errorf("No state change found for block %d", blockNumber)
return nil, nil
}
return change, nil
}
Expand Down
Loading

0 comments on commit 4790cd9

Please sign in to comment.