Skip to content

Commit 25a4c94

Browse files
author
jagdeep sidhu
committed
initial PoDA integration
1) batch inbox to verify blobs in array 2) send to inbox during batch submission 3) verify blobs during derivation (WIP)
1 parent e2f6fb4 commit 25a4c94

34 files changed

+1370
-318
lines changed

op-batcher/batch_submitter.go

Lines changed: 101 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ const (
4242
// defaultDialTimeout is default duration the service will wait on
4343
// startup to make a connection to either the L1 or L2 backends.
4444
defaultDialTimeout = 5 * time.Second
45+
// SYSCOIN
46+
appendSequencerBatchMethodName = "appendSequencerBatch()"
4547
)
4648

4749
// Main is the entrypoint into the Batch Submitter. This method returns a
@@ -206,6 +208,16 @@ func NewBatchSubmitter(cfg Config, l log.Logger) (*BatchSubmitter, error) {
206208
return nil, err
207209
}
208210

211+
// SYSCOIN
212+
syscoinClient, err := dialSyscoinClientWithTimeout(ctx, cfg.SyscoinRpc)
213+
if err != nil {
214+
return nil, err
215+
}
216+
podaClient, err := dialPoDAClientWithTimeout(ctx, cfg.PoDARpc)
217+
if err != nil {
218+
return nil, err
219+
}
220+
209221
chainID, err := l1Client.ChainID(ctx)
210222
if err != nil {
211223
return nil, err
@@ -217,7 +229,6 @@ func NewBatchSubmitter(cfg Config, l log.Logger) (*BatchSubmitter, error) {
217229
}
218230

219231
log.Info("starting batch submitter", "submitter_addr", addr, "submitter_bal", sequencerBalance)
220-
221232
txManagerConfig := txmgr.Config{
222233
Log: l,
223234
Name: "Batch Submitter",
@@ -233,6 +244,8 @@ func NewBatchSubmitter(cfg Config, l log.Logger) (*BatchSubmitter, error) {
233244
L1Client: l1Client,
234245
L2Client: l2Client,
235246
RollupNode: rollupClient,
247+
SyscoinNode: syscoinClient,
248+
PoDANode: podaClient,
236249
MinL1TxSize: cfg.MinL1TxSize,
237250
MaxL1TxSize: cfg.MaxL1TxSize,
238251
BatchInboxAddress: batchInboxAddress,
@@ -243,7 +256,6 @@ func NewBatchSubmitter(cfg Config, l log.Logger) (*BatchSubmitter, error) {
243256
}
244257

245258
ctx, cancel := context.WithCancel(context.Background())
246-
247259
return &BatchSubmitter{
248260
cfg: batcherCfg,
249261
addr: addr,
@@ -338,6 +350,7 @@ mainLoop:
338350
continue
339351
}
340352
// Hand role do-while loop to fully pull all frames out of the channel
353+
VHs := make([]common.Hash, 0)
341354
for {
342355
// Collect the output frame
343356
data := new(bytes.Buffer)
@@ -350,52 +363,74 @@ mainLoop:
350363
l.log.Error("error outputting frame", "err", err)
351364
continue mainLoop
352365
}
353-
354-
// Query for the submitter's current nonce.
355-
walletAddr := crypto.PubkeyToAddress(l.cfg.PrivKey.PublicKey)
356-
ctx, cancel = context.WithTimeout(l.ctx, time.Second*10)
357-
nonce, err := l.cfg.L1Client.NonceAt(ctx, walletAddr, nil)
358-
cancel()
366+
// post data.Bytes() into SYS RPC to get version hash
367+
vh, err := l.cfg.SyscoinNode.CreatePoDA(ctx, data.Bytes())
359368
if err != nil {
360-
l.log.Error("unable to get current nonce", "err", err)
369+
l.log.Error("unable to create PoDA tx", "err", err)
361370
continue mainLoop
362371
}
363-
364-
// Create the transaction
365-
ctx, cancel = context.WithTimeout(l.ctx, time.Second*10)
366-
tx, err := l.CraftTx(ctx, data.Bytes(), nonce)
367-
cancel()
372+
VHs = append(VHs, vh)
373+
// If `ch.OutputFrame` returned io.EOF we don't need to submit any more frames for this channel.
374+
if done {
375+
break // local do-while loop
376+
}
377+
}
378+
vhBytes := make([]byte, 0)
379+
for _, vh := range VHs {
380+
// wait for VH to confirm (MTP > 0)
381+
podaCreateStatus, err := l.cfg.SyscoinNode.IsPoDAConfirmed(ctx, vh)
368382
if err != nil {
369-
l.log.Error("unable to craft tx", "err", err)
383+
l.log.Error("unable to check for PoDA confirmation", "err", err)
370384
continue mainLoop
371385
}
372-
373-
// Construct the a closure that will update the txn with the current gas prices.
374-
updateGasPrice := func(ctx context.Context) (*types.Transaction, error) {
375-
l.log.Debug("updating batch tx gas price")
376-
return l.UpdateGasPrice(ctx, tx)
377-
}
378-
379-
// Wait until one of our submitted transactions confirms. If no
380-
// receipt is received it's likely our gas price was too low.
381-
// TODO: does the tx manager nicely replace the tx?
382-
// (submit a new one, that's within the channel timeout, but higher fee than previously submitted tx? Or use a cheap cancel tx?)
383-
ctx, cancel = context.WithTimeout(l.ctx, time.Second*time.Duration(l.cfg.ChannelTimeout))
384-
receipt, err := l.txMgr.Send(ctx, updateGasPrice, l.cfg.L1Client.SendTransaction)
385-
cancel()
386-
if err != nil {
387-
l.log.Warn("unable to publish tx", "err", err)
386+
if podaCreateStatus == false {
387+
l.log.Error("PoDA not confirmed", "err", err)
388388
continue mainLoop
389389
}
390+
vhBytes = append(vhBytes, vh.Bytes()...)
391+
}
392+
// Query for the submitter's current nonce.
393+
walletAddr := crypto.PubkeyToAddress(l.cfg.PrivKey.PublicKey)
394+
ctx, cancel = context.WithTimeout(l.ctx, time.Second*10)
395+
nonce, err := l.cfg.L1Client.NonceAt(ctx, walletAddr, nil)
396+
cancel()
397+
if err != nil {
398+
l.log.Error("unable to get current nonce", "err", err)
399+
continue mainLoop
400+
}
401+
// Create the transaction
402+
ctx, cancel = context.WithTimeout(l.ctx, time.Second*10)
403+
// call the appendSequencerBatch in the batch inbox contract, append the function sig infront of array of VH 32 byte array
404+
sig := crypto.Keccak256([]byte(appendSequencerBatchMethodName))[:4]
405+
calldata := append(sig, vhBytes...)
406+
tx, err := l.CraftTx(ctx, calldata, nonce)
407+
cancel()
408+
if err != nil {
409+
l.log.Error("unable to craft tx", "err", err)
410+
continue mainLoop
411+
}
390412

391-
// The transaction was successfully submitted.
392-
l.log.Info("tx successfully published", "tx_hash", receipt.TxHash, "channel_id", l.ch.ID())
413+
// Construct the a closure that will update the txn with the current gas prices.
414+
updateGasPrice := func(ctx context.Context) (*types.Transaction, error) {
415+
l.log.Debug("updating batch tx gas price")
416+
return l.UpdateGasPrice(ctx, tx, uint64(len(VHs))*1800)
417+
}
393418

394-
// If `ch.OutputFrame` returned io.EOF we don't need to submit any more frames for this channel.
395-
if done {
396-
break // local do-while loop
397-
}
419+
// Wait until one of our submitted transactions confirms. If no
420+
// receipt is received it's likely our gas price was too low.
421+
// TODO: does the tx manager nicely replace the tx?
422+
// (submit a new one, that's within the channel timeout, but higher fee than previously submitted tx? Or use a cheap cancel tx?)
423+
ctx, cancel = context.WithTimeout(l.ctx, time.Second*time.Duration(l.cfg.ChannelTimeout))
424+
receipt, err := l.txMgr.Send(ctx, updateGasPrice, l.cfg.L1Client.SendTransaction)
425+
cancel()
426+
if err != nil {
427+
l.log.Warn("unable to publish tx", "err", err)
428+
continue mainLoop
398429
}
430+
431+
// The transaction was successfully submitted.
432+
l.log.Info("tx successfully published", "tx_hash", receipt.TxHash, "channel_id", l.ch.ID())
433+
399434
// TODO: if we exit to the mainLoop early on an error,
400435
// it would be nice if we can determine which blocks are still readable from the partially submitted data.
401436
// We can open a channel-in-reader, parse the data up to which we managed to submit it,
@@ -423,7 +458,6 @@ func (l *BatchSubmitter) CraftTx(ctx context.Context, data []byte, nonce uint64)
423458
}
424459

425460
gasFeeCap := txmgr.CalcGasFeeCap(head.BaseFee, gasTipCap)
426-
427461
rawTx := &types.DynamicFeeTx{
428462
ChainID: l.cfg.ChainID,
429463
Nonce: nonce,
@@ -447,7 +481,7 @@ func (l *BatchSubmitter) CraftTx(ctx context.Context, data []byte, nonce uint64)
447481
// updated gas prices sampled from the existing network conditions.
448482
//
449483
// NOTE: Thie method SHOULD NOT publish the resulting transaction.
450-
func (l *BatchSubmitter) UpdateGasPrice(ctx context.Context, tx *types.Transaction) (*types.Transaction, error) {
484+
func (l *BatchSubmitter) UpdateGasPrice(ctx context.Context, tx *types.Transaction, additionalGas uint64) (*types.Transaction, error) {
451485
gasTipCap, err := l.cfg.L1Client.SuggestGasTipCap(ctx)
452486
if err != nil {
453487
return nil, err
@@ -466,7 +500,7 @@ func (l *BatchSubmitter) UpdateGasPrice(ctx context.Context, tx *types.Transacti
466500
To: tx.To(),
467501
GasTipCap: gasTipCap,
468502
GasFeeCap: gasFeeCap,
469-
Gas: tx.Gas(),
503+
Gas: tx.Gas() + additionalGas,
470504
Data: tx.Data(),
471505
}
472506

@@ -506,6 +540,33 @@ func dialRollupClientWithTimeout(ctx context.Context, url string) (*sources.Roll
506540
return sources.NewRollupClient(client.NewBaseRPCClient(rpcCl)), nil
507541
}
508542

543+
// SYSCOIN
544+
// dialRollupClientWithTimeout attempts to dial the RPC provider using the provided
545+
// URL. If the dial doesn't complete within defaultDialTimeout seconds, this
546+
// method will return an error.
547+
func dialSyscoinClientWithTimeout(ctx context.Context, url string) (*sources.SyscoinClient, error) {
548+
ctxt, cancel := context.WithTimeout(ctx, defaultDialTimeout)
549+
defer cancel()
550+
551+
rpcCl, err := rpc.DialContext(ctxt, url)
552+
if err != nil {
553+
return nil, err
554+
}
555+
556+
return sources.NewSyscoinClient(client.NewBaseRPCClient(rpcCl)), nil
557+
}
558+
func dialPoDAClientWithTimeout(ctx context.Context, url string) (*sources.PoDAClient, error) {
559+
ctxt, cancel := context.WithTimeout(ctx, defaultDialTimeout)
560+
defer cancel()
561+
562+
rpcCl, err := rpc.DialContext(ctxt, url)
563+
if err != nil {
564+
return nil, err
565+
}
566+
567+
return sources.NewPoDAClient(client.NewBaseRPCClient(rpcCl)), nil
568+
}
569+
509570
// parseAddress parses an ETH address from a hex string. This method will fail if
510571
// the address is not a valid hexadecimal address.
511572
func parseAddress(address string) (common.Address, error) {

op-batcher/config.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ type Config struct {
2424
// RollupRpc is the HTTP provider URL for the L2 rollup node.
2525
RollupRpc string
2626

27+
// SYSCOIN SyscoinRpc is the HTTP provider URL for the L1 Syscoin UTXO node.
28+
SyscoinRpc string
29+
30+
// PoDARpc is the HTTP provider URL for the public PoDA archiving service.
31+
PoDARpc string
32+
2733
// MinL1TxSize is the minimum size of a batch tx submitted to L1.
2834
MinL1TxSize uint64
2935

@@ -101,6 +107,9 @@ func NewConfig(ctx *cli.Context) Config {
101107
L1EthRpc: ctx.GlobalString(flags.L1EthRpcFlag.Name),
102108
L2EthRpc: ctx.GlobalString(flags.L2EthRpcFlag.Name),
103109
RollupRpc: ctx.GlobalString(flags.RollupRpcFlag.Name),
110+
// SYSCOIN
111+
SyscoinRpc: ctx.GlobalString(flags.SyscoinRpcFlag.Name),
112+
PoDARpc: ctx.GlobalString(flags.PoDARpcFlag.Name),
104113
MinL1TxSize: ctx.GlobalUint64(flags.MinL1TxSizeBytesFlag.Name),
105114
MaxL1TxSize: ctx.GlobalUint64(flags.MaxL1TxSizeBytesFlag.Name),
106115
ChannelTimeout: ctx.GlobalUint64(flags.ChannelTimeoutFlag.Name),

op-batcher/flags/flags.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,19 @@ var (
3333
Required: true,
3434
EnvVar: opservice.PrefixEnvVar(envVarPrefix, "ROLLUP_RPC"),
3535
}
36+
// SYSCOIN
37+
SyscoinRpcFlag = cli.StringFlag{
38+
Name: "syscoin-rpc",
39+
Usage: "HTTP provider URL for Syscoin node",
40+
Required: true,
41+
EnvVar: opservice.PrefixEnvVar(envVarPrefix, "SYSCOIN_RPC"),
42+
}
43+
PoDARpcFlag = cli.StringFlag{
44+
Name: "poda-rpc",
45+
Usage: "HTTP provider URL for PoDA node",
46+
Required: true,
47+
EnvVar: opservice.PrefixEnvVar(envVarPrefix, "PODA_RPC"),
48+
}
3649
MinL1TxSizeBytesFlag = cli.Uint64Flag{
3750
Name: "min-l1-tx-size-bytes",
3851
Usage: "The minimum size of a batch tx submitted to L1.",
@@ -109,6 +122,9 @@ var requiredFlags = []cli.Flag{
109122
L1EthRpcFlag,
110123
L2EthRpcFlag,
111124
RollupRpcFlag,
125+
// SYSCOIN
126+
SyscoinRpcFlag,
127+
PoDARpcFlag,
112128
MinL1TxSizeBytesFlag,
113129
MaxL1TxSizeBytesFlag,
114130
ChannelTimeoutFlag,

op-batcher/sequencer/driver.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ type Config struct {
2323
L2Client *ethclient.Client
2424

2525
RollupNode *sources.RollupClient
26+
// SYSCOIN
27+
SyscoinNode *sources.SyscoinClient
28+
PoDANode *sources.PoDAClient
2629

2730
// Limit the size of txs
2831
MinL1TxSize uint64

op-node/cmd/genesis/cmd.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ var Subcommands = cli.Commands{
6565
if err != nil {
6666
return err
6767
}
68-
69-
rollupConfig := makeRollupConfig(config, l1StartBlock, l2Genesis, predeploys.DevOptimismPortalAddr, predeploys.DevL2OutputOracleAddr)
68+
// SYSCOIN
69+
rollupConfig := makeRollupConfig(config, l1StartBlock, l2Genesis, predeploys.DevOptimismPortalAddr, predeploys.DevL2OutputOracleAddr, config.BatchInboxAddress)
7070

7171
if err := writeGenesisFile(ctx.String("outfile.l1"), l1Genesis); err != nil {
7272
return err
@@ -154,6 +154,10 @@ var Subcommands = cli.Commands{
154154
if err != nil {
155155
return err
156156
}
157+
batchInboxAddr, err := hh.GetDeployment("BatchInbox")
158+
if err != nil {
159+
return err
160+
}
157161
l2Addrs := &genesis.L2Addresses{
158162
ProxyAdmin: proxyAdmin.Address,
159163
L1StandardBridgeProxy: l1SBP.Address,
@@ -164,7 +168,7 @@ var Subcommands = cli.Commands{
164168
return err
165169
}
166170

167-
rollupConfig := makeRollupConfig(config, l1StartBlock, l2Genesis, portalProxy.Address, outputOracle.Address)
171+
rollupConfig := makeRollupConfig(config, l1StartBlock, l2Genesis, portalProxy.Address, outputOracle.Address, batchInboxAddr.Address)
168172

169173
if err := writeGenesisFile(ctx.String("outfile.l2"), l2Genesis); err != nil {
170174
return err
@@ -180,6 +184,7 @@ func makeRollupConfig(
180184
l2Genesis *core.Genesis,
181185
portalAddr common.Address,
182186
outputOracleAddr common.Address,
187+
batchInboxAddr common.Address,
183188
) *rollup.Config {
184189
return &rollup.Config{
185190
Genesis: rollup.Genesis{
@@ -201,7 +206,7 @@ func makeRollupConfig(
201206
L2ChainID: new(big.Int).SetUint64(config.L2ChainID),
202207
P2PSequencerAddress: config.P2PSequencerAddress,
203208
FeeRecipientAddress: config.OptimismL2FeeRecipient,
204-
BatchInboxAddress: config.BatchInboxAddress,
209+
BatchInboxAddress: batchInboxAddr,
205210
BatchSenderAddress: config.BatchSenderAddress,
206211
DepositContractAddress: portalAddr,
207212
L2OutputOracleAddress: outputOracleAddr,

0 commit comments

Comments
 (0)