-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(eventindexer): introduce disperser (#16694)
- Loading branch information
1 parent
ca45aa6
commit 977b5cb
Showing
17 changed files
with
8,331 additions
and
5 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package flags | ||
|
||
import "github.com/urfave/cli/v2" | ||
|
||
var ( | ||
DisperserPrivateKey = &cli.StringFlag{ | ||
Name: "disperserPrivateKey", | ||
Usage: "Disperser private key which contains TTKO", | ||
Required: true, | ||
Category: disperserCategory, | ||
EnvVars: []string{"DISPERSER_PRIVATE_KEY"}, | ||
} | ||
TaikoTokenAddress = &cli.StringFlag{ | ||
Name: "taikoTokenAddress", | ||
Usage: "Address of the TaikoToken contract", | ||
Required: true, | ||
Category: disperserCategory, | ||
EnvVars: []string{"TAIKO_TOKEN_ADDRESS"}, | ||
} | ||
DispersalAmount = &cli.StringFlag{ | ||
Name: "taikoTokenAddress", | ||
Usage: "Dispersal amount in wei", | ||
Required: true, | ||
Category: disperserCategory, | ||
EnvVars: []string{"DISPERSAL_AMOUNT"}, | ||
} | ||
RPCUrl = &cli.StringFlag{ | ||
Name: "rpcUrl", | ||
Usage: "RPC URL for the source chain", | ||
Required: true, | ||
Category: commonCategory, | ||
EnvVars: []string{"RPC_URL"}, | ||
} | ||
) | ||
|
||
var DisperserFlags = MergeFlags(CommonFlags, []cli.Flag{ | ||
DisperserPrivateKey, | ||
TaikoTokenAddress, | ||
DispersalAmount, | ||
RPCUrl, | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2,371 changes: 2,371 additions & 0 deletions
2,371
packages/eventindexer/contracts/sgxverifier/SgxVerifier.go
Large diffs are not rendered by default.
Oops, something went wrong.
3,455 changes: 3,455 additions & 0 deletions
3,455
packages/eventindexer/contracts/taikotoken/TaikoToken.go
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
package disperser | ||
|
||
import ( | ||
"crypto/ecdsa" | ||
"database/sql" | ||
"fmt" | ||
"math/big" | ||
|
||
"github.com/ethereum-optimism/optimism/op-service/txmgr" | ||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/ethereum/go-ethereum/crypto" | ||
"github.com/taikoxyz/taiko-mono/packages/eventindexer/cmd/flags" | ||
"github.com/taikoxyz/taiko-mono/packages/eventindexer/pkg/db" | ||
pkgFlags "github.com/taikoxyz/taiko-mono/packages/relayer/pkg/flags" | ||
"github.com/urfave/cli/v2" | ||
"gorm.io/driver/mysql" | ||
"gorm.io/gorm" | ||
"gorm.io/gorm/logger" | ||
) | ||
|
||
type DB interface { | ||
DB() (*sql.DB, error) | ||
GormDB() *gorm.DB | ||
} | ||
|
||
type Config struct { | ||
// db configs | ||
DatabaseUsername string | ||
DatabasePassword string | ||
DatabaseName string | ||
DatabaseHost string | ||
DatabaseMaxIdleConns uint64 | ||
DatabaseMaxOpenConns uint64 | ||
DatabaseMaxConnLifetime uint64 | ||
MetricsHTTPPort uint64 | ||
DisperserPrivateKey *ecdsa.PrivateKey | ||
DispersalAmount *big.Int | ||
TaikoTokenAddress common.Address | ||
TxmgrConfigs *txmgr.CLIConfig | ||
RPCURL string | ||
OpenDBFunc func() (DB, error) | ||
} | ||
|
||
// NewConfigFromCliContext creates a new config instance from command line flags. | ||
func NewConfigFromCliContext(c *cli.Context) (*Config, error) { | ||
disperserPrivateKey, err := crypto.ToECDSA( | ||
common.Hex2Bytes(c.String(flags.DisperserPrivateKey.Name)), | ||
) | ||
if err != nil { | ||
return nil, fmt.Errorf("invalid disperserPrivateKey: %w", err) | ||
} | ||
|
||
dispersalAmount, ok := new(big.Int).SetString(c.String(flags.DispersalAmount.Name), 10) | ||
if !ok { | ||
return nil, fmt.Errorf("Invalid dispersal amount") | ||
} | ||
|
||
return &Config{ | ||
DatabaseUsername: c.String(flags.DatabaseUsername.Name), | ||
DatabasePassword: c.String(flags.DatabasePassword.Name), | ||
DatabaseName: c.String(flags.DatabaseName.Name), | ||
DatabaseHost: c.String(flags.DatabaseHost.Name), | ||
DatabaseMaxIdleConns: c.Uint64(flags.DatabaseMaxIdleConns.Name), | ||
DatabaseMaxOpenConns: c.Uint64(flags.DatabaseMaxOpenConns.Name), | ||
DatabaseMaxConnLifetime: c.Uint64(flags.DatabaseConnMaxLifetime.Name), | ||
MetricsHTTPPort: c.Uint64(flags.MetricsHTTPPort.Name), | ||
DisperserPrivateKey: disperserPrivateKey, | ||
RPCURL: c.String(flags.RPCUrl.Name), | ||
DispersalAmount: dispersalAmount, | ||
TaikoTokenAddress: common.HexToAddress(c.String(flags.TaikoTokenAddress.Name)), | ||
TxmgrConfigs: pkgFlags.InitTxmgrConfigsFromCli( | ||
c.String(flags.RPCUrl.Name), | ||
disperserPrivateKey, | ||
c, | ||
), | ||
OpenDBFunc: func() (DB, error) { | ||
return db.OpenDBConnection(db.DBConnectionOpts{ | ||
Name: c.String(flags.DatabaseUsername.Name), | ||
Password: c.String(flags.DatabasePassword.Name), | ||
Database: c.String(flags.DatabaseName.Name), | ||
Host: c.String(flags.DatabaseHost.Name), | ||
MaxIdleConns: c.Uint64(flags.DatabaseMaxIdleConns.Name), | ||
MaxOpenConns: c.Uint64(flags.DatabaseMaxOpenConns.Name), | ||
MaxConnLifetime: c.Uint64(flags.DatabaseConnMaxLifetime.Name), | ||
OpenFunc: func(dsn string) (*db.DB, error) { | ||
gormDB, err := gorm.Open(mysql.Open(dsn), &gorm.Config{ | ||
Logger: logger.Default.LogMode(logger.Silent), | ||
}) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return db.New(gormDB), nil | ||
}, | ||
}) | ||
}, | ||
}, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
package disperser | ||
|
||
import ( | ||
"context" | ||
"log/slog" | ||
"math/big" | ||
|
||
txmgrMetrics "github.com/ethereum-optimism/optimism/op-service/txmgr/metrics" | ||
"github.com/taikoxyz/taiko-mono/packages/eventindexer/encoding" | ||
|
||
"github.com/ethereum-optimism/optimism/op-service/txmgr" | ||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/ethereum/go-ethereum/log" | ||
"github.com/urfave/cli/v2" | ||
) | ||
|
||
var ( | ||
ZeroAddress = common.HexToAddress("0x0000000000000000000000000000000000000000") | ||
) | ||
|
||
// Disperser is a subcommand which is intended to be run on an interval, like | ||
// a cronjob, to parse the indexed data from the database, and generate | ||
// time series data that can easily be displayed via charting libraries. | ||
type Disperser struct { | ||
db DB | ||
dispersalAmount *big.Int | ||
taikoTokenAddress common.Address | ||
txmgr txmgr.TxManager | ||
} | ||
|
||
func (d *Disperser) InitFromCli(ctx context.Context, c *cli.Context) error { | ||
config, err := NewConfigFromCliContext(c) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return InitFromConfig(ctx, d, config) | ||
} | ||
|
||
func InitFromConfig(ctx context.Context, d *Disperser, cfg *Config) error { | ||
db, err := cfg.OpenDBFunc() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if d.txmgr, err = txmgr.NewSimpleTxManager( | ||
"disperser", | ||
log.Root(), | ||
new(txmgrMetrics.NoopTxMetrics), | ||
*cfg.TxmgrConfigs, | ||
); err != nil { | ||
return err | ||
} | ||
|
||
d.db = db | ||
|
||
d.dispersalAmount = cfg.DispersalAmount | ||
d.taikoTokenAddress = cfg.TaikoTokenAddress | ||
|
||
return nil | ||
} | ||
|
||
func (d *Disperser) Name() string { | ||
return "disperser" | ||
} | ||
|
||
func (d *Disperser) Start() error { | ||
addresses, err := d.findAllAddresses() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
for _, address := range addresses { | ||
slog.Info("dispersing to", "address", address) | ||
|
||
data, err := encoding.TaikoTokenABI.Pack("transfer", common.HexToAddress(address), d.dispersalAmount) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
candidate := txmgr.TxCandidate{ | ||
TxData: data, | ||
Blobs: nil, | ||
To: &d.taikoTokenAddress, | ||
} | ||
|
||
receipt, err := d.txmgr.Send(context.Background(), candidate) | ||
if err != nil { | ||
slog.Warn("Failed to send transfer transaction", "error", err.Error()) | ||
return err | ||
} | ||
|
||
slog.Info("sent tx", "tx", receipt.TxHash.Hex()) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (d *Disperser) findAllAddresses() ([]string, error) { | ||
var addresses []string | ||
// Execute raw SQL query to find distinct addresses where event is 'InstanceAdded' | ||
err := d.db.GormDB().Raw("SELECT DISTINCT address FROM events WHERE event = ?", "InstanceAdded").Scan(&addresses).Error | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return addresses, nil | ||
} | ||
|
||
func (d *Disperser) Close(ctx context.Context) { | ||
sqlDB, err := d.db.DB() | ||
if err != nil { | ||
slog.Error("error getting sqldb when closing Disperser", "err", err.Error()) | ||
} | ||
|
||
if err := sqlDB.Close(); err != nil { | ||
slog.Error("error closing sqlbd connection", "err", err.Error()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package encoding | ||
|
||
import ( | ||
"github.com/ethereum/go-ethereum/accounts/abi" | ||
|
||
"github.com/ethereum/go-ethereum/log" | ||
"github.com/taikoxyz/taiko-mono/packages/eventindexer/contracts/taikotoken" | ||
) | ||
|
||
var TaikoTokenABI *abi.ABI | ||
|
||
var err error | ||
|
||
func init() { | ||
if TaikoTokenABI, err = taikotoken.TaikoTokenMetaData.GetAbi(); err != nil { | ||
log.Crit("Get TaikoTokenABI ABI error", "error", err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.