Commit 71c1b929 authored by mergify[bot]'s avatar mergify[bot] Committed by GitHub

Merge branch 'develop' into dependabot/npm_and_yarn/nrwl/nx-cloud-16.3.0

parents 56e29726 9c92d049
......@@ -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),
}
}
......
......@@ -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,
}
}
......
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())
}
})
}
......@@ -7,18 +7,25 @@ CREATE DOMAIN UINT256 AS NUMERIC
*/
CREATE TABLE IF NOT EXISTS l1_block_headers (
-- Searchable fields
hash VARCHAR NOT NULL PRIMARY KEY,
parent_hash VARCHAR NOT NULL,
number UINT256 NOT NULL,
timestamp INTEGER NOT NULL CHECK (timestamp > 0)
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 NOT NULL,
timestamp INTEGER NOT NULL CHECK (timestamp > 0)
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.
......
......@@ -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
}
......
......@@ -49,7 +49,7 @@ type CrossDomainMessengerRelayedMessageEvent struct {
}
func CrossDomainMessengerSentMessageEvents(events *ProcessedContractEvents) ([]CrossDomainMessengerSentMessageEvent, error) {
crossDomainMessengerABI, err := bindings.L1CrossDomainMessengerMetaData.GetAbi()
crossDomainMessengerABI, err := bindings.CrossDomainMessengerMetaData.GetAbi()
if err != nil {
return nil, err
}
......@@ -60,16 +60,18 @@ func CrossDomainMessengerSentMessageEvents(events *ProcessedContractEvents) ([]C
processedSentMessageEvents := events.eventsBySignature[sentMessageEventAbi.ID]
crossDomainMessageEvents := make([]CrossDomainMessengerSentMessageEvent, len(processedSentMessageEvents))
for i, sentMessageEvent := range processedSentMessageEvents {
log := events.eventLog[sentMessageEvent.GUID]
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.eventLog[events.eventByLogIndex[ProcessedContractEventLogIndexKey{log.BlockHash, log.Index + 1}].GUID]
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
......@@ -101,15 +103,19 @@ func CrossDomainMessengerRelayedMessageEvents(events *ProcessedContractEvents) (
processedRelayedMessageEvents := events.eventsBySignature[relayedMessageEventAbi.ID]
crossDomainMessageEvents := make([]CrossDomainMessengerRelayedMessageEvent, len(processedRelayedMessageEvents))
for i, relayedMessageEvent := range processedRelayedMessageEvents {
log := events.eventLog[relayedMessageEvent.GUID]
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{&relayedMsgData, relayedMessageEvent}
crossDomainMessageEvents[i] = CrossDomainMessengerRelayedMessageEvent{
CrossDomainMessengerRelayedMessage: &relayedMsgData,
RawEvent: relayedMessageEvent,
}
}
return crossDomainMessageEvents, nil
......
......@@ -399,10 +399,10 @@ func l1ProcessContractEventsBridgeCrossDomainMessages(processLog log.Logger, db
sentMessages := make([]*database.L1BridgeMessage, len(sentMessageEvents))
for i, sentMessageEvent := range sentMessageEvents {
log := events.eventLog[sentMessageEvent.RawEvent.GUID]
log := sentMessageEvent.RawEvent.GethLog
// extract the deposit hash from the previous TransactionDepositedEvent
transactionDepositedLog := events.eventLog[events.eventByLogIndex[ProcessedContractEventLogIndexKey{log.BlockHash, log.Index - 1}].GUID]
transactionDepositedLog := events.eventByLogIndex[ProcessedContractEventLogIndexKey{log.BlockHash, log.Index - 1}].GethLog
depositTx, err := derive.UnmarshalDepositLogEvent(transactionDepositedLog)
if err != nil {
return err
......@@ -479,10 +479,10 @@ func l1ProcessContractEventsStandardBridge(processLog log.Logger, db *database.D
deposits := make([]*database.L1BridgeDeposit, len(initiatedDepositEvents))
for i, initiatedBridgeEvent := range initiatedDepositEvents {
log := events.eventLog[initiatedBridgeEvent.RawEvent.GUID]
log := initiatedBridgeEvent.RawEvent.GethLog
// extract the deposit hash from the following TransactionDeposited event
transactionDepositedLog := events.eventLog[events.eventByLogIndex[ProcessedContractEventLogIndexKey{log.BlockHash, log.Index + 1}].GUID]
transactionDepositedLog := events.eventByLogIndex[ProcessedContractEventLogIndexKey{log.BlockHash, log.Index + 1}].GethLog
depositTx, err := derive.UnmarshalDepositLogEvent(transactionDepositedLog)
if err != nil {
return err
......
......@@ -106,17 +106,8 @@ func l2ProcessFn(processLog log.Logger, ethClient node.EthClient, l2Contracts L2
l2Headers := make([]*database.L2BlockHeader, len(headers))
l2HeaderMap := make(map[common.Hash]*types.Header)
for i, header := range headers {
blockHash := header.Hash()
l2Headers[i] = &database.L2BlockHeader{
BlockHeader: database.BlockHeader{
Hash: blockHash,
ParentHash: header.ParentHash,
Number: database.U256{Int: header.Number},
Timestamp: header.Time,
},
}
l2HeaderMap[blockHash] = header
l2Headers[i] = &database.L2BlockHeader{BlockHeader: database.BlockHeaderFromGethHeader(header)}
l2HeaderMap[l2Headers[i].Hash] = header
}
/** Watch for Contract Events **/
......@@ -255,10 +246,10 @@ func l2ProcessContractEventsBridgeCrossDomainMessages(processLog log.Logger, db
sentMessages := make([]*database.L2BridgeMessage, len(sentMessageEvents))
for i, sentMessageEvent := range sentMessageEvents {
log := events.eventLog[sentMessageEvent.RawEvent.GUID]
log := sentMessageEvent.RawEvent.GethLog
// extract the withdrawal hash from the previous MessagePassed event
msgPassedLog := events.eventLog[events.eventByLogIndex[ProcessedContractEventLogIndexKey{log.BlockHash, log.Index - 1}].GUID]
msgPassedLog := events.eventByLogIndex[ProcessedContractEventLogIndexKey{log.BlockHash, log.Index - 1}].GethLog
msgPassedEvent, err := l2ToL1MessagePasserABI.ParseMessagePassed(*msgPassedLog)
if err != nil {
return err
......@@ -355,10 +346,10 @@ func l2ProcessContractEventsStandardBridge(processLog log.Logger, db *database.D
withdrawals := make([]*database.L2BridgeWithdrawal, len(initiatedWithdrawalEvents))
for i, initiatedBridgeEvent := range initiatedWithdrawalEvents {
log := events.eventLog[initiatedBridgeEvent.RawEvent.GUID]
log := initiatedBridgeEvent.RawEvent.GethLog
// extract the withdrawal hash from the following MessagePassed event
msgPassedLog := events.eventLog[events.eventByLogIndex[ProcessedContractEventLogIndexKey{log.BlockHash, log.Index + 1}].GUID]
msgPassedLog := events.eventByLogIndex[ProcessedContractEventLogIndexKey{log.BlockHash, log.Index + 1}].GethLog
msgPassedEvent, err := l2ToL1MessagePasserABI.ParseMessagePassed(*msgPassedLog)
if err != nil {
return err
......
......@@ -20,15 +20,19 @@ func L2ToL1MessagePasserMessagesPassed(events *ProcessedContractEvents) ([]L2ToL
processedMessagePassedEvents := events.eventsBySignature[l2ToL1MessagePasserAbi.Events[eventName].ID]
messagesPassed := make([]L2ToL1MessagePasserMessagePassed, len(processedMessagePassedEvents))
for i, messagePassedEvent := range processedMessagePassedEvents {
log := events.eventLog[messagePassedEvent.GUID]
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{&messagePassed, messagePassedEvent}
messagesPassed[i] = L2ToL1MessagePasserMessagePassed{
L2ToL1MessagePasserMessagePassed: &messagePassed,
RawEvent: messagePassedEvent,
}
}
return messagesPassed, nil
......
package processor
import (
"context"
"errors"
"math/big"
......@@ -9,10 +8,7 @@ import (
"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/core/types"
"github.com/ethereum/go-ethereum/ethclient"
)
type OptimismPortalTransactionDepositEvent struct {
......@@ -51,7 +47,7 @@ func OptimismPortalTransactionDepositEvents(events *ProcessedContractEvents) ([]
processedTxDepositedEvents := events.eventsBySignature[derive.DepositEventABIHash]
txDeposits := make([]OptimismPortalTransactionDepositEvent, len(processedTxDepositedEvents))
for i, txDepositEvent := range processedTxDepositedEvents {
log := events.eventLog[txDepositEvent.GUID]
log := txDepositEvent.GethLog
depositTx, err := derive.UnmarshalDepositLogEvent(log)
if err != nil {
......@@ -59,12 +55,17 @@ func OptimismPortalTransactionDepositEvents(events *ProcessedContractEvents) ([]
}
var txDeposit bindings.OptimismPortalTransactionDeposited
txDeposit.Raw = *log
err = UnpackLog(&txDeposit, log, eventName, optimismPortalAbi)
if err != nil {
return nil, err
}
txDeposits[i] = OptimismPortalTransactionDepositEvent{&txDeposit, depositTx, txDepositEvent}
txDeposits[i] = OptimismPortalTransactionDepositEvent{
OptimismPortalTransactionDeposited: &txDeposit,
DepositTx: depositTx,
RawEvent: txDepositEvent,
}
}
return txDeposits, nil
......@@ -80,15 +81,19 @@ func OptimismPortalWithdrawalProvenEvents(events *ProcessedContractEvents) ([]Op
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
......@@ -104,7 +109,7 @@ func OptimismPortalWithdrawalFinalizedEvents(events *ProcessedContractEvents) ([
processedWithdrawalFinalizedEvents := events.eventsBySignature[optimismPortalAbi.Events[eventName].ID]
finalizedEvents := make([]OptimismPortalWithdrawalFinalizedEvent, len(processedWithdrawalFinalizedEvents))
for i, finalizedEvent := range processedWithdrawalFinalizedEvents {
log := events.eventLog[finalizedEvent.GUID]
log := finalizedEvent.GethLog
var withdrawalFinalized bindings.OptimismPortalWithdrawalFinalized
err := UnpackLog(&withdrawalFinalized, log, eventName, optimismPortalAbi)
......@@ -112,36 +117,11 @@ func OptimismPortalWithdrawalFinalizedEvents(events *ProcessedContractEvents) ([
return nil, err
}
finalizedEvents[i] = OptimismPortalWithdrawalFinalizedEvent{&withdrawalFinalized, finalizedEvent}
finalizedEvents[i] = OptimismPortalWithdrawalFinalizedEvent{
OptimismPortalWithdrawalFinalized: &withdrawalFinalized,
RawEvent: finalizedEvent,
}
}
return finalizedEvents, nil
}
func OptimismPortalQueryProvenWithdrawal(ethClient *ethclient.Client, portalAddress common.Address, withdrawalHash common.Hash) (OptimismPortalProvenWithdrawal, error) {
var provenWithdrawal OptimismPortalProvenWithdrawal
optimismPortalAbi, err := bindings.OptimismPortalMetaData.GetAbi()
if err != nil {
return provenWithdrawal, err
}
name := "provenWithdrawals"
txData, err := optimismPortalAbi.Pack(name, withdrawalHash)
if err != nil {
return provenWithdrawal, err
}
callMsg := ethereum.CallMsg{To: &portalAddress, Data: txData}
data, err := ethClient.CallContract(context.Background(), callMsg, nil)
if err != nil {
return provenWithdrawal, err
}
err = optimismPortalAbi.UnpackIntoInterface(&provenWithdrawal, name, data)
if err != nil {
return provenWithdrawal, err
}
return provenWithdrawal, 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
......
......@@ -297,7 +297,78 @@ LegacyERC20ETH_Test:test_transferFrom_doesNotExist_reverts() (gas: 12957)
LegacyERC20ETH_Test:test_transfer_doesNotExist_reverts() (gas: 10755)
LegacyMessagePasser_Test:test_passMessageToL1_succeeds() (gas: 34524)
LibPosition_Test:test_pos_correctness_succeeds() (gas: 38689)
MIPS_Test:test_step_abi_succeeds() (gas: 57803)
MIPS_Test:test_add_succeeds() (gas: 121593)
MIPS_Test:test_addi_succeeds() (gas: 121896)
MIPS_Test:test_addu_succeeds() (gas: 121645)
MIPS_Test:test_addui_succeeds() (gas: 121953)
MIPS_Test:test_and_succeeds() (gas: 121628)
MIPS_Test:test_andi_succeeds() (gas: 121770)
MIPS_Test:test_beq_succeeds() (gas: 202355)
MIPS_Test:test_bgez_succeeds() (gas: 121507)
MIPS_Test:test_bgtz_succeeds() (gas: 121428)
MIPS_Test:test_blez_succeeds() (gas: 121406)
MIPS_Test:test_bltz_succeeds() (gas: 121482)
MIPS_Test:test_bne_succeeds() (gas: 121548)
MIPS_Test:test_branch_inDelaySlot_fails() (gas: 85977)
MIPS_Test:test_brk_succeeds() (gas: 121509)
MIPS_Test:test_clo_succeeds() (gas: 121991)
MIPS_Test:test_clone_succeeds() (gas: 121484)
MIPS_Test:test_clz_succeeds() (gas: 122440)
MIPS_Test:test_div_succeeds() (gas: 121806)
MIPS_Test:test_divu_succeeds() (gas: 121806)
MIPS_Test:test_exit_succeeds() (gas: 121386)
MIPS_Test:test_fcntl_succeeds() (gas: 203171)
MIPS_Test:test_illegal_instruction_fails() (gas: 91153)
MIPS_Test:test_invalid_root_fails() (gas: 435656)
MIPS_Test:test_jal_succeeds() (gas: 117399)
MIPS_Test:test_jalr_succeeds() (gas: 121349)
MIPS_Test:test_jr_succeeds() (gas: 121138)
MIPS_Test:test_jump_inDelaySlot_fails() (gas: 85512)
MIPS_Test:test_jump_succeeds() (gas: 120353)
MIPS_Test:test_lb_succeeds() (gas: 127346)
MIPS_Test:test_lbu_succeeds() (gas: 127266)
MIPS_Test:test_lh_succeeds() (gas: 127345)
MIPS_Test:test_lhu_succeeds() (gas: 127262)
MIPS_Test:test_ll_succeeds() (gas: 127282)
MIPS_Test:test_lui_succeeds() (gas: 121531)
MIPS_Test:test_lw_succeeds() (gas: 127158)
MIPS_Test:test_lwl_succeeds() (gas: 241457)
MIPS_Test:test_lwr_succeeds() (gas: 241767)
MIPS_Test:test_mfhi_succeeds() (gas: 121458)
MIPS_Test:test_mflo_succeeds() (gas: 121484)
MIPS_Test:test_mmap_succeeds() (gas: 118492)
MIPS_Test:test_movn_succeeds() (gas: 202409)
MIPS_Test:test_movz_succeeds() (gas: 202313)
MIPS_Test:test_mthi_succeeds() (gas: 121428)
MIPS_Test:test_mtlo_succeeds() (gas: 121478)
MIPS_Test:test_mul_succeeds() (gas: 121541)
MIPS_Test:test_mult_succeeds() (gas: 121645)
MIPS_Test:test_multu_succeeds() (gas: 121698)
MIPS_Test:test_nor_succeeds() (gas: 121739)
MIPS_Test:test_or_succeeds() (gas: 121635)
MIPS_Test:test_ori_succeeds() (gas: 121865)
MIPS_Test:test_preimage_read_succeeds() (gas: 235922)
MIPS_Test:test_preimage_write_succeeds() (gas: 126473)
MIPS_Test:test_prestate_exited_succeeds() (gas: 112970)
MIPS_Test:test_sb_succeeds() (gas: 159993)
MIPS_Test:test_sc_succeeds() (gas: 160187)
MIPS_Test:test_sh_succeeds() (gas: 160096)
MIPS_Test:test_sll_succeeds() (gas: 121434)
MIPS_Test:test_sllv_succeeds() (gas: 121624)
MIPS_Test:test_slt_succeeds() (gas: 203244)
MIPS_Test:test_sltu_succeeds() (gas: 121871)
MIPS_Test:test_sra_succeeds() (gas: 121719)
MIPS_Test:test_srav_succeeds() (gas: 121959)
MIPS_Test:test_srl_succeeds() (gas: 121514)
MIPS_Test:test_srlv_succeeds() (gas: 121707)
MIPS_Test:test_step_abi_succeeds() (gas: 57871)
MIPS_Test:test_sub_succeeds() (gas: 121674)
MIPS_Test:test_subu_succeeds() (gas: 121682)
MIPS_Test:test_sw_succeeds() (gas: 160050)
MIPS_Test:test_swl_succeeds() (gas: 160066)
MIPS_Test:test_swr_succeeds() (gas: 160141)
MIPS_Test:test_xor_succeeds() (gas: 121685)
MIPS_Test:test_xori_succeeds() (gas: 121894)
MerkleTrie_get_Test:test_get_corruptedProof_reverts() (gas: 5733)
MerkleTrie_get_Test:test_get_extraProofElements_reverts() (gas: 58889)
MerkleTrie_get_Test:test_get_invalidDataRemainder_reverts() (gas: 35845)
......@@ -360,9 +431,9 @@ OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutp
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifOutputTimestampIsNotFinalized_reverts() (gas: 182306)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalNotProven_reverts() (gas: 41780)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_ifWithdrawalProofNotOldEnough_reverts() (gas: 173953)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() (gas: 180701)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onInsufficientGas_reverts() (gas: 180724)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onRecentWithdrawal_reverts() (gas: 154740)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReentrancy_reverts() (gas: 218747)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReentrancy_reverts() (gas: 218770)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_onReplay_reverts() (gas: 220983)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_paused_reverts() (gas: 38706)
OptimismPortal_FinalizeWithdrawal_Test:test_finalizeWithdrawalTransaction_provenWithdrawalHash_succeeds() (gas: 209679)
......
......@@ -5,7 +5,9 @@ import (
"fmt"
"math/big"
"os"
"strconv"
"github.com/ethereum-optimism/optimism/cannon/mipsevm"
"github.com/ethereum-optimism/optimism/op-bindings/predeploys"
"github.com/ethereum-optimism/optimism/op-chain-ops/crossdomain"
"github.com/ethereum/go-ethereum/accounts/abi"
......@@ -60,6 +62,15 @@ var (
proveWithdrawalInputsArgs = abi.Arguments{
{Name: "inputs", Type: proveWithdrawalInputs},
}
// cannonMemoryProof inputs tuple (bytes32, bytes)
cannonMemoryProof, _ = abi.NewType("tuple", "CannonMemoryProof", []abi.ArgumentMarshaling{
{Name: "memRoot", Type: "bytes32"},
{Name: "proof", Type: "bytes"},
})
cannonMemoryProofArgs = abi.Arguments{
{Name: "encodedCannonMemoryProof", Type: cannonMemoryProof},
}
)
func main() {
......@@ -312,6 +323,39 @@ func main() {
// Print the output
fmt.Print(hexutil.Encode(packed[32:]))
case "cannonMemoryProof":
// <pc, insn, [memAddr, memValue]>
mem := mipsevm.NewMemory()
if len(args) != 3 && len(args) != 5 {
panic("Error: cannonMemoryProofWithProof requires 2 or 4 arguments")
}
pc, err := strconv.ParseUint(args[1], 10, 32)
checkErr(err, "Error decocding addr")
insn, err := strconv.ParseUint(args[2], 10, 32)
checkErr(err, "Error decocding insn")
mem.SetMemory(uint32(pc), uint32(insn))
var insnProof, memProof [896]byte
if len(args) == 5 {
memAddr, err := strconv.ParseUint(args[3], 10, 32)
checkErr(err, "Error decocding memAddr")
memValue, err := strconv.ParseUint(args[4], 10, 32)
checkErr(err, "Error decocding memValue")
mem.SetMemory(uint32(memAddr), uint32(memValue))
memProof = mem.MerkleProof(uint32(memAddr))
}
insnProof = mem.MerkleProof(uint32(pc))
output := struct {
MemRoot common.Hash
Proof []byte
}{
MemRoot: mem.MerkleRoot(),
Proof: append(insnProof[:], memProof[:]...),
}
packed, err := cannonMemoryProofArgs.Pack(&output)
checkErr(err, "Error encoding output")
fmt.Print(hexutil.Encode(packed[32:]))
default:
panic(fmt.Errorf("Unknown command: %s", args[0]))
}
......
......@@ -678,6 +678,38 @@ contract FFIInterface is Test {
return abi.decode(vm.ffi(cmds), (bytes32, bytes, bytes, bytes[]));
}
function getCannonMemoryProof(uint32 pc, uint32 insn) external returns (bytes32, bytes memory) {
string[] memory cmds = new string[](4);
cmds[0] = "scripts/differential-testing/differential-testing";
cmds[1] = "cannonMemoryProof";
cmds[2] = vm.toString(pc);
cmds[3] = vm.toString(insn);
bytes memory result = vm.ffi(cmds);
(bytes32 memRoot, bytes memory proof) = abi.decode(result, (bytes32, bytes));
return (memRoot, proof);
}
function getCannonMemoryProof(
uint32 pc,
uint32 insn,
uint32 memAddr,
uint32 memVal
)
external
returns (bytes32, bytes memory)
{
string[] memory cmds = new string[](6);
cmds[0] = "scripts/differential-testing/differential-testing";
cmds[1] = "cannonMemoryProof";
cmds[2] = vm.toString(pc);
cmds[3] = vm.toString(insn);
cmds[4] = vm.toString(memAddr);
cmds[5] = vm.toString(memVal);
bytes memory result = vm.ffi(cmds);
(bytes32 memRoot, bytes memory proof) = abi.decode(result, (bytes32, bytes));
return (memRoot, proof);
}
}
// Used for testing a future upgrade beyond the current implementations.
......
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