forked from ethereum-optimism/optimism
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
op-proposer: cleanup proposer logic, update outputAtBlock API (ethere…
…um-optimism#3805) * op-proposer: cleanup proposer logic, update outputAtBlock API * op-e2e,op-proposer: action test proposer * fix flags Co-authored-by: Matthew Slipper <[email protected]>
- Loading branch information
1 parent
3f6c670
commit 05d367e
Showing
16 changed files
with
425 additions
and
206 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package actions | ||
|
||
import ( | ||
"crypto/ecdsa" | ||
"math/big" | ||
|
||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/ethereum/go-ethereum/crypto" | ||
"github.com/ethereum/go-ethereum/ethclient" | ||
"github.com/ethereum/go-ethereum/log" | ||
"github.com/stretchr/testify/require" | ||
|
||
"github.com/ethereum-optimism/optimism/op-node/sources" | ||
"github.com/ethereum-optimism/optimism/op-proposer/drivers/l2output" | ||
) | ||
|
||
type ProposerCfg struct { | ||
OutputOracleAddr common.Address | ||
ProposerKey *ecdsa.PrivateKey | ||
AllowNonFinalized bool | ||
} | ||
|
||
type L2Proposer struct { | ||
log log.Logger | ||
l1 *ethclient.Client | ||
driver *l2output.Driver | ||
address common.Address | ||
lastTx common.Hash | ||
} | ||
|
||
func NewL2Proposer(t Testing, log log.Logger, cfg *ProposerCfg, l1 *ethclient.Client, rollupCl *sources.RollupClient) *L2Proposer { | ||
chainID, err := l1.ChainID(t.Ctx()) | ||
require.NoError(t, err) | ||
dr, err := l2output.NewDriver(l2output.Config{ | ||
Log: log, | ||
Name: "proposer", | ||
L1Client: l1, | ||
RollupClient: rollupCl, | ||
AllowNonFinalized: cfg.AllowNonFinalized, | ||
L2OOAddr: cfg.OutputOracleAddr, | ||
ChainID: chainID, | ||
PrivKey: cfg.ProposerKey, | ||
}) | ||
require.NoError(t, err) | ||
return &L2Proposer{ | ||
log: log, | ||
l1: l1, | ||
driver: dr, | ||
address: crypto.PubkeyToAddress(cfg.ProposerKey.PublicKey), | ||
} | ||
} | ||
|
||
func (p *L2Proposer) CanPropose(t Testing) bool { | ||
start, end, err := p.driver.GetBlockRange(t.Ctx()) | ||
require.NoError(t, err) | ||
return start.Cmp(end) < 0 | ||
} | ||
|
||
func (p *L2Proposer) ActMakeProposalTx(t Testing) { | ||
start, end, err := p.driver.GetBlockRange(t.Ctx()) | ||
require.NoError(t, err) | ||
if start.Cmp(end) == 0 { | ||
t.InvalidAction("nothing to propose, block range starts and ends at %s", start.String()) | ||
} | ||
nonce, err := p.l1.PendingNonceAt(t.Ctx(), p.address) | ||
require.NoError(t, err) | ||
|
||
tx, err := p.driver.CraftTx(t.Ctx(), start, end, new(big.Int).SetUint64(nonce)) | ||
require.NoError(t, err) | ||
|
||
err = p.driver.SendTransaction(t.Ctx(), tx) | ||
require.NoError(t, err) | ||
p.lastTx = tx.Hash() | ||
} | ||
|
||
func (p *L2Proposer) LastProposalTx() common.Hash { | ||
return p.lastTx | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package actions | ||
|
||
import ( | ||
"math/big" | ||
"testing" | ||
|
||
"github.com/ethereum/go-ethereum/core/types" | ||
"github.com/ethereum/go-ethereum/log" | ||
"github.com/stretchr/testify/require" | ||
|
||
"github.com/ethereum-optimism/optimism/op-bindings/bindings" | ||
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils" | ||
"github.com/ethereum-optimism/optimism/op-node/eth" | ||
"github.com/ethereum-optimism/optimism/op-node/testlog" | ||
) | ||
|
||
func TestProposer(gt *testing.T) { | ||
t := NewDefaultTesting(gt) | ||
dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) | ||
sd := e2eutils.Setup(t, dp, defaultAlloc) | ||
log := testlog.Logger(t, log.LvlDebug) | ||
miner, seqEngine, sequencer := setupSequencerTest(t, sd, log) | ||
|
||
rollupSeqCl := sequencer.RollupClient() | ||
batcher := NewL2Batcher(log, sd.RollupCfg, &BatcherCfg{ | ||
MinL1TxSize: 0, | ||
MaxL1TxSize: 128_000, | ||
BatcherKey: dp.Secrets.Batcher, | ||
}, rollupSeqCl, miner.EthClient(), seqEngine.EthClient()) | ||
|
||
proposer := NewL2Proposer(t, log, &ProposerCfg{ | ||
OutputOracleAddr: sd.DeploymentsL1.L2OutputOracleProxy, | ||
ProposerKey: dp.Secrets.Proposer, | ||
AllowNonFinalized: false, | ||
}, miner.EthClient(), sequencer.RollupClient()) | ||
|
||
// L1 block | ||
miner.ActEmptyBlock(t) | ||
// L2 block | ||
sequencer.ActL1HeadSignal(t) | ||
sequencer.ActL2PipelineFull(t) | ||
sequencer.ActBuildToL1Head(t) | ||
// submit and include in L1 | ||
batcher.ActSubmitAll(t) | ||
miner.ActL1StartBlock(12)(t) | ||
miner.ActL1IncludeTx(dp.Addresses.Batcher)(t) | ||
miner.ActL1EndBlock(t) | ||
// finalize the first and second L1 blocks, including the batch | ||
miner.ActL1SafeNext(t) | ||
miner.ActL1SafeNext(t) | ||
miner.ActL1FinalizeNext(t) | ||
miner.ActL1FinalizeNext(t) | ||
// derive and see the L2 chain fully finalize | ||
sequencer.ActL2PipelineFull(t) | ||
sequencer.ActL1SafeSignal(t) | ||
sequencer.ActL1FinalizedSignal(t) | ||
require.Equal(t, sequencer.SyncStatus().UnsafeL2, sequencer.SyncStatus().FinalizedL2) | ||
// make proposals until there is nothing left to propose | ||
for proposer.CanPropose(t) { | ||
// and propose it to L1 | ||
proposer.ActMakeProposalTx(t) | ||
// include proposal on L1 | ||
miner.ActL1StartBlock(12)(t) | ||
miner.ActL1IncludeTx(dp.Addresses.Proposer)(t) | ||
miner.ActL1EndBlock(t) | ||
// Check proposal was successful | ||
receipt, err := miner.EthClient().TransactionReceipt(t.Ctx(), proposer.LastProposalTx()) | ||
require.NoError(t, err) | ||
require.Equal(t, types.ReceiptStatusSuccessful, receipt.Status, "proposal failed") | ||
} | ||
|
||
// check that L1 stored the expected output root | ||
outputOracleContract, err := bindings.NewL2OutputOracle(sd.DeploymentsL1.L2OutputOracleProxy, miner.EthClient()) | ||
require.NoError(t, err) | ||
block := sequencer.SyncStatus().FinalizedL2 | ||
outputOnL1, err := outputOracleContract.GetL2Output(nil, new(big.Int).SetUint64(block.Number)) | ||
require.NoError(t, err) | ||
require.Less(t, block.Time, outputOnL1.Timestamp.Uint64(), "output is registered with L1 timestamp of proposal tx, past L2 block") | ||
outputComputed, err := sequencer.RollupClient().OutputAtBlock(t.Ctx(), block.Number) | ||
require.NoError(t, err) | ||
require.Equal(t, eth.Bytes32(outputOnL1.OutputRoot), outputComputed.OutputRoot, "output roots must match") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package eth | ||
|
||
import ( | ||
"github.com/ethereum/go-ethereum/common" | ||
) | ||
|
||
type OutputResponse struct { | ||
Version Bytes32 `json:"version"` | ||
OutputRoot Bytes32 `json:"outputRoot"` | ||
BlockRef L2BlockRef `json:"blockRef"` | ||
WithdrawalStorageRoot common.Hash `json:"withdrawalStorageRoot"` | ||
StateRoot common.Hash `json:"stateRoot"` | ||
Status *SyncStatus `json:"syncStatus"` | ||
} |
Oops, something went wrong.