Commit 9b61a14c authored by mergify[bot]'s avatar mergify[bot] Committed by GitHub

Merge branch 'develop' into kevin/fix-bedrock-foundry-toml

parents 654ba4c7 3b76cfb5
......@@ -822,11 +822,9 @@ jobs:
name: print go's available MIPS targets
command: go tool dist list | grep mips
- run:
name: generate cannon prestate
command: make cannon-prestate
- run:
name: generate L1 state
command: make devnet-allocs
name: Run all init steps for op-e2e
command: make pre-test
working_directory: <<parameters.module>>
- run:
name: run tests
command: |
......
package cmd
import (
"fmt"
"os"
"github.com/ethereum-optimism/optimism/cannon/mipsevm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/urfave/cli/v2"
)
var (
WitnessInputFlag = &cli.PathFlag{
Name: "input",
Usage: "path of input JSON state.",
TakesFile: true,
Required: true,
}
WitnessOutputFlag = &cli.PathFlag{
Name: "output",
Usage: "path to write binary witness.",
TakesFile: true,
}
)
func Witness(ctx *cli.Context) error {
input := ctx.Path(WitnessInputFlag.Name)
output := ctx.Path(WitnessOutputFlag.Name)
state, err := loadJSON[mipsevm.State](input)
if err != nil {
return fmt.Errorf("invalid input state (%v): %w", input, err)
}
witness := state.EncodeWitness()
h := crypto.Keccak256Hash(witness)
if output != "" {
if err := os.WriteFile(output, witness, 0755); err != nil {
return fmt.Errorf("writing output to %v: %w", output, err)
}
}
fmt.Println(h.Hex())
return nil
}
var WitnessCommand = &cli.Command{
Name: "witness",
Usage: "Convert a Cannon JSON state into a binary witness",
Description: "Convert a Cannon JSON state into a binary witness. The hash of the witness is written to stdout",
Action: Witness,
Flags: []cli.Flag{
WitnessInputFlag,
WitnessOutputFlag,
},
}
......@@ -20,6 +20,7 @@ func main() {
app.Description = "MIPS Fault Proof tool"
app.Commands = []*cli.Command{
cmd.LoadELFCommand,
cmd.WitnessCommand,
cmd.RunCommand,
}
ctx, cancel := context.WithCancel(context.Background())
......
......@@ -17,7 +17,7 @@ require (
github.com/google/uuid v1.3.0
github.com/gorilla/mux v1.8.0
github.com/hashicorp/go-multierror v1.1.1
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d
github.com/hashicorp/golang-lru v1.0.2
github.com/hashicorp/golang-lru/v2 v2.0.1
github.com/holiman/uint256 v1.2.3
github.com/ipfs/go-datastore v0.6.0
......
......@@ -319,8 +319,8 @@ github.com/hashicorp/go-bexpr v0.1.11/go.mod h1:f03lAo0duBlDIUMGCuad8oLcgejw4m7U
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs=
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru/v2 v2.0.1 h1:5pv5N1lT1fjLg2VQ5KWc7kmucp2x/kvFOnxuVTqZ6x4=
github.com/hashicorp/golang-lru/v2 v2.0.1/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
......
......@@ -8,32 +8,25 @@ import (
"github.com/ethereum-optimism/optimism/indexer/database"
"github.com/ethereum/go-ethereum/common"
"github.com/google/uuid"
"github.com/stretchr/testify/assert"
)
// MockBridgeTransfersView mocks the BridgeTransfersView interface
type MockBridgeTransfersView struct{}
const (
guid1 = "8408b6d2-7c90-4cfc-8604-b2204116cb6a"
guid2 = "8408b6d2-7c90-4cfc-8604-b2204116cb6b"
)
var (
deposit = database.L1BridgeDeposit{
GUID: uuid.MustParse(guid1),
InitiatedL1EventGUID: uuid.MustParse(guid2),
Tx: database.Transaction{},
TokenPair: database.TokenPair{},
TransactionSourceHash: common.HexToHash("abc"),
CrossDomainMessengerNonce: &database.U256{Int: big.NewInt(0)},
Tx: database.Transaction{},
TokenPair: database.TokenPair{},
}
withdrawal = database.L2BridgeWithdrawal{
GUID: uuid.MustParse(guid2),
InitiatedL2EventGUID: uuid.MustParse(guid1),
WithdrawalHash: common.HexToHash("0x456"),
Tx: database.Transaction{},
TokenPair: database.TokenPair{},
TransactionWithdrawalHash: common.HexToHash("0x456"),
CrossDomainMessengerNonce: &database.U256{Int: big.NewInt(0)},
Tx: database.Transaction{},
TokenPair: database.TokenPair{},
}
)
......@@ -54,7 +47,7 @@ func (mbv *MockBridgeTransfersView) L1BridgeDepositsByAddress(address common.Add
}, nil
}
func (mbv *MockBridgeTransfersView) L2BridgeWithdrawalByWithdrawalHash(address common.Hash) (*database.L2BridgeWithdrawal, error) {
func (mbv *MockBridgeTransfersView) L2BridgeWithdrawal(address common.Hash) (*database.L2BridgeWithdrawal, error) {
return &withdrawal, nil
}
......
......@@ -22,6 +22,8 @@ type BlockHeader struct {
ParentHash common.Hash `gorm:"serializer:json"`
Number U256
Timestamp uint64
GethHeader *GethHeader `gorm:"serializer:rlp;column:rlp_bytes"`
}
func BlockHeaderFromGethHeader(header *types.Header) BlockHeader {
......@@ -30,6 +32,8 @@ func BlockHeaderFromGethHeader(header *types.Header) BlockHeader {
ParentHash: header.ParentHash,
Number: U256{Int: header.Number},
Timestamp: header.Time,
GethHeader: (*GethHeader)(header),
}
}
......
package database
import (
"errors"
"fmt"
"math/big"
"gorm.io/gorm"
"github.com/ethereum/go-ethereum/common"
"github.com/google/uuid"
)
/**
* Types
*/
type BridgeMessage struct {
Nonce U256 `gorm:"primaryKey"`
MessageHash common.Hash `gorm:"serializer:json"`
SentMessageEventGUID uuid.UUID
RelayedMessageEventGUID *uuid.UUID
Tx Transaction `gorm:"embedded"`
GasLimit U256
}
type L1BridgeMessage struct {
BridgeMessage `gorm:"embedded"`
TransactionSourceHash common.Hash `gorm:"serializer:json"`
}
type L2BridgeMessage struct {
BridgeMessage `gorm:"embedded"`
TransactionWithdrawalHash common.Hash `gorm:"serializer:json"`
}
type BridgeMessagesView interface {
L1BridgeMessage(*big.Int) (*L1BridgeMessage, error)
L1BridgeMessageByHash(common.Hash) (*L1BridgeMessage, error)
LatestL1BridgeMessageNonce() (*big.Int, error)
L2BridgeMessage(*big.Int) (*L2BridgeMessage, error)
L2BridgeMessageByHash(common.Hash) (*L2BridgeMessage, error)
LatestL2BridgeMessageNonce() (*big.Int, error)
}
type BridgeMessagesDB interface {
BridgeMessagesView
StoreL1BridgeMessages([]*L1BridgeMessage) error
MarkRelayedL1BridgeMessage(common.Hash, uuid.UUID) error
StoreL2BridgeMessages([]*L2BridgeMessage) error
MarkRelayedL2BridgeMessage(common.Hash, uuid.UUID) error
}
/**
* Implementation
*/
type bridgeMessagesDB struct {
gorm *gorm.DB
}
func newBridgeMessagesDB(db *gorm.DB) BridgeMessagesDB {
return &bridgeMessagesDB{gorm: db}
}
/**
* Arbitrary Messages Sent from L1
*/
func (db bridgeMessagesDB) StoreL1BridgeMessages(messages []*L1BridgeMessage) error {
result := db.gorm.Create(&messages)
return result.Error
}
func (db bridgeMessagesDB) L1BridgeMessage(nonce *big.Int) (*L1BridgeMessage, error) {
var sentMessage L1BridgeMessage
result := db.gorm.Where(&BridgeMessage{Nonce: U256{Int: nonce}}).Take(&sentMessage)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, result.Error
}
return &sentMessage, nil
}
func (db bridgeMessagesDB) L1BridgeMessageByHash(messageHash common.Hash) (*L1BridgeMessage, error) {
var sentMessage L1BridgeMessage
result := db.gorm.Where(&BridgeMessage{MessageHash: messageHash}).Take(&sentMessage)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, result.Error
}
return &sentMessage, nil
}
func (db bridgeMessagesDB) LatestL1BridgeMessageNonce() (*big.Int, error) {
var sentMessage L1BridgeMessage
result := db.gorm.Order("nonce DESC").Take(&sentMessage)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, result.Error
}
return sentMessage.Nonce.Int, nil
}
/**
* Arbitrary Messages Sent from L2
*/
func (db bridgeMessagesDB) MarkRelayedL1BridgeMessage(messageHash common.Hash, relayEvent uuid.UUID) error {
message, err := db.L1BridgeMessageByHash(messageHash)
if err != nil {
return err
} else if message == nil {
return fmt.Errorf("L1BridgeMessage with message hash %s not found", messageHash)
}
message.RelayedMessageEventGUID = &relayEvent
result := db.gorm.Save(message)
return result.Error
}
func (db bridgeMessagesDB) StoreL2BridgeMessages(messages []*L2BridgeMessage) error {
result := db.gorm.Create(&messages)
return result.Error
}
func (db bridgeMessagesDB) L2BridgeMessage(nonce *big.Int) (*L2BridgeMessage, error) {
var sentMessage L2BridgeMessage
result := db.gorm.Where(&BridgeMessage{Nonce: U256{Int: nonce}}).Take(&sentMessage)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, result.Error
}
return &sentMessage, nil
}
func (db bridgeMessagesDB) L2BridgeMessageByHash(messageHash common.Hash) (*L2BridgeMessage, error) {
var sentMessage L2BridgeMessage
result := db.gorm.Where(&BridgeMessage{MessageHash: messageHash}).Take(&sentMessage)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, result.Error
}
return &sentMessage, nil
}
func (db bridgeMessagesDB) LatestL2BridgeMessageNonce() (*big.Int, error) {
var sentMessage L2BridgeMessage
result := db.gorm.Order("nonce DESC").Take(&sentMessage)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, result.Error
}
return sentMessage.Nonce.Int, nil
}
func (db bridgeMessagesDB) MarkRelayedL2BridgeMessage(messageHash common.Hash, relayEvent uuid.UUID) error {
message, err := db.L2BridgeMessageByHash(messageHash)
if err != nil {
return err
} else if message == nil {
return fmt.Errorf("L2BridgeMessage with message hash %s not found", messageHash)
}
message.RelayedMessageEventGUID = &relayEvent
result := db.gorm.Save(message)
return result.Error
}
package database
import (
"errors"
"fmt"
"github.com/google/uuid"
"gorm.io/gorm"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
)
/**
* Types
*/
type Transaction struct {
FromAddress common.Address `gorm:"serializer:json"`
ToAddress common.Address `gorm:"serializer:json"`
Amount U256
Data hexutil.Bytes `gorm:"serializer:json"`
Timestamp uint64
}
type L1TransactionDeposit struct {
SourceHash common.Hash `gorm:"serializer:json;primaryKey"`
L2TransactionHash common.Hash `gorm:"serializer:json"`
InitiatedL1EventGUID uuid.UUID
Version U256
OpaqueData hexutil.Bytes `gorm:"serializer:json"`
Tx Transaction `gorm:"embedded"`
GasLimit U256
}
type L2TransactionWithdrawal struct {
WithdrawalHash common.Hash `gorm:"serializer:json;primaryKey"`
Nonce U256
InitiatedL2EventGUID uuid.UUID
ProvenL1EventGUID *uuid.UUID
FinalizedL1EventGUID *uuid.UUID
Succeeded *bool
Tx Transaction `gorm:"embedded"`
GasLimit U256
}
type BridgeTransactionsView interface {
L1TransactionDeposit(common.Hash) (*L1TransactionDeposit, error)
L2TransactionWithdrawal(common.Hash) (*L2TransactionWithdrawal, error)
}
type BridgeTransactionsDB interface {
BridgeTransactionsView
StoreL1TransactionDeposits([]*L1TransactionDeposit) error
StoreL2TransactionWithdrawals([]*L2TransactionWithdrawal) error
MarkL2TransactionWithdrawalProvenEvent(common.Hash, uuid.UUID) error
MarkL2TransactionWithdrawalFinalizedEvent(common.Hash, uuid.UUID, bool) error
}
/**
* Implementation
*/
type bridgeTransactionsDB struct {
gorm *gorm.DB
}
func newBridgeTransactionsDB(db *gorm.DB) BridgeTransactionsDB {
return &bridgeTransactionsDB{gorm: db}
}
/**
* Transactions deposited from L1
*/
func (db *bridgeTransactionsDB) StoreL1TransactionDeposits(deposits []*L1TransactionDeposit) error {
result := db.gorm.Create(&deposits)
return result.Error
}
func (db *bridgeTransactionsDB) L1TransactionDeposit(sourceHash common.Hash) (*L1TransactionDeposit, error) {
var deposit L1TransactionDeposit
result := db.gorm.Where(&L1TransactionDeposit{SourceHash: sourceHash}).Take(&deposit)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, result.Error
}
return &deposit, nil
}
/**
* Transactions withdrawn from L2
*/
func (db *bridgeTransactionsDB) StoreL2TransactionWithdrawals(withdrawals []*L2TransactionWithdrawal) error {
result := db.gorm.Create(&withdrawals)
return result.Error
}
func (db *bridgeTransactionsDB) L2TransactionWithdrawal(withdrawalHash common.Hash) (*L2TransactionWithdrawal, error) {
var withdrawal L2TransactionWithdrawal
result := db.gorm.Where(&L2TransactionWithdrawal{WithdrawalHash: withdrawalHash}).Take(&withdrawal)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, result.Error
}
return &withdrawal, nil
}
// MarkL2TransactionWithdrawalProvenEvent links a withdrawn transaction with associated Prove action on L1.
func (db *bridgeTransactionsDB) MarkL2TransactionWithdrawalProvenEvent(withdrawalHash common.Hash, provenL1EventGuid uuid.UUID) error {
withdrawal, err := db.L2TransactionWithdrawal(withdrawalHash)
if err != nil {
return err
}
if withdrawal == nil {
return fmt.Errorf("transaction withdrawal hash %s not found", withdrawalHash)
}
withdrawal.ProvenL1EventGUID = &provenL1EventGuid
result := db.gorm.Save(&withdrawal)
return result.Error
}
// MarkL2TransactionWithdrawalProvenEvent links a withdrawn transaction in its finalized state
func (db *bridgeTransactionsDB) MarkL2TransactionWithdrawalFinalizedEvent(withdrawalHash common.Hash, finalizedL1EventGuid uuid.UUID, succeeded bool) error {
withdrawal, err := db.L2TransactionWithdrawal(withdrawalHash)
if err != nil {
return err
}
if withdrawal == nil {
return fmt.Errorf("transaction withdrawal hash %s not found", withdrawalHash)
}
if withdrawal.ProvenL1EventGUID == nil {
return fmt.Errorf("cannot mark unproven withdrawal hash %s as finalized", withdrawal.WithdrawalHash)
}
withdrawal.FinalizedL1EventGUID = &finalizedL1EventGuid
withdrawal.Succeeded = &succeeded
result := db.gorm.Save(&withdrawal)
return result.Error
}
This diff is collapsed.
......@@ -16,26 +16,37 @@ import (
*/
type ContractEvent struct {
GUID uuid.UUID `gorm:"primaryKey"`
BlockHash common.Hash `gorm:"serializer:json"`
TransactionHash common.Hash `gorm:"serializer:json"`
GUID uuid.UUID `gorm:"primaryKey"`
BlockHash common.Hash `gorm:"serializer:json"`
ContractAddress common.Address `gorm:"serializer:json"`
TransactionHash common.Hash `gorm:"serializer:json"`
EventSignature common.Hash `gorm:"serializer:json"`
LogIndex uint64
Timestamp uint64
GethLog *types.Log `gorm:"serializer:rlp;column:rlp_bytes"`
}
func ContractEventFromGethLog(log *types.Log, timestamp uint64) ContractEvent {
eventSig := common.Hash{}
if len(log.Topics) > 0 {
eventSig = log.Topics[0]
}
return ContractEvent{
GUID: uuid.New(),
BlockHash: log.BlockHash,
ContractAddress: log.Address,
TransactionHash: log.TxHash,
EventSignature: log.Topics[0],
EventSignature: eventSig,
LogIndex: uint64(log.Index),
Timestamp: timestamp,
GethLog: log,
}
}
......
......@@ -10,9 +10,11 @@ import (
type DB struct {
gorm *gorm.DB
Blocks BlocksDB
ContractEvents ContractEventsDB
BridgeTransfers BridgeTransfersDB
Blocks BlocksDB
ContractEvents ContractEventsDB
BridgeTransfers BridgeTransfersDB
BridgeMessages BridgeMessagesDB
BridgeTransactions BridgeTransactionsDB
}
func NewDB(dsn string) (*DB, error) {
......@@ -31,10 +33,12 @@ func NewDB(dsn string) (*DB, error) {
}
db := &DB{
gorm: gorm,
Blocks: newBlocksDB(gorm),
ContractEvents: newContractEventsDB(gorm),
BridgeTransfers: newBridgeTransfersDB(gorm),
gorm: gorm,
Blocks: newBlocksDB(gorm),
ContractEvents: newContractEventsDB(gorm),
BridgeTransfers: newBridgeTransfersDB(gorm),
BridgeMessages: newBridgeMessagesDB(gorm),
BridgeTransactions: newBridgeTransactionsDB(gorm),
}
return db, nil
......@@ -59,9 +63,11 @@ func (db *DB) Close() error {
func dbFromGormTx(tx *gorm.DB) *DB {
return &DB{
gorm: tx,
Blocks: newBlocksDB(tx),
ContractEvents: newContractEventsDB(tx),
BridgeTransfers: newBridgeTransfersDB(tx),
gorm: tx,
Blocks: newBlocksDB(tx),
ContractEvents: newContractEventsDB(tx),
BridgeTransfers: newBridgeTransfersDB(tx),
BridgeMessages: newBridgeMessagesDB(tx),
BridgeTransactions: newBridgeTransactionsDB(tx),
}
}
package database
import (
"context"
"fmt"
"reflect"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/rlp"
"gorm.io/gorm/schema"
)
type RLPSerializer struct{}
type RLPInterface interface {
rlp.Encoder
rlp.Decoder
}
func init() {
schema.RegisterSerializer("rlp", RLPSerializer{})
}
func (RLPSerializer) Scan(ctx context.Context, field *schema.Field, dst reflect.Value, dbValue interface{}) error {
fieldValue := reflect.New(field.FieldType)
if dbValue != nil {
var bytes []byte
switch v := dbValue.(type) {
case []byte:
bytes = v
case string:
b, err := hexutil.Decode(v)
if err != nil {
return err
}
bytes = b
default:
return fmt.Errorf("unrecognized RLP bytes: %#v", dbValue)
}
if len(bytes) > 0 {
err := rlp.DecodeBytes(bytes, fieldValue.Interface())
if err != nil {
return err
}
}
}
field.ReflectValueOf(ctx, dst).Set(fieldValue.Elem())
return nil
}
func (RLPSerializer) Value(ctx context.Context, field *schema.Field, dst reflect.Value, fieldValue interface{}) (interface{}, error) {
// Even though rlp.Encode takes an interface and will error out if the passed interface does not
// satisfy the interface, we check here since we also want to make sure this type satisfies the
// rlp.Decoder interface as well
i := reflect.TypeOf(new(RLPInterface)).Elem()
if !reflect.TypeOf(fieldValue).Implements(i) {
return nil, fmt.Errorf("%T does not satisfy RLP Encoder & Decoder interface", fieldValue)
}
rlpBytes, err := rlp.EncodeToBytes(fieldValue)
if err != nil {
return nil, err
}
return hexutil.Bytes(rlpBytes).MarshalText()
}
......@@ -3,8 +3,12 @@ package database
import (
"database/sql/driver"
"errors"
"io"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
"github.com/jackc/pgtype"
)
......@@ -13,7 +17,7 @@ var big10 = big.NewInt(10)
var ErrU256Overflow = errors.New("number exceeds u256")
var ErrU256ContainsDecimal = errors.New("number contains fractional digits")
var ErrU256NotNull = errors.New("number cannot be null")
var ErrU256Null = errors.New("number cannot be null")
// U256 is a wrapper over big.Int that conforms to the database U256 numeric domain type
type U256 struct {
......@@ -30,7 +34,7 @@ func (u256 *U256) Scan(src interface{}) error {
} else if numeric.Exp < 0 {
return ErrU256ContainsDecimal
} else if numeric.Status == pgtype.Null {
return ErrU256NotNull
return ErrU256Null
}
// factor in the powers of 10
......@@ -54,7 +58,7 @@ func (u256 *U256) Scan(src interface{}) error {
func (u256 U256) Value() (driver.Value, error) {
// check bounds
if u256.Int == nil {
return nil, ErrU256NotNull
return nil, ErrU256Null
} else if u256.Int.Cmp(u256BigIntOverflow) >= 0 {
return nil, ErrU256Overflow
}
......@@ -63,3 +67,29 @@ func (u256 U256) Value() (driver.Value, error) {
numeric := pgtype.Numeric{Int: u256.Int, Status: pgtype.Present}
return numeric.Value()
}
type GethHeader types.Header
func (h *GethHeader) EncodeRLP(w io.Writer) error {
return types.NewBlockWithHeader((*types.Header)(h)).EncodeRLP(w)
}
func (h *GethHeader) DecodeRLP(s *rlp.Stream) error {
block := new(types.Block)
err := block.DecodeRLP(s)
if err != nil {
return err
}
header := block.Header()
*h = (GethHeader)(*header)
return nil
}
func (h *GethHeader) Header() *types.Header {
return (*types.Header)(h)
}
func (h *GethHeader) Hash() common.Hash {
return h.Header().Hash()
}
......@@ -16,6 +16,7 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/rlp"
"github.com/stretchr/testify/require"
)
......@@ -62,6 +63,9 @@ func TestE2EBlockHeaders(t *testing.T) {
require.Equal(t, header.Hash(), indexedHeader.Hash)
require.Equal(t, header.ParentHash, indexedHeader.ParentHash)
require.Equal(t, header.Time, indexedHeader.Timestamp)
// ensure the right rlp encoding is stored. checking the hashes sufficies
require.Equal(t, header.Hash(), indexedHeader.GethHeader.Hash())
}
})
......@@ -116,9 +120,17 @@ func TestE2EBlockHeaders(t *testing.T) {
require.NoError(t, err)
require.Equal(t, log.Topics[0], contractEvent.EventSignature)
require.Equal(t, log.BlockHash, contractEvent.BlockHash)
require.Equal(t, log.Address, contractEvent.ContractAddress)
require.Equal(t, log.TxHash, contractEvent.TransactionHash)
require.Equal(t, log.Index, uint(contractEvent.LogIndex))
// ensure the right rlp encoding of the contract log is stored
logRlp, err := rlp.EncodeToBytes(&log)
require.NoError(t, err)
contractEventRlp, err := rlp.EncodeToBytes(contractEvent.GethLog)
require.NoError(t, err)
require.ElementsMatch(t, logRlp, contractEventRlp)
// ensure the block is also indexed
block, err := testSuite.L1Client.BlockByNumber(testCtx, big.NewInt(int64(log.BlockNumber)))
require.NoError(t, err)
......@@ -131,6 +143,10 @@ func TestE2EBlockHeaders(t *testing.T) {
require.Equal(t, block.ParentHash(), l1BlockHeader.ParentHash)
require.Equal(t, block.Number(), l1BlockHeader.Number.Int)
require.Equal(t, block.Time(), l1BlockHeader.Timestamp)
// ensure the right rlp encoding is stored. checking the hashes
// suffices as it is based on the rlp bytes of the header
require.Equal(t, block.Hash(), l1BlockHeader.GethHeader.Hash())
}
})
}
package e2e_tests
import (
"context"
"math/big"
"testing"
"time"
e2etest_utils "github.com/ethereum-optimism/optimism/indexer/e2e_tests/utils"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
op_e2e "github.com/ethereum-optimism/optimism/op-e2e"
"github.com/ethereum-optimism/optimism/op-node/withdrawals"
"github.com/ethereum-optimism/optimism/op-service/client/utils"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"
)
func TestE2EBridgeL1CrossDomainMessenger(t *testing.T) {
testSuite := createE2ETestSuite(t)
l1CrossDomainMessenger, err := bindings.NewL1CrossDomainMessenger(testSuite.OpCfg.L1Deployments.L1CrossDomainMessengerProxy, testSuite.L1Client)
require.NoError(t, err)
aliceAddr := testSuite.OpCfg.Secrets.Addresses().Alice
// Attach 1ETH and random calldata to the sent messages
calldata := []byte{byte(1), byte(2), byte(3)}
l1Opts, err := bind.NewKeyedTransactorWithChainID(testSuite.OpCfg.Secrets.Alice, testSuite.OpCfg.L1ChainIDBig())
require.NoError(t, err)
l1Opts.Value = big.NewInt(params.Ether)
// Pause the processor to track relayed event
testSuite.Indexer.L2Processor.PauseForTest()
// (1) Send the Message
sentMsgTx, err := l1CrossDomainMessenger.SendMessage(l1Opts, aliceAddr, calldata, 100_000)
require.NoError(t, err)
sentMsgReceipt, err := utils.WaitReceiptOK(context.Background(), testSuite.L1Client, sentMsgTx.Hash())
require.NoError(t, err)
depositInfo, err := e2etest_utils.ParseDepositInfo(sentMsgReceipt)
require.NoError(t, err)
// wait for processor catchup
require.NoError(t, utils.WaitFor(context.Background(), 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.L1Processor.LatestProcessedHeader()
return l1Header != nil && l1Header.Number.Uint64() >= sentMsgReceipt.BlockNumber.Uint64(), nil
}))
parsedMessage, err := e2etest_utils.ParseCrossDomainMessage(sentMsgReceipt)
require.NoError(t, err)
// nonce for this message is zero but the current cross domain message version is 1.
nonceBytes := [31]byte{0: byte(1)}
nonce := new(big.Int).SetBytes(nonceBytes[:])
sentMessage, err := testSuite.DB.BridgeMessages.L1BridgeMessage(nonce)
require.NoError(t, err)
require.NotNil(t, sentMessage)
require.NotNil(t, sentMessage.SentMessageEventGUID)
require.Equal(t, depositInfo.DepositTx.SourceHash, sentMessage.TransactionSourceHash)
require.Equal(t, parsedMessage.MessageHash, sentMessage.MessageHash)
require.Equal(t, uint64(100_000), sentMessage.GasLimit.Int.Uint64())
require.Equal(t, big.NewInt(params.Ether), sentMessage.Tx.Amount.Int)
require.Equal(t, aliceAddr, sentMessage.Tx.FromAddress)
require.Equal(t, aliceAddr, sentMessage.Tx.ToAddress)
require.ElementsMatch(t, calldata, sentMessage.Tx.Data)
// (2) Process RelayedMesssage on inclusion
require.Nil(t, sentMessage.RelayedMessageEventGUID)
testSuite.Indexer.L2Processor.ResumeForTest()
transaction, err := testSuite.DB.BridgeTransactions.L1TransactionDeposit(sentMessage.TransactionSourceHash)
require.NoError(t, err)
// wait for processor catchup
depositReceipt, err := utils.WaitReceiptOK(context.Background(), testSuite.L2Client, transaction.L2TransactionHash)
require.NoError(t, err)
require.NoError(t, utils.WaitFor(context.Background(), 500*time.Millisecond, func() (bool, error) {
l2Header := testSuite.Indexer.L2Processor.LatestProcessedHeader()
return l2Header != nil && l2Header.Number.Uint64() >= depositReceipt.BlockNumber.Uint64(), nil
}))
sentMessage, err = testSuite.DB.BridgeMessages.L1BridgeMessage(nonce)
require.NoError(t, err)
require.NotNil(t, sentMessage)
require.NotNil(t, sentMessage.RelayedMessageEventGUID)
event, err := testSuite.DB.ContractEvents.L2ContractEvent(*sentMessage.RelayedMessageEventGUID)
require.NoError(t, err)
require.NotNil(t, event)
require.Equal(t, event.TransactionHash, transaction.L2TransactionHash)
}
func TestE2EBridgeL2CrossDomainMessenger(t *testing.T) {
testSuite := createE2ETestSuite(t)
optimismPortal, err := bindings.NewOptimismPortal(testSuite.OpCfg.L1Deployments.OptimismPortalProxy, testSuite.L1Client)
require.NoError(t, err)
l2CrossDomainMessenger, err := bindings.NewL2CrossDomainMessenger(predeploys.L2CrossDomainMessengerAddr, testSuite.L2Client)
require.NoError(t, err)
aliceAddr := testSuite.OpCfg.Secrets.Addresses().Alice
// Attach 1ETH and random calldata to the sent messages
calldata := []byte{byte(1), byte(2), byte(3)}
l2Opts, err := bind.NewKeyedTransactorWithChainID(testSuite.OpCfg.Secrets.Alice, testSuite.OpCfg.L2ChainIDBig())
require.NoError(t, err)
l2Opts.Value = big.NewInt(params.Ether)
// Ensure L1 has enough funds for the withdrawal by depositing an equal amount into the OptimismPortal
l1Opts, err := bind.NewKeyedTransactorWithChainID(testSuite.OpCfg.Secrets.Alice, testSuite.OpCfg.L1ChainIDBig())
require.NoError(t, err)
l1Opts.Value = l2Opts.Value
depositTx, err := optimismPortal.Receive(l1Opts)
require.NoError(t, err)
_, err = utils.WaitReceiptOK(context.Background(), testSuite.L1Client, depositTx.Hash())
require.NoError(t, err)
// (1) Send the Message
sentMsgTx, err := l2CrossDomainMessenger.SendMessage(l2Opts, aliceAddr, calldata, 100_000)
require.NoError(t, err)
sentMsgReceipt, err := utils.WaitReceiptOK(context.Background(), testSuite.L2Client, sentMsgTx.Hash())
require.NoError(t, err)
msgPassed, err := withdrawals.ParseMessagePassed(sentMsgReceipt)
require.NoError(t, err)
withdrawalHash, err := withdrawals.WithdrawalHash(msgPassed)
require.NoError(t, err)
// wait for processor catchup
require.NoError(t, utils.WaitFor(context.Background(), 500*time.Millisecond, func() (bool, error) {
l2Header := testSuite.Indexer.L2Processor.LatestProcessedHeader()
return l2Header != nil && l2Header.Number.Uint64() >= sentMsgReceipt.BlockNumber.Uint64(), nil
}))
parsedMessage, err := e2etest_utils.ParseCrossDomainMessage(sentMsgReceipt)
require.NoError(t, err)
// nonce for this message is zero but the current message version is 1.
nonceBytes := [31]byte{0: byte(1)}
nonce := new(big.Int).SetBytes(nonceBytes[:])
sentMessage, err := testSuite.DB.BridgeMessages.L2BridgeMessage(nonce)
require.NoError(t, err)
require.NotNil(t, sentMessage)
require.NotNil(t, sentMessage.SentMessageEventGUID)
require.Equal(t, withdrawalHash, sentMessage.TransactionWithdrawalHash)
require.Equal(t, parsedMessage.MessageHash, sentMessage.MessageHash)
require.Equal(t, uint64(100_000), sentMessage.GasLimit.Int.Uint64())
require.Equal(t, big.NewInt(params.Ether), sentMessage.Tx.Amount.Int)
require.Equal(t, aliceAddr, sentMessage.Tx.FromAddress)
require.Equal(t, aliceAddr, sentMessage.Tx.ToAddress)
require.ElementsMatch(t, calldata, sentMessage.Tx.Data)
// (2) Process RelayedMessage on withdrawal finalization
require.Nil(t, sentMessage.RelayedMessageEventGUID)
_, finalizedReceipt := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.L1Client, testSuite.OpSys.Nodes["sequencer"], testSuite.OpCfg.Secrets.Alice, sentMsgReceipt)
// wait for processor catchup
require.NoError(t, utils.WaitFor(context.Background(), 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.L1Processor.LatestProcessedHeader()
return l1Header != nil && l1Header.Number.Uint64() >= finalizedReceipt.BlockNumber.Uint64(), nil
}))
// message is marked as relayed
sentMessage, err = testSuite.DB.BridgeMessages.L2BridgeMessage(nonce)
require.NoError(t, err)
require.NotNil(t, sentMessage)
require.NotNil(t, sentMessage.RelayedMessageEventGUID)
event, err := testSuite.DB.ContractEvents.L1ContractEvent(*sentMessage.RelayedMessageEventGUID)
require.NoError(t, err)
require.NotNil(t, event)
require.Equal(t, event.TransactionHash, finalizedReceipt.TxHash)
}
package e2e_tests
import (
"context"
"math/big"
"testing"
"time"
e2etest_utils "github.com/ethereum-optimism/optimism/indexer/e2e_tests/utils"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
op_e2e "github.com/ethereum-optimism/optimism/op-e2e"
"github.com/ethereum-optimism/optimism/op-node/withdrawals"
"github.com/ethereum-optimism/optimism/op-service/client/utils"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
"github.com/stretchr/testify/require"
)
func TestE2EBridgeTransactionsOptimismPortalDeposits(t *testing.T) {
testSuite := createE2ETestSuite(t)
optimismPortal, err := bindings.NewOptimismPortal(testSuite.OpCfg.L1Deployments.OptimismPortalProxy, testSuite.L1Client)
require.NoError(t, err)
aliceAddr := testSuite.OpCfg.Secrets.Addresses().Alice
// attach 1 ETH to the deposit and random calldata
calldata := []byte{byte(1), byte(2), byte(3)}
l1Opts, err := bind.NewKeyedTransactorWithChainID(testSuite.OpCfg.Secrets.Alice, testSuite.OpCfg.L1ChainIDBig())
require.NoError(t, err)
l1Opts.Value = big.NewInt(params.Ether)
depositTx, err := optimismPortal.DepositTransaction(l1Opts, aliceAddr, l1Opts.Value, 100_000, false, calldata)
require.NoError(t, err)
depositReceipt, err := utils.WaitReceiptOK(context.Background(), testSuite.L1Client, depositTx.Hash())
require.NoError(t, err)
depositInfo, err := e2etest_utils.ParseDepositInfo(depositReceipt)
require.NoError(t, err)
depositL2TxHash := types.NewTx(depositInfo.DepositTx).Hash()
// wait for processor catchup
require.NoError(t, utils.WaitFor(context.Background(), 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.L1Processor.LatestProcessedHeader()
return l1Header != nil && l1Header.Number.Uint64() >= depositReceipt.BlockNumber.Uint64(), nil
}))
deposit, err := testSuite.DB.BridgeTransactions.L1TransactionDeposit(depositInfo.DepositTx.SourceHash)
require.NoError(t, err)
require.Equal(t, depositL2TxHash, deposit.L2TransactionHash)
require.Equal(t, big.NewInt(100_000), deposit.GasLimit.Int)
require.Equal(t, big.NewInt(params.Ether), deposit.Tx.Amount.Int)
require.Equal(t, aliceAddr, deposit.Tx.FromAddress)
require.Equal(t, aliceAddr, deposit.Tx.ToAddress)
require.ElementsMatch(t, calldata, deposit.Tx.Data)
require.Equal(t, depositInfo.Version.Uint64(), deposit.Version.Int.Uint64())
require.ElementsMatch(t, depositInfo.OpaqueData, deposit.OpaqueData)
event, err := testSuite.DB.ContractEvents.L1ContractEvent(deposit.InitiatedL1EventGUID)
require.NoError(t, err)
require.NotNil(t, event)
require.Equal(t, event.TransactionHash, depositTx.Hash())
// NOTE: The indexer does not track deposit inclusion as it's apart of the block derivation process.
// If this changes, we'd like to test for this here.
}
func TestE2EBridgeTransactionsL2ToL1MessagePasserWithdrawal(t *testing.T) {
testSuite := createE2ETestSuite(t)
optimismPortal, err := bindings.NewOptimismPortal(testSuite.OpCfg.L1Deployments.OptimismPortalProxy, testSuite.L1Client)
require.NoError(t, err)
l2ToL1MessagePasser, err := bindings.NewL2ToL1MessagePasser(predeploys.L2ToL1MessagePasserAddr, testSuite.L2Client)
require.NoError(t, err)
aliceAddr := testSuite.OpCfg.Secrets.Addresses().Alice
// attach 1 ETH to the withdrawal and random calldata
calldata := []byte{byte(1), byte(2), byte(3)}
l2Opts, err := bind.NewKeyedTransactorWithChainID(testSuite.OpCfg.Secrets.Alice, testSuite.OpCfg.L2ChainIDBig())
require.NoError(t, err)
l2Opts.Value = big.NewInt(params.Ether)
// Ensure L1 has enough funds for the withdrawal by depositing an equal amount into the OptimismPortal
l1Opts, err := bind.NewKeyedTransactorWithChainID(testSuite.OpCfg.Secrets.Alice, testSuite.OpCfg.L1ChainIDBig())
require.NoError(t, err)
l1Opts.Value = l2Opts.Value
depositTx, err := optimismPortal.Receive(l1Opts)
require.NoError(t, err)
_, err = utils.WaitReceiptOK(context.Background(), testSuite.L1Client, depositTx.Hash())
require.NoError(t, err)
withdrawTx, err := l2ToL1MessagePasser.InitiateWithdrawal(l2Opts, aliceAddr, big.NewInt(100_000), calldata)
require.NoError(t, err)
withdrawReceipt, err := utils.WaitReceiptOK(context.Background(), testSuite.L2Client, withdrawTx.Hash())
require.NoError(t, err)
// wait for processor catchup
require.NoError(t, utils.WaitFor(context.Background(), 500*time.Millisecond, func() (bool, error) {
l2Header := testSuite.Indexer.L2Processor.LatestProcessedHeader()
return l2Header != nil && l2Header.Number.Uint64() >= withdrawReceipt.BlockNumber.Uint64(), nil
}))
msgPassed, err := withdrawals.ParseMessagePassed(withdrawReceipt)
require.NoError(t, err)
withdrawalHash, err := withdrawals.WithdrawalHash(msgPassed)
require.NoError(t, err)
withdraw, err := testSuite.DB.BridgeTransactions.L2TransactionWithdrawal(withdrawalHash)
require.NoError(t, err)
require.Equal(t, msgPassed.Nonce.Uint64(), withdraw.Nonce.Int.Uint64())
require.Equal(t, big.NewInt(100_000), withdraw.GasLimit.Int)
require.Equal(t, big.NewInt(params.Ether), withdraw.Tx.Amount.Int)
require.Equal(t, aliceAddr, withdraw.Tx.FromAddress)
require.Equal(t, aliceAddr, withdraw.Tx.ToAddress)
require.ElementsMatch(t, calldata, withdraw.Tx.Data)
event, err := testSuite.DB.ContractEvents.L2ContractEvent(withdraw.InitiatedL2EventGUID)
require.NoError(t, err)
require.NotNil(t, event)
require.Equal(t, event.TransactionHash, withdrawTx.Hash())
// Test Withdrawal Proven
require.Nil(t, withdraw.ProvenL1EventGUID)
require.Nil(t, withdraw.FinalizedL1EventGUID)
withdrawParams, proveReceipt := op_e2e.ProveWithdrawal(t, *testSuite.OpCfg, testSuite.L1Client, testSuite.OpSys.Nodes["sequencer"], testSuite.OpCfg.Secrets.Alice, withdrawReceipt)
require.NoError(t, utils.WaitFor(context.Background(), 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.L1Processor.LatestProcessedHeader()
return l1Header != nil && l1Header.Number.Uint64() >= proveReceipt.BlockNumber.Uint64(), nil
}))
withdraw, err = testSuite.DB.BridgeTransactions.L2TransactionWithdrawal(withdrawalHash)
require.NoError(t, err)
require.NotNil(t, withdraw.ProvenL1EventGUID)
proveEvent, err := testSuite.DB.ContractEvents.L1ContractEvent(*withdraw.ProvenL1EventGUID)
require.NoError(t, err)
require.NotNil(t, event)
require.Equal(t, proveEvent.TransactionHash, proveReceipt.TxHash)
// Test Withdrawal Finalized
require.Nil(t, withdraw.FinalizedL1EventGUID)
finalizeReceipt := op_e2e.FinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.L1Client, testSuite.OpCfg.Secrets.Alice, proveReceipt, withdrawParams)
require.NoError(t, utils.WaitFor(context.Background(), 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.L1Processor.LatestProcessedHeader()
return l1Header != nil && l1Header.Number.Uint64() >= finalizeReceipt.BlockNumber.Uint64(), nil
}))
withdraw, err = testSuite.DB.BridgeTransactions.L2TransactionWithdrawal(withdrawalHash)
require.NoError(t, err)
require.NotNil(t, withdraw.FinalizedL1EventGUID)
require.NotNil(t, withdraw.Succeeded)
require.True(t, *withdraw.Succeeded)
finalizedEvent, err := testSuite.DB.ContractEvents.L1ContractEvent(*withdraw.FinalizedL1EventGUID)
require.NoError(t, err)
require.NotNil(t, event)
require.Equal(t, finalizedEvent.TransactionHash, finalizeReceipt.TxHash)
}
func TestE2EBridgeTransactionsL2ToL1MessagePasserFailedWithdrawal(t *testing.T) {
testSuite := createE2ETestSuite(t)
l2ToL1MessagePasser, err := bindings.NewL2ToL1MessagePasser(predeploys.L2ToL1MessagePasserAddr, testSuite.L2Client)
require.NoError(t, err)
aliceAddr := testSuite.OpCfg.Secrets.Addresses().Alice
// Try to withdraw 1 ETH from L2 without any corresponding deposits on L1
l2Opts, err := bind.NewKeyedTransactorWithChainID(testSuite.OpCfg.Secrets.Alice, testSuite.OpCfg.L2ChainIDBig())
require.NoError(t, err)
l2Opts.Value = big.NewInt(params.Ether)
withdrawTx, err := l2ToL1MessagePasser.InitiateWithdrawal(l2Opts, aliceAddr, big.NewInt(100_000), nil)
require.NoError(t, err)
withdrawReceipt, err := utils.WaitReceiptOK(context.Background(), testSuite.L2Client, withdrawTx.Hash())
require.NoError(t, err)
msgPassed, err := withdrawals.ParseMessagePassed(withdrawReceipt)
require.NoError(t, err)
withdrawalHash, err := withdrawals.WithdrawalHash(msgPassed)
require.NoError(t, err)
// Prove&Finalize withdrawal
_, finalizeReceipt := op_e2e.ProveAndFinalizeWithdrawal(t, *testSuite.OpCfg, testSuite.L1Client, testSuite.OpSys.Nodes["sequencer"], testSuite.OpCfg.Secrets.Alice, withdrawReceipt)
require.NoError(t, utils.WaitFor(context.Background(), 500*time.Millisecond, func() (bool, error) {
l1Header := testSuite.Indexer.L1Processor.LatestProcessedHeader()
return l1Header != nil && l1Header.Number.Uint64() >= finalizeReceipt.BlockNumber.Uint64(), nil
}))
// Withdrawal registered but marked as unsuccessful
withdraw, err := testSuite.DB.BridgeTransactions.L2TransactionWithdrawal(withdrawalHash)
require.NoError(t, err)
require.NotNil(t, withdraw.Succeeded)
require.False(t, *withdraw.Succeeded)
}
......@@ -53,6 +53,10 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite {
opSys, err := opCfg.Start()
require.NoError(t, err)
// E2E tests can run on the order of magnitude of minutes. Once
// the system is running, mark this test for Parallel execution
t.Parallel()
// Indexer Configuration and Start
indexerCfg := config.Config{
Logger: logger,
......@@ -82,21 +86,19 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite {
indexer, err := indexer.NewIndexer(indexerCfg)
require.NoError(t, err)
indexerStoppedCh := make(chan interface{}, 1)
indexerCtx, indexerStop := context.WithCancel(context.Background())
go func() {
err := indexer.Run(indexerCtx)
require.NoError(t, err)
indexer.Cleanup()
indexerStoppedCh <- nil
}()
t.Cleanup(func() {
indexerStop()
<-indexerStoppedCh
// wait a second for the stop signal to be received
time.Sleep(1 * time.Second)
indexer.Cleanup()
db.Close()
opSys.Close()
})
......@@ -114,6 +116,8 @@ func createE2ETestSuite(t *testing.T) E2ETestSuite {
func setupTestDatabase(t *testing.T) string {
user := os.Getenv("DB_USER")
require.NotEmpty(t, user, "DB_USER env variable expected to instantiate test database")
pg, err := sql.Open("pgx", fmt.Sprintf("postgres://%s@localhost:5432?sslmode=disable", user))
require.NoError(t, err)
require.NoError(t, pg.Ping())
......
package utils
import (
"errors"
"math/big"
"github.com/ethereum-optimism/optimism/indexer/processor"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
type CrossDomainMessengerSentMessage struct {
*bindings.CrossDomainMessengerSentMessage
Value *big.Int
MessageHash common.Hash
}
func ParseCrossDomainMessage(sentMessageReceipt *types.Receipt) (CrossDomainMessengerSentMessage, error) {
abi, err := bindings.CrossDomainMessengerMetaData.GetAbi()
if err != nil {
return CrossDomainMessengerSentMessage{}, err
}
sentMessageEventAbi := abi.Events["SentMessage"]
messenger, err := bindings.NewCrossDomainMessenger(common.Address{}, nil)
if err != nil {
return CrossDomainMessengerSentMessage{}, err
}
for i, log := range sentMessageReceipt.Logs {
if len(log.Topics) > 0 && log.Topics[0] == sentMessageEventAbi.ID {
sentMessage, err := messenger.ParseSentMessage(*log)
if err != nil {
return CrossDomainMessengerSentMessage{}, err
}
sentMessageExtension, err := messenger.ParseSentMessageExtension1(*sentMessageReceipt.Logs[i+1])
if err != nil {
return CrossDomainMessengerSentMessage{}, err
}
msgHash, err := CrossDomainMessengerSentMessageHash(sentMessage, sentMessageExtension.Value)
if err != nil {
return CrossDomainMessengerSentMessage{}, err
}
return CrossDomainMessengerSentMessage{sentMessage, sentMessageExtension.Value, msgHash}, nil
}
}
return CrossDomainMessengerSentMessage{}, errors.New("missing SentMessage receipts")
}
func CrossDomainMessengerSentMessageHash(sentMessage *bindings.CrossDomainMessengerSentMessage, value *big.Int) (common.Hash, error) {
abi, err := bindings.CrossDomainMessengerMetaData.GetAbi()
if err != nil {
return common.Hash{}, err
}
return processor.CrossDomainMessageHash(abi, sentMessage, value)
}
CREATE DOMAIN UINT256 AS NUMERIC NOT NULL
CREATE DOMAIN UINT256 AS NUMERIC
CHECK (VALUE >= 0 AND VALUE < 2^256 and SCALE(VALUE) = 0);
/**
......@@ -7,18 +7,25 @@ CREATE DOMAIN UINT256 AS NUMERIC NOT NULL
*/
CREATE TABLE IF NOT EXISTS l1_block_headers (
-- Searchable fields
hash VARCHAR NOT NULL PRIMARY KEY,
parent_hash VARCHAR NOT NULL,
number UINT256,
timestamp INTEGER NOT NULL CHECK (timestamp > 0)
number UINT256 NOT NULL,
timestamp INTEGER NOT NULL CHECK (timestamp > 0),
-- Raw Data
rlp_bytes VARCHAR NOT NULL
);
CREATE TABLE IF NOT EXISTS l2_block_headers (
-- Block header
-- Searchable fields
hash VARCHAR NOT NULL PRIMARY KEY,
parent_hash VARCHAR NOT NULL,
number UINT256,
timestamp INTEGER NOT NULL CHECK (timestamp > 0)
number UINT256 NOT NULL,
timestamp INTEGER NOT NULL CHECK (timestamp > 0),
-- Raw Data
rlp_bytes VARCHAR NOT NULL
);
/**
......@@ -26,21 +33,31 @@ CREATE TABLE IF NOT EXISTS l2_block_headers (
*/
CREATE TABLE IF NOT EXISTS l1_contract_events (
-- Searchable fields
guid VARCHAR NOT NULL PRIMARY KEY,
block_hash VARCHAR NOT NULL REFERENCES l1_block_headers(hash),
contract_address VARCHAR NOT NULL,
transaction_hash VARCHAR NOT NULL,
event_signature VARCHAR NOT NULL,
log_index INTEGER NOT NULL,
timestamp INTEGER NOT NULL CHECK (timestamp > 0)
event_signature VARCHAR NOT NULL, -- bytes32(0x0) when topics are missing
timestamp INTEGER NOT NULL CHECK (timestamp > 0),
-- Raw Data
rlp_bytes VARCHAR NOT NULL
);
CREATE TABLE IF NOT EXISTS l2_contract_events (
-- Searchable fields
guid VARCHAR NOT NULL PRIMARY KEY,
block_hash VARCHAR NOT NULL REFERENCES l2_block_headers(hash),
contract_address VARCHAR NOT NULL,
transaction_hash VARCHAR NOT NULL,
event_signature VARCHAR NOT NULL,
log_index INTEGER NOT NULL,
timestamp INTEGER NOT NULL CHECK (timestamp > 0)
event_signature VARCHAR NOT NULL, -- bytes32(0x0) when topics are missing
timestamp INTEGER NOT NULL CHECK (timestamp > 0),
-- Raw Data
rlp_bytes VARCHAR NOT NULL
);
-- Tables that index finalization markers for L2 blocks.
......@@ -57,8 +74,8 @@ CREATE TABLE IF NOT EXISTS legacy_state_batches (
CREATE TABLE IF NOT EXISTS output_proposals (
output_root VARCHAR NOT NULL PRIMARY KEY,
l2_output_index UINT256,
l2_block_number UINT256,
l2_output_index UINT256 NOT NULL,
l2_block_number UINT256 NOT NULL,
l1_contract_event_guid VARCHAR REFERENCES l1_contract_events(guid)
);
......@@ -67,47 +84,111 @@ CREATE TABLE IF NOT EXISTS output_proposals (
* BRIDGING DATA
*/
CREATE TABLE IF NOT EXISTS l1_bridge_deposits (
guid VARCHAR PRIMARY KEY NOT NULL,
-- OptimismPortal/L2ToL1MessagePasser
CREATE TABLE IF NOT EXISTS l1_transaction_deposits (
source_hash VARCHAR NOT NULL PRIMARY KEY,
l2_transaction_hash VARCHAR NOT NULL,
-- Event causing the deposit
initiated_l1_event_guid VARCHAR NOT NULL REFERENCES l1_contract_events(guid),
cross_domain_messenger_nonce UINT256 UNIQUE,
initiated_l1_event_guid VARCHAR NOT NULL REFERENCES l1_contract_events(guid),
-- Finalization marker for the deposit
finalized_l2_event_guid VARCHAR REFERENCES l2_contract_events(guid),
-- OptimismPortal specific
version UINT256 NOT NULL,
opaque_data VARCHAR NOT NULL,
-- Deposit information (do we need indexes on from/to?)
from_address VARCHAR NOT NULL,
-- transaction data
from_address VARCHAR NOT NULL,
to_address VARCHAR NOT NULL,
amount UINT256 NOT NULL,
gas_limit UINT256 NOT NULL,
data VARCHAR NOT NULL,
timestamp INTEGER NOT NULL CHECK (timestamp > 0)
);
CREATE TABLE IF NOT EXISTS l2_transaction_withdrawals (
withdrawal_hash VARCHAR NOT NULL PRIMARY KEY,
initiated_l2_event_guid VARCHAR NOT NULL REFERENCES l2_contract_events(guid),
-- Multistep (bedrock) process of a withdrawal
proven_l1_event_guid VARCHAR REFERENCES l1_contract_events(guid),
finalized_l1_event_guid VARCHAR REFERENCES l1_contract_events(guid),
succeeded BOOLEAN,
-- L2ToL1MessagePasser specific
nonce UINT256 UNIQUE,
-- transaction data
from_address VARCHAR NOT NULL,
to_address VARCHAR NOT NULL,
amount UINT256 NOT NULL,
gas_limit UINT256 NOT NULL,
data VARCHAR NOT NULL,
timestamp INTEGER NOT NULL CHECK (timestamp > 0)
);
-- CrossDomainMessenger
CREATE TABLE IF NOT EXISTS l1_bridge_messages(
nonce UINT256 NOT NULL PRIMARY KEY,
message_hash VARCHAR NOT NULL,
transaction_source_hash VARCHAR NOT NULL REFERENCES l1_transaction_deposits(source_hash),
sent_message_event_guid VARCHAR NOT NULL UNIQUE REFERENCES l1_contract_events(guid),
relayed_message_event_guid VARCHAR UNIQUE REFERENCES l2_contract_events(guid),
-- sent message
from_address VARCHAR NOT NULL,
to_address VARCHAR NOT NULL,
amount UINT256 NOT NULL,
gas_limit UINT256 NOT NULL,
data VARCHAR NOT NULL,
timestamp INTEGER NOT NULL CHECK (timestamp > 0)
);
CREATE TABLE IF NOT EXISTS l2_bridge_messages(
nonce UINT256 NOT NULL PRIMARY KEY,
message_hash VARCHAR NOT NULL,
transaction_withdrawal_hash VARCHAR NOT NULL REFERENCES l2_transaction_withdrawals(withdrawal_hash),
sent_message_event_guid VARCHAR NOT NULL UNIQUE REFERENCES l2_contract_events(guid),
relayed_message_event_guid VARCHAR UNIQUE REFERENCES l1_contract_events(guid),
-- sent message
from_address VARCHAR NOT NULL,
to_address VARCHAR NOT NULL,
amount UINT256 NOT NULL,
gas_limit UINT256 NOT NULL,
data VARCHAR NOT NULL,
timestamp INTEGER NOT NULL CHECK (timestamp > 0)
);
-- StandardBridge
CREATE TABLE IF NOT EXISTS l1_bridge_deposits (
transaction_source_hash VARCHAR PRIMARY KEY REFERENCES l1_transaction_deposits(source_hash),
-- We allow the cross_domain_messenger_nonce to be NULL-able to account
-- for scenarios where ETH is simply sent to the OptimismPortal contract
cross_domain_messenger_nonce UINT256 UNIQUE REFERENCES l1_bridge_messages(nonce),
-- Deposit information
from_address VARCHAR NOT NULL,
to_address VARCHAR NOT NULL,
l1_token_address VARCHAR NOT NULL,
l2_token_address VARCHAR NOT NULL,
amount UINT256,
amount UINT256 NOT NULL,
data VARCHAR NOT NULL,
timestamp INTEGER NOT NULL CHECK (timestamp > 0)
);
CREATE TABLE IF NOT EXISTS l2_bridge_withdrawals (
guid VARCHAR PRIMARY KEY NOT NULL,
-- Event causing this withdrawal
initiated_l2_event_guid VARCHAR NOT NULL REFERENCES l2_contract_events(guid),
cross_domain_messenger_nonce UINT256 UNIQUE,
transaction_withdrawal_hash VARCHAR PRIMARY KEY REFERENCES l2_transaction_withdrawals(withdrawal_hash),
-- Multistep (bedrock) process of a withdrawal
withdrawal_hash VARCHAR NOT NULL,
proven_l1_event_guid VARCHAR REFERENCES l1_contract_events(guid),
-- Finalization marker (legacy & bedrock)
finalized_l1_event_guid VARCHAR REFERENCES l1_contract_events(guid),
-- We allow the cross_domain_messenger_nonce to be NULL-able to account for
-- scenarios where ETH is simply sent to the L2ToL1MessagePasser contract
cross_domain_messenger_nonce UINT256 UNIQUE REFERENCES l2_bridge_messages(nonce),
-- Withdrawal information (do we need indexes on from/to?)
-- Withdrawal information
from_address VARCHAR NOT NULL,
to_address VARCHAR NOT NULL,
l1_token_address VARCHAR NOT NULL,
l2_token_address VARCHAR NOT NULL,
amount UINT256,
amount UINT256 NOT NULL,
data VARCHAR NOT NULL,
timestamp INTEGER NOT NULL CHECK (timestamp > 0)
);
......@@ -9,20 +9,17 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/google/uuid"
)
type ProcessedContractEventLogIndexKey struct {
header common.Hash
index uint
blockHash common.Hash
index uint
}
type ProcessedContractEvents struct {
events []*database.ContractEvent
eventsBySignature map[common.Hash][]*database.ContractEvent
eventByLogIndex map[ProcessedContractEventLogIndexKey]*database.ContractEvent
eventLog map[uuid.UUID]*types.Log
}
func NewProcessedContractEvents() *ProcessedContractEvents {
......@@ -30,17 +27,18 @@ func NewProcessedContractEvents() *ProcessedContractEvents {
events: []*database.ContractEvent{},
eventsBySignature: make(map[common.Hash][]*database.ContractEvent),
eventByLogIndex: make(map[ProcessedContractEventLogIndexKey]*database.ContractEvent),
eventLog: make(map[uuid.UUID]*types.Log),
}
}
func (p *ProcessedContractEvents) AddLog(log *types.Log, time uint64) *database.ContractEvent {
contractEvent := database.ContractEventFromGethLog(log, time)
emptyHash := common.Hash{}
p.events = append(p.events, &contractEvent)
p.eventsBySignature[contractEvent.EventSignature] = append(p.eventsBySignature[contractEvent.EventSignature], &contractEvent)
p.eventByLogIndex[ProcessedContractEventLogIndexKey{log.BlockHash, log.Index}] = &contractEvent
p.eventLog[contractEvent.GUID] = log
if contractEvent.EventSignature != emptyHash { // ignore anon events
p.eventsBySignature[contractEvent.EventSignature] = append(p.eventsBySignature[contractEvent.EventSignature], &contractEvent)
}
return &contractEvent
}
......
package processor
import (
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum-optimism/optimism/indexer/database"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
)
var (
// Standard ABI types copied from golang ABI tests
Uint256Type, _ = abi.NewType("uint256", "", nil)
BytesType, _ = abi.NewType("bytes", "", nil)
AddressType, _ = abi.NewType("address", "", nil)
LegacyCrossDomainMessengerRelayMessageMethod = abi.NewMethod(
"relayMessage",
"relayMessage",
abi.Function,
"external", // mutability
false, // isConst
true, // payable
abi.Arguments{ // inputs
{Name: "sender", Type: AddressType},
{Name: "target", Type: AddressType},
{Name: "data", Type: BytesType},
{Name: "nonce", Type: Uint256Type},
},
abi.Arguments{}, // outputs
)
)
type CrossDomainMessengerSentMessageEvent struct {
*bindings.CrossDomainMessengerSentMessage
Value *big.Int
MessageHash common.Hash
RawEvent *database.ContractEvent
}
type CrossDomainMessengerRelayedMessageEvent struct {
*bindings.CrossDomainMessengerRelayedMessage
RawEvent *database.ContractEvent
}
func CrossDomainMessengerSentMessageEvents(events *ProcessedContractEvents) ([]CrossDomainMessengerSentMessageEvent, error) {
crossDomainMessengerABI, err := bindings.CrossDomainMessengerMetaData.GetAbi()
if err != nil {
return nil, err
}
sentMessageEventAbi := crossDomainMessengerABI.Events["SentMessage"]
sentMessageEventExtensionAbi := crossDomainMessengerABI.Events["SentMessageExtension1"]
processedSentMessageEvents := events.eventsBySignature[sentMessageEventAbi.ID]
crossDomainMessageEvents := make([]CrossDomainMessengerSentMessageEvent, len(processedSentMessageEvents))
for i, sentMessageEvent := range processedSentMessageEvents {
log := sentMessageEvent.GethLog
var sentMsgData bindings.CrossDomainMessengerSentMessage
sentMsgData.Raw = *log
err = UnpackLog(&sentMsgData, log, sentMessageEventAbi.Name, crossDomainMessengerABI)
if err != nil {
return nil, err
}
var sentMsgExtensionData bindings.CrossDomainMessengerSentMessageExtension1
extensionLog := events.eventByLogIndex[ProcessedContractEventLogIndexKey{log.BlockHash, log.Index + 1}].GethLog
sentMsgExtensionData.Raw = *extensionLog
err = UnpackLog(&sentMsgExtensionData, extensionLog, sentMessageEventExtensionAbi.Name, crossDomainMessengerABI)
if err != nil {
return nil, err
}
msgHash, err := CrossDomainMessageHash(crossDomainMessengerABI, &sentMsgData, sentMsgExtensionData.Value)
if err != nil {
return nil, err
}
crossDomainMessageEvents[i] = CrossDomainMessengerSentMessageEvent{
CrossDomainMessengerSentMessage: &sentMsgData,
Value: sentMsgExtensionData.Value,
MessageHash: msgHash,
RawEvent: sentMessageEvent,
}
}
return crossDomainMessageEvents, nil
}
func CrossDomainMessengerRelayedMessageEvents(events *ProcessedContractEvents) ([]CrossDomainMessengerRelayedMessageEvent, error) {
crossDomainMessengerABI, err := bindings.L1CrossDomainMessengerMetaData.GetAbi()
if err != nil {
return nil, err
}
relayedMessageEventAbi := crossDomainMessengerABI.Events["RelayedMessage"]
processedRelayedMessageEvents := events.eventsBySignature[relayedMessageEventAbi.ID]
crossDomainMessageEvents := make([]CrossDomainMessengerRelayedMessageEvent, len(processedRelayedMessageEvents))
for i, relayedMessageEvent := range processedRelayedMessageEvents {
log := relayedMessageEvent.GethLog
var relayedMsgData bindings.CrossDomainMessengerRelayedMessage
relayedMsgData.Raw = *log
err = UnpackLog(&relayedMsgData, log, relayedMessageEventAbi.Name, crossDomainMessengerABI)
if err != nil {
return nil, err
}
crossDomainMessageEvents[i] = CrossDomainMessengerRelayedMessageEvent{
CrossDomainMessengerRelayedMessage: &relayedMsgData,
RawEvent: relayedMessageEvent,
}
}
return crossDomainMessageEvents, nil
}
// Replica of `Hashing.sol#hashCrossDomainMessage` solidity implementation
func CrossDomainMessageHash(abi *abi.ABI, sentMsg *bindings.CrossDomainMessengerSentMessage, value *big.Int) (common.Hash, error) {
version, _ := DecodeVersionedNonce(sentMsg.MessageNonce)
switch version {
case 0:
// Legacy Message
inputBytes, err := LegacyCrossDomainMessengerRelayMessageMethod.Inputs.Pack(sentMsg.Sender, sentMsg.Target, sentMsg.Message, sentMsg.MessageNonce)
if err != nil {
return common.Hash{}, err
}
msgBytes := append(LegacyCrossDomainMessengerRelayMessageMethod.ID, inputBytes...)
return crypto.Keccak256Hash(msgBytes), nil
case 1:
// Current Message
msgBytes, err := abi.Pack("relayMessage", sentMsg.MessageNonce, sentMsg.Sender, sentMsg.Target, value, sentMsg.GasLimit, sentMsg.Message)
if err != nil {
return common.Hash{}, err
}
return crypto.Keccak256Hash(msgBytes), nil
}
return common.Hash{}, fmt.Errorf("unsupported cross domain messenger version: %d", version)
}
package processor
import (
"encoding/binary"
"math/big"
)
// DecodeVersionNonce is an re-implementation of Encoding.sol#decodeVersionedNonce.
// If the nonce is greater than 32 bytes (solidity uint256), bytes [32:] are ignored
func DecodeVersionedNonce(nonce *big.Int) (uint16, *big.Int) {
nonceBytes := nonce.Bytes()
nonceByteLen := len(nonceBytes)
if nonceByteLen < 30 {
// version is 0x0000
return 0, nonce
} else if nonceByteLen == 31 {
// version is 0x00[01..ff]
return uint16(nonceBytes[0]), new(big.Int).SetBytes(nonceBytes[1:])
} else {
// fully specified
version := binary.BigEndian.Uint16(nonceBytes[:2])
return version, new(big.Int).SetBytes(nonceBytes[2:])
}
}
This diff is collapsed.
This diff is collapsed.
package processor
import (
"github.com/ethereum-optimism/optimism/indexer/database"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
)
type L2ToL1MessagePasserMessagePassed struct {
*bindings.L2ToL1MessagePasserMessagePassed
RawEvent *database.ContractEvent
}
func L2ToL1MessagePasserMessagesPassed(events *ProcessedContractEvents) ([]L2ToL1MessagePasserMessagePassed, error) {
l2ToL1MessagePasserAbi, err := bindings.L2ToL1MessagePasserMetaData.GetAbi()
if err != nil {
return nil, err
}
eventName := "MessagePassed"
processedMessagePassedEvents := events.eventsBySignature[l2ToL1MessagePasserAbi.Events[eventName].ID]
messagesPassed := make([]L2ToL1MessagePasserMessagePassed, len(processedMessagePassedEvents))
for i, messagePassedEvent := range processedMessagePassedEvents {
log := messagePassedEvent.GethLog
var messagePassed bindings.L2ToL1MessagePasserMessagePassed
messagePassed.Raw = *log
err := UnpackLog(&messagePassed, log, eventName, l2ToL1MessagePasserAbi)
if err != nil {
return nil, err
}
messagesPassed[i] = L2ToL1MessagePasserMessagePassed{
L2ToL1MessagePasserMessagePassed: &messagePassed,
RawEvent: messagePassedEvent,
}
}
return messagesPassed, nil
}
package processor
import (
"context"
"errors"
"math/big"
"github.com/ethereum-optimism/optimism/indexer/database"
"github.com/ethereum-optimism/optimism/op-bindings/bindings"
"github.com/ethereum-optimism/optimism/op-node/rollup/derive"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/core/types"
)
type OptimismPortalTransactionDepositEvent struct {
*bindings.OptimismPortalTransactionDeposited
DepositTx *types.DepositTx
RawEvent *database.ContractEvent
}
type OptimismPortalWithdrawalProvenEvent struct {
*bindings.OptimismPortalWithdrawalProven
RawEvent *database.ContractEvent
}
type OptimismPortalWithdrawalFinalizedEvent struct {
*bindings.OptimismPortalWithdrawalFinalized
RawEvent *database.ContractEvent
}
......@@ -24,6 +33,44 @@ type OptimismPortalProvenWithdrawal struct {
L2OutputIndex *big.Int
}
func OptimismPortalTransactionDepositEvents(events *ProcessedContractEvents) ([]OptimismPortalTransactionDepositEvent, error) {
optimismPortalAbi, err := bindings.OptimismPortalMetaData.GetAbi()
if err != nil {
return nil, err
}
eventName := "TransactionDeposited"
if optimismPortalAbi.Events[eventName].ID != derive.DepositEventABIHash {
return nil, errors.New("op-node deposit event abi hash & optimism portal tx deposit mismatch")
}
processedTxDepositedEvents := events.eventsBySignature[derive.DepositEventABIHash]
txDeposits := make([]OptimismPortalTransactionDepositEvent, len(processedTxDepositedEvents))
for i, txDepositEvent := range processedTxDepositedEvents {
log := txDepositEvent.GethLog
depositTx, err := derive.UnmarshalDepositLogEvent(log)
if err != nil {
return nil, err
}
var txDeposit bindings.OptimismPortalTransactionDeposited
txDeposit.Raw = *log
err = UnpackLog(&txDeposit, log, eventName, optimismPortalAbi)
if err != nil {
return nil, err
}
txDeposits[i] = OptimismPortalTransactionDepositEvent{
OptimismPortalTransactionDeposited: &txDeposit,
DepositTx: depositTx,
RawEvent: txDepositEvent,
}
}
return txDeposits, nil
}
func OptimismPortalWithdrawalProvenEvents(events *ProcessedContractEvents) ([]OptimismPortalWithdrawalProvenEvent, error) {
optimismPortalAbi, err := bindings.OptimismPortalMetaData.GetAbi()
if err != nil {
......@@ -31,48 +78,50 @@ func OptimismPortalWithdrawalProvenEvents(events *ProcessedContractEvents) ([]Op
}
eventName := "WithdrawalProven"
processedWithdrawalProvenEvents := events.eventsBySignature[optimismPortalAbi.Events[eventName].ID]
provenEvents := make([]OptimismPortalWithdrawalProvenEvent, len(processedWithdrawalProvenEvents))
for i, provenEvent := range processedWithdrawalProvenEvents {
log := events.eventLog[provenEvent.GUID]
log := provenEvent.GethLog
var withdrawalProven bindings.OptimismPortalWithdrawalProven
withdrawalProven.Raw = *log
err := UnpackLog(&withdrawalProven, log, eventName, optimismPortalAbi)
if err != nil {
return nil, err
}
provenEvents[i] = OptimismPortalWithdrawalProvenEvent{&withdrawalProven, provenEvent}
provenEvents[i] = OptimismPortalWithdrawalProvenEvent{
OptimismPortalWithdrawalProven: &withdrawalProven,
RawEvent: provenEvent,
}
}
return provenEvents, nil
}
func OptimismPortalQueryProvenWithdrawal(ethClient *ethclient.Client, portalAddress common.Address, withdrawalHash common.Hash) (OptimismPortalProvenWithdrawal, error) {
var provenWithdrawal OptimismPortalProvenWithdrawal
func OptimismPortalWithdrawalFinalizedEvents(events *ProcessedContractEvents) ([]OptimismPortalWithdrawalFinalizedEvent, error) {
optimismPortalAbi, err := bindings.OptimismPortalMetaData.GetAbi()
if err != nil {
return provenWithdrawal, err
return nil, err
}
name := "provenWithdrawals"
txData, err := optimismPortalAbi.Pack(name, withdrawalHash)
if err != nil {
return provenWithdrawal, err
}
eventName := "WithdrawalFinalized"
processedWithdrawalFinalizedEvents := events.eventsBySignature[optimismPortalAbi.Events[eventName].ID]
finalizedEvents := make([]OptimismPortalWithdrawalFinalizedEvent, len(processedWithdrawalFinalizedEvents))
for i, finalizedEvent := range processedWithdrawalFinalizedEvents {
log := finalizedEvent.GethLog
callMsg := ethereum.CallMsg{To: &portalAddress, Data: txData}
data, err := ethClient.CallContract(context.Background(), callMsg, nil)
if err != nil {
return provenWithdrawal, err
}
var withdrawalFinalized bindings.OptimismPortalWithdrawalFinalized
err := UnpackLog(&withdrawalFinalized, log, eventName, optimismPortalAbi)
if err != nil {
return nil, err
}
err = optimismPortalAbi.UnpackIntoInterface(&provenWithdrawal, name, data)
if err != nil {
return provenWithdrawal, err
finalizedEvents[i] = OptimismPortalWithdrawalFinalizedEvent{
OptimismPortalWithdrawalFinalized: &withdrawalFinalized,
RawEvent: finalizedEvent,
}
}
return provenWithdrawal, nil
return finalizedEvents, nil
}
......@@ -97,7 +97,7 @@ func _standardBridgeInitiatedEvents[BridgeEvent bindings.StandardBridgeETHBridge
processedInitiatedBridgeEvents := events.eventsBySignature[StandardBridgeABI.Events[eventName].ID]
initiatedBridgeEvents := make([]StandardBridgeInitiatedEvent, len(processedInitiatedBridgeEvents))
for i, bridgeInitiatedEvent := range processedInitiatedBridgeEvents {
log := events.eventLog[bridgeInitiatedEvent.GUID]
log := bridgeInitiatedEvent.GethLog
var bridgeData BridgeEvent
err := UnpackLog(&bridgeData, log, eventName, StandardBridgeABI)
......@@ -109,7 +109,8 @@ func _standardBridgeInitiatedEvents[BridgeEvent bindings.StandardBridgeETHBridge
// - L1: BridgeInitiated -> Portal#DepositTransaction -> SentMessage ...
// - L1: BridgeInitiated -> L2ToL1MessagePasser#MessagePassed -> SentMessage ...
var sentMsgData bindings.L1CrossDomainMessengerSentMessage
sentMsgLog := events.eventLog[events.eventByLogIndex[ProcessedContractEventLogIndexKey{log.BlockHash, log.Index + 2}].GUID]
sentMsgLog := events.eventByLogIndex[ProcessedContractEventLogIndexKey{log.BlockHash, log.Index + 2}].GethLog
sentMsgData.Raw = *sentMsgLog
err = UnpackLog(&sentMsgData, sentMsgLog, sentMessageEventAbi.Name, l1CrossDomainMessengerABI)
if err != nil {
return nil, err
......@@ -127,6 +128,7 @@ func _standardBridgeInitiatedEvents[BridgeEvent bindings.StandardBridgeETHBridge
// represent eth bridge as an erc20
erc20BridgeData = &bindings.StandardBridgeERC20BridgeInitiated{
Raw: *log,
// Represent ETH using the hardcoded address
LocalToken: predeploys.LegacyERC20ETHAddr, RemoteToken: predeploys.LegacyERC20ETHAddr,
// Bridge data
......@@ -136,6 +138,7 @@ func _standardBridgeInitiatedEvents[BridgeEvent bindings.StandardBridgeETHBridge
case bindings.StandardBridgeERC20BridgeInitiated:
_temp := any(bridgeData).(bindings.StandardBridgeERC20BridgeInitiated)
erc20BridgeData = &_temp
erc20BridgeData.Raw = *log
expectedCrossDomainMessage, err = StandardBridgeABI.Pack(finalizeMethodName, erc20BridgeData.RemoteToken, erc20BridgeData.LocalToken, erc20BridgeData.From, erc20BridgeData.To, erc20BridgeData.Amount, erc20BridgeData.ExtraData)
if err != nil {
return nil, err
......@@ -146,7 +149,11 @@ func _standardBridgeInitiatedEvents[BridgeEvent bindings.StandardBridgeETHBridge
return nil, errors.New("bridge cross domain message mismatch")
}
initiatedBridgeEvents[i] = StandardBridgeInitiatedEvent{erc20BridgeData, sentMsgData.MessageNonce, bridgeInitiatedEvent}
initiatedBridgeEvents[i] = StandardBridgeInitiatedEvent{
StandardBridgeERC20BridgeInitiated: erc20BridgeData,
CrossDomainMessengerNonce: sentMsgData.MessageNonce,
RawEvent: bridgeInitiatedEvent,
}
}
return initiatedBridgeEvents, nil
......@@ -190,7 +197,7 @@ func _standardBridgeFinalizedEvents[BridgeEvent bindings.StandardBridgeETHBridge
processedFinalizedBridgeEvents := events.eventsBySignature[StandardBridgeABI.Events[eventName].ID]
finalizedBridgeEvents := make([]StandardBridgeFinalizedEvent, len(processedFinalizedBridgeEvents))
for i, bridgeFinalizedEvent := range processedFinalizedBridgeEvents {
log := events.eventLog[bridgeFinalizedEvent.GUID]
log := bridgeFinalizedEvent.GethLog
var bridgeData BridgeEvent
err := UnpackLog(&bridgeData, log, eventName, StandardBridgeABI)
......@@ -199,7 +206,7 @@ func _standardBridgeFinalizedEvents[BridgeEvent bindings.StandardBridgeETHBridge
}
// Look for the RelayedMessage event that follows right after the BridgeFinalized Event
relayedMsgLog := events.eventLog[events.eventByLogIndex[ProcessedContractEventLogIndexKey{log.BlockHash, log.Index + 1}].GUID]
relayedMsgLog := events.eventByLogIndex[ProcessedContractEventLogIndexKey{log.BlockHash, log.Index + 1}].GethLog
if relayedMsgLog.Topics[0] != relayedMessageEventAbi.ID {
return nil, errors.New("unexpected bridge event ordering")
}
......@@ -257,6 +264,7 @@ func _standardBridgeFinalizedEvents[BridgeEvent bindings.StandardBridgeETHBridge
case bindings.StandardBridgeETHBridgeFinalized:
ethBridgeData := any(bridgeData).(bindings.StandardBridgeETHBridgeFinalized)
erc20BridgeData = &bindings.StandardBridgeERC20BridgeFinalized{
Raw: *log,
// Represent ETH using the hardcoded address
LocalToken: predeploys.LegacyERC20ETHAddr, RemoteToken: predeploys.LegacyERC20ETHAddr,
// Bridge data
......@@ -266,9 +274,14 @@ func _standardBridgeFinalizedEvents[BridgeEvent bindings.StandardBridgeETHBridge
case bindings.StandardBridgeERC20BridgeFinalized:
_temp := any(bridgeData).(bindings.StandardBridgeERC20BridgeFinalized)
erc20BridgeData = &_temp
erc20BridgeData.Raw = *log
}
finalizedBridgeEvents[i] = StandardBridgeFinalizedEvent{erc20BridgeData, nonce, bridgeFinalizedEvent}
finalizedBridgeEvents[i] = StandardBridgeFinalizedEvent{
StandardBridgeERC20BridgeFinalized: erc20BridgeData,
CrossDomainMessengerNonce: nonce,
RawEvent: bridgeFinalizedEvent,
}
}
return finalizedBridgeEvents, nil
......
......@@ -28,11 +28,8 @@ func (e *EthBridge) GetDepositsByBlockRange(ctx context.Context, start, end uint
End: &end,
}
var iter *bindings.L1StandardBridgeETHDepositInitiatedIterator
err := backoff.Do(3, backoff.Exponential(), func() error {
var err error
iter, err = e.contract.FilterETHDepositInitiated(opts, nil, nil)
return err
iter, err := backoff.Do(ctx, 3, backoff.Exponential(), func() (*bindings.L1StandardBridgeETHDepositInitiatedIterator, error) {
return e.contract.FilterETHDepositInitiated(opts, nil, nil)
})
if err != nil {
return nil, err
......
......@@ -37,11 +37,8 @@ func (p *Portal) GetProvenWithdrawalsByBlockRange(ctx context.Context, start, en
End: &end,
}
var iter *bindings.OptimismPortalWithdrawalProvenIterator
err := backoff.Do(3, backoff.Exponential(), func() error {
var err error
iter, err = p.contract.FilterWithdrawalProven(opts, nil, nil, nil)
return err
iter, err := backoff.Do(ctx, 3, backoff.Exponential(), func() (*bindings.OptimismPortalWithdrawalProvenIterator, error) {
return p.contract.FilterWithdrawalProven(opts, nil, nil, nil)
})
if err != nil {
return nil, err
......@@ -71,11 +68,8 @@ func (p *Portal) GetFinalizedWithdrawalsByBlockRange(ctx context.Context, start,
End: &end,
}
var iter *bindings.OptimismPortalWithdrawalFinalizedIterator
err := backoff.Do(3, backoff.Exponential(), func() error {
var err error
iter, err = p.contract.FilterWithdrawalFinalized(opts, nil)
return err
iter, err := backoff.Do(ctx, 3, backoff.Exponential(), func() (*bindings.OptimismPortalWithdrawalFinalizedIterator, error) {
return p.contract.FilterWithdrawalFinalized(opts, nil)
})
if err != nil {
return nil, err
......
......@@ -28,11 +28,8 @@ func (s *StandardBridge) GetDepositsByBlockRange(ctx context.Context, start, end
End: &end,
}
var iter *bindings.L1StandardBridgeERC20DepositInitiatedIterator
err := backoff.Do(3, backoff.Exponential(), func() error {
var err error
iter, err = s.contract.FilterERC20DepositInitiated(opts, nil, nil, nil)
return err
iter, err := backoff.Do(ctx, 3, backoff.Exponential(), func() (*bindings.L1StandardBridgeERC20DepositInitiatedIterator, error) {
return s.contract.FilterERC20DepositInitiated(opts, nil, nil, nil)
})
if err != nil {
return nil, err
......
......@@ -35,11 +35,8 @@ func (s *StandardBridge) GetWithdrawalsByBlockRange(ctx context.Context, start,
End: &end,
}
var iter *bindings.L2StandardBridgeWithdrawalInitiatedIterator
err := backoff.Do(3, backoff.Exponential(), func() error {
var err error
iter, err = s.l2SB.FilterWithdrawalInitiated(opts, nil, nil, nil)
return err
iter, err := backoff.Do(ctx, 3, backoff.Exponential(), func() (*bindings.L2StandardBridgeWithdrawalInitiatedIterator, error) {
return s.l2SB.FilterWithdrawalInitiated(opts, nil, nil, nil)
})
if err != nil {
return nil, err
......
......@@ -10,11 +10,7 @@ import (
// HeaderByNumberWithRetry retries getting headers.
func HeaderByNumberWithRetry(ctx context.Context, client *ethclient.Client) (*types.Header, error) {
var res *types.Header
err := backoff.DoCtx(ctx, 3, backoff.Exponential(), func() error {
var err error
res, err = client.HeaderByNumber(ctx, nil)
return err
return backoff.Do(ctx, 3, backoff.Exponential(), func() (*types.Header, error) {
return client.HeaderByNumber(ctx, nil)
})
return res, err
}
......@@ -50,17 +50,17 @@ func NewBatchSubmitterFromCLIConfig(cfg CLIConfig, l log.Logger, m metrics.Metri
// Connect to L1 and L2 providers. Perform these last since they are the
// most expensive.
l1Client, err := opclient.DialEthClientWithTimeout(ctx, cfg.L1EthRpc, opclient.DefaultDialTimeout)
l1Client, err := opclient.DialEthClientWithTimeout(opclient.DefaultDialTimeout, l, cfg.L1EthRpc)
if err != nil {
return nil, err
}
l2Client, err := opclient.DialEthClientWithTimeout(ctx, cfg.L2EthRpc, opclient.DefaultDialTimeout)
l2Client, err := opclient.DialEthClientWithTimeout(opclient.DefaultDialTimeout, l, cfg.L2EthRpc)
if err != nil {
return nil, err
}
rollupClient, err := opclient.DialRollupClientWithTimeout(ctx, cfg.RollupRpc, opclient.DefaultDialTimeout)
rollupClient, err := opclient.DialRollupClientWithTimeout(opclient.DefaultDialTimeout, l, cfg.RollupRpc)
if err != nil {
return nil, err
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -31,7 +31,7 @@ var (
// L1BlockNumberMetaData contains all meta data concerning the L1BlockNumber contract.
var L1BlockNumberMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"stateMutability\":\"payable\",\"type\":\"fallback\"},{\"inputs\":[],\"name\":\"getL1BlockNumber\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"stateMutability\":\"payable\",\"type\":\"receive\"}]",
Bin: "0x60e060405234801561001057600080fd5b5060016080819052600060a081905260c08290528161059461004a8339600061018d015260006101640152600061013b01526105946000f3fe60806040526004361061002d5760003560e01c806354fd4d5014610052578063b9b3efe91461007d57610048565b3661004857600061003c6100a0565b90508060005260206000f35b600061003c6100a0565b34801561005e57600080fd5b50610067610134565b6040516100749190610344565b60405180910390f35b34801561008957600080fd5b506100926100a0565b604051908152602001610074565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638381f58a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610101573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101259190610395565b67ffffffffffffffff16905090565b606061015f7f00000000000000000000000000000000000000000000000000000000000000006101d7565b6101887f00000000000000000000000000000000000000000000000000000000000000006101d7565b6101b17f00000000000000000000000000000000000000000000000000000000000000006101d7565b6040516020016101c3939291906103c6565b604051602081830303815290604052905090565b60608160000361021a57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610244578061022e8161046b565b915061023d9050600a836104d2565b915061021e565b60008167ffffffffffffffff81111561025f5761025f6104e6565b6040519080825280601f01601f191660200182016040528015610289576020820181803683370190505b5090505b841561030c5761029e600183610515565b91506102ab600a8661052c565b6102b6906030610540565b60f81b8183815181106102cb576102cb610558565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610305600a866104d2565b945061028d565b949350505050565b60005b8381101561032f578181015183820152602001610317565b8381111561033e576000848401525b50505050565b6020815260008251806020840152610363816040850160208701610314565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000602082840312156103a757600080fd5b815167ffffffffffffffff811681146103bf57600080fd5b9392505050565b600084516103d8818460208901610314565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610414816001850160208a01610314565b6001920191820152835161042f816002840160208801610314565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361049c5761049c61043c565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826104e1576104e16104a3565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156105275761052761043c565b500390565b60008261053b5761053b6104a3565b500690565b600082198211156105535761055361043c565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a",
Bin: "0x60e060405234801561001057600080fd5b506001608052600060a052600260c05260805160a05160c05161059461004f600039600061018d015260006101640152600061013b01526105946000f3fe60806040526004361061002d5760003560e01c806354fd4d5014610052578063b9b3efe91461007d57610048565b3661004857600061003c6100a0565b90508060005260206000f35b600061003c6100a0565b34801561005e57600080fd5b50610067610134565b6040516100749190610344565b60405180910390f35b34801561008957600080fd5b506100926100a0565b604051908152602001610074565b600073420000000000000000000000000000000000001573ffffffffffffffffffffffffffffffffffffffff16638381f58a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610101573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101259190610395565b67ffffffffffffffff16905090565b606061015f7f00000000000000000000000000000000000000000000000000000000000000006101d7565b6101887f00000000000000000000000000000000000000000000000000000000000000006101d7565b6101b17f00000000000000000000000000000000000000000000000000000000000000006101d7565b6040516020016101c3939291906103c6565b604051602081830303815290604052905090565b60608160000361021a57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115610244578061022e8161046b565b915061023d9050600a836104d2565b915061021e565b60008167ffffffffffffffff81111561025f5761025f6104e6565b6040519080825280601f01601f191660200182016040528015610289576020820181803683370190505b5090505b841561030c5761029e600183610515565b91506102ab600a8661052c565b6102b6906030610540565b60f81b8183815181106102cb576102cb610558565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610305600a866104d2565b945061028d565b949350505050565b60005b8381101561032f578181015183820152602001610317565b8381111561033e576000848401525b50505050565b6020815260008251806020840152610363816040850160208701610314565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000602082840312156103a757600080fd5b815167ffffffffffffffff811681146103bf57600080fd5b9392505050565b600084516103d8818460208901610314565b80830190507f2e000000000000000000000000000000000000000000000000000000000000008082528551610414816001850160208a01610314565b6001920191820152835161042f816002840160208801610314565b0160020195945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361049c5761049c61043c565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826104e1576104e16104a3565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000828210156105275761052761043c565b500390565b60008261053b5761053b6104a3565b500690565b600082198211156105535761055361043c565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a",
}
// L1BlockNumberABI is the input ABI used to generate the binding from.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -31,7 +31,7 @@ var (
// LegacyMessagePasserMetaData contains all meta data concerning the LegacyMessagePasser contract.
var LegacyMessagePasserMetaData = &bind.MetaData{
ABI: "[{\"inputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_message\",\"type\":\"bytes\"}],\"name\":\"passMessageToL1\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"sentMessages\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}]",
Bin: "0x60e060405234801561001057600080fd5b5060016080819052600060a081905260c082905281610698610048833960006101050152600060dc0152600060b301526106986000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d501461004657806382e3702d14610064578063cafa81dc14610097575b600080fd5b61004e6100ac565b60405161005b9190610347565b60405180910390f35b610087610072366004610398565b60006020819052908152604090205460ff1681565b604051901515815260200161005b565b6100aa6100a53660046103e0565b61014f565b005b60606100d77f00000000000000000000000000000000000000000000000000000000000000006101da565b6101007f00000000000000000000000000000000000000000000000000000000000000006101da565b6101297f00000000000000000000000000000000000000000000000000000000000000006101da565b60405160200161013b939291906104af565b604051602081830303815290604052905090565b60016000808333604051602001610167929190610525565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291815281516020928301208352908201929092520160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905550565b60608160000361021d57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561024757806102318161059e565b91506102409050600a83610605565b9150610221565b60008167ffffffffffffffff811115610262576102626103b1565b6040519080825280601f01601f19166020018201604052801561028c576020820181803683370190505b5090505b841561030f576102a1600183610619565b91506102ae600a86610630565b6102b9906030610644565b60f81b8183815181106102ce576102ce61065c565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610308600a86610605565b9450610290565b949350505050565b60005b8381101561033257818101518382015260200161031a565b83811115610341576000848401525b50505050565b6020815260008251806020840152610366816040850160208701610317565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000602082840312156103aa57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156103f257600080fd5b813567ffffffffffffffff8082111561040a57600080fd5b818401915084601f83011261041e57600080fd5b813581811115610430576104306103b1565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610476576104766103b1565b8160405282815287602084870101111561048f57600080fd5b826020860160208301376000928101602001929092525095945050505050565b600084516104c1818460208901610317565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516104fd816001850160208a01610317565b60019201918201528351610518816002840160208801610317565b0160020195945050505050565b60008351610537818460208801610317565b60609390931b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169190920190815260140192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036105cf576105cf61056f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610614576106146105d6565b500490565b60008282101561062b5761062b61056f565b500390565b60008261063f5761063f6105d6565b500690565b600082198211156106575761065761056f565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a",
Bin: "0x60e060405234801561001057600080fd5b506001608052600060a052600260c05260805160a05160c05161069861004d60003960006101050152600060dc0152600060b301526106986000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806354fd4d501461004657806382e3702d14610064578063cafa81dc14610097575b600080fd5b61004e6100ac565b60405161005b9190610347565b60405180910390f35b610087610072366004610398565b60006020819052908152604090205460ff1681565b604051901515815260200161005b565b6100aa6100a53660046103e0565b61014f565b005b60606100d77f00000000000000000000000000000000000000000000000000000000000000006101da565b6101007f00000000000000000000000000000000000000000000000000000000000000006101da565b6101297f00000000000000000000000000000000000000000000000000000000000000006101da565b60405160200161013b939291906104af565b604051602081830303815290604052905090565b60016000808333604051602001610167929190610525565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe001815291815281516020928301208352908201929092520160002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001691151591909117905550565b60608160000361021d57505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b811561024757806102318161059e565b91506102409050600a83610605565b9150610221565b60008167ffffffffffffffff811115610262576102626103b1565b6040519080825280601f01601f19166020018201604052801561028c576020820181803683370190505b5090505b841561030f576102a1600183610619565b91506102ae600a86610630565b6102b9906030610644565b60f81b8183815181106102ce576102ce61065c565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350610308600a86610605565b9450610290565b949350505050565b60005b8381101561033257818101518382015260200161031a565b83811115610341576000848401525b50505050565b6020815260008251806020840152610366816040850160208701610317565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b6000602082840312156103aa57600080fd5b5035919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156103f257600080fd5b813567ffffffffffffffff8082111561040a57600080fd5b818401915084601f83011261041e57600080fd5b813581811115610430576104306103b1565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715610476576104766103b1565b8160405282815287602084870101111561048f57600080fd5b826020860160208301376000928101602001929092525095945050505050565b600084516104c1818460208901610317565b80830190507f2e0000000000000000000000000000000000000000000000000000000000000080825285516104fd816001850160208a01610317565b60019201918201528351610518816002840160208801610317565b0160020195945050505050565b60008351610537818460208801610317565b60609390931b7fffffffffffffffffffffffffffffffffffffffff000000000000000000000000169190920190815260140192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036105cf576105cf61056f565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082610614576106146105d6565b500490565b60008282101561062b5761062b61056f565b500390565b60008261063f5761063f6105d6565b500690565b600082198211156106575761065761056f565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea164736f6c634300080f000a",
}
// LegacyMessagePasserABI is the input ABI used to generate the binding from.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -9,7 +9,7 @@ import (
"github.com/ethereum-optimism/optimism/op-bindings/solc"
)
const StandardBridgeStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src/universal/StandardBridge.sol:StandardBridge\",\"label\":\"spacer_0_0_20\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":1001,\"contract\":\"src/universal/StandardBridge.sol:StandardBridge\",\"label\":\"spacer_1_0_20\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_address\"},{\"astId\":1002,\"contract\":\"src/universal/StandardBridge.sol:StandardBridge\",\"label\":\"deposits\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"},{\"astId\":1003,\"contract\":\"src/universal/StandardBridge.sol:StandardBridge\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_array(t_uint256)47_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)47_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[47]\",\"numberOfBytes\":\"1504\",\"base\":\"t_uint256\"},\"t_mapping(t_address,t_mapping(t_address,t_uint256))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(address =\u003e uint256))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_address,t_uint256)\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"}}}"
const StandardBridgeStorageLayoutJSON = "{\"storage\":[{\"astId\":1000,\"contract\":\"src/universal/StandardBridge.sol:StandardBridge\",\"label\":\"_initialized\",\"offset\":0,\"slot\":\"0\",\"type\":\"t_uint8\"},{\"astId\":1001,\"contract\":\"src/universal/StandardBridge.sol:StandardBridge\",\"label\":\"_initializing\",\"offset\":1,\"slot\":\"0\",\"type\":\"t_bool\"},{\"astId\":1002,\"contract\":\"src/universal/StandardBridge.sol:StandardBridge\",\"label\":\"spacer_0_2_20\",\"offset\":2,\"slot\":\"0\",\"type\":\"t_address\"},{\"astId\":1003,\"contract\":\"src/universal/StandardBridge.sol:StandardBridge\",\"label\":\"spacer_1_0_20\",\"offset\":0,\"slot\":\"1\",\"type\":\"t_address\"},{\"astId\":1004,\"contract\":\"src/universal/StandardBridge.sol:StandardBridge\",\"label\":\"deposits\",\"offset\":0,\"slot\":\"2\",\"type\":\"t_mapping(t_address,t_mapping(t_address,t_uint256))\"},{\"astId\":1005,\"contract\":\"src/universal/StandardBridge.sol:StandardBridge\",\"label\":\"messenger\",\"offset\":0,\"slot\":\"3\",\"type\":\"t_contract(CrossDomainMessenger)1007\"},{\"astId\":1006,\"contract\":\"src/universal/StandardBridge.sol:StandardBridge\",\"label\":\"__gap\",\"offset\":0,\"slot\":\"4\",\"type\":\"t_array(t_uint256)46_storage\"}],\"types\":{\"t_address\":{\"encoding\":\"inplace\",\"label\":\"address\",\"numberOfBytes\":\"20\"},\"t_array(t_uint256)46_storage\":{\"encoding\":\"inplace\",\"label\":\"uint256[46]\",\"numberOfBytes\":\"1472\",\"base\":\"t_uint256\"},\"t_bool\":{\"encoding\":\"inplace\",\"label\":\"bool\",\"numberOfBytes\":\"1\"},\"t_contract(CrossDomainMessenger)1007\":{\"encoding\":\"inplace\",\"label\":\"contract CrossDomainMessenger\",\"numberOfBytes\":\"20\"},\"t_mapping(t_address,t_mapping(t_address,t_uint256))\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e mapping(address =\u003e uint256))\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_mapping(t_address,t_uint256)\"},\"t_mapping(t_address,t_uint256)\":{\"encoding\":\"mapping\",\"label\":\"mapping(address =\u003e uint256)\",\"numberOfBytes\":\"32\",\"key\":\"t_address\",\"value\":\"t_uint256\"},\"t_uint256\":{\"encoding\":\"inplace\",\"label\":\"uint256\",\"numberOfBytes\":\"32\"},\"t_uint8\":{\"encoding\":\"inplace\",\"label\":\"uint8\",\"numberOfBytes\":\"1\"}}}"
var StandardBridgeStorageLayout = new(solc.StorageLayout)
......
This diff is collapsed.
This diff is collapsed.
......@@ -64,6 +64,15 @@ func (s *StorageLayout) GetStorageLayoutEntry(name string) (StorageLayoutEntry,
return StorageLayoutEntry{}, fmt.Errorf("%s not found", name)
}
// GetStorageLayoutType returns the StorageLayoutType where the label matches
// the provided name.
func (s *StorageLayout) GetStorageLayoutType(name string) (StorageLayoutType, error) {
if ty, ok := s.Types[name]; ok {
return ty, nil
}
return StorageLayoutType{}, fmt.Errorf("%s not found", name)
}
type StorageLayoutEntry struct {
AstId uint `json:"astId"`
Contract string `json:"contract"`
......
This diff is collapsed.
......@@ -656,6 +656,11 @@ func NewL2StorageConfig(config *DeployConfig, block *types.Block) (state.Storage
"xDomainMsgSender": "0x000000000000000000000000000000000000dEaD",
"msgNonce": 0,
}
storage["L2StandardBridge"] = state.StorageValues{
"_initialized": 2,
"_initializing": false,
"messenger": predeploys.L2CrossDomainMessengerAddr,
}
storage["L1Block"] = state.StorageValues{
"number": block.Number(),
"timestamp": block.Time(),
......@@ -685,6 +690,11 @@ func NewL2StorageConfig(config *DeployConfig, block *types.Block) (state.Storage
storage["ProxyAdmin"] = state.StorageValues{
"_owner": config.ProxyAdminOwner,
}
storage["L2ERC721Bridge"] = state.StorageValues{
"messenger": predeploys.L2CrossDomainMessengerAddr,
"_initialized": 2,
"_initializing": false,
}
return storage, nil
}
......
......@@ -131,7 +131,6 @@ func BuildOptimism(immutable ImmutableConfig) (DeploymentResults, error) {
{
Name: "L2ERC721Bridge",
Args: []interface{}{
predeploys.L2CrossDomainMessengerAddr,
immutable["L2ERC721Bridge"]["otherBridge"],
},
},
......@@ -225,16 +224,11 @@ func l2Deployer(backend *backends.SimulatedBackend, opts *bind.TransactOpts, dep
case "L1BlockNumber":
_, tx, _, err = bindings.DeployL1BlockNumber(opts, backend)
case "L2ERC721Bridge":
// TODO(tynes): messenger should be hardcoded in the contract
messenger, ok := deployment.Args[0].(common.Address)
if !ok {
return nil, fmt.Errorf("invalid type for messenger")
}
otherBridge, ok := deployment.Args[1].(common.Address)
otherBridge, ok := deployment.Args[0].(common.Address)
if !ok {
return nil, fmt.Errorf("invalid type for otherBridge")
}
_, tx, _, err = bindings.DeployL2ERC721Bridge(opts, backend, messenger, otherBridge)
_, tx, _, err = bindings.DeployL2ERC721Bridge(opts, backend, otherBridge)
case "OptimismMintableERC721Factory":
bridge, ok := deployment.Args[0].(common.Address)
if !ok {
......
......@@ -52,7 +52,11 @@ func TestCode(t *testing.T) {
db.SetCode(addr, code)
post := db.GetCode(addr)
require.Equal(t, post, code)
if len(code) == 0 {
require.Nil(t, post)
} else {
require.Equal(t, post, code)
}
size := db.GetCodeSize(addr)
require.Equal(t, size, len(code))
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -134,23 +134,19 @@ func (a *Agent) step(ctx context.Context, claim types.Claim, game types.Game) er
return nil
}
oracleData, err := a.solver.GetOracleData(ctx, claim)
if err != nil {
a.log.Debug("Failed to get oracle data", "err", err)
return nil
}
a.log.Info("Updating oracle data", "oracleKey", oracleData.OracleKey, "oracleData", oracleData.OracleData)
if err := a.updater.UpdateOracle(ctx, *oracleData); err != nil {
return fmt.Errorf("failed to load oracle data: %w", err)
}
a.log.Info("Attempting step", "claim_depth", claim.Depth(), "maxDepth", a.maxDepth)
step, err := a.solver.AttemptStep(ctx, claim, agreeWithClaimLevel)
if err != nil {
return fmt.Errorf("attempt step: %w", err)
}
if step.OracleData != nil {
a.log.Info("Updating oracle data", "oracleKey", step.OracleData.OracleKey, "oracleData", step.OracleData.OracleData)
if err := a.updater.UpdateOracle(ctx, step.OracleData); err != nil {
return fmt.Errorf("failed to load oracle data: %w", err)
}
}
a.log.Info("Performing step", "is_attack", step.IsAttack,
"depth", step.LeafClaim.Depth(), "index_at_depth", step.LeafClaim.IndexAtDepth(), "value", step.LeafClaim.Value)
callData := types.StepCallData{
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -74,7 +74,8 @@ func newTestCannonUpdater(t *testing.T, sendFails bool) (*cannonUpdater, *mockTx
func TestCannonUpdater_UpdateOracle(t *testing.T) {
t.Run("succeeds", func(t *testing.T) {
updater, mockTxMgr := newTestCannonUpdater(t, false)
require.Nil(t, updater.UpdateOracle(context.Background(), types.PreimageOracleData{
require.NoError(t, updater.UpdateOracle(context.Background(), &types.PreimageOracleData{
OracleKey: common.Hash{0xaa}.Bytes(),
OracleData: common.Hex2Bytes("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"),
}))
require.Equal(t, 1, mockTxMgr.sends)
......@@ -82,7 +83,8 @@ func TestCannonUpdater_UpdateOracle(t *testing.T) {
t.Run("send fails", func(t *testing.T) {
updater, mockTxMgr := newTestCannonUpdater(t, true)
require.Error(t, updater.UpdateOracle(context.Background(), types.PreimageOracleData{
require.Error(t, updater.UpdateOracle(context.Background(), &types.PreimageOracleData{
OracleKey: common.Hash{0xaa}.Bytes(),
OracleData: common.Hex2Bytes("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"),
}))
require.Equal(t, 1, mockTxMgr.failedSends)
......@@ -93,7 +95,7 @@ func TestCannonUpdater_UpdateOracle(t *testing.T) {
// builds a valid tx candidate for a local oracle update.
func TestCannonUpdater_BuildLocalOracleData(t *testing.T) {
updater, _ := newTestCannonUpdater(t, false)
oracleData := types.PreimageOracleData{
oracleData := &types.PreimageOracleData{
OracleKey: common.Hex2Bytes("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
OracleData: common.Hex2Bytes("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"),
OracleOffset: 7,
......@@ -117,7 +119,7 @@ func TestCannonUpdater_BuildLocalOracleData(t *testing.T) {
// builds a valid tx candidate for a global oracle update.
func TestCannonUpdater_BuildGlobalOracleData(t *testing.T) {
updater, _ := newTestCannonUpdater(t, false)
oracleData := types.PreimageOracleData{
oracleData := &types.PreimageOracleData{
OracleKey: common.Hex2Bytes("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"),
OracleData: common.Hex2Bytes("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"),
OracleOffset: 7,
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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