Skip to content

Commit

Permalink
apply review suggestions
Browse files Browse the repository at this point in the history
1. add SignerConfig for signer and gas price
2. reduce duplicated code in ProveWithdrawalTransaction and FinalizeWithdrawalTransaction
3. fix type definition ContractAddress
4. add ci workflow build.yaml
  • Loading branch information
bendanzhentan committed Nov 21, 2023
1 parent cdd234d commit 2ffa2c9
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 85 deletions.
41 changes: 41 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Build

on:
push:
# branches: [ main ]
# pull_request:
# branches: [ main ]

jobs:

'build-go':
name: make build-go
runs-on: ubuntu-latest
steps:

- name: Set up Go 1.x
uses: actions/setup-go@v2
with:
go-version: ^1.21

- name: Check out
uses: actions/checkout@v3

- name: Make build-go
run: make build-go

'build-solidity':
name: make build-solidity
runs-on: ubuntu-latest
steps:

- name: Check out
uses: actions/checkout@v3
with:
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1

- name: Make build-solidity
run: cd contracts && forge build
37 changes: 37 additions & 0 deletions core/config.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package core

import (
"crypto/ecdsa"
"errors"
"fmt"
"os"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"

"github.com/BurntSushi/toml"
"github.com/ethereum-optimism/optimism/indexer/config"
"github.com/ethereum/go-ethereum/log"
Expand All @@ -19,6 +25,7 @@ type Config struct {
RPCs config.RPCsConfig `toml:"rpcs"`
DB config.DBConfig `toml:"db"`
L1Contracts config.L1Contracts `toml:"l1-contracts"`
Signer SignerConfig `toml:"signer"`
}

type MiscConfig struct {
Expand All @@ -29,6 +36,11 @@ type MiscConfig struct {
LogFilterBlockRange int64 `toml:"log-filter-block-range"`
}

type SignerConfig struct {
Privkey string `toml:"privkey"`
GasPrice int64 `toml:"gas-price"`
}

// LoadConfig loads the `bot.toml` config file from a given path
func LoadConfig(log log.Logger, path string) (Config, error) {
log.Debug("loading config", "path", path)
Expand Down Expand Up @@ -61,6 +73,31 @@ func LoadConfig(log log.Logger, path string) (Config, error) {
return conf, errors.New("challenge-time-window must be set")
}

if _, _, err = conf.SignerKeyPair(); err != nil {
return conf, err
}
if conf.Signer.GasPrice == 0 {
return conf, errors.New("gas-price must be set")
}

log.Info("loaded config")
return conf, nil
}

func (c *Config) SignerKeyPair() (*ecdsa.PrivateKey, *common.Address, error) {
privkey, err := crypto.HexToECDSA(c.Signer.Privkey)
if err != nil {
return nil, nil, fmt.Errorf("failed to parse privkey: %w", err)
}

pubKey := privkey.Public()
pubKeyECDSA, ok := pubKey.(*ecdsa.PublicKey)
if !ok {
return nil, nil, errors.New("failed to cast public key to ECDSA")
}

pubKeyBytes := crypto.FromECDSAPub(pubKeyECDSA)
pubKeyHash := crypto.Keccak256(pubKeyBytes[1:])[12:]
address := common.HexToAddress(hexutil.Encode(pubKeyHash))
return privkey, &address, nil
}
125 changes: 41 additions & 84 deletions core/processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,17 @@ package core

import (
"context"
"crypto/ecdsa"
"errors"
"fmt"
"math/big"
"os"

"github.com/ethereum-optimism/optimism/indexer/config"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/log"
"math/big"
)

type Processor struct {
Expand All @@ -25,7 +21,7 @@ type Processor struct {
L1Client *ClientExt
L2Client *ClientExt

L1Contracts config.L1Contracts
cfg Config
L2Contracts config.L2Contracts
}

Expand All @@ -38,17 +34,10 @@ func NewProcessor(
log = log.New("processor", "Processor")

l2Contracts := config.L2ContractsFromPredeploys()
return &Processor{log, l1Client, l2Client, cfg.L1Contracts, l2Contracts}
return &Processor{log, l1Client, l2Client, cfg, l2Contracts}
}

func (b *Processor) ProveWithdrawalTransaction(botDelegatedWithdrawToEvent *L2ContractEvent) error {
receipt, err := b.L2Client.TransactionReceipt(context.Background(), common.HexToHash(botDelegatedWithdrawToEvent.TransactionHash))
if err != nil {
return err
}

l2BlockNumber := receipt.BlockNumber

func (b *Processor) toWithdrawal(botDelegatedWithdrawToEvent *L2ContractEvent, receipt *types.Receipt) (*bindings.TypesWithdrawalTransaction, error) {
// Events flow:
//
// event[i-5]: WithdrawalInitiated
Expand All @@ -58,7 +47,7 @@ func (b *Processor) ProveWithdrawalTransaction(botDelegatedWithdrawToEvent *L2Co
// event[i-1]: SentMessageExtension1
// event[i] : L2StandardBridgeBot.WithdrawTo
if botDelegatedWithdrawToEvent.LogIndex < 5 || len(receipt.Logs) < 5 {
return fmt.Errorf("invalid botDelegatedWithdrawToEvent: %v", botDelegatedWithdrawToEvent)
return nil, fmt.Errorf("invalid botDelegatedWithdrawToEvent: %v", botDelegatedWithdrawToEvent)
}

messagePassedLog := receipt.Logs[botDelegatedWithdrawToEvent.LogIndex-3]
Expand All @@ -67,16 +56,31 @@ func (b *Processor) ProveWithdrawalTransaction(botDelegatedWithdrawToEvent *L2Co

sentMessageEvent, err := b.toL2CrossDomainMessengerSentMessageExtension1(sentMessageLog, sentMessageExtension1Log)
if err != nil {
return err
return nil, err
}
messagePassedEvent, err := b.toMessagePassed(messagePassedLog)
if err != nil {
return err
return nil, err
}

withdrawalTx, err := b.toLowLevelMessage(sentMessageEvent, messagePassedEvent)
if err != nil {
return fmt.Errorf("toLowLevelMessage err: %v", err)
return nil, fmt.Errorf("toLowLevelMessage err: %v", err)
}

return withdrawalTx, nil
}

func (b *Processor) ProveWithdrawalTransaction(botDelegatedWithdrawToEvent *L2ContractEvent) error {
receipt, err := b.L2Client.TransactionReceipt(context.Background(), common.HexToHash(botDelegatedWithdrawToEvent.TransactionHash))
if err != nil {
return err
}

l2BlockNumber := receipt.BlockNumber
withdrawalTx, err := b.toWithdrawal(botDelegatedWithdrawToEvent, receipt)
if err != nil {
return fmt.Errorf("toWithdrawal err: %v", err)
}

hash, err := b.hashWithdrawal(withdrawalTx)
Expand Down Expand Up @@ -125,33 +129,22 @@ func (b *Processor) ProveWithdrawalTransaction(botDelegatedWithdrawToEvent *L2Co
return err
}

// Retrieve the private key from the environment variable OPBNB_BRIDGE_BOT_PRIVKEY
botPrivkey, err := crypto.HexToECDSA(os.Getenv("OPBNB_BRIDGE_BOT_PRIVKEY"))
gasPrice := big.NewInt(b.cfg.Signer.GasPrice)
signerPrivkey, signerAddress, err := b.cfg.SignerKeyPair()
if err != nil {
return fmt.Errorf("invalid $OPBNB_BRIDGE_BOT_PRIVKEY: %w", err)
}

pubKey := botPrivkey.Public()
pubKeyECDSA, ok := pubKey.(*ecdsa.PublicKey)
if !ok {
return errors.New("cannot assert type: publicKey is not of type *ecdsa.PublicKey")
return err
}
pubKeyBytes := crypto.FromECDSAPub(pubKeyECDSA)
pubKeyHash := crypto.Keccak256(pubKeyBytes[1:])[12:]
fromAddress := common.HexToAddress(hexutil.Encode(pubKeyHash))

const gasPrice = 9000000000 // 9 GWei

optimismPortalTransactor, _ := bindings.NewOptimismPortalTransactor(
b.L1Contracts.OptimismPortalProxy,
b.cfg.L1Contracts.OptimismPortalProxy,
b.L1Client,
)
signedTx, err := optimismPortalTransactor.ProveWithdrawalTransaction(
&bind.TransactOpts{
From: fromAddress,
GasPrice: big.NewInt(gasPrice),
From: *signerAddress,
GasPrice: gasPrice,
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
return types.SignTx(tx, types.NewEIP155Signer(l1ChainId), botPrivkey)
return types.SignTx(tx, types.NewEIP155Signer(l1ChainId), signerPrivkey)
},
},
*withdrawalTx,
Expand All @@ -174,68 +167,32 @@ func (b *Processor) FinalizeMessage(botDelegatedWithdrawToEvent *L2ContractEvent
return err
}

// Events flow:
//
// event[i-5]: WithdrawalInitiated
// event[i-4]: ETHBridgeInitiated
// event[i-3]: MessagePassed
// event[i-2]: SentMessage
// event[i-1]: SentMessageExtension1
// event[i] : L2StandardBridgeBot.WithdrawTo
if botDelegatedWithdrawToEvent.LogIndex < 5 || len(receipt.Logs) < 5 {
return fmt.Errorf("invalid botDelegatedWithdrawToEvent: %v", botDelegatedWithdrawToEvent)
}

messagePassedLog := receipt.Logs[botDelegatedWithdrawToEvent.LogIndex-3]
sentMessageLog := receipt.Logs[botDelegatedWithdrawToEvent.LogIndex-2]
sentMessageExtension1Log := receipt.Logs[botDelegatedWithdrawToEvent.LogIndex-1]

sentMessageEvent, err := b.toL2CrossDomainMessengerSentMessageExtension1(sentMessageLog, sentMessageExtension1Log)
if err != nil {
return err
}
messagePassedEvent, err := b.toMessagePassed(messagePassedLog)
if err != nil {
return err
}

withdrawalTx, err := b.toLowLevelMessage(sentMessageEvent, messagePassedEvent)
withdrawalTx, err := b.toWithdrawal(botDelegatedWithdrawToEvent, receipt)
if err != nil {
return fmt.Errorf("toLowLevelMessage err: %v", err)
return fmt.Errorf("toWithdrawal err: %v", err)
}

l1ChainId, err := b.L1Client.ChainID(context.Background())
if err != nil {
return err
}

// Retrieve the private key from the environment variable OPBNB_BRIDGE_BOT_PRIVKEY
botPrivkey, err := crypto.HexToECDSA(os.Getenv("OPBNB_BRIDGE_BOT_PRIVKEY"))
gasPrice := big.NewInt(b.cfg.Signer.GasPrice)
signerPrivkey, signerAddress, err := b.cfg.SignerKeyPair()
if err != nil {
return fmt.Errorf("invalid $OPBNB_BRIDGE_BOT_PRIVKEY: %w", err)
}

pubKey := botPrivkey.Public()
pubKeyECDSA, ok := pubKey.(*ecdsa.PublicKey)
if !ok {
return errors.New("cannot assert type: publicKey is not of type *ecdsa.PublicKey")
return err
}
pubKeyBytes := crypto.FromECDSAPub(pubKeyECDSA)
pubKeyHash := crypto.Keccak256(pubKeyBytes[1:])[12:]
fromAddress := common.HexToAddress(hexutil.Encode(pubKeyHash))

const gasPrice = 9000000000 // 9 GWei

optimismPortalTransactor, _ := bindings.NewOptimismPortalTransactor(
b.L1Contracts.OptimismPortalProxy,
b.cfg.L1Contracts.OptimismPortalProxy,
b.L1Client,
)
signedTx, err := optimismPortalTransactor.FinalizeWithdrawalTransaction(
&bind.TransactOpts{
From: fromAddress,
GasPrice: big.NewInt(gasPrice),
From: *signerAddress,
GasPrice: gasPrice,
Signer: func(address common.Address, tx *types.Transaction) (*types.Transaction, error) {
return types.SignTx(tx, types.NewEIP155Signer(l1ChainId), botPrivkey)
return types.SignTx(tx, types.NewEIP155Signer(l1ChainId), signerPrivkey)
},
},
*withdrawalTx,
Expand Down Expand Up @@ -492,7 +449,7 @@ func (b *Processor) getMessagePassedMessagesFromReceipt(receipt *types.Receipt)

func (b *Processor) getL2OutputAfter(l2BlockNumber *big.Int) (*big.Int, *bindings.TypesOutputProposal, error) {
l2OutputOracleCaller, err := bindings.NewL2OutputOracleCaller(
b.L1Contracts.L2OutputOracleProxy,
b.cfg.L1Contracts.L2OutputOracleProxy,
b.L1Client,
)
if err != nil {
Expand Down Expand Up @@ -535,7 +492,7 @@ func (b *Processor) toLowLevelMessage(
withdrawalTx := bindings.TypesWithdrawalTransaction{
Nonce: messagePassedEvent.Nonce,
Sender: b.L2Contracts.L2CrossDomainMessenger,
Target: b.L1Contracts.L1CrossDomainMessengerProxy,
Target: b.cfg.L1Contracts.L1CrossDomainMessengerProxy,
Value: sentMessageEvent.Value,
GasLimit: messagePassedEvent.GasLimit,
Data: relayMessageCalldata,
Expand Down
2 changes: 1 addition & 1 deletion core/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type L2ContractEvent struct {
ID uint `gorm:"primarykey"`
BlockTime int64 `gorm:"type:integer;not null;index:idx_l2_contract_events_block_time"`
BlockHash string `gorm:"type:varchar(256);not null;uniqueIndex:idx_l2_contract_events_block_hash_log_index_key,priority:1;"`
ContractAddress string `gorm:"type:varchar(256);not nul"`
ContractAddress string `gorm:"type:varchar(256);not null"`
TransactionHash string `gorm:"type:varchar(256);not null"`
LogIndex int `gorm:"type:integer;not null;uniqueIndex:idx_l2_contract_events_block_hash_log_index_key,priority:2"`
EventSignature string `gorm:"type:varchar(256);not null"`
Expand Down

0 comments on commit 2ffa2c9

Please sign in to comment.