From f0087300a19ded9a15fe7e1b8115606fcf5d0415 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toni=20Ram=C3=ADrez?= <58293609+ToniRamirezM@users.noreply.github.com> Date: Tue, 9 Jul 2024 16:46:31 +0200 Subject: [PATCH 01/20] use dbTx in SequentialBatchSanityCheck (#3722) * use dbTx in SequentialBatchSanityCheck --- sequencer/batch.go | 14 +++++++------- sequencer/finalizer_test.go | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/sequencer/batch.go b/sequencer/batch.go index b7cb731fe5..e960efa97a 100644 --- a/sequencer/batch.go +++ b/sequencer/batch.go @@ -57,7 +57,7 @@ func (f *finalizer) processBatchesPendingtoCheck(ctx context.Context) { oldStateRoot := prevBatch.StateRoot for _, notCheckedBatch := range notCheckedBatches { - _, _ = f.batchSanityCheck(ctx, notCheckedBatch.BatchNumber, oldStateRoot, notCheckedBatch.StateRoot) + _, _ = f.batchSanityCheck(ctx, notCheckedBatch.BatchNumber, oldStateRoot, notCheckedBatch.StateRoot, nil) oldStateRoot = notCheckedBatch.StateRoot } } @@ -397,11 +397,11 @@ func (f *finalizer) closeSIPBatch(ctx context.Context, dbTx pgx.Tx) error { // Reprocess full batch as sanity check if f.cfg.SequentialBatchSanityCheck { // Do the full batch reprocess now - _, _ = f.batchSanityCheck(ctx, batchNumber, initialStateRoot, finalStateRoot) + _, _ = f.batchSanityCheck(ctx, batchNumber, initialStateRoot, finalStateRoot, dbTx) } else { // Do the full batch reprocess in parallel go func() { - _, _ = f.batchSanityCheck(ctx, batchNumber, initialStateRoot, finalStateRoot) + _, _ = f.batchSanityCheck(ctx, batchNumber, initialStateRoot, finalStateRoot, nil) }() } @@ -416,7 +416,7 @@ func (f *finalizer) closeSIPBatch(ctx context.Context, dbTx pgx.Tx) error { } // batchSanityCheck reprocesses a batch used as sanity check -func (f *finalizer) batchSanityCheck(ctx context.Context, batchNum uint64, initialStateRoot common.Hash, expectedNewStateRoot common.Hash) (*state.ProcessBatchResponse, error) { +func (f *finalizer) batchSanityCheck(ctx context.Context, batchNum uint64, initialStateRoot common.Hash, expectedNewStateRoot common.Hash, dbTx pgx.Tx) (*state.ProcessBatchResponse, error) { reprocessError := func(batch *state.Batch) { rawL2Blocks, err := state.DecodeBatchV2(batch.BatchL2Data) if err != nil { @@ -442,7 +442,7 @@ func (f *finalizer) batchSanityCheck(ctx context.Context, batchNum uint64, initi log.Debugf("batch %d sanity check: initialStateRoot: %s, expectedNewStateRoot: %s", batchNum, initialStateRoot, expectedNewStateRoot) - batch, err := f.stateIntf.GetBatchByNumber(ctx, batchNum, nil) + batch, err := f.stateIntf.GetBatchByNumber(ctx, batchNum, dbTx) if err != nil { log.Errorf("failed to get batch %d, error: %v", batchNum, err) return nil, ErrGetBatchByNumber @@ -459,7 +459,7 @@ func (f *finalizer) batchSanityCheck(ctx context.Context, batchNum uint64, initi SkipVerifyL1InfoRoot_V2: true, Caller: stateMetrics.DiscardCallerLabel, } - batchRequest.L1InfoTreeData_V2, _, _, err = f.stateIntf.GetL1InfoTreeDataFromBatchL2Data(ctx, batch.BatchL2Data, nil) + batchRequest.L1InfoTreeData_V2, _, _, err = f.stateIntf.GetL1InfoTreeDataFromBatchL2Data(ctx, batch.BatchL2Data, dbTx) if err != nil { log.Errorf("failed to get L1InfoTreeData for batch %d, error: %v", batch.BatchNumber, err) reprocessError(nil) @@ -502,7 +502,7 @@ func (f *finalizer) batchSanityCheck(ctx context.Context, batchNum uint64, initi return nil, ErrStateRootNoMatch } - err = f.stateIntf.UpdateBatchAsChecked(ctx, batch.BatchNumber, nil) + err = f.stateIntf.UpdateBatchAsChecked(ctx, batch.BatchNumber, dbTx) if err != nil { log.Errorf("failed to update batch %d as checked, error: %v", batch.BatchNumber, err) reprocessError(batch) diff --git a/sequencer/finalizer_test.go b/sequencer/finalizer_test.go index 35a03ef4ea..7efdf59907 100644 --- a/sequencer/finalizer_test.go +++ b/sequencer/finalizer_test.go @@ -984,11 +984,11 @@ func TestFinalizer_finalizeSIPBatch(t *testing.T) { stateMock.On("CloseWIPBatch", ctx, receipt, mock.Anything).Return(tc.managerErr).Once() if tc.managerErr == nil { - stateMock.On("GetBatchByNumber", ctx, f.sipBatch.batchNumber, nil).Return(&state.Batch{BatchNumber: f.sipBatch.batchNumber}, nilErr).Once() + stateMock.On("GetBatchByNumber", ctx, f.sipBatch.batchNumber, mock.Anything).Return(&state.Batch{BatchNumber: f.sipBatch.batchNumber}, nilErr).Once() stateMock.On("GetForkIDByBatchNumber", f.wipBatch.batchNumber).Return(uint64(9)).Once() - stateMock.On("GetL1InfoTreeDataFromBatchL2Data", ctx, mock.Anything, nil).Return(map[uint32]state.L1DataV2{}, state.ZeroHash, state.ZeroHash, nil) + stateMock.On("GetL1InfoTreeDataFromBatchL2Data", ctx, mock.Anything, mock.Anything).Return(map[uint32]state.L1DataV2{}, state.ZeroHash, state.ZeroHash, nil) stateMock.On("ProcessBatchV2", ctx, mock.Anything, false).Return(&state.ProcessBatchResponse{}, "", nil) - stateMock.On("UpdateBatchAsChecked", ctx, f.sipBatch.batchNumber, nil).Return(nil) + stateMock.On("UpdateBatchAsChecked", ctx, f.sipBatch.batchNumber, mock.Anything).Return(nil) dbTxMock.On("Commit", ctx).Return(nilErr).Once() } else { dbTxMock.On("Rollback", ctx).Return(nilErr).Once() From 96648183b478ed9de82122c40227bf887c37d4bd Mon Sep 17 00:00:00 2001 From: Joan Esteban <129153821+joanestebanr@users.noreply.github.com> Date: Tue, 16 Jul 2024 10:13:55 +0200 Subject: [PATCH 02/20] support forkid 10 and forkid11 (#3731) --- state/forkid.go | 4 ++++ synchronizer/actions/forksids.go | 6 +++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/state/forkid.go b/state/forkid.go index ed035a53e1..bfd78c6c91 100644 --- a/state/forkid.go +++ b/state/forkid.go @@ -19,6 +19,10 @@ const ( FORKID_ELDERBERRY = 8 // FORKID_9 is the fork id 9 FORKID_9 = 9 + // FORKID_10 is the fork id 10 + FORKID_10 = 10 + // FORKID_11 is the fork id 11 + FORKID_11 = 11 ) // ForkIDInterval is a fork id interval diff --git a/synchronizer/actions/forksids.go b/synchronizer/actions/forksids.go index 1383ef98c5..e379dcb136 100644 --- a/synchronizer/actions/forksids.go +++ b/synchronizer/actions/forksids.go @@ -14,6 +14,10 @@ const ( ForkIDElderberry = ForkIdType(8) //nolint:gomnd // ForkID9 is the forkId for 9 ForkID9 = ForkIdType(9) //nolint:gomnd + // ForkID10 is the forkId for 10 (support more counters) + ForkID10 = ForkIdType(10) //nolint:gomnd + // ForkID11 is the forkId for 11 (support even more counters) + ForkID11 = ForkIdType(11) //nolint:gomnd ) var ( @@ -22,7 +26,7 @@ var ( ForksIdAll = []ForkIdType{WildcardForkId} // ForksIdOnlyElderberry support only elderberry forkId - ForksIdOnlyElderberry = []ForkIdType{ForkIDElderberry, ForkID9} + ForksIdOnlyElderberry = []ForkIdType{ForkIDElderberry, ForkID9, ForkID10, ForkID11} // ForksIdOnlyEtrog support only etrog forkId ForksIdOnlyEtrog = []ForkIdType{ForkIDEtrog} From 7aa74dcfeff266fe3f56892d0d08b6745aa7a1c5 Mon Sep 17 00:00:00 2001 From: agnusmor <100322135+agnusmor@users.noreply.github.com> Date: Tue, 16 Jul 2024 10:14:37 +0200 Subject: [PATCH 03/20] kill inactive datastream clients (#3727) --- config/config_test.go | 8 +++ config/default.go | 2 + .../environments/local/local.node.config.toml | 2 + docs/config-file/node-config-doc.html | 4 ++ docs/config-file/node-config-doc.md | 54 +++++++++++++++++++ docs/config-file/node-config-schema.json | 20 +++++++ go.mod | 18 +++---- go.sum | 43 +++++++-------- sequencer/config.go | 4 ++ sequencer/sequencer.go | 2 +- test/config/debug.node.config.toml | 2 + test/config/test.node.config.toml | 2 + tools/datastreamer/config/config.go | 4 ++ tools/datastreamer/config/tool.config.toml | 2 + tools/datastreamer/main.go | 2 +- 15 files changed, 137 insertions(+), 32 deletions(-) diff --git a/config/config_test.go b/config/config_test.go index d6c40ed30a..3786da6023 100644 --- a/config/config_test.go +++ b/config/config_test.go @@ -173,6 +173,14 @@ func Test_Defaults(t *testing.T) { path: "Sequencer.StreamServer.WriteTimeout", expectedValue: types.NewDuration(5 * time.Second), }, + { + path: "Sequencer.StreamServer.InactivityTimeout", + expectedValue: types.NewDuration(120 * time.Second), + }, + { + path: "Sequencer.StreamServer.InactivityCheckInterval", + expectedValue: types.NewDuration(5 * time.Second), + }, { path: "Sequencer.StreamServer.Enabled", expectedValue: false, diff --git a/config/default.go b/config/default.go index bff3d90a70..4d2f50f1a4 100644 --- a/config/default.go +++ b/config/default.go @@ -164,6 +164,8 @@ StateConsistencyCheckInterval = "5s" Filename = "" Version = 0 WriteTimeout = "5s" + InactivityTimeout = "120s" + InactivityCheckInterval = "5s" Enabled = false [SequenceSender] diff --git a/config/environments/local/local.node.config.toml b/config/environments/local/local.node.config.toml index c403a0718a..d3ebc8e0e6 100644 --- a/config/environments/local/local.node.config.toml +++ b/config/environments/local/local.node.config.toml @@ -113,6 +113,8 @@ StateConsistencyCheckInterval = "5s" Port = 0 Filename = "" WriteTimeout = "5s" + InactivityTimeout = "120s" + InactivityCheckInterval = "5s" Enabled = false [SequenceSender] diff --git a/docs/config-file/node-config-doc.html b/docs/config-file/node-config-doc.html index 14800feab3..0c5400fb2a 100644 --- a/docs/config-file/node-config-doc.html +++ b/docs/config-file/node-config-doc.html @@ -58,6 +58,10 @@
"300ms"
 

Default: trueType: boolean

EnableLog is a flag to enable/disable metrics logs


StreamServerCfg is the config for the stream server
Default: 0Type: integer

Port to listen on


Default: ""Type: string

Filename of the binary data file


Default: 0Type: integer

Version of the binary data file


Default: 0Type: integer

ChainID is the chain ID


Default: falseType: boolean

Enabled is a flag to enable/disable the data streamer


Log is the log configuration
Default: ""Type: enum (of string)

Must be one of:

  • "production"
  • "development"

Default: ""Type: enum (of string)

Must be one of:

  • "debug"
  • "info"
  • "warn"
  • "error"
  • "dpanic"
  • "panic"
  • "fatal"

Type: array of string

Each item of this array must be:


Default: 0Type: integer

UpgradeEtrogBatchNumber is the batch number of the upgrade etrog


Default: "5s"Type: string

WriteTimeout is the TCP write timeout when sending data to a datastream client


Examples:

"1m"
 
"300ms"
+

Default: "2m0s"Type: string

InactivityTimeout is the timeout to kill an inactive datastream client connection


Examples:

"1m"
+
"300ms"
+

Default: "5s"Type: string

InactivityCheckInterval is the time interval to check for datastream client connections that have reached the inactivity timeout to kill them


Examples:

"1m"
+
"300ms"
 

Configuration of the sequence sender service
Default: "5s"Type: string

WaitPeriodSendSequence is the time the sequencer waits until
trying to send a sequence to L1


Examples:

"1m"
 
"300ms"
 

Default: "5s"Type: string

LastBatchVirtualizationTimeMaxWaitPeriod is time since sequences should be sent


Examples:

"1m"
diff --git a/docs/config-file/node-config-doc.md b/docs/config-file/node-config-doc.md
index 3dab591984..dc70d93791 100644
--- a/docs/config-file/node-config-doc.md
+++ b/docs/config-file/node-config-doc.md
@@ -2488,6 +2488,8 @@ EnableLog=true
 | - [Log](#Sequencer_StreamServer_Log )                                         | No      | object  | No         | -          | Log is the log configuration                                     |
 | - [UpgradeEtrogBatchNumber](#Sequencer_StreamServer_UpgradeEtrogBatchNumber ) | No      | integer | No         | -          | UpgradeEtrogBatchNumber is the batch number of the upgrade etrog |
 | - [WriteTimeout](#Sequencer_StreamServer_WriteTimeout )                       | No      | string  | No         | -          | Duration                                                         |
+| - [InactivityTimeout](#Sequencer_StreamServer_InactivityTimeout )             | No      | string  | No         | -          | Duration                                                         |
+| - [InactivityCheckInterval](#Sequencer_StreamServer_InactivityCheckInterval ) | No      | string  | No         | -          | Duration                                                         |
 
 #### 10.9.1. `Sequencer.StreamServer.Port`
 
@@ -2651,6 +2653,58 @@ UpgradeEtrogBatchNumber=0
 WriteTimeout="5s"
 ```
 
+#### 10.9.9. `Sequencer.StreamServer.InactivityTimeout`
+
+**Title:** Duration
+
+**Type:** : `string`
+
+**Default:** `"2m0s"`
+
+**Description:** InactivityTimeout is the timeout to kill an inactive datastream client connection
+
+**Examples:** 
+
+```json
+"1m"
+```
+
+```json
+"300ms"
+```
+
+**Example setting the default value** ("2m0s"):
+```
+[Sequencer.StreamServer]
+InactivityTimeout="2m0s"
+```
+
+#### 10.9.10. `Sequencer.StreamServer.InactivityCheckInterval`
+
+**Title:** Duration
+
+**Type:** : `string`
+
+**Default:** `"5s"`
+
+**Description:** InactivityCheckInterval is the time interval to check for datastream client connections that have reached the inactivity timeout to kill them
+
+**Examples:** 
+
+```json
+"1m"
+```
+
+```json
+"300ms"
+```
+
+**Example setting the default value** ("5s"):
+```
+[Sequencer.StreamServer]
+InactivityCheckInterval="5s"
+```
+
 ## 11. `[SequenceSender]`
 
 **Type:** : `object`
diff --git a/docs/config-file/node-config-schema.json b/docs/config-file/node-config-schema.json
index 489ee17274..5b1b218cf5 100644
--- a/docs/config-file/node-config-schema.json
+++ b/docs/config-file/node-config-schema.json
@@ -1008,6 +1008,26 @@
 								"1m",
 								"300ms"
 							]
+						},
+						"InactivityTimeout": {
+							"type": "string",
+							"title": "Duration",
+							"description": "InactivityTimeout is the timeout to kill an inactive datastream client connection",
+							"default": "2m0s",
+							"examples": [
+								"1m",
+								"300ms"
+							]
+						},
+						"InactivityCheckInterval": {
+							"type": "string",
+							"title": "Duration",
+							"description": "InactivityCheckInterval is the time interval to check for datastream client connections that have reached the inactivity timeout to kill them",
+							"default": "5s",
+							"examples": [
+								"1m",
+								"300ms"
+							]
 						}
 					},
 					"additionalProperties": false,
diff --git a/go.mod b/go.mod
index 64ced2a895..9544b9b958 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@ module github.com/0xPolygonHermez/zkevm-node
 go 1.21
 
 require (
-	github.com/0xPolygonHermez/zkevm-data-streamer v0.2.3-RC4
+	github.com/0xPolygonHermez/zkevm-data-streamer v0.2.3-RC5
 	github.com/didip/tollbooth/v6 v6.1.2
 	github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127
 	github.com/ethereum/go-ethereum v1.13.11
@@ -22,11 +22,11 @@ require (
 	github.com/prometheus/common v0.45.0
 	github.com/rubenv/sql-migrate v1.6.1
 	github.com/spf13/afero v1.11.0
-	github.com/spf13/viper v1.17.0
-	github.com/stretchr/testify v1.8.4
+	github.com/spf13/viper v1.18.2
+	github.com/stretchr/testify v1.9.0
 	github.com/umbracle/ethgo v0.1.3
-	github.com/urfave/cli/v2 v2.26.0
-	go.uber.org/zap v1.26.0
+	github.com/urfave/cli/v2 v2.27.1
+	go.uber.org/zap v1.27.0
 	golang.org/x/crypto v0.18.0
 	golang.org/x/net v0.20.0
 	golang.org/x/sync v0.5.0
@@ -68,7 +68,7 @@ require (
 	github.com/emirpasic/gods v1.18.1 // indirect
 	github.com/ethereum/c-kzg-4844 v0.4.0 // indirect
 	github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 // indirect
-	github.com/fsnotify/fsnotify v1.6.0 // indirect
+	github.com/fsnotify/fsnotify v1.7.0 // indirect
 	github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff // indirect
 	github.com/gballet/go-verkle v0.1.1-0.20231031103413-a67434b50f46 // indirect
 	github.com/getsentry/sentry-go v0.18.0 // indirect
@@ -128,17 +128,17 @@ require (
 	github.com/rogpeppe/go-internal v1.11.0 // indirect
 	github.com/rs/cors v1.7.0 // indirect
 	github.com/russross/blackfriday/v2 v2.1.0 // indirect
-	github.com/sagikazarmark/locafero v0.3.0 // indirect
+	github.com/sagikazarmark/locafero v0.4.0 // indirect
 	github.com/sagikazarmark/slog-shim v0.1.0 // indirect
 	github.com/sergi/go-diff v1.2.0 // indirect
 	github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
 	github.com/sirupsen/logrus v1.9.0 // indirect
 	github.com/skeema/knownhosts v1.2.1 // indirect
 	github.com/sourcegraph/conc v0.3.0 // indirect
-	github.com/spf13/cast v1.5.1 // indirect
+	github.com/spf13/cast v1.6.0 // indirect
 	github.com/spf13/pflag v1.0.5 // indirect
 	github.com/status-im/keycard-go v0.2.0 // indirect
-	github.com/stretchr/objx v0.5.0 // indirect
+	github.com/stretchr/objx v0.5.2 // indirect
 	github.com/subosito/gotenv v1.6.0 // indirect
 	github.com/supranational/blst v0.3.11 // indirect
 	github.com/tklauser/go-sysconf v0.3.12 // indirect
diff --git a/go.sum b/go.sum
index da7a1cbead..4aacd939e6 100644
--- a/go.sum
+++ b/go.sum
@@ -39,8 +39,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
 dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
 dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
-github.com/0xPolygonHermez/zkevm-data-streamer v0.2.3-RC4 h1:+4K+xSzv0ImbK30B/T9FauNTrTFUmWcNKYhIgwsE4C4=
-github.com/0xPolygonHermez/zkevm-data-streamer v0.2.3-RC4/go.mod h1:0QkAXcFa92mFJrCbN3UPUJGJYes851yEgYHLONnaosE=
+github.com/0xPolygonHermez/zkevm-data-streamer v0.2.3-RC5 h1:ofcfKofJCn3AyOYnEeQ6YbKm0slEKRXk+TbeuvIUymw=
+github.com/0xPolygonHermez/zkevm-data-streamer v0.2.3-RC5/go.mod h1:bv7DjATsczN2WvFt26jv34TWv6rfvYM1SqegrgrFwfI=
 github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
 github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
 github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
@@ -209,13 +209,13 @@ github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4Nij
 github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
 github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c=
 github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
-github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
-github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
+github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
+github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
 github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
-github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
-github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
+github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
+github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
 github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc=
 github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
 github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
@@ -680,8 +680,8 @@ github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf
 github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
 github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
 github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
-github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ=
-github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U=
+github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ=
+github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4=
 github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
 github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
 github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
@@ -719,8 +719,8 @@ github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
 github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
 github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
 github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
-github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
+github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
+github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
 github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
 github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
 github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
@@ -730,16 +730,17 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
 github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
-github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI=
-github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI=
+github.com/spf13/viper v1.18.2 h1:LUXCnvUvSM6FXAsj6nnfc8Q2tp1dIgUfY9Kc8GsSOiQ=
+github.com/spf13/viper v1.18.2/go.mod h1:EKmWIqdnk5lOcmR72yw6hS+8OPYcwD0jteitLMVB+yk=
 github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA=
 github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
-github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
 github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
+github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
+github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@@ -750,8 +751,9 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
 github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
 github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
+github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
 github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
 github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
@@ -775,8 +777,8 @@ github.com/umbracle/ethgo v0.1.3 h1:s8D7Rmphnt71zuqrgsGTMS5gTNbueGO1zKLh7qsFzTM=
 github.com/umbracle/ethgo v0.1.3/go.mod h1:g9zclCLixH8liBI27Py82klDkW7Oo33AxUOr+M9lzrU=
 github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722 h1:10Nbw6cACsnQm7r34zlpJky+IzxVLRk6MKTS2d3Vp0E=
 github.com/umbracle/fastrlp v0.0.0-20220527094140-59d5dd30e722/go.mod h1:c8J0h9aULj2i3umrfyestM6jCq0LK0U6ly6bWy96nd4=
-github.com/urfave/cli/v2 v2.26.0 h1:3f3AMg3HpThFNT4I++TKOejZO8yU55t3JnnSr4S4QEI=
-github.com/urfave/cli/v2 v2.26.0/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
+github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho=
+github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
 github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
 github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
 github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
@@ -830,8 +832,8 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
 go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
 go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
-go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
-go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
+go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
+go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
 go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
 go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
 go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
@@ -843,8 +845,8 @@ go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
 go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
-go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
-go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
+go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
+go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
 golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@@ -1060,7 +1062,6 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
 golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
diff --git a/sequencer/config.go b/sequencer/config.go
index 5f34cad1d9..918042291c 100644
--- a/sequencer/config.go
+++ b/sequencer/config.go
@@ -54,6 +54,10 @@ type StreamServerCfg struct {
 	UpgradeEtrogBatchNumber uint64 `mapstructure:"UpgradeEtrogBatchNumber"`
 	// WriteTimeout is the TCP write timeout when sending data to a datastream client
 	WriteTimeout types.Duration `mapstructure:"WriteTimeout"`
+	// InactivityTimeout is the timeout to kill an inactive datastream client connection
+	InactivityTimeout types.Duration `mapstructure:"InactivityTimeout"`
+	// InactivityCheckInterval is the time interval to check for datastream client connections that have reached the inactivity timeout to kill them
+	InactivityCheckInterval types.Duration `mapstructure:"InactivityCheckInterval"`
 }
 
 // FinalizerCfg contains the finalizer's configuration properties
diff --git a/sequencer/sequencer.go b/sequencer/sequencer.go
index 3f57d9cc85..eaeab94f33 100644
--- a/sequencer/sequencer.go
+++ b/sequencer/sequencer.go
@@ -72,7 +72,7 @@ func (s *Sequencer) Start(ctx context.Context) {
 
 	// Start stream server if enabled
 	if s.cfg.StreamServer.Enabled {
-		s.streamServer, err = datastreamer.NewServer(s.cfg.StreamServer.Port, s.cfg.StreamServer.Version, s.cfg.StreamServer.ChainID, state.StreamTypeSequencer, s.cfg.StreamServer.Filename, s.cfg.StreamServer.WriteTimeout.Duration, &s.cfg.StreamServer.Log)
+		s.streamServer, err = datastreamer.NewServer(s.cfg.StreamServer.Port, s.cfg.StreamServer.Version, s.cfg.StreamServer.ChainID, state.StreamTypeSequencer, s.cfg.StreamServer.Filename, s.cfg.StreamServer.WriteTimeout.Duration, s.cfg.StreamServer.InactivityTimeout.Duration, s.cfg.StreamServer.InactivityCheckInterval.Duration, &s.cfg.StreamServer.Log)
 		if err != nil {
 			log.Fatalf("failed to create stream server, error: %v", err)
 		}
diff --git a/test/config/debug.node.config.toml b/test/config/debug.node.config.toml
index 54ca62a789..7ec0d496ea 100644
--- a/test/config/debug.node.config.toml
+++ b/test/config/debug.node.config.toml
@@ -113,6 +113,8 @@ StateConsistencyCheckInterval = "5s"
 		Filename = "/datastreamer/datastream.bin"
 		Version = 1
 		WriteTimeout = "5s"
+		InactivityTimeout = "120s"
+		InactivityCheckInterval = "5s"
 		Enabled = true
 
 [SequenceSender]
diff --git a/test/config/test.node.config.toml b/test/config/test.node.config.toml
index 0358afa59e..d13ff02ca5 100644
--- a/test/config/test.node.config.toml
+++ b/test/config/test.node.config.toml
@@ -129,6 +129,8 @@ StateConsistencyCheckInterval = "5s"
 		Version = 1
 		ChainID = 1337
 		WriteTimeout = "5s"
+		InactivityTimeout = "120s"
+		InactivityCheckInterval = "5s"		
 		Enabled = true
 
 [SequenceSender]
diff --git a/tools/datastreamer/config/config.go b/tools/datastreamer/config/config.go
index b6c841e591..b2651c538b 100644
--- a/tools/datastreamer/config/config.go
+++ b/tools/datastreamer/config/config.go
@@ -51,6 +51,10 @@ type StreamServerCfg struct {
 	UpgradeEtrogBatchNumber uint64 `mapstructure:"UpgradeEtrogBatchNumber"`
 	// WriteTimeout is the TCP write timeout when sending data to a datastream client
 	WriteTimeout types.Duration `mapstructure:"WriteTimeout"`
+	// InactivityTimeout is the timeout to kill an inactive datastream client connection
+	InactivityTimeout types.Duration `mapstructure:"InactivityTimeout"`
+	// InactivityCheckInterval is the time interval to check for datastream client connections that have reached the inactivity timeout to kill them
+	InactivityCheckInterval types.Duration `mapstructure:"InactivityCheckInterval"`
 }
 
 // Config is the configuration for the tool
diff --git a/tools/datastreamer/config/tool.config.toml b/tools/datastreamer/config/tool.config.toml
index f5530b8271..60d04aafb3 100644
--- a/tools/datastreamer/config/tool.config.toml
+++ b/tools/datastreamer/config/tool.config.toml
@@ -8,6 +8,8 @@ Filename = "datastream.bin"
 Version = 3
 ChainID = 1440
 WriteTimeout = "5s"
+InactivityTimeout = "120s"
+InactivityCheckInterval = "5s"
 UpgradeEtrogBatchNumber = 0
 
 [StateDB]
diff --git a/tools/datastreamer/main.go b/tools/datastreamer/main.go
index fc069117af..c6b43155f8 100644
--- a/tools/datastreamer/main.go
+++ b/tools/datastreamer/main.go
@@ -184,7 +184,7 @@ func main() {
 
 func initializeStreamServer(c *config.Config) (*datastreamer.StreamServer, error) {
 	// Create a stream server
-	streamServer, err := datastreamer.NewServer(c.Offline.Port, c.Offline.Version, c.Offline.ChainID, state.StreamTypeSequencer, c.Offline.Filename, c.Offline.WriteTimeout.Duration, &c.Log)
+	streamServer, err := datastreamer.NewServer(c.Offline.Port, c.Offline.Version, c.Offline.ChainID, state.StreamTypeSequencer, c.Offline.Filename, c.Offline.WriteTimeout.Duration, c.Offline.InactivityTimeout.Duration, c.Offline.InactivityCheckInterval.Duration, &c.Log)
 	if err != nil {
 		return nil, err
 	}

From 19beaa94880bec8098d88c675d28a7522e952577 Mon Sep 17 00:00:00 2001
From: agnusmor <100322135+agnusmor@users.noreply.github.com>
Date: Thu, 18 Jul 2024 12:48:59 +0200
Subject: [PATCH 04/20] Add mined l1blocknumber to MonitoredTxResult. Undo
 forkid10 and forkid11 changes (#3734)

---
 ethtxmanager/ethtxmanager.go     |  7 ++++---
 ethtxmanager/monitoredtx.go      |  7 ++++---
 sequencesender/sequencesender.go | 23 +++++------------------
 state/forkid.go                  |  4 ----
 synchronizer/actions/forksids.go |  6 +-----
 5 files changed, 14 insertions(+), 33 deletions(-)

diff --git a/ethtxmanager/ethtxmanager.go b/ethtxmanager/ethtxmanager.go
index 79f9262962..ae640bab7c 100644
--- a/ethtxmanager/ethtxmanager.go
+++ b/ethtxmanager/ethtxmanager.go
@@ -184,9 +184,10 @@ func (c *Client) buildResult(ctx context.Context, mTx monitoredTx) (MonitoredTxR
 	}
 
 	result := MonitoredTxResult{
-		ID:     mTx.id,
-		Status: mTx.status,
-		Txs:    txs,
+		ID:          mTx.id,
+		Status:      mTx.status,
+		BlockNumber: mTx.blockNumber,
+		Txs:         txs,
 	}
 
 	return result, nil
diff --git a/ethtxmanager/monitoredtx.go b/ethtxmanager/monitoredtx.go
index 716030763b..b0c4182b95 100644
--- a/ethtxmanager/monitoredtx.go
+++ b/ethtxmanager/monitoredtx.go
@@ -182,9 +182,10 @@ func (mTx *monitoredTx) blockNumberU64Ptr() *uint64 {
 
 // MonitoredTxResult represents the result of a execution of a monitored tx
 type MonitoredTxResult struct {
-	ID     string
-	Status MonitoredTxStatus
-	Txs    map[common.Hash]TxResult
+	ID          string
+	Status      MonitoredTxStatus
+	BlockNumber *big.Int
+	Txs         map[common.Hash]TxResult
 }
 
 // TxResult represents the result of a execution of a ethereum transaction in the block chain
diff --git a/sequencesender/sequencesender.go b/sequencesender/sequencesender.go
index 81b2c68fc6..80a467eafd 100644
--- a/sequencesender/sequencesender.go
+++ b/sequencesender/sequencesender.go
@@ -12,7 +12,6 @@ import (
 	"github.com/0xPolygonHermez/zkevm-node/event"
 	"github.com/0xPolygonHermez/zkevm-node/log"
 	"github.com/0xPolygonHermez/zkevm-node/state"
-	"github.com/ethereum/go-ethereum/common"
 	ethTypes "github.com/ethereum/go-ethereum/core/types"
 	"github.com/jackc/pgx/v4"
 )
@@ -97,25 +96,13 @@ func (s *SequenceSender) tryToSendSequence(ctx context.Context) {
 	s.ethTxManager.ProcessPendingMonitoredTxs(ctx, ethTxManagerOwner, func(result ethtxmanager.MonitoredTxResult, dbTx pgx.Tx) {
 		if result.Status == ethtxmanager.MonitoredTxStatusConfirmed {
 			if len(result.Txs) > 0 {
-				var txL1BlockNumber uint64
-				var txHash common.Hash
-				receiptFound := false
-				for _, tx := range result.Txs {
-					if tx.Receipt != nil {
-						txL1BlockNumber = tx.Receipt.BlockNumber.Uint64()
-						txHash = tx.Tx.Hash()
-						receiptFound = true
-						break
-					}
-				}
-
-				if !receiptFound {
-					s.halt(ctx, fmt.Errorf("monitored tx %s for sequence [%d-%d] is confirmed but doesn't have a receipt", result.ID, s.lastSequenceInitialBatch, s.lastSequenceEndBatch))
+				if result.BlockNumber == nil {
+					s.halt(ctx, fmt.Errorf("monitored tx %s for sequence [%d-%d] is confirmed but doesn't have L1 block number where tx was mined", result.ID, s.lastSequenceInitialBatch, s.lastSequenceEndBatch))
 				}
 
 				// wait L1 confirmation blocks
-				log.Infof("waiting %d L1 block confirmations for sequence [%d-%d], L1 block: %d, tx: %s",
-					s.cfg.SequenceL1BlockConfirmations, s.lastSequenceInitialBatch, s.lastSequenceEndBatch, txL1BlockNumber, txHash)
+				log.Infof("waiting %d L1 block confirmations for sequence [%d-%d], L1 block: %d",
+					s.cfg.SequenceL1BlockConfirmations, s.lastSequenceInitialBatch, s.lastSequenceEndBatch, result.BlockNumber)
 				for {
 					lastL1BlockHeader, err := s.etherman.GetLatestBlockHeader(ctx)
 					if err != nil {
@@ -123,7 +110,7 @@ func (s *SequenceSender) tryToSendSequence(ctx context.Context) {
 					} else {
 						lastL1BlockNumber := lastL1BlockHeader.Number.Uint64()
 
-						if lastL1BlockNumber >= txL1BlockNumber+s.cfg.SequenceL1BlockConfirmations {
+						if lastL1BlockNumber >= result.BlockNumber.Uint64()+s.cfg.SequenceL1BlockConfirmations {
 							log.Infof("continuing, last L1 block: %d", lastL1BlockNumber)
 							break
 						}
diff --git a/state/forkid.go b/state/forkid.go
index bfd78c6c91..ed035a53e1 100644
--- a/state/forkid.go
+++ b/state/forkid.go
@@ -19,10 +19,6 @@ const (
 	FORKID_ELDERBERRY = 8
 	// FORKID_9 is the fork id 9
 	FORKID_9 = 9
-	// FORKID_10 is the fork id 10
-	FORKID_10 = 10
-	// FORKID_11 is the fork id 11
-	FORKID_11 = 11
 )
 
 // ForkIDInterval is a fork id interval
diff --git a/synchronizer/actions/forksids.go b/synchronizer/actions/forksids.go
index e379dcb136..1383ef98c5 100644
--- a/synchronizer/actions/forksids.go
+++ b/synchronizer/actions/forksids.go
@@ -14,10 +14,6 @@ const (
 	ForkIDElderberry = ForkIdType(8) //nolint:gomnd
 	// ForkID9 is the forkId for 9
 	ForkID9 = ForkIdType(9) //nolint:gomnd
-	// ForkID10 is the forkId for 10 (support more counters)
-	ForkID10 = ForkIdType(10) //nolint:gomnd
-	// ForkID11 is the forkId for 11 (support even more counters)
-	ForkID11 = ForkIdType(11) //nolint:gomnd
 )
 
 var (
@@ -26,7 +22,7 @@ var (
 	ForksIdAll = []ForkIdType{WildcardForkId}
 
 	// ForksIdOnlyElderberry support only elderberry forkId
-	ForksIdOnlyElderberry = []ForkIdType{ForkIDElderberry, ForkID9, ForkID10, ForkID11}
+	ForksIdOnlyElderberry = []ForkIdType{ForkIDElderberry, ForkID9}
 
 	// ForksIdOnlyEtrog support only etrog forkId
 	ForksIdOnlyEtrog = []ForkIdType{ForkIDEtrog}

From 8a1e192bcea45185c7f37db4719d400c83ceab20 Mon Sep 17 00:00:00 2001
From: agnusmor <100322135+agnusmor@users.noreply.github.com>
Date: Thu, 18 Jul 2024 13:16:38 +0200
Subject: [PATCH 05/20] Wait the state to be synced when starting (#3735)

---
 aggregator/aggregator.go | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/aggregator/aggregator.go b/aggregator/aggregator.go
index 751ade1ff7..0e41d796de 100644
--- a/aggregator/aggregator.go
+++ b/aggregator/aggregator.go
@@ -124,6 +124,12 @@ func (a *Aggregator) Start(ctx context.Context) error {
 		return fmt.Errorf("failed to initialize proofs cache %w", err)
 	}
 
+	for !a.isSynced(ctx, nil) {
+		log.Info("Waiting for synchronizer to sync...")
+		time.Sleep(a.cfg.RetryTime.Duration)
+		continue
+	}
+
 	address := fmt.Sprintf("%s:%d", a.cfg.Host, a.cfg.Port)
 	lis, err := net.Listen("tcp", address)
 	if err != nil {

From 1adc67d1e00e737e2f3e0afb9636b15a1d382074 Mon Sep 17 00:00:00 2001
From: agnusmor <100322135+agnusmor@users.noreply.github.com>
Date: Wed, 24 Jul 2024 11:46:58 +0200
Subject: [PATCH 06/20] Fix update datastream file (#3741)

* Update datastream file fixes: end batch entry, previous L2 block timestamp, current batch number

* Use GetFirstEventAfterBookmark
---
 state/datastream.go | 57 ++++++++++++++++++++++++++++++---------------
 1 file changed, 38 insertions(+), 19 deletions(-)

diff --git a/state/datastream.go b/state/datastream.go
index 236a69df43..a9544d4e69 100644
--- a/state/datastream.go
+++ b/state/datastream.go
@@ -258,26 +258,43 @@ func GenerateDataStreamFile(ctx context.Context, streamServer *datastreamer.Stre
 			}
 
 			currentL2BlockNumber := transaction.L2BlockNumber
-			currentBatchNumber = transaction.L2BlockNumber
 			lastAddedL2BlockNumber = currentL2BlockNumber
 
-			// Get Previous l2block timestamp
-			bookMark := &datastream.BookMark{
+			// Get current batch number
+			bookMarkCurrentL2Block := &datastream.BookMark{
 				Type:  datastream.BookmarkType_BOOKMARK_TYPE_L2_BLOCK,
-				Value: currentL2BlockNumber - 1,
+				Value: currentL2BlockNumber,
 			}
 
-			marshalledBookMark, err := proto.Marshal(bookMark)
+			marshalledBookMarkCurrentL2Block, err := proto.Marshal(bookMarkCurrentL2Block)
+			if err != nil {
+				return err
+			}
+
+			currentL2BlockEntry, err := streamServer.GetFirstEventAfterBookmark(marshalledBookMarkCurrentL2Block)
 			if err != nil {
 				return err
 			}
 
-			prevL2BlockEntryNumber, err := streamServer.GetBookmark(marshalledBookMark)
+			currentL2Block := &datastream.L2Block{}
+			if err := proto.Unmarshal(currentL2BlockEntry.Data, currentL2Block); err != nil {
+				return err
+			}
+
+			currentBatchNumber = currentL2Block.BatchNumber
+
+			// Get Previous l2block timestamp
+			bookMarkPrevL2Block := &datastream.BookMark{
+				Type:  datastream.BookmarkType_BOOKMARK_TYPE_L2_BLOCK,
+				Value: currentL2BlockNumber - 1,
+			}
+
+			marshalledBookMarkPrevL2Block, err := proto.Marshal(bookMarkPrevL2Block)
 			if err != nil {
 				return err
 			}
 
-			prevL2BlockEntry, err := streamServer.GetEntry(prevL2BlockEntryNumber)
+			prevL2BlockEntry, err := streamServer.GetFirstEventAfterBookmark(marshalledBookMarkPrevL2Block)
 			if err != nil {
 				return err
 			}
@@ -610,20 +627,22 @@ func GenerateDataStreamFile(ctx context.Context, streamServer *datastreamer.Stre
 				}
 			}
 
-			batchEnd := &datastream.BatchEnd{
-				Number:        batch.BatchNumber,
-				LocalExitRoot: batch.LocalExitRoot.Bytes(),
-				StateRoot:     batch.StateRoot.Bytes(),
-			}
+			if !batch.WIP {
+				batchEnd := &datastream.BatchEnd{
+					Number:        batch.BatchNumber,
+					LocalExitRoot: batch.LocalExitRoot.Bytes(),
+					StateRoot:     batch.StateRoot.Bytes(),
+				}
 
-			marshalledBatch, err := proto.Marshal(batchEnd)
-			if err != nil {
-				return err
-			}
+				marshalledBatch, err := proto.Marshal(batchEnd)
+				if err != nil {
+					return err
+				}
 
-			_, err = streamServer.AddStreamEntry(datastreamer.EntryType(datastream.EntryType_ENTRY_TYPE_BATCH_END), marshalledBatch)
-			if err != nil {
-				return err
+				_, err = streamServer.AddStreamEntry(datastreamer.EntryType(datastream.EntryType_ENTRY_TYPE_BATCH_END), marshalledBatch)
+				if err != nil {
+					return err
+				}
 			}
 
 			// Commit at the end of each batch group

From f594715590511689c40abebba8e20e6915c20234 Mon Sep 17 00:00:00 2001
From: Thiago Coimbra Lemos 
Date: Wed, 24 Jul 2024 12:58:18 -0300
Subject: [PATCH 07/20] fix tracer previous step memory pointers (#3740)

---
 .../tracers/structlogger/structlogger.go      |   9 +
 state/trace.go                                |   3 +-
 test/contracts/auto/Sha.sol                   |   8 +
 test/contracts/bin/Sha/Sha.go                 | 224 ++++++++++++++++++
 .../bin/triggerErrors/triggerErrors.go        |   2 +-
 test/e2e/debug_calltracer_test.go             |   1 +
 test/e2e/debug_shared.go                      |  27 +++
 test/e2e/debug_test.go                        |  30 ++-
 8 files changed, 291 insertions(+), 13 deletions(-)
 create mode 100644 test/contracts/auto/Sha.sol
 create mode 100644 test/contracts/bin/Sha/Sha.go

diff --git a/state/runtime/instrumentation/tracers/structlogger/structlogger.go b/state/runtime/instrumentation/tracers/structlogger/structlogger.go
index 3a4cf037ad..bd9e20afd3 100644
--- a/state/runtime/instrumentation/tracers/structlogger/structlogger.go
+++ b/state/runtime/instrumentation/tracers/structlogger/structlogger.go
@@ -27,6 +27,7 @@ type StructLogRes struct {
 	Depth         int                `json:"depth"`
 	Error         string             `json:"error,omitempty"`
 	Stack         *[]string          `json:"stack,omitempty"`
+	ReturnData    *string            `json:"returnData,omitempty"`
 	Memory        *[]string          `json:"memory,omitempty"`
 	Storage       *map[string]string `json:"storage,omitempty"`
 	RefundCounter uint64             `json:"refund,omitempty"`
@@ -123,6 +124,14 @@ func (l *JSONLogger) ParseTrace(result *runtime.ExecutionResult, receipt types.R
 			structLogRes.Storage = &storage
 		}
 
+		var returnData *string
+		if l.cfg.EnableReturnData && len(step.ReturnData) > 0 {
+			rd := hex.EncodeToHex(step.ReturnData)
+			returnData = &rd
+		}
+
+		structLogRes.ReturnData = returnData
+
 		structLogs = append(structLogs, structLogRes)
 	}
 
diff --git a/state/trace.go b/state/trace.go
index a1c367f067..4fcca8f08d 100644
--- a/state/trace.go
+++ b/state/trace.go
@@ -502,7 +502,8 @@ func (s *State) buildTrace(evm *fakevm.FakeEVM, result *runtime.ExecutionResult,
 		}
 
 		// Populate the step memory for future steps
-		step.Memory = memory.Data()
+		step.Memory = make([]byte, len(memory.Data()))
+		copy(step.Memory[0:], memory.Data()[0:])
 
 		// set Contract
 		contract := fakevm.NewContract(
diff --git a/test/contracts/auto/Sha.sol b/test/contracts/auto/Sha.sol
new file mode 100644
index 0000000000..90621e59d2
--- /dev/null
+++ b/test/contracts/auto/Sha.sol
@@ -0,0 +1,8 @@
+// SPDX-License-Identifier: GPL-3.0
+pragma solidity ^0.8.4;
+
+contract Sha {
+    function hash() public {
+        sha256("hello world");
+    }
+}
diff --git a/test/contracts/bin/Sha/Sha.go b/test/contracts/bin/Sha/Sha.go
new file mode 100644
index 0000000000..887d168db1
--- /dev/null
+++ b/test/contracts/bin/Sha/Sha.go
@@ -0,0 +1,224 @@
+// Code generated - DO NOT EDIT.
+// This file is a generated binding and any manual changes will be lost.
+
+package Sha
+
+import (
+	"errors"
+	"math/big"
+	"strings"
+
+	ethereum "github.com/ethereum/go-ethereum"
+	"github.com/ethereum/go-ethereum/accounts/abi"
+	"github.com/ethereum/go-ethereum/accounts/abi/bind"
+	"github.com/ethereum/go-ethereum/common"
+	"github.com/ethereum/go-ethereum/core/types"
+	"github.com/ethereum/go-ethereum/event"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var (
+	_ = errors.New
+	_ = big.NewInt
+	_ = strings.NewReader
+	_ = ethereum.NotFound
+	_ = bind.Bind
+	_ = common.Big1
+	_ = types.BloomLookup
+	_ = event.NewSubscription
+	_ = abi.ConvertType
+)
+
+// ShaMetaData contains all meta data concerning the Sha contract.
+var ShaMetaData = &bind.MetaData{
+	ABI: "[{\"inputs\":[],\"name\":\"hash\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
+	Bin: "0x608060405234801561001057600080fd5b5060dd8061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c806309bd5a6014602d575b600080fd5b60336035565b005b6040516a1a195b1b1bc81ddbdc9b1960aa1b8152600290600b01602060405180830381855afa158015606b573d6000803e3d6000fd5b5050506040513d601f19601f82011682018060405250810190608c9190608f565b50565b60006020828403121560a057600080fd5b505191905056fea2646970667358221220fe50f9cdaf095e844b048d17690c0862e54c7d7b550c4e2d9045215198e571d564736f6c634300080c0033",
+}
+
+// ShaABI is the input ABI used to generate the binding from.
+// Deprecated: Use ShaMetaData.ABI instead.
+var ShaABI = ShaMetaData.ABI
+
+// ShaBin is the compiled bytecode used for deploying new contracts.
+// Deprecated: Use ShaMetaData.Bin instead.
+var ShaBin = ShaMetaData.Bin
+
+// DeploySha deploys a new Ethereum contract, binding an instance of Sha to it.
+func DeploySha(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Sha, error) {
+	parsed, err := ShaMetaData.GetAbi()
+	if err != nil {
+		return common.Address{}, nil, nil, err
+	}
+	if parsed == nil {
+		return common.Address{}, nil, nil, errors.New("GetABI returned nil")
+	}
+
+	address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(ShaBin), backend)
+	if err != nil {
+		return common.Address{}, nil, nil, err
+	}
+	return address, tx, &Sha{ShaCaller: ShaCaller{contract: contract}, ShaTransactor: ShaTransactor{contract: contract}, ShaFilterer: ShaFilterer{contract: contract}}, nil
+}
+
+// Sha is an auto generated Go binding around an Ethereum contract.
+type Sha struct {
+	ShaCaller     // Read-only binding to the contract
+	ShaTransactor // Write-only binding to the contract
+	ShaFilterer   // Log filterer for contract events
+}
+
+// ShaCaller is an auto generated read-only Go binding around an Ethereum contract.
+type ShaCaller struct {
+	contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// ShaTransactor is an auto generated write-only Go binding around an Ethereum contract.
+type ShaTransactor struct {
+	contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// ShaFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
+type ShaFilterer struct {
+	contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// ShaSession is an auto generated Go binding around an Ethereum contract,
+// with pre-set call and transact options.
+type ShaSession struct {
+	Contract     *Sha              // Generic contract binding to set the session for
+	CallOpts     bind.CallOpts     // Call options to use throughout this session
+	TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
+}
+
+// ShaCallerSession is an auto generated read-only Go binding around an Ethereum contract,
+// with pre-set call options.
+type ShaCallerSession struct {
+	Contract *ShaCaller    // Generic contract caller binding to set the session for
+	CallOpts bind.CallOpts // Call options to use throughout this session
+}
+
+// ShaTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
+// with pre-set transact options.
+type ShaTransactorSession struct {
+	Contract     *ShaTransactor    // Generic contract transactor binding to set the session for
+	TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
+}
+
+// ShaRaw is an auto generated low-level Go binding around an Ethereum contract.
+type ShaRaw struct {
+	Contract *Sha // Generic contract binding to access the raw methods on
+}
+
+// ShaCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
+type ShaCallerRaw struct {
+	Contract *ShaCaller // Generic read-only contract binding to access the raw methods on
+}
+
+// ShaTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
+type ShaTransactorRaw struct {
+	Contract *ShaTransactor // Generic write-only contract binding to access the raw methods on
+}
+
+// NewSha creates a new instance of Sha, bound to a specific deployed contract.
+func NewSha(address common.Address, backend bind.ContractBackend) (*Sha, error) {
+	contract, err := bindSha(address, backend, backend, backend)
+	if err != nil {
+		return nil, err
+	}
+	return &Sha{ShaCaller: ShaCaller{contract: contract}, ShaTransactor: ShaTransactor{contract: contract}, ShaFilterer: ShaFilterer{contract: contract}}, nil
+}
+
+// NewShaCaller creates a new read-only instance of Sha, bound to a specific deployed contract.
+func NewShaCaller(address common.Address, caller bind.ContractCaller) (*ShaCaller, error) {
+	contract, err := bindSha(address, caller, nil, nil)
+	if err != nil {
+		return nil, err
+	}
+	return &ShaCaller{contract: contract}, nil
+}
+
+// NewShaTransactor creates a new write-only instance of Sha, bound to a specific deployed contract.
+func NewShaTransactor(address common.Address, transactor bind.ContractTransactor) (*ShaTransactor, error) {
+	contract, err := bindSha(address, nil, transactor, nil)
+	if err != nil {
+		return nil, err
+	}
+	return &ShaTransactor{contract: contract}, nil
+}
+
+// NewShaFilterer creates a new log filterer instance of Sha, bound to a specific deployed contract.
+func NewShaFilterer(address common.Address, filterer bind.ContractFilterer) (*ShaFilterer, error) {
+	contract, err := bindSha(address, nil, nil, filterer)
+	if err != nil {
+		return nil, err
+	}
+	return &ShaFilterer{contract: contract}, nil
+}
+
+// bindSha binds a generic wrapper to an already deployed contract.
+func bindSha(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
+	parsed, err := ShaMetaData.GetAbi()
+	if err != nil {
+		return nil, err
+	}
+	return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil
+}
+
+// Call invokes the (constant) contract method with params as input values and
+// sets the output to result. The result type might be a single field for simple
+// returns, a slice of interfaces for anonymous returns and a struct for named
+// returns.
+func (_Sha *ShaRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
+	return _Sha.Contract.ShaCaller.contract.Call(opts, result, method, params...)
+}
+
+// Transfer initiates a plain transaction to move funds to the contract, calling
+// its default method if one is available.
+func (_Sha *ShaRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+	return _Sha.Contract.ShaTransactor.contract.Transfer(opts)
+}
+
+// Transact invokes the (paid) contract method with params as input values.
+func (_Sha *ShaRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+	return _Sha.Contract.ShaTransactor.contract.Transact(opts, method, params...)
+}
+
+// Call invokes the (constant) contract method with params as input values and
+// sets the output to result. The result type might be a single field for simple
+// returns, a slice of interfaces for anonymous returns and a struct for named
+// returns.
+func (_Sha *ShaCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
+	return _Sha.Contract.contract.Call(opts, result, method, params...)
+}
+
+// Transfer initiates a plain transaction to move funds to the contract, calling
+// its default method if one is available.
+func (_Sha *ShaTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+	return _Sha.Contract.contract.Transfer(opts)
+}
+
+// Transact invokes the (paid) contract method with params as input values.
+func (_Sha *ShaTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+	return _Sha.Contract.contract.Transact(opts, method, params...)
+}
+
+// Hash is a paid mutator transaction binding the contract method 0x09bd5a60.
+//
+// Solidity: function hash() returns()
+func (_Sha *ShaTransactor) Hash(opts *bind.TransactOpts) (*types.Transaction, error) {
+	return _Sha.contract.Transact(opts, "hash")
+}
+
+// Hash is a paid mutator transaction binding the contract method 0x09bd5a60.
+//
+// Solidity: function hash() returns()
+func (_Sha *ShaSession) Hash() (*types.Transaction, error) {
+	return _Sha.Contract.Hash(&_Sha.TransactOpts)
+}
+
+// Hash is a paid mutator transaction binding the contract method 0x09bd5a60.
+//
+// Solidity: function hash() returns()
+func (_Sha *ShaTransactorSession) Hash() (*types.Transaction, error) {
+	return _Sha.Contract.Hash(&_Sha.TransactOpts)
+}
diff --git a/test/contracts/bin/triggerErrors/triggerErrors.go b/test/contracts/bin/triggerErrors/triggerErrors.go
index d3778b808b..4fede2d110 100644
--- a/test/contracts/bin/triggerErrors/triggerErrors.go
+++ b/test/contracts/bin/triggerErrors/triggerErrors.go
@@ -32,7 +32,7 @@ var (
 // TriggerErrorsMetaData contains all meta data concerning the TriggerErrors contract.
 var TriggerErrorsMetaData = &bind.MetaData{
 	ABI: "[{\"inputs\":[],\"name\":\"count\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"outOfCountersKeccaks\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"test\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"outOfCountersPoseidon\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"outOfCountersSteps\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"outOfGas\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
-	Bin: "0x60806040526000805534801561001457600080fd5b5061016c806100246000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c806306661abd1461005c5780632621002a1461007757806331fe52e8146100835780638bd7b5381461008d578063cb4e8cd114610095575b600080fd5b61006560005481565b60405190815260200160405180910390f35b620f4240600020610065565b61008b61009d565b005b61008b6100c3565b61008b6100e9565b60005b60648110156100c0578060005580806100b89061010d565b9150506100a0565b50565b60005b620186a08110156100c0576104d2600052806100e18161010d565b9150506100c6565b60005b61c3508110156100c0578060005580806101059061010d565b9150506100ec565b600060001982141561012f57634e487b7160e01b600052601160045260246000fd5b506001019056fea264697066735822122097beacfaa873e4896937143dfea406cc278b929a28023f7e7020b6dea6e9fc7364736f6c634300080c0033",
+	Bin: "0x60806040526000805534801561001457600080fd5b5061016c806100246000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c806306661abd1461005c5780632621002a1461007757806331fe52e8146100835780638bd7b5381461008d578063cb4e8cd114610095575b600080fd5b61006560005481565b60405190815260200160405180910390f35b620f4240600020610065565b61008b61009d565b005b61008b6100c3565b61008b6100e9565b60005b60648110156100c0578060005580806100b89061010d565b9150506100a0565b50565b60005b620186a08110156100c0576104d2600052806100e18161010d565b9150506100c6565b60005b61c3508110156100c0578060005580806101059061010d565b9150506100ec565b600060001982141561012f57634e487b7160e01b600052601160045260246000fd5b506001019056fea26469706673582212208f01c5dc055b1f376f5da5deb33e2c96ee776174bf48874c5ebba0f606de2ac564736f6c634300080c0033",
 }
 
 // TriggerErrorsABI is the input ABI used to generate the binding from.
diff --git a/test/e2e/debug_calltracer_test.go b/test/e2e/debug_calltracer_test.go
index f2a8d756fe..1c28e132c4 100644
--- a/test/e2e/debug_calltracer_test.go
+++ b/test/e2e/debug_calltracer_test.go
@@ -107,6 +107,7 @@ func TestDebugTraceTransactionCallTracer(t *testing.T) {
 		{name: "log0 all zeros", prepare: prepareLog0, createSignedTx: createLog0AllZeros},
 		{name: "log0 empty", prepare: prepareLog0, createSignedTx: createLog0Empty},
 		{name: "log0 short", prepare: prepareLog0, createSignedTx: createLog0Short},
+		{name: "sha256", prepare: prepareSha256, createSignedTx: createSha256},
 
 		// failed transactions
 		{name: "sc deployment reverted", createSignedTx: createScDeployRevertedSignedTx},
diff --git a/test/e2e/debug_shared.go b/test/e2e/debug_shared.go
index f0c78ed663..67fc4dbeb8 100644
--- a/test/e2e/debug_shared.go
+++ b/test/e2e/debug_shared.go
@@ -30,6 +30,7 @@ import (
 	"github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/Memory"
 	"github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/OpCallAux"
 	"github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/Revert2"
+	"github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/Sha"
 	"github.com/0xPolygonHermez/zkevm-node/test/operations"
 	"github.com/0xPolygonHermez/zkevm-node/test/testutils"
 	"github.com/ethereum/go-ethereum"
@@ -953,3 +954,29 @@ func createLog0Short(t *testing.T, ctx context.Context, auth *bind.TransactOpts,
 
 	return tx, nil
 }
+
+func prepareSha256(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client) (map[string]interface{}, error) {
+	_, tx, sc, err := Sha.DeploySha(auth, client)
+	require.NoError(t, err)
+
+	err = operations.WaitTxToBeMined(ctx, client, tx, operations.DefaultTimeoutTxToBeMined)
+	require.NoError(t, err)
+
+	return map[string]interface{}{
+		"sc": sc,
+	}, nil
+}
+
+func createSha256(t *testing.T, ctx context.Context, auth *bind.TransactOpts, client *ethclient.Client, customData map[string]interface{}) (*ethTypes.Transaction, error) {
+	scInterface := customData["sc"]
+	sc := scInterface.(*Sha.Sha)
+
+	opts := *auth
+	opts.NoSend = true
+	opts.GasLimit = fixedTxGasLimit
+
+	tx, err := sc.Hash(&opts)
+	require.NoError(t, err)
+
+	return tx, nil
+}
diff --git a/test/e2e/debug_test.go b/test/e2e/debug_test.go
index 0e425b4f6e..7923e67446 100644
--- a/test/e2e/debug_test.go
+++ b/test/e2e/debug_test.go
@@ -321,6 +321,7 @@ func TestDebugTraceTransaction(t *testing.T) {
 		{name: "log0 all zeros", prepare: prepareLog0, createSignedTx: createLog0AllZeros},
 		{name: "log0 empty", prepare: prepareLog0, createSignedTx: createLog0Empty},
 		{name: "log0 short", prepare: prepareLog0, createSignedTx: createLog0Short},
+		{name: "sha256", prepare: prepareSha256, createSignedTx: createSha256},
 
 		// failed transactions
 		{name: "sc deployment reverted", createSignedTx: createScDeployRevertedSignedTx},
@@ -479,20 +480,27 @@ func TestDebugTraceTransaction(t *testing.T) {
 					referenceStructLogMap := referenceStructLogsMap[structLogIndex].(map[string]interface{})
 					resultStructLogMap := resultStructLogsMap[structLogIndex].(map[string]interface{})
 
-					require.Equal(t, referenceStructLogMap["pc"], resultStructLogMap["pc"], fmt.Sprintf("invalid struct log pc for network %s", networkName))
-					require.Equal(t, referenceStructLogMap["op"], resultStructLogMap["op"], fmt.Sprintf("invalid struct log op for network %s", networkName))
-					require.Equal(t, referenceStructLogMap["depth"], resultStructLogMap["depth"], fmt.Sprintf("invalid struct log depth for network %s", networkName))
+					referencePC := referenceStructLogMap["pc"]
+					referenceOP := referenceStructLogMap["op"]
 
-					pc := referenceStructLogMap["pc"]
-					op := referenceStructLogMap["op"]
+					require.Equal(t, referencePC, resultStructLogMap["pc"], fmt.Sprintf("invalid struct log pc for network %s", networkName))
+					require.Equal(t, referenceOP, resultStructLogMap["op"], fmt.Sprintf("invalid struct log op for network %s pc %v", networkName, referencePC))
+					require.Equal(t, referenceStructLogMap["depth"], resultStructLogMap["depth"], fmt.Sprintf("invalid struct log depth for network %s pc %v op %v", networkName, referencePC, referenceOP))
+
+					referenceReturnData, found := referenceStructLogMap["returnData"].([]interface{})
+					if found {
+						resultReturnData := resultStructLogMap["returnData"].([]interface{})
+
+						require.Equal(t, referenceReturnData, resultReturnData, fmt.Sprintf("return data doesn't match for pc %v op %v", referencePC, referenceOP))
+					}
 
 					referenceStack, found := referenceStructLogMap["stack"].([]interface{})
 					if found {
 						resultStack := resultStructLogMap["stack"].([]interface{})
 
-						require.Equal(t, len(referenceStack), len(resultStack), fmt.Sprintf("stack size doesn't match for pc %v op %v", pc, op))
+						require.Equal(t, len(referenceStack), len(resultStack), fmt.Sprintf("stack size doesn't match for pc %v op %v", referencePC, referenceOP))
 						for stackIndex := range referenceStack {
-							require.Equal(t, referenceStack[stackIndex], resultStack[stackIndex], fmt.Sprintf("stack index %v doesn't match for pc %v op %v", stackIndex, pc, op))
+							require.Equal(t, referenceStack[stackIndex], resultStack[stackIndex], fmt.Sprintf("stack index %v doesn't match for pc %v op %v", stackIndex, referencePC, referenceOP))
 						}
 					}
 
@@ -500,9 +508,9 @@ func TestDebugTraceTransaction(t *testing.T) {
 					if found {
 						resultMemory := resultStructLogMap["memory"].([]interface{})
 
-						require.Equal(t, len(referenceMemory), len(resultMemory), fmt.Sprintf("memory size doesn't match for pc %v op %v", pc, op))
+						require.Equal(t, len(referenceMemory), len(resultMemory), fmt.Sprintf("memory size doesn't match for pc %v op %v", referencePC, referenceOP))
 						for memoryIndex := range referenceMemory {
-							require.Equal(t, referenceMemory[memoryIndex], resultMemory[memoryIndex], fmt.Sprintf("memory index %v doesn't match for pc %v op %v", memoryIndex, pc, op))
+							require.Equal(t, referenceMemory[memoryIndex], resultMemory[memoryIndex], fmt.Sprintf("memory index %v doesn't match for pc %v op %v", memoryIndex, referencePC, referenceOP))
 						}
 					}
 
@@ -510,11 +518,11 @@ func TestDebugTraceTransaction(t *testing.T) {
 					if found {
 						resultStorage := resultStructLogMap["storage"].(map[string]interface{})
 
-						require.Equal(t, len(referenceStorage), len(resultStorage), fmt.Sprintf("storage size doesn't match for pc %v op %v", pc, op))
+						require.Equal(t, len(referenceStorage), len(resultStorage), fmt.Sprintf("storage size doesn't match for pc %v op %v", referencePC, referenceOP))
 						for storageKey, referenceStorageValue := range referenceStorage {
 							resultStorageValue, found := resultStorage[storageKey]
 							require.True(t, found, "storage address not found")
-							require.Equal(t, referenceStorageValue, resultStorageValue, fmt.Sprintf("storage value doesn't match for address %v for pc %v op %v", storageKey, pc, op))
+							require.Equal(t, referenceStorageValue, resultStorageValue, fmt.Sprintf("storage value doesn't match for address %v for pc %v op %v", storageKey, referencePC, referenceOP))
 						}
 					}
 				}

From d20b6b2b981abaec24cc59ac6fd41e661d748435 Mon Sep 17 00:00:00 2001
From: agnusmor <100322135+agnusmor@users.noreply.github.com>
Date: Tue, 30 Jul 2024 10:00:57 +0200
Subject: [PATCH 08/20] Refactor datastream logs (#3743)

* refactor ds logs

* update ds library to v0.2.3
---
 go.mod | 2 +-
 go.sum | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/go.mod b/go.mod
index 9544b9b958..d85ab3ca10 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@ module github.com/0xPolygonHermez/zkevm-node
 go 1.21
 
 require (
-	github.com/0xPolygonHermez/zkevm-data-streamer v0.2.3-RC5
+	github.com/0xPolygonHermez/zkevm-data-streamer v0.2.3
 	github.com/didip/tollbooth/v6 v6.1.2
 	github.com/dop251/goja v0.0.0-20230806174421-c933cf95e127
 	github.com/ethereum/go-ethereum v1.13.11
diff --git a/go.sum b/go.sum
index 4aacd939e6..317b2623cd 100644
--- a/go.sum
+++ b/go.sum
@@ -39,8 +39,8 @@ cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9
 dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
 dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
 dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
-github.com/0xPolygonHermez/zkevm-data-streamer v0.2.3-RC5 h1:ofcfKofJCn3AyOYnEeQ6YbKm0slEKRXk+TbeuvIUymw=
-github.com/0xPolygonHermez/zkevm-data-streamer v0.2.3-RC5/go.mod h1:bv7DjATsczN2WvFt26jv34TWv6rfvYM1SqegrgrFwfI=
+github.com/0xPolygonHermez/zkevm-data-streamer v0.2.3 h1:zJ06KCGLMDOap4slop/QmiMUO+VPsKSS3+944SY06ww=
+github.com/0xPolygonHermez/zkevm-data-streamer v0.2.3/go.mod h1:bv7DjATsczN2WvFt26jv34TWv6rfvYM1SqegrgrFwfI=
 github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
 github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
 github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=

From adf526c97698a0e12bb0de977b51f235f4fb1a51 Mon Sep 17 00:00:00 2001
From: agnusmor <100322135+agnusmor@users.noreply.github.com>
Date: Fri, 2 Aug 2024 14:17:34 +0200
Subject: [PATCH 09/20] Fix tx OOC (node level) when first empty L2 block in
 batch (#3744)

* Fix tx OOC (node level) for first empty L2 block in batch

* change log level for ooc (node level) when adding tx to the worker

* fix check OOC (node level) when preexecuting the tx in RPC

* Fix linter and test
---
 pool/config_test.go      | 23 +++++++++++-------
 pool/pool.go             | 17 ++++++++------
 sequencer/finalizer.go   | 27 +++++++++++++++++----
 sequencer/interfaces.go  |  2 +-
 sequencer/l2block.go     |  2 +-
 sequencer/mock_worker.go | 33 ++++++++++++++++----------
 sequencer/worker.go      | 35 +++++++++++++++++++--------
 sequencer/worker_test.go |  2 +-
 state/config.go          | 51 +++++++++++++++++++++++++++++++---------
 9 files changed, 135 insertions(+), 57 deletions(-)

diff --git a/pool/config_test.go b/pool/config_test.go
index 96b2cd3831..52ae398329 100644
--- a/pool/config_test.go
+++ b/pool/config_test.go
@@ -1,9 +1,11 @@
 package pool
 
 import (
+	"fmt"
 	"testing"
 
 	"github.com/0xPolygonHermez/zkevm-node/state"
+	"github.com/stretchr/testify/assert"
 )
 
 func TestIsWithinConstraints(t *testing.T) {
@@ -20,9 +22,9 @@ func TestIsWithinConstraints(t *testing.T) {
 	}
 
 	testCases := []struct {
-		desc     string
-		counters state.ZKCounters
-		expected bool
+		desc        string
+		counters    state.ZKCounters
+		errExpected error
 	}{
 		{
 			desc: "All constraints within limits",
@@ -37,7 +39,7 @@ func TestIsWithinConstraints(t *testing.T) {
 				Steps:            2000,
 				Sha256Hashes_V2:  4000,
 			},
-			expected: true,
+			errExpected: nil,
 		},
 		{
 			desc: "All constraints exceed limits",
@@ -52,14 +54,17 @@ func TestIsWithinConstraints(t *testing.T) {
 				Steps:            5000,
 				Sha256Hashes_V2:  6000,
 			},
-			expected: false,
+			errExpected: fmt.Errorf("out of counters at node level (GasUsed, KeccakHashes, PoseidonHashes, PoseidonPaddings, MemAligns, Arithmetics, Binaries, Steps, Sha256Hashes)"),
 		},
 	}
 
-	for _, tC := range testCases {
-		t.Run(tC.desc, func(t *testing.T) {
-			if got := cfg.IsWithinConstraints(tC.counters); got != tC.expected {
-				t.Errorf("Expected %v, got %v", tC.expected, got)
+	for _, tc := range testCases {
+		t.Run(tc.desc, func(t *testing.T) {
+			err := cfg.CheckNodeLevelOOC(tc.counters)
+			if tc.errExpected != nil {
+				assert.EqualError(t, err, tc.errExpected.Error())
+			} else {
+				assert.NoError(t, err)
 			}
 		})
 	}
diff --git a/pool/pool.go b/pool/pool.go
index 62f7611ea4..1e5fc50736 100644
--- a/pool/pool.go
+++ b/pool/pool.go
@@ -196,7 +196,16 @@ func (p *Pool) StoreTx(ctx context.Context, tx types.Transaction, ip string, isW
 		return err
 	}
 
+	var oocError error
 	if preExecutionResponse.OOCError != nil {
+		oocError = preExecutionResponse.OOCError
+	} else {
+		if err = p.batchConstraintsCfg.CheckNodeLevelOOC(preExecutionResponse.reservedZKCounters); err != nil {
+			oocError = err
+		}
+	}
+
+	if oocError != nil {
 		event := &event.Event{
 			ReceivedAt:  time.Now(),
 			IPAddress:   ip,
@@ -212,7 +221,7 @@ func (p *Pool) StoreTx(ctx context.Context, tx types.Transaction, ip string, isW
 			log.Errorf("error adding event: %v", err)
 		}
 		// Do not add tx to the pool
-		return fmt.Errorf("failed to add tx to the pool: %w", preExecutionResponse.OOCError)
+		return fmt.Errorf("failed to add tx to the pool: %w", oocError)
 	} else if preExecutionResponse.OOGError != nil {
 		event := &event.Event{
 			ReceivedAt:  time.Now(),
@@ -332,12 +341,6 @@ func (p *Pool) preExecuteTx(ctx context.Context, tx types.Transaction) (preExecu
 			if errors.Is(errorToCheck, runtime.ErrOutOfGas) {
 				response.OOGError = err
 			}
-		} else {
-			if !p.batchConstraintsCfg.IsWithinConstraints(processBatchResponse.UsedZkCounters) {
-				err := fmt.Errorf("OutOfCounters Error (Node level) for tx: %s", tx.Hash().String())
-				response.OOCError = err
-				log.Error(err.Error())
-			}
 		}
 
 		response.usedZKCounters = processBatchResponse.UsedZkCounters
diff --git a/sequencer/finalizer.go b/sequencer/finalizer.go
index 4522a2e50a..f3124e9cc6 100644
--- a/sequencer/finalizer.go
+++ b/sequencer/finalizer.go
@@ -404,9 +404,26 @@ func (f *finalizer) finalizeBatches(ctx context.Context) {
 			f.finalizeWIPL2Block(ctx)
 		}
 
-		tx, err := f.workerIntf.GetBestFittingTx(f.wipBatch.imRemainingResources, f.wipBatch.imHighReservedZKCounters)
+		tx, oocTxs, err := f.workerIntf.GetBestFittingTx(f.wipBatch.imRemainingResources, f.wipBatch.imHighReservedZKCounters, (f.wipBatch.countOfL2Blocks == 0 && f.wipL2Block.isEmpty()))
 
-		// If we have txs pending to process but none of them fits into the wip batch, we close the wip batch and open a new one
+		// Set as invalid txs in the worker pool that will never fit into an empty batch
+		for _, oocTx := range oocTxs {
+			log.Infof("tx %s doesn't fits in empty batch %d (node OOC), setting tx as invalid in the pool", oocTx.HashStr, f.wipL2Block.trackingNum, f.wipBatch.batchNumber)
+
+			f.LogEvent(ctx, event.Level_Info, event.EventID_NodeOOC,
+				fmt.Sprintf("tx %s doesn't fits in empty batch %d (node OOC), from: %s, IP: %s", oocTx.HashStr, f.wipBatch.batchNumber, oocTx.FromStr, oocTx.IP), nil)
+
+			// Delete the transaction from the worker
+			f.workerIntf.DeleteTx(oocTx.Hash, oocTx.From)
+
+			errMsg := "node OOC"
+			err = f.poolIntf.UpdateTxStatus(ctx, oocTx.Hash, pool.TxStatusInvalid, false, &errMsg)
+			if err != nil {
+				log.Errorf("failed to update status to invalid in the pool for tx %s, error: %v", oocTx.Hash.String(), err)
+			}
+		}
+
+		// We have txs pending to process but none of them fits into the wip batch we close the wip batch and open a new one
 		if err == ErrNoFittingTransaction {
 			f.finalizeWIPBatch(ctx, state.NoTxFitsClosingReason)
 			continue
@@ -690,11 +707,11 @@ func (f *finalizer) handleProcessTransactionResponse(ctx context.Context, tx *Tx
 	} else {
 		log.Infof("current tx %s needed resources exceeds the remaining batch resources, overflow resource: %s, updating metadata for tx in worker and continuing. counters: {batch: %s, used: %s, reserved: %s, needed: %s, high: %s}",
 			tx.HashStr, overflowResource, f.logZKCounters(f.wipBatch.imRemainingResources.ZKCounters), f.logZKCounters(result.UsedZkCounters), f.logZKCounters(result.ReservedZkCounters), f.logZKCounters(neededZKCounters), f.logZKCounters(f.wipBatch.imHighReservedZKCounters))
-		if !f.batchConstraints.IsWithinConstraints(result.ReservedZkCounters) {
-			log.Infof("current tx %s reserved resources exceeds the max limit for batch resources (node OOC), setting tx as invalid in the pool", tx.HashStr)
+		if err := f.batchConstraints.CheckNodeLevelOOC(result.ReservedZkCounters); err != nil {
+			log.Infof("current tx %s reserved resources exceeds the max limit for batch resources (node OOC), setting tx as invalid in the pool, error: %v", tx.HashStr, err)
 
 			f.LogEvent(ctx, event.Level_Info, event.EventID_NodeOOC,
-				fmt.Sprintf("tx %s exceeds node max limit batch resources (node OOC), from: %s, IP: %s", tx.HashStr, tx.FromStr, tx.IP), nil)
+				fmt.Sprintf("tx %s exceeds node max limit batch resources (node OOC), from: %s, IP: %s, error: %v", tx.HashStr, tx.FromStr, tx.IP, err), nil)
 
 			// Delete the transaction from the txSorted list
 			f.workerIntf.DeleteTx(tx.Hash, tx.From)
diff --git a/sequencer/interfaces.go b/sequencer/interfaces.go
index 72beb71578..173635f90b 100644
--- a/sequencer/interfaces.go
+++ b/sequencer/interfaces.go
@@ -84,7 +84,7 @@ type stateInterface interface {
 }
 
 type workerInterface interface {
-	GetBestFittingTx(remainingResources state.BatchResources, highReservedCounters state.ZKCounters) (*TxTracker, error)
+	GetBestFittingTx(remainingResources state.BatchResources, highReservedCounters state.ZKCounters, fistL2Block bool) (*TxTracker, []*TxTracker, error)
 	UpdateAfterSingleSuccessfulTxExecution(from common.Address, touchedAddresses map[common.Address]*state.InfoReadWrite) []*TxTracker
 	UpdateTxZKCounters(txHash common.Hash, from common.Address, usedZKCounters state.ZKCounters, reservedZKCounters state.ZKCounters)
 	AddTxTracker(ctx context.Context, txTracker *TxTracker) (replacedTx *TxTracker, dropReason error)
diff --git a/sequencer/l2block.go b/sequencer/l2block.go
index 511d233988..a0da9fd0e3 100644
--- a/sequencer/l2block.go
+++ b/sequencer/l2block.go
@@ -657,7 +657,7 @@ func (f *finalizer) openNewWIPL2Block(ctx context.Context, prevTimestamp uint64,
 
 		f.wipBatch.imHighReservedZKCounters = newHighZKCounters
 	} else {
-		log.Infof("new wip L2 block [%d] reserved resources exceeds the remaining batch resources, overflow resource: %s, closing WIP batch and creating new one. counters: {batch: %s, used: %s, reserved: %s, needed: %s, high: %s}",
+		log.Infof("new wip L2 block [%d] needed resources exceeds the remaining batch resources, overflow resource: %s, closing WIP batch and creating new one. counters: {batch: %s, used: %s, reserved: %s, needed: %s, high: %s}",
 			f.wipL2Block.trackingNum, overflowResource,
 			f.logZKCounters(f.wipBatch.imRemainingResources.ZKCounters), f.logZKCounters(f.wipL2Block.usedZKCountersOnNew), f.logZKCounters(f.wipL2Block.reservedZKCountersOnNew), f.logZKCounters(neededZKCounters), f.logZKCounters(f.wipBatch.imHighReservedZKCounters))
 	}
diff --git a/sequencer/mock_worker.go b/sequencer/mock_worker.go
index 3ff546f724..a627bf5533 100644
--- a/sequencer/mock_worker.go
+++ b/sequencer/mock_worker.go
@@ -70,34 +70,43 @@ func (_m *WorkerMock) DeleteTxPendingToStore(txHash common.Hash, addr common.Add
 	_m.Called(txHash, addr)
 }
 
-// GetBestFittingTx provides a mock function with given fields: remainingResources, highReservedCounters
-func (_m *WorkerMock) GetBestFittingTx(remainingResources state.BatchResources, highReservedCounters state.ZKCounters) (*TxTracker, error) {
-	ret := _m.Called(remainingResources, highReservedCounters)
+// GetBestFittingTx provides a mock function with given fields: remainingResources, highReservedCounters, fistL2Block
+func (_m *WorkerMock) GetBestFittingTx(remainingResources state.BatchResources, highReservedCounters state.ZKCounters, fistL2Block bool) (*TxTracker, []*TxTracker, error) {
+	ret := _m.Called(remainingResources, highReservedCounters, fistL2Block)
 
 	if len(ret) == 0 {
 		panic("no return value specified for GetBestFittingTx")
 	}
 
 	var r0 *TxTracker
-	var r1 error
-	if rf, ok := ret.Get(0).(func(state.BatchResources, state.ZKCounters) (*TxTracker, error)); ok {
-		return rf(remainingResources, highReservedCounters)
+	var r1 []*TxTracker
+	var r2 error
+	if rf, ok := ret.Get(0).(func(state.BatchResources, state.ZKCounters, bool) (*TxTracker, []*TxTracker, error)); ok {
+		return rf(remainingResources, highReservedCounters, fistL2Block)
 	}
-	if rf, ok := ret.Get(0).(func(state.BatchResources, state.ZKCounters) *TxTracker); ok {
-		r0 = rf(remainingResources, highReservedCounters)
+	if rf, ok := ret.Get(0).(func(state.BatchResources, state.ZKCounters, bool) *TxTracker); ok {
+		r0 = rf(remainingResources, highReservedCounters, fistL2Block)
 	} else {
 		if ret.Get(0) != nil {
 			r0 = ret.Get(0).(*TxTracker)
 		}
 	}
 
-	if rf, ok := ret.Get(1).(func(state.BatchResources, state.ZKCounters) error); ok {
-		r1 = rf(remainingResources, highReservedCounters)
+	if rf, ok := ret.Get(1).(func(state.BatchResources, state.ZKCounters, bool) []*TxTracker); ok {
+		r1 = rf(remainingResources, highReservedCounters, fistL2Block)
 	} else {
-		r1 = ret.Error(1)
+		if ret.Get(1) != nil {
+			r1 = ret.Get(1).([]*TxTracker)
+		}
 	}
 
-	return r0, r1
+	if rf, ok := ret.Get(2).(func(state.BatchResources, state.ZKCounters, bool) error); ok {
+		r2 = rf(remainingResources, highReservedCounters, fistL2Block)
+	} else {
+		r2 = ret.Error(2)
+	}
+
+	return r0, r1, r2
 }
 
 // MoveTxPendingToStore provides a mock function with given fields: txHash, addr
diff --git a/sequencer/worker.go b/sequencer/worker.go
index c6be5ed5ab..94a5969cd1 100644
--- a/sequencer/worker.go
+++ b/sequencer/worker.go
@@ -64,8 +64,8 @@ func (w *Worker) addTxTracker(ctx context.Context, tx *TxTracker, mutex *sync.Mu
 	}
 
 	// Make sure the transaction's reserved ZKCounters are within the constraints.
-	if !w.batchConstraints.IsWithinConstraints(tx.ReservedZKCounters) {
-		log.Errorf("outOfCounters error (node level) for tx %s", tx.Hash.String())
+	if err := w.batchConstraints.CheckNodeLevelOOC(tx.ReservedZKCounters); err != nil {
+		log.Infof("out of counters (node level) when adding tx %s from address %s, error: %v", tx.Hash, tx.From, err)
 		mutexUnlock(mutex)
 		return nil, pool.ErrOutOfCounters
 	}
@@ -405,7 +405,7 @@ func (w *Worker) DeleteTxPendingToStore(txHash common.Hash, addr common.Address)
 }
 
 // GetBestFittingTx gets the most efficient tx that fits in the available batch resources
-func (w *Worker) GetBestFittingTx(remainingResources state.BatchResources, highReservedCounters state.ZKCounters) (*TxTracker, error) {
+func (w *Worker) GetBestFittingTx(remainingResources state.BatchResources, highReservedCounters state.ZKCounters, isFistL2BlockAndEmpty bool) (*TxTracker, []*TxTracker, error) {
 	w.workerMutex.Lock()
 	defer w.workerMutex.Unlock()
 
@@ -417,7 +417,7 @@ func (w *Worker) GetBestFittingTx(remainingResources state.BatchResources, highR
 		w.reorgedTxs = w.reorgedTxs[1:]
 		if addrQueue, found := w.pool[reorgedTx.FromStr]; found {
 			if addrQueue.readyTx != nil && addrQueue.readyTx.Hash == reorgedTx.Hash {
-				return reorgedTx, nil
+				return reorgedTx, nil, nil
 			} else {
 				log.Warnf("reorged tx %s is not the ready tx for addrQueue %s, this shouldn't happen", reorgedTx.Hash, reorgedTx.From)
 			}
@@ -427,12 +427,14 @@ func (w *Worker) GetBestFittingTx(remainingResources state.BatchResources, highR
 	}
 
 	if w.txSortedList.len() == 0 {
-		return nil, ErrTransactionsListEmpty
+		return nil, nil, ErrTransactionsListEmpty
 	}
 
 	var (
-		tx         *TxTracker
-		foundMutex sync.RWMutex
+		tx          *TxTracker
+		foundMutex  sync.RWMutex
+		oocTxs      []*TxTracker
+		oocTxsMutex sync.Mutex
 	)
 
 	nGoRoutines := runtime.NumCPU()
@@ -457,7 +459,14 @@ func (w *Worker) GetBestFittingTx(remainingResources state.BatchResources, highR
 				needed, _ := getNeededZKCounters(highReservedCounters, txCandidate.UsedZKCounters, txCandidate.ReservedZKCounters)
 				fits, _ := bresources.Fits(state.BatchResources{ZKCounters: needed, Bytes: txCandidate.Bytes})
 				if !fits {
-					// We don't add this Tx
+					// If we are looking for a tx for the first empty L2 block in the batch and this tx doesn't fits in the batch, then this tx will never fit in any batch.
+					// We add the tx to the oocTxs slice. That slice will be returned to set these txs as invalid (and delete them from the worker) from the finalizer code
+					if isFistL2BlockAndEmpty {
+						oocTxsMutex.Lock()
+						oocTxs = append(oocTxs, txCandidate)
+						oocTxsMutex.Unlock()
+					}
+					// We continue looking for a tx that fits in the batch
 					continue
 				}
 
@@ -477,9 +486,15 @@ func (w *Worker) GetBestFittingTx(remainingResources state.BatchResources, highR
 	if foundAt != -1 {
 		log.Debugf("best fitting tx %s found at index %d with gasPrice %d", tx.HashStr, foundAt, tx.GasPrice)
 		w.wipTx = tx
-		return tx, nil
+		return tx, oocTxs, nil
 	} else {
-		return nil, ErrNoFittingTransaction
+		// If the length of the oocTxs slice is equal to the length of the txSortedList this means that all the txs are ooc,
+		// therefore we need to return an error indicating that the list is empty
+		if w.txSortedList.len() == len(oocTxs) {
+			return nil, oocTxs, ErrTransactionsListEmpty
+		} else {
+			return nil, oocTxs, ErrNoFittingTransaction
+		}
 	}
 }
 
diff --git a/sequencer/worker_test.go b/sequencer/worker_test.go
index 0e2375ad37..3f489cc0be 100644
--- a/sequencer/worker_test.go
+++ b/sequencer/worker_test.go
@@ -258,7 +258,7 @@ func TestWorkerGetBestTx(t *testing.T) {
 	ct := 0
 
 	for {
-		tx, _ := worker.GetBestFittingTx(rc, state.ZKCounters{})
+		tx, _, _ := worker.GetBestFittingTx(rc, state.ZKCounters{}, true)
 		if tx != nil {
 			if ct >= len(expectedGetBestTx) {
 				t.Fatalf("Error getting more best tx than expected. Expected=%d, Actual=%d", len(expectedGetBestTx), ct+1)
diff --git a/state/config.go b/state/config.go
index 61e74e63d6..35975d1977 100644
--- a/state/config.go
+++ b/state/config.go
@@ -1,6 +1,8 @@
 package state
 
 import (
+	"fmt"
+
 	"github.com/0xPolygonHermez/zkevm-node/config/types"
 	"github.com/0xPolygonHermez/zkevm-node/db"
 )
@@ -71,15 +73,42 @@ type BatchConstraintsCfg struct {
 	MaxSHA256Hashes      uint32 `mapstructure:"MaxSHA256Hashes"`
 }
 
-// IsWithinConstraints checks if the counters are within the batch constraints
-func (c BatchConstraintsCfg) IsWithinConstraints(counters ZKCounters) bool {
-	return counters.GasUsed <= c.MaxCumulativeGasUsed &&
-		counters.KeccakHashes <= c.MaxKeccakHashes &&
-		counters.PoseidonHashes <= c.MaxPoseidonHashes &&
-		counters.PoseidonPaddings <= c.MaxPoseidonPaddings &&
-		counters.MemAligns <= c.MaxMemAligns &&
-		counters.Arithmetics <= c.MaxArithmetics &&
-		counters.Binaries <= c.MaxBinaries &&
-		counters.Steps <= c.MaxSteps &&
-		counters.Sha256Hashes_V2 <= c.MaxSHA256Hashes
+// CheckNodeLevelOOC checks if the counters are within the batch constraints
+func (c BatchConstraintsCfg) CheckNodeLevelOOC(counters ZKCounters) error {
+	oocList := ""
+
+	if counters.GasUsed > c.MaxCumulativeGasUsed {
+		oocList += "GasUsed, "
+	}
+	if counters.KeccakHashes > c.MaxKeccakHashes {
+		oocList += "KeccakHashes, "
+	}
+	if counters.PoseidonHashes > c.MaxPoseidonHashes {
+		oocList += "PoseidonHashes, "
+	}
+	if counters.PoseidonPaddings > c.MaxPoseidonPaddings {
+		oocList += "PoseidonPaddings, "
+	}
+	if counters.MemAligns > c.MaxMemAligns {
+		oocList += "MemAligns, "
+	}
+	if counters.Arithmetics > c.MaxArithmetics {
+		oocList += "Arithmetics, "
+	}
+	if counters.Binaries > c.MaxBinaries {
+		oocList += "Binaries, "
+	}
+	if counters.Steps > c.MaxSteps {
+		oocList += "Steps, "
+	}
+	if counters.Sha256Hashes_V2 > c.MaxSHA256Hashes {
+		oocList += "Sha256Hashes, "
+	}
+
+	if oocList != "" {
+		oocList = oocList[:len(oocList)-2] // Remove last comma and blank space
+		return fmt.Errorf("out of counters at node level (%s)", oocList)
+	}
+
+	return nil
 }

From b9e0f644aefbacfbf7c5cff6959701c6fd150c28 Mon Sep 17 00:00:00 2001
From: agnusmor <100322135+agnusmor@users.noreply.github.com>
Date: Fri, 2 Aug 2024 22:03:23 +0200
Subject: [PATCH 10/20] Fix release github action (#3745) (#3747)

* fix releaser

* goreleaser yaml update version 2

* fix goreleaser version

* remove testnet.zip from releaser
---
 .github/workflows/release.yml | 16 +++-------------
 .goreleaser.yaml              |  2 ++
 2 files changed, 5 insertions(+), 13 deletions(-)

diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index f72164cc09..88f939c3d9 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -14,7 +14,7 @@ jobs:
           fetch-depth: 0
 
       - name: Set up Go
-        uses: actions/setup-go@v3
+        uses: actions/setup-go@v5
         with:
           go-version: 1.21
 
@@ -22,9 +22,9 @@ jobs:
         run: go install github.com/gobuffalo/packr/v2/packr2@v2.8.3
 
       - name: Run GoReleaser
-        uses: goreleaser/goreleaser-action@v4
+        uses: goreleaser/goreleaser-action@v6
         with:
-          version: latest
+          version: '~> v2'
           args: release --clean
         env:
           GITHUB_TOKEN: ${{ secrets.TOKEN_RELEASE }}
@@ -45,16 +45,6 @@ jobs:
           mv cardona/config/environments/cardona/example.env cardona
           sed -i -e "s/image: zkevm-node/image: hermeznetwork\/zkevm-node:$GIT_TAG_NAME/g" cardona/docker-compose.yml
           zip -r cardona.zip cardona
-          # TESTNET
-          mkdir -p testnet/config/environments/testnet
-          mkdir -p testnet/db/scripts
-          cp config/environments/testnet/* testnet/config/environments/testnet
-          cp docker-compose.yml testnet
-          sed -i 's/\/config\/environments\/${ZKEVM_NETWORK}/\/config\/environments\/testnet/g' testnet/docker-compose.yml
-          cp db/scripts/init_prover_db.sql testnet/db/scripts
-          mv testnet/config/environments/testnet/example.env testnet
-          sed -i -e "s/image: zkevm-node/image: hermeznetwork\/zkevm-node:$GIT_TAG_NAME/g" testnet/docker-compose.yml
-          zip -r testnet.zip testnet
           # MAINNET
           mkdir -p mainnet/config/environments/mainnet
           mkdir -p mainnet/db/scripts
diff --git a/.goreleaser.yaml b/.goreleaser.yaml
index 09519520d1..c75746b82e 100644
--- a/.goreleaser.yaml
+++ b/.goreleaser.yaml
@@ -1,4 +1,6 @@
 # .goreleaser.yaml
+version: 2
+
 builds:
 - main: ./cmd/
   goos:

From 520c9e3a388226395a1eddb1e6638900dbb46192 Mon Sep 17 00:00:00 2001
From: agnusmor <100322135+agnusmor@users.noreply.github.com>
Date: Mon, 5 Aug 2024 15:42:54 +0200
Subject: [PATCH 11/20] fix invalid "updateGER" entry when updating datastream
 file on startup (#3748)

---
 state/datastream.go | 42 ++++++++++++++++++++++--------------------
 1 file changed, 22 insertions(+), 20 deletions(-)

diff --git a/state/datastream.go b/state/datastream.go
index a9544d4e69..c3aa6c814f 100644
--- a/state/datastream.go
+++ b/state/datastream.go
@@ -436,29 +436,31 @@ func GenerateDataStreamFile(ctx context.Context, streamServer *datastreamer.Stre
 			}
 
 			if len(batch.L2Blocks) == 0 {
-				// Empty batch
-				// Check if there is a GER update
-				if batch.GlobalExitRoot != currentGER && batch.GlobalExitRoot != (common.Hash{}) {
-					updateGER := &datastream.UpdateGER{
-						BatchNumber:    batch.BatchNumber,
-						Timestamp:      uint64(batch.Timestamp.Unix()),
-						GlobalExitRoot: batch.GlobalExitRoot.Bytes(),
-						Coinbase:       batch.Coinbase.Bytes(),
-						ForkId:         batch.ForkID,
-						ChainId:        chainID,
-						StateRoot:      batch.StateRoot.Bytes(),
-					}
+				if !batch.WIP && batch.ForkID < FORKID_ETROG {
+					// Empty batch
+					// Check if there is a GER update
+					if batch.GlobalExitRoot != currentGER && batch.GlobalExitRoot != (common.Hash{}) {
+						updateGER := &datastream.UpdateGER{
+							BatchNumber:    batch.BatchNumber,
+							Timestamp:      uint64(batch.Timestamp.Unix()),
+							GlobalExitRoot: batch.GlobalExitRoot.Bytes(),
+							Coinbase:       batch.Coinbase.Bytes(),
+							ForkId:         batch.ForkID,
+							ChainId:        chainID,
+							StateRoot:      batch.StateRoot.Bytes(),
+						}
 
-					marshalledUpdateGER, err := proto.Marshal(updateGER)
-					if err != nil {
-						return err
-					}
+						marshalledUpdateGER, err := proto.Marshal(updateGER)
+						if err != nil {
+							return err
+						}
 
-					_, err = streamServer.AddStreamEntry(datastreamer.EntryType(datastream.EntryType_ENTRY_TYPE_UPDATE_GER), marshalledUpdateGER)
-					if err != nil {
-						return err
+						_, err = streamServer.AddStreamEntry(datastreamer.EntryType(datastream.EntryType_ENTRY_TYPE_UPDATE_GER), marshalledUpdateGER)
+						if err != nil {
+							return err
+						}
+						currentGER = batch.GlobalExitRoot
 					}
-					currentGER = batch.GlobalExitRoot
 				}
 			} else {
 				for blockIndex, l2Block := range batch.L2Blocks {

From 8735f062b95e2731e82770e55a780e7a99983fef Mon Sep 17 00:00:00 2001
From: agnusmor <100322135+agnusmor@users.noreply.github.com>
Date: Mon, 5 Aug 2024 22:34:52 +0200
Subject: [PATCH 12/20] fix tx order in zkevm_getBatchByNumber endpoint (#3749)

---
 state/pgstatestorage/transaction.go | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/state/pgstatestorage/transaction.go b/state/pgstatestorage/transaction.go
index f25554d44e..109d266726 100644
--- a/state/pgstatestorage/transaction.go
+++ b/state/pgstatestorage/transaction.go
@@ -124,7 +124,13 @@ func (p *PostgresStorage) GetTxsOlderThanNL1Blocks(ctx context.Context, nL1Block
 // GetEncodedTransactionsByBatchNumber returns the encoded field of all
 // transactions in the given batch.
 func (p *PostgresStorage) GetEncodedTransactionsByBatchNumber(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (encodedTxs []string, effectivePercentages []uint8, err error) {
-	const getEncodedTransactionsByBatchNumberSQL = "SELECT encoded, COALESCE(effective_percentage, 255) FROM state.transaction t INNER JOIN state.l2block b ON t.l2_block_num = b.block_num WHERE b.batch_num = $1 ORDER BY l2_block_num ASC"
+	const getEncodedTransactionsByBatchNumberSQL = `
+		SELECT encoded, COALESCE(effective_percentage, 255) FROM state.transaction t 
+		INNER JOIN state.l2block b ON t.l2_block_num = b.block_num 
+		INNER JOIN state.receipt r ON t.hash = r.tx_hash
+		WHERE b.batch_num = $1 
+		ORDER BY l2_block_num, r.tx_index ASC
+		`
 
 	e := p.getExecQuerier(dbTx)
 	rows, err := e.Query(ctx, getEncodedTransactionsByBatchNumberSQL, batchNumber)

From 336b9b0e0d2fbae599fc0a581d6d36a614d262a8 Mon Sep 17 00:00:00 2001
From: zhangkai 
Date: Tue, 6 Aug 2024 14:41:02 +0800
Subject: [PATCH 13/20] Fix asset signer tool (#239)

* update

* fix rollup id

* fix comment

* add docker image

---------

Co-authored-by: JianGuo 
---
 etherman/etherman_xlayer.go     | 2 +-
 test/docker-compose.yml         | 4 ++--
 tools/signer/config/config.go   | 9 +++++----
 tools/signer/service/service.go | 2 ++
 4 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/etherman/etherman_xlayer.go b/etherman/etherman_xlayer.go
index 764af960b4..c04b5c5707 100644
--- a/etherman/etherman_xlayer.go
+++ b/etherman/etherman_xlayer.go
@@ -281,7 +281,7 @@ func NewClient(cfg Config, l1Config L1Config) (*Client, error) {
 	// Get RollupID
 	rollupID, err := rollupManager.RollupAddressToID(&bind.CallOpts{Pending: false}, l1Config.ZkEVMAddr)
 	if err != nil {
-		log.Debugf("error rollupManager.RollupAddressToID(%s). Error: %w", l1Config.RollupManagerAddr, err)
+		log.Debugf("error rollupManager.RollupAddressToID(%s). Error: %w", l1Config.ZkEVMAddr, err)
 		return nil, err
 	}
 	log.Debug("rollupID: ", rollupID)
diff --git a/test/docker-compose.yml b/test/docker-compose.yml
index 3849a69439..5d69f77acd 100644
--- a/test/docker-compose.yml
+++ b/test/docker-compose.yml
@@ -775,7 +775,7 @@ services:
   xlayer-signer:
     container_name: xlayer-signer
     restart: unless-stopped
-    image: xlayer-signer
+    image: giskook/xlayer-signer:0001
     ports:
       - 7001:7001
     volumes:
@@ -887,4 +887,4 @@ services:
       - ENABLE_DEPOSIT_WARNING=true
       - ENABLE_REPORT_FORM=false
       - USE_FIAT_EXCHANGE_RATES=false
-      - SHOW_OUTDATED_NETWORK_MODAL=false
\ No newline at end of file
+      - SHOW_OUTDATED_NETWORK_MODAL=false
diff --git a/tools/signer/config/config.go b/tools/signer/config/config.go
index c6e49db5eb..f1837ccfb7 100644
--- a/tools/signer/config/config.go
+++ b/tools/signer/config/config.go
@@ -25,10 +25,11 @@ type L1 struct {
 	SeqPrivateKey types.KeystoreFileConfig `mapstructure:"SeqPrivateKey"`
 	AggPrivateKey types.KeystoreFileConfig `mapstructure:"AggPrivateKey"`
 
-	PolygonMaticAddress       common.Address `mapstructure:"PolygonMaticAddress"`
-	GlobalExitRootManagerAddr common.Address `mapstructure:"GlobalExitRootManagerAddress"`
-	DataCommitteeAddr         common.Address `mapstructure:"DataCommitteeAddress"`
-	PolygonZkEVMAddress       common.Address `mapstructure:"PolygonZkEVMAddress"`
+	PolygonMaticAddress         common.Address `mapstructure:"PolygonMaticAddress"`
+	GlobalExitRootManagerAddr   common.Address `mapstructure:"GlobalExitRootManagerAddress"`
+	DataCommitteeAddr           common.Address `mapstructure:"DataCommitteeAddress"`
+	PolygonZkEVMAddress         common.Address `mapstructure:"PolygonZkEVMAddress"`
+	PolygonRollupManagerAddress common.Address `mapstructure:"PolygonRollupManagerAddress"`
 }
 
 // Config is the configuration for the tool
diff --git a/tools/signer/service/service.go b/tools/signer/service/service.go
index 4339b527d1..94331fde73 100644
--- a/tools/signer/service/service.go
+++ b/tools/signer/service/service.go
@@ -66,10 +66,12 @@ func NewServer(cfg *config.Config, ctx context.Context) *Server {
 		ZkEVMAddr:                 cfg.L1.PolygonZkEVMAddress,
 		PolAddr:                   cfg.L1.PolygonMaticAddress,
 		GlobalExitRootManagerAddr: cfg.L1.GlobalExitRootManagerAddr,
+		RollupManagerAddr:         cfg.L1.PolygonRollupManagerAddress,
 	}
 
 	var err error
 	srv.ethClient, err = etherman.NewClient(srv.ethCfg, srv.l1Cfg)
+	log.Infof("url: %v, l1 chain id: %v, zkevm addr: %v, rollup manager addr: %v", srv.ethCfg.URL, srv.l1Cfg.L1ChainID, srv.l1Cfg.ZkEVMAddr, srv.l1Cfg.RollupManagerAddr)
 	if err != nil {
 		log.Fatal("error creating etherman client. Error: %v", err)
 	}

From 45a74134e5dcd6c630d8a33bcc4a0d524551a38c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Toni=20Ram=C3=ADrez?=
 <58293609+ToniRamirezM@users.noreply.github.com>
Date: Tue, 6 Aug 2024 10:42:46 +0200
Subject: [PATCH 14/20] add l2blockend to DS (#3751)

* add l2blockend to DS

* move l2blockend creation
---
 .../src/proto/datastream/v1/datastream.proto  |   6 +
 sequencer/sequencer.go                        |  24 +-
 state/datastream.go                           |  75 ++++-
 state/datastream/datastream.pb.go             | 308 +++++++++++-------
 test/config/debug.node.config.toml            |   2 +-
 test/config/test.node.config.toml             |   2 +-
 tools/datastreamer/config/default.go          |   2 +-
 tools/datastreamer/config/tool.config.toml    |   2 +-
 tools/datastreamer/main.go                    |  35 +-
 9 files changed, 329 insertions(+), 127 deletions(-)

diff --git a/proto/src/proto/datastream/v1/datastream.proto b/proto/src/proto/datastream/v1/datastream.proto
index 9cdd0266c1..f514a03db4 100644
--- a/proto/src/proto/datastream/v1/datastream.proto
+++ b/proto/src/proto/datastream/v1/datastream.proto
@@ -36,6 +36,10 @@ message L2Block {
     Debug debug = 14;
 }
 
+message L2BlockEnd {
+  uint64 number = 1;
+}
+
 message Transaction {
     uint64 l2block_number = 1;
     uint64 index = 2;
@@ -79,6 +83,7 @@ enum EntryType {
     ENTRY_TYPE_TRANSACTION = 3;
     ENTRY_TYPE_BATCH_END = 4;
     ENTRY_TYPE_UPDATE_GER = 5;
+    ENTRY_TYPE_L2_BLOCK_END = 6;
 }
 
 enum BatchType {
@@ -86,4 +91,5 @@ enum BatchType {
     BATCH_TYPE_REGULAR = 1;
     BATCH_TYPE_FORCED = 2;
     BATCH_TYPE_INJECTED = 3;
+    BATCH_TYPE_INVALID = 4;
 }
diff --git a/sequencer/sequencer.go b/sequencer/sequencer.go
index eaeab94f33..dbee34221e 100644
--- a/sequencer/sequencer.go
+++ b/sequencer/sequencer.go
@@ -86,7 +86,7 @@ func (s *Sequencer) Start(ctx context.Context) {
 	}
 
 	if s.streamServer != nil {
-		go s.sendDataToStreamer(s.cfg.StreamServer.ChainID)
+		go s.sendDataToStreamer(s.cfg.StreamServer.ChainID, s.cfg.StreamServer.Version)
 	}
 
 	s.workerReadyTxsCond = newTimeoutCond(&sync.Mutex{})
@@ -129,7 +129,7 @@ func (s *Sequencer) checkStateInconsistency(ctx context.Context) {
 }
 
 func (s *Sequencer) updateDataStreamerFile(ctx context.Context, chainID uint64) {
-	err := state.GenerateDataStreamFile(ctx, s.streamServer, s.stateIntf, true, nil, chainID, s.cfg.StreamServer.UpgradeEtrogBatchNumber)
+	err := state.GenerateDataStreamFile(ctx, s.streamServer, s.stateIntf, true, nil, chainID, s.cfg.StreamServer.UpgradeEtrogBatchNumber, s.cfg.StreamServer.Version)
 	if err != nil {
 		log.Fatalf("failed to generate data streamer file, error: %v", err)
 	}
@@ -241,7 +241,7 @@ func (s *Sequencer) addTxToWorker(ctx context.Context, tx pool.Transaction) erro
 }
 
 // sendDataToStreamer sends data to the data stream server
-func (s *Sequencer) sendDataToStreamer(chainID uint64) {
+func (s *Sequencer) sendDataToStreamer(chainID uint64, version uint8) {
 	var err error
 	for {
 		// Read error from previous iteration
@@ -369,6 +369,24 @@ func (s *Sequencer) sendDataToStreamer(chainID uint64) {
 					}
 				}
 
+				if version >= state.DSVersion4 {
+					streamL2BlockEnd := &datastream.L2BlockEnd{
+						Number: l2Block.L2BlockNumber,
+					}
+
+					marshalledL2BlockEnd, err := proto.Marshal(streamL2BlockEnd)
+					if err != nil {
+						log.Errorf("failed to marshal l2block %d, error: %v", l2Block.L2BlockNumber, err)
+						continue
+					}
+
+					_, err = s.streamServer.AddStreamEntry(datastreamer.EntryType(datastream.EntryType_ENTRY_TYPE_L2_BLOCK_END), marshalledL2BlockEnd)
+					if err != nil {
+						log.Errorf("failed to add stream entry for l2blockEnd %d, error: %v", l2Block.L2BlockNumber, err)
+						continue
+					}
+				}
+
 				err = s.streamServer.CommitAtomicOp()
 				if err != nil {
 					log.Errorf("failed to commit atomic op for l2block %d, error: %v ", l2Block.L2BlockNumber, err)
diff --git a/state/datastream.go b/state/datastream.go
index c3aa6c814f..0b6024f3f5 100644
--- a/state/datastream.go
+++ b/state/datastream.go
@@ -23,6 +23,10 @@ const (
 	SystemSC = "0x000000000000000000000000000000005ca1ab1e"
 	// posConstant is the constant used to compute the position of the intermediate state root
 	posConstant = 1
+	// DSVersion3 is the first protobuf version
+	DSVersion3 uint8 = 3
+	// DSVersion4 is the second protobuf version, includes l2BlockEnd
+	DSVersion4 uint8 = 4
 )
 
 // DSBatch represents a data stream batch
@@ -87,7 +91,7 @@ type DSState interface {
 }
 
 // GenerateDataStreamFile generates or resumes a data stream file
-func GenerateDataStreamFile(ctx context.Context, streamServer *datastreamer.StreamServer, stateDB DSState, readWIPBatch bool, imStateRoots *map[uint64][]byte, chainID uint64, upgradeEtrogBatchNumber uint64) error {
+func GenerateDataStreamFile(ctx context.Context, streamServer *datastreamer.StreamServer, stateDB DSState, readWIPBatch bool, imStateRoots *map[uint64][]byte, chainID uint64, upgradeEtrogBatchNumber uint64, version uint8) error {
 	header := streamServer.GetHeader()
 
 	var currentBatchNumber uint64 = 0
@@ -177,6 +181,22 @@ func GenerateDataStreamFile(ctx context.Context, streamServer *datastreamer.Stre
 			return err
 		}
 
+		if version >= DSVersion4 {
+			genesisBlockEnd := &datastream.L2BlockEnd{
+				Number: genesisL2Block.L2BlockNumber,
+			}
+
+			marshalledGenesisBlockEnd, err := proto.Marshal(genesisBlockEnd)
+			if err != nil {
+				return err
+			}
+
+			_, err = streamServer.AddStreamEntry(datastreamer.EntryType(datastream.EntryType_ENTRY_TYPE_L2_BLOCK_END), marshalledGenesisBlockEnd)
+			if err != nil {
+				return err
+			}
+		}
+
 		genesisBatchEnd := &datastream.BatchEnd{
 			Number:        genesisL2Block.BatchNumber,
 			LocalExitRoot: common.Hash{}.Bytes(),
@@ -249,6 +269,43 @@ func GenerateDataStreamFile(ctx context.Context, streamServer *datastreamer.Stre
 			currentBatchNumber = l2Block.BatchNumber
 			previousTimestamp = l2Block.Timestamp
 			lastAddedL2BlockNumber = currentL2BlockNumber
+
+		case datastreamer.EntryType(datastream.EntryType_ENTRY_TYPE_L2_BLOCK_END):
+			log.Info("Latest entry type is L2BlockEnd")
+
+			l2BlockEnd := &datastream.L2BlockEnd{}
+			if err := proto.Unmarshal(latestEntry.Data, l2BlockEnd); err != nil {
+				return err
+			}
+
+			currentL2BlockNumber := l2BlockEnd.Number
+
+			// Getting the l2 block is needed in order to get the batch number and the timestamp
+			bookMark := &datastream.BookMark{
+				Type:  datastream.BookmarkType_BOOKMARK_TYPE_L2_BLOCK,
+				Value: currentL2BlockNumber,
+			}
+
+			marshalledBookMark, err := proto.Marshal(bookMark)
+			if err != nil {
+				return err
+			}
+
+			l2BlockEntry, err := streamServer.GetFirstEventAfterBookmark(marshalledBookMark)
+			if err != nil {
+				return err
+			}
+
+			l2Block := &datastream.L2Block{}
+
+			if err := proto.Unmarshal(l2BlockEntry.Data, l2Block); err != nil {
+				return err
+			}
+
+			currentBatchNumber = l2Block.BatchNumber
+			previousTimestamp = l2Block.Timestamp
+			lastAddedL2BlockNumber = currentL2BlockNumber
+
 		case datastreamer.EntryType(datastream.EntryType_ENTRY_TYPE_TRANSACTION):
 			log.Info("Latest entry type is Transaction")
 
@@ -626,6 +683,22 @@ func GenerateDataStreamFile(ctx context.Context, streamServer *datastreamer.Stre
 					}
 
 					currentGER = l2Block.GlobalExitRoot
+
+					if version >= DSVersion4 {
+						streamL2BlockEnd := &datastream.L2BlockEnd{
+							Number: l2Block.L2BlockNumber,
+						}
+
+						marshalledL2BlockEnd, err := proto.Marshal(streamL2BlockEnd)
+						if err != nil {
+							return err
+						}
+
+						_, err = streamServer.AddStreamEntry(datastreamer.EntryType(datastream.EntryType_ENTRY_TYPE_L2_BLOCK_END), marshalledL2BlockEnd)
+						if err != nil {
+							return err
+						}
+					}
 				}
 			}
 
diff --git a/state/datastream/datastream.pb.go b/state/datastream/datastream.pb.go
index 02a0e2267f..1c9535ee38 100644
--- a/state/datastream/datastream.pb.go
+++ b/state/datastream/datastream.pb.go
@@ -1,7 +1,7 @@
 // Code generated by protoc-gen-go. DO NOT EDIT.
 // versions:
-// 	protoc-gen-go v1.32.0
-// 	protoc        v4.25.3
+// 	protoc-gen-go v1.34.1
+// 	protoc        v5.27.0
 // source: datastream.proto
 
 package datastream
@@ -72,12 +72,13 @@ func (BookmarkType) EnumDescriptor() ([]byte, []int) {
 type EntryType int32
 
 const (
-	EntryType_ENTRY_TYPE_UNSPECIFIED EntryType = 0
-	EntryType_ENTRY_TYPE_BATCH_START EntryType = 1
-	EntryType_ENTRY_TYPE_L2_BLOCK    EntryType = 2
-	EntryType_ENTRY_TYPE_TRANSACTION EntryType = 3
-	EntryType_ENTRY_TYPE_BATCH_END   EntryType = 4
-	EntryType_ENTRY_TYPE_UPDATE_GER  EntryType = 5
+	EntryType_ENTRY_TYPE_UNSPECIFIED  EntryType = 0
+	EntryType_ENTRY_TYPE_BATCH_START  EntryType = 1
+	EntryType_ENTRY_TYPE_L2_BLOCK     EntryType = 2
+	EntryType_ENTRY_TYPE_TRANSACTION  EntryType = 3
+	EntryType_ENTRY_TYPE_BATCH_END    EntryType = 4
+	EntryType_ENTRY_TYPE_UPDATE_GER   EntryType = 5
+	EntryType_ENTRY_TYPE_L2_BLOCK_END EntryType = 6
 )
 
 // Enum value maps for EntryType.
@@ -89,14 +90,16 @@ var (
 		3: "ENTRY_TYPE_TRANSACTION",
 		4: "ENTRY_TYPE_BATCH_END",
 		5: "ENTRY_TYPE_UPDATE_GER",
+		6: "ENTRY_TYPE_L2_BLOCK_END",
 	}
 	EntryType_value = map[string]int32{
-		"ENTRY_TYPE_UNSPECIFIED": 0,
-		"ENTRY_TYPE_BATCH_START": 1,
-		"ENTRY_TYPE_L2_BLOCK":    2,
-		"ENTRY_TYPE_TRANSACTION": 3,
-		"ENTRY_TYPE_BATCH_END":   4,
-		"ENTRY_TYPE_UPDATE_GER":  5,
+		"ENTRY_TYPE_UNSPECIFIED":  0,
+		"ENTRY_TYPE_BATCH_START":  1,
+		"ENTRY_TYPE_L2_BLOCK":     2,
+		"ENTRY_TYPE_TRANSACTION":  3,
+		"ENTRY_TYPE_BATCH_END":    4,
+		"ENTRY_TYPE_UPDATE_GER":   5,
+		"ENTRY_TYPE_L2_BLOCK_END": 6,
 	}
 )
 
@@ -134,6 +137,7 @@ const (
 	BatchType_BATCH_TYPE_REGULAR     BatchType = 1
 	BatchType_BATCH_TYPE_FORCED      BatchType = 2
 	BatchType_BATCH_TYPE_INJECTED    BatchType = 3
+	BatchType_BATCH_TYPE_INVALID     BatchType = 4
 )
 
 // Enum value maps for BatchType.
@@ -143,12 +147,14 @@ var (
 		1: "BATCH_TYPE_REGULAR",
 		2: "BATCH_TYPE_FORCED",
 		3: "BATCH_TYPE_INJECTED",
+		4: "BATCH_TYPE_INVALID",
 	}
 	BatchType_value = map[string]int32{
 		"BATCH_TYPE_UNSPECIFIED": 0,
 		"BATCH_TYPE_REGULAR":     1,
 		"BATCH_TYPE_FORCED":      2,
 		"BATCH_TYPE_INJECTED":    3,
+		"BATCH_TYPE_INVALID":     4,
 	}
 )
 
@@ -480,6 +486,53 @@ func (x *L2Block) GetDebug() *Debug {
 	return nil
 }
 
+type L2BlockEnd struct {
+	state         protoimpl.MessageState
+	sizeCache     protoimpl.SizeCache
+	unknownFields protoimpl.UnknownFields
+
+	Number uint64 `protobuf:"varint,1,opt,name=number,proto3" json:"number,omitempty"`
+}
+
+func (x *L2BlockEnd) Reset() {
+	*x = L2BlockEnd{}
+	if protoimpl.UnsafeEnabled {
+		mi := &file_datastream_proto_msgTypes[3]
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		ms.StoreMessageInfo(mi)
+	}
+}
+
+func (x *L2BlockEnd) String() string {
+	return protoimpl.X.MessageStringOf(x)
+}
+
+func (*L2BlockEnd) ProtoMessage() {}
+
+func (x *L2BlockEnd) ProtoReflect() protoreflect.Message {
+	mi := &file_datastream_proto_msgTypes[3]
+	if protoimpl.UnsafeEnabled && x != nil {
+		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
+		if ms.LoadMessageInfo() == nil {
+			ms.StoreMessageInfo(mi)
+		}
+		return ms
+	}
+	return mi.MessageOf(x)
+}
+
+// Deprecated: Use L2BlockEnd.ProtoReflect.Descriptor instead.
+func (*L2BlockEnd) Descriptor() ([]byte, []int) {
+	return file_datastream_proto_rawDescGZIP(), []int{3}
+}
+
+func (x *L2BlockEnd) GetNumber() uint64 {
+	if x != nil {
+		return x.Number
+	}
+	return 0
+}
+
 type Transaction struct {
 	state         protoimpl.MessageState
 	sizeCache     protoimpl.SizeCache
@@ -497,7 +550,7 @@ type Transaction struct {
 func (x *Transaction) Reset() {
 	*x = Transaction{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_datastream_proto_msgTypes[3]
+		mi := &file_datastream_proto_msgTypes[4]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -510,7 +563,7 @@ func (x *Transaction) String() string {
 func (*Transaction) ProtoMessage() {}
 
 func (x *Transaction) ProtoReflect() protoreflect.Message {
-	mi := &file_datastream_proto_msgTypes[3]
+	mi := &file_datastream_proto_msgTypes[4]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -523,7 +576,7 @@ func (x *Transaction) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use Transaction.ProtoReflect.Descriptor instead.
 func (*Transaction) Descriptor() ([]byte, []int) {
-	return file_datastream_proto_rawDescGZIP(), []int{3}
+	return file_datastream_proto_rawDescGZIP(), []int{4}
 }
 
 func (x *Transaction) GetL2BlockNumber() uint64 {
@@ -593,7 +646,7 @@ type UpdateGER struct {
 func (x *UpdateGER) Reset() {
 	*x = UpdateGER{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_datastream_proto_msgTypes[4]
+		mi := &file_datastream_proto_msgTypes[5]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -606,7 +659,7 @@ func (x *UpdateGER) String() string {
 func (*UpdateGER) ProtoMessage() {}
 
 func (x *UpdateGER) ProtoReflect() protoreflect.Message {
-	mi := &file_datastream_proto_msgTypes[4]
+	mi := &file_datastream_proto_msgTypes[5]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -619,7 +672,7 @@ func (x *UpdateGER) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use UpdateGER.ProtoReflect.Descriptor instead.
 func (*UpdateGER) Descriptor() ([]byte, []int) {
-	return file_datastream_proto_rawDescGZIP(), []int{4}
+	return file_datastream_proto_rawDescGZIP(), []int{5}
 }
 
 func (x *UpdateGER) GetBatchNumber() uint64 {
@@ -690,7 +743,7 @@ type BookMark struct {
 func (x *BookMark) Reset() {
 	*x = BookMark{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_datastream_proto_msgTypes[5]
+		mi := &file_datastream_proto_msgTypes[6]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -703,7 +756,7 @@ func (x *BookMark) String() string {
 func (*BookMark) ProtoMessage() {}
 
 func (x *BookMark) ProtoReflect() protoreflect.Message {
-	mi := &file_datastream_proto_msgTypes[5]
+	mi := &file_datastream_proto_msgTypes[6]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -716,7 +769,7 @@ func (x *BookMark) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use BookMark.ProtoReflect.Descriptor instead.
 func (*BookMark) Descriptor() ([]byte, []int) {
-	return file_datastream_proto_rawDescGZIP(), []int{5}
+	return file_datastream_proto_rawDescGZIP(), []int{6}
 }
 
 func (x *BookMark) GetType() BookmarkType {
@@ -744,7 +797,7 @@ type Debug struct {
 func (x *Debug) Reset() {
 	*x = Debug{}
 	if protoimpl.UnsafeEnabled {
-		mi := &file_datastream_proto_msgTypes[6]
+		mi := &file_datastream_proto_msgTypes[7]
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		ms.StoreMessageInfo(mi)
 	}
@@ -757,7 +810,7 @@ func (x *Debug) String() string {
 func (*Debug) ProtoMessage() {}
 
 func (x *Debug) ProtoReflect() protoreflect.Message {
-	mi := &file_datastream_proto_msgTypes[6]
+	mi := &file_datastream_proto_msgTypes[7]
 	if protoimpl.UnsafeEnabled && x != nil {
 		ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
 		if ms.LoadMessageInfo() == nil {
@@ -770,7 +823,7 @@ func (x *Debug) ProtoReflect() protoreflect.Message {
 
 // Deprecated: Use Debug.ProtoReflect.Descriptor instead.
 func (*Debug) Descriptor() ([]byte, []int) {
-	return file_datastream_proto_rawDescGZIP(), []int{6}
+	return file_datastream_proto_rawDescGZIP(), []int{7}
 }
 
 func (x *Debug) GetMessage() string {
@@ -837,77 +890,83 @@ var file_datastream_proto_rawDesc = []byte{
 	0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2a, 0x0a, 0x05, 0x64, 0x65, 0x62,
 	0x75, 0x67, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x73,
 	0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x52, 0x05,
-	0x64, 0x65, 0x62, 0x75, 0x67, 0x22, 0x94, 0x02, 0x0a, 0x0b, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61,
-	0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x6c, 0x32, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
-	0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0d, 0x6c,
-	0x32, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05,
-	0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64,
-	0x65, 0x78, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x18, 0x03,
-	0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x12, 0x18, 0x0a,
-	0x07, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07,
-	0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x12, 0x43, 0x0a, 0x1e, 0x65, 0x66, 0x66, 0x65, 0x63,
-	0x74, 0x69, 0x76, 0x65, 0x5f, 0x67, 0x61, 0x73, 0x5f, 0x70, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x70,
-	0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52,
-	0x1b, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x47, 0x61, 0x73, 0x50, 0x72, 0x69,
-	0x63, 0x65, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x61, 0x67, 0x65, 0x12, 0x22, 0x0a, 0x0d,
-	0x69, 0x6d, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x06, 0x20,
-	0x01, 0x28, 0x0c, 0x52, 0x0b, 0x69, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74,
-	0x12, 0x2a, 0x0a, 0x05, 0x64, 0x65, 0x62, 0x75, 0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32,
-	0x14, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x76, 0x31, 0x2e,
-	0x44, 0x65, 0x62, 0x75, 0x67, 0x52, 0x05, 0x64, 0x65, 0x62, 0x75, 0x67, 0x22, 0x91, 0x02, 0x0a,
-	0x09, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x47, 0x45, 0x52, 0x12, 0x21, 0x0a, 0x0c, 0x62, 0x61,
-	0x74, 0x63, 0x68, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04,
-	0x52, 0x0b, 0x62, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x1c, 0x0a,
-	0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04,
-	0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x28, 0x0a, 0x10, 0x67,
-	0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x65, 0x78, 0x69, 0x74, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18,
-	0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x45, 0x78, 0x69,
-	0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73,
-	0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73,
-	0x65, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x6f, 0x72, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01,
-	0x28, 0x04, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6b, 0x49, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x68,
-	0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x63, 0x68,
-	0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72,
-	0x6f, 0x6f, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65,
-	0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2a, 0x0a, 0x05, 0x64, 0x65, 0x62, 0x75, 0x67, 0x18, 0x08, 0x20,
-	0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d,
-	0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x52, 0x05, 0x64, 0x65, 0x62, 0x75, 0x67,
-	0x22, 0x51, 0x0a, 0x08, 0x42, 0x6f, 0x6f, 0x6b, 0x4d, 0x61, 0x72, 0x6b, 0x12, 0x2f, 0x0a, 0x04,
-	0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1b, 0x2e, 0x64, 0x61, 0x74,
-	0x61, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x6f, 0x6b, 0x6d,
-	0x61, 0x72, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a,
-	0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x76, 0x61,
-	0x6c, 0x75, 0x65, 0x22, 0x21, 0x0a, 0x05, 0x44, 0x65, 0x62, 0x75, 0x67, 0x12, 0x18, 0x0a, 0x07,
-	0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d,
-	0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2a, 0x62, 0x0a, 0x0c, 0x42, 0x6f, 0x6f, 0x6b, 0x6d, 0x61,
-	0x72, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x42, 0x4f, 0x4f, 0x4b, 0x4d, 0x41,
-	0x52, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46,
-	0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x42, 0x4f, 0x4f, 0x4b, 0x4d, 0x41, 0x52,
-	0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x41, 0x54, 0x43, 0x48, 0x10, 0x01, 0x12, 0x1a,
-	0x0a, 0x16, 0x42, 0x4f, 0x4f, 0x4b, 0x4d, 0x41, 0x52, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f,
-	0x4c, 0x32, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x10, 0x02, 0x2a, 0xad, 0x01, 0x0a, 0x09, 0x45,
-	0x6e, 0x74, 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x45, 0x4e, 0x54, 0x52,
-	0x59, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49,
-	0x45, 0x44, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x45, 0x4e, 0x54, 0x52, 0x59, 0x5f, 0x54, 0x59,
-	0x50, 0x45, 0x5f, 0x42, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x10, 0x01,
-	0x12, 0x17, 0x0a, 0x13, 0x45, 0x4e, 0x54, 0x52, 0x59, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4c,
-	0x32, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x45, 0x4e, 0x54,
-	0x52, 0x59, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x54, 0x52, 0x41, 0x4e, 0x53, 0x41, 0x43, 0x54,
-	0x49, 0x4f, 0x4e, 0x10, 0x03, 0x12, 0x18, 0x0a, 0x14, 0x45, 0x4e, 0x54, 0x52, 0x59, 0x5f, 0x54,
-	0x59, 0x50, 0x45, 0x5f, 0x42, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x45, 0x4e, 0x44, 0x10, 0x04, 0x12,
-	0x19, 0x0a, 0x15, 0x45, 0x4e, 0x54, 0x52, 0x59, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x50,
-	0x44, 0x41, 0x54, 0x45, 0x5f, 0x47, 0x45, 0x52, 0x10, 0x05, 0x2a, 0x6f, 0x0a, 0x09, 0x42, 0x61,
-	0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x42, 0x41, 0x54, 0x43, 0x48,
-	0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45,
-	0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x42, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50,
-	0x45, 0x5f, 0x52, 0x45, 0x47, 0x55, 0x4c, 0x41, 0x52, 0x10, 0x01, 0x12, 0x15, 0x0a, 0x11, 0x42,
-	0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x44,
-	0x10, 0x02, 0x12, 0x17, 0x0a, 0x13, 0x42, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45,
-	0x5f, 0x49, 0x4e, 0x4a, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x03, 0x42, 0x38, 0x5a, 0x36, 0x67,
-	0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x78, 0x50, 0x6f, 0x6c, 0x79,
-	0x67, 0x6f, 0x6e, 0x48, 0x65, 0x72, 0x6d, 0x65, 0x7a, 0x2f, 0x7a, 0x6b, 0x65, 0x76, 0x6d, 0x2d,
-	0x6e, 0x6f, 0x64, 0x65, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x73,
-	0x74, 0x72, 0x65, 0x61, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+	0x64, 0x65, 0x62, 0x75, 0x67, 0x22, 0x24, 0x0a, 0x0a, 0x4c, 0x32, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
+	0x45, 0x6e, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x04, 0x52, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x94, 0x02, 0x0a, 0x0b,
+	0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0e, 0x6c,
+	0x32, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x04, 0x52, 0x0d, 0x6c, 0x32, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x4e, 0x75, 0x6d, 0x62,
+	0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28,
+	0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x73, 0x5f, 0x76,
+	0x61, 0x6c, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x69, 0x73, 0x56, 0x61,
+	0x6c, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x18, 0x04,
+	0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x12, 0x43, 0x0a,
+	0x1e, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x67, 0x61, 0x73, 0x5f, 0x70,
+	0x72, 0x69, 0x63, 0x65, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x61, 0x67, 0x65, 0x18,
+	0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x1b, 0x65, 0x66, 0x66, 0x65, 0x63, 0x74, 0x69, 0x76, 0x65,
+	0x47, 0x61, 0x73, 0x50, 0x72, 0x69, 0x63, 0x65, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x61,
+	0x67, 0x65, 0x12, 0x22, 0x0a, 0x0d, 0x69, 0x6d, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x5f, 0x72,
+	0x6f, 0x6f, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x69, 0x6d, 0x53, 0x74, 0x61,
+	0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2a, 0x0a, 0x05, 0x64, 0x65, 0x62, 0x75, 0x67, 0x18,
+	0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x72, 0x65,
+	0x61, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x52, 0x05, 0x64, 0x65, 0x62,
+	0x75, 0x67, 0x22, 0x91, 0x02, 0x0a, 0x09, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x47, 0x45, 0x52,
+	0x12, 0x21, 0x0a, 0x0c, 0x62, 0x61, 0x74, 0x63, 0x68, 0x5f, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72,
+	0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x62, 0x61, 0x74, 0x63, 0x68, 0x4e, 0x75, 0x6d,
+	0x62, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
+	0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
+	0x70, 0x12, 0x28, 0x0a, 0x10, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x65, 0x78, 0x69, 0x74,
+	0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x67, 0x6c, 0x6f,
+	0x62, 0x61, 0x6c, 0x45, 0x78, 0x69, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x63,
+	0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63,
+	0x6f, 0x69, 0x6e, 0x62, 0x61, 0x73, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x6f, 0x72, 0x6b, 0x5f,
+	0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6b, 0x49, 0x64,
+	0x12, 0x19, 0x0a, 0x08, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01,
+	0x28, 0x04, 0x52, 0x07, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x73,
+	0x74, 0x61, 0x74, 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52,
+	0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x2a, 0x0a, 0x05, 0x64, 0x65,
+	0x62, 0x75, 0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x64, 0x61, 0x74, 0x61,
+	0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x62, 0x75, 0x67, 0x52,
+	0x05, 0x64, 0x65, 0x62, 0x75, 0x67, 0x22, 0x51, 0x0a, 0x08, 0x42, 0x6f, 0x6f, 0x6b, 0x4d, 0x61,
+	0x72, 0x6b, 0x12, 0x2f, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e,
+	0x32, 0x1b, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x2e, 0x76, 0x31,
+	0x2e, 0x42, 0x6f, 0x6f, 0x6b, 0x6d, 0x61, 0x72, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74,
+	0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01,
+	0x28, 0x04, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x22, 0x21, 0x0a, 0x05, 0x44, 0x65, 0x62,
+	0x75, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20,
+	0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x2a, 0x62, 0x0a, 0x0c,
+	0x42, 0x6f, 0x6f, 0x6b, 0x6d, 0x61, 0x72, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x19,
+	0x42, 0x4f, 0x4f, 0x4b, 0x4d, 0x41, 0x52, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e,
+	0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x42,
+	0x4f, 0x4f, 0x4b, 0x4d, 0x41, 0x52, 0x4b, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x41, 0x54,
+	0x43, 0x48, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x42, 0x4f, 0x4f, 0x4b, 0x4d, 0x41, 0x52, 0x4b,
+	0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4c, 0x32, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x10, 0x02,
+	0x2a, 0xca, 0x01, 0x0a, 0x09, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a,
+	0x0a, 0x16, 0x45, 0x4e, 0x54, 0x52, 0x59, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53,
+	0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x1a, 0x0a, 0x16, 0x45, 0x4e,
+	0x54, 0x52, 0x59, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x53,
+	0x54, 0x41, 0x52, 0x54, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x45, 0x4e, 0x54, 0x52, 0x59, 0x5f,
+	0x54, 0x59, 0x50, 0x45, 0x5f, 0x4c, 0x32, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x10, 0x02, 0x12,
+	0x1a, 0x0a, 0x16, 0x45, 0x4e, 0x54, 0x52, 0x59, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x54, 0x52,
+	0x41, 0x4e, 0x53, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x10, 0x03, 0x12, 0x18, 0x0a, 0x14, 0x45,
+	0x4e, 0x54, 0x52, 0x59, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x42, 0x41, 0x54, 0x43, 0x48, 0x5f,
+	0x45, 0x4e, 0x44, 0x10, 0x04, 0x12, 0x19, 0x0a, 0x15, 0x45, 0x4e, 0x54, 0x52, 0x59, 0x5f, 0x54,
+	0x59, 0x50, 0x45, 0x5f, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x47, 0x45, 0x52, 0x10, 0x05,
+	0x12, 0x1b, 0x0a, 0x17, 0x45, 0x4e, 0x54, 0x52, 0x59, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x4c,
+	0x32, 0x5f, 0x42, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x45, 0x4e, 0x44, 0x10, 0x06, 0x2a, 0x87, 0x01,
+	0x0a, 0x09, 0x42, 0x61, 0x74, 0x63, 0x68, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x42,
+	0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43,
+	0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x42, 0x41, 0x54, 0x43, 0x48,
+	0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x52, 0x45, 0x47, 0x55, 0x4c, 0x41, 0x52, 0x10, 0x01, 0x12,
+	0x15, 0x0a, 0x11, 0x42, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x46, 0x4f,
+	0x52, 0x43, 0x45, 0x44, 0x10, 0x02, 0x12, 0x17, 0x0a, 0x13, 0x42, 0x41, 0x54, 0x43, 0x48, 0x5f,
+	0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e, 0x4a, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x03, 0x12,
+	0x16, 0x0a, 0x12, 0x42, 0x41, 0x54, 0x43, 0x48, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x49, 0x4e,
+	0x56, 0x41, 0x4c, 0x49, 0x44, 0x10, 0x04, 0x42, 0x38, 0x5a, 0x36, 0x67, 0x69, 0x74, 0x68, 0x75,
+	0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x30, 0x78, 0x50, 0x6f, 0x6c, 0x79, 0x67, 0x6f, 0x6e, 0x48,
+	0x65, 0x72, 0x6d, 0x65, 0x7a, 0x2f, 0x7a, 0x6b, 0x65, 0x76, 0x6d, 0x2d, 0x6e, 0x6f, 0x64, 0x65,
+	0x2f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x73, 0x74, 0x72, 0x65, 0x61,
+	0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
 }
 
 var (
@@ -923,7 +982,7 @@ func file_datastream_proto_rawDescGZIP() []byte {
 }
 
 var file_datastream_proto_enumTypes = make([]protoimpl.EnumInfo, 3)
-var file_datastream_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
+var file_datastream_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
 var file_datastream_proto_goTypes = []interface{}{
 	(BookmarkType)(0),   // 0: datastream.v1.BookmarkType
 	(EntryType)(0),      // 1: datastream.v1.EntryType
@@ -931,24 +990,25 @@ var file_datastream_proto_goTypes = []interface{}{
 	(*BatchStart)(nil),  // 3: datastream.v1.BatchStart
 	(*BatchEnd)(nil),    // 4: datastream.v1.BatchEnd
 	(*L2Block)(nil),     // 5: datastream.v1.L2Block
-	(*Transaction)(nil), // 6: datastream.v1.Transaction
-	(*UpdateGER)(nil),   // 7: datastream.v1.UpdateGER
-	(*BookMark)(nil),    // 8: datastream.v1.BookMark
-	(*Debug)(nil),       // 9: datastream.v1.Debug
+	(*L2BlockEnd)(nil),  // 6: datastream.v1.L2BlockEnd
+	(*Transaction)(nil), // 7: datastream.v1.Transaction
+	(*UpdateGER)(nil),   // 8: datastream.v1.UpdateGER
+	(*BookMark)(nil),    // 9: datastream.v1.BookMark
+	(*Debug)(nil),       // 10: datastream.v1.Debug
 }
 var file_datastream_proto_depIdxs = []int32{
-	2, // 0: datastream.v1.BatchStart.type:type_name -> datastream.v1.BatchType
-	9, // 1: datastream.v1.BatchStart.debug:type_name -> datastream.v1.Debug
-	9, // 2: datastream.v1.BatchEnd.debug:type_name -> datastream.v1.Debug
-	9, // 3: datastream.v1.L2Block.debug:type_name -> datastream.v1.Debug
-	9, // 4: datastream.v1.Transaction.debug:type_name -> datastream.v1.Debug
-	9, // 5: datastream.v1.UpdateGER.debug:type_name -> datastream.v1.Debug
-	0, // 6: datastream.v1.BookMark.type:type_name -> datastream.v1.BookmarkType
-	7, // [7:7] is the sub-list for method output_type
-	7, // [7:7] is the sub-list for method input_type
-	7, // [7:7] is the sub-list for extension type_name
-	7, // [7:7] is the sub-list for extension extendee
-	0, // [0:7] is the sub-list for field type_name
+	2,  // 0: datastream.v1.BatchStart.type:type_name -> datastream.v1.BatchType
+	10, // 1: datastream.v1.BatchStart.debug:type_name -> datastream.v1.Debug
+	10, // 2: datastream.v1.BatchEnd.debug:type_name -> datastream.v1.Debug
+	10, // 3: datastream.v1.L2Block.debug:type_name -> datastream.v1.Debug
+	10, // 4: datastream.v1.Transaction.debug:type_name -> datastream.v1.Debug
+	10, // 5: datastream.v1.UpdateGER.debug:type_name -> datastream.v1.Debug
+	0,  // 6: datastream.v1.BookMark.type:type_name -> datastream.v1.BookmarkType
+	7,  // [7:7] is the sub-list for method output_type
+	7,  // [7:7] is the sub-list for method input_type
+	7,  // [7:7] is the sub-list for extension type_name
+	7,  // [7:7] is the sub-list for extension extendee
+	0,  // [0:7] is the sub-list for field type_name
 }
 
 func init() { file_datastream_proto_init() }
@@ -994,7 +1054,7 @@ func file_datastream_proto_init() {
 			}
 		}
 		file_datastream_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*Transaction); i {
+			switch v := v.(*L2BlockEnd); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1006,7 +1066,7 @@ func file_datastream_proto_init() {
 			}
 		}
 		file_datastream_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*UpdateGER); i {
+			switch v := v.(*Transaction); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1018,7 +1078,7 @@ func file_datastream_proto_init() {
 			}
 		}
 		file_datastream_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
-			switch v := v.(*BookMark); i {
+			switch v := v.(*UpdateGER); i {
 			case 0:
 				return &v.state
 			case 1:
@@ -1030,6 +1090,18 @@ func file_datastream_proto_init() {
 			}
 		}
 		file_datastream_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
+			switch v := v.(*BookMark); i {
+			case 0:
+				return &v.state
+			case 1:
+				return &v.sizeCache
+			case 2:
+				return &v.unknownFields
+			default:
+				return nil
+			}
+		}
+		file_datastream_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
 			switch v := v.(*Debug); i {
 			case 0:
 				return &v.state
@@ -1048,7 +1120,7 @@ func file_datastream_proto_init() {
 			GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
 			RawDescriptor: file_datastream_proto_rawDesc,
 			NumEnums:      3,
-			NumMessages:   7,
+			NumMessages:   8,
 			NumExtensions: 0,
 			NumServices:   0,
 		},
diff --git a/test/config/debug.node.config.toml b/test/config/debug.node.config.toml
index 7ec0d496ea..ee79039ed3 100644
--- a/test/config/debug.node.config.toml
+++ b/test/config/debug.node.config.toml
@@ -111,7 +111,7 @@ StateConsistencyCheckInterval = "5s"
 	[Sequencer.StreamServer]
 		Port = 6900
 		Filename = "/datastreamer/datastream.bin"
-		Version = 1
+		Version = 4
 		WriteTimeout = "5s"
 		InactivityTimeout = "120s"
 		InactivityCheckInterval = "5s"
diff --git a/test/config/test.node.config.toml b/test/config/test.node.config.toml
index d13ff02ca5..040ef7058c 100644
--- a/test/config/test.node.config.toml
+++ b/test/config/test.node.config.toml
@@ -126,7 +126,7 @@ StateConsistencyCheckInterval = "5s"
 	[Sequencer.StreamServer]
 		Port = 6900
 		Filename = "/datastreamer/datastream.bin"
-		Version = 1
+		Version = 4
 		ChainID = 1337
 		WriteTimeout = "5s"
 		InactivityTimeout = "120s"
diff --git a/tools/datastreamer/config/default.go b/tools/datastreamer/config/default.go
index 74c6f35b24..dc7aa3bacf 100644
--- a/tools/datastreamer/config/default.go
+++ b/tools/datastreamer/config/default.go
@@ -9,7 +9,7 @@ StreamType = 1
 [Offline]
 Port = 6901
 Filename = "datastreamer.bin"
-Version = 1
+Version = 4
 ChainID = 1440
 UpgradeEtrogBatchNumber = 0
 
diff --git a/tools/datastreamer/config/tool.config.toml b/tools/datastreamer/config/tool.config.toml
index 60d04aafb3..8309edfe76 100644
--- a/tools/datastreamer/config/tool.config.toml
+++ b/tools/datastreamer/config/tool.config.toml
@@ -5,7 +5,7 @@ StreamType = 1
 [Offline]
 Port = 6901
 Filename = "datastream.bin"
-Version = 3
+Version = 4
 ChainID = 1440
 WriteTimeout = "5s"
 InactivityTimeout = "120s"
diff --git a/tools/datastreamer/main.go b/tools/datastreamer/main.go
index c6b43155f8..b0bc2680a0 100644
--- a/tools/datastreamer/main.go
+++ b/tools/datastreamer/main.go
@@ -297,7 +297,7 @@ func generate(cliCtx *cli.Context) error {
 		}
 	}
 
-	err = state.GenerateDataStreamFile(cliCtx.Context, streamServer, stateDB, false, &imStateRoots, c.Offline.ChainID, c.Offline.UpgradeEtrogBatchNumber)
+	err = state.GenerateDataStreamFile(cliCtx.Context, streamServer, stateDB, false, &imStateRoots, c.Offline.ChainID, c.Offline.UpgradeEtrogBatchNumber, c.Offline.Version)
 	if err != nil {
 		log.Error(err)
 		os.Exit(1)
@@ -424,6 +424,15 @@ func decodeL2Block(cliCtx *cli.Context) error {
 		i++
 	}
 
+	if c.Offline.Version >= state.DSVersion4 {
+		l2BlockEnd, err := client.ExecCommandGetEntry(secondEntry.Number)
+		if err != nil {
+			log.Error(err)
+			os.Exit(1)
+		}
+		printEntry(l2BlockEnd)
+	}
+
 	return nil
 }
 
@@ -505,6 +514,15 @@ func decodeL2BlockOffline(cliCtx *cli.Context) error {
 		i++
 	}
 
+	if c.Offline.Version >= state.DSVersion4 {
+		l2BlockEnd, err := streamServer.GetEntry(secondEntry.Number)
+		if err != nil {
+			log.Error(err)
+			os.Exit(1)
+		}
+		printEntry(l2BlockEnd)
+	}
+
 	return nil
 }
 
@@ -761,6 +779,21 @@ func printEntry(entry datastreamer.FileEntry) {
 			printColored(color.FgHiWhite, fmt.Sprintf("%s\n", l2Block.Debug))
 		}
 
+	case datastreamer.EntryType(datastream.EntryType_ENTRY_TYPE_L2_BLOCK_END):
+		l2BlockEnd := &datastream.L2BlockEnd{}
+		err := proto.Unmarshal(entry.Data, l2BlockEnd)
+		if err != nil {
+			log.Error(err)
+			os.Exit(1)
+		}
+
+		printColored(color.FgGreen, "Entry Type......: ")
+		printColored(color.FgHiYellow, "L2 Block End\n")
+		printColored(color.FgGreen, "Entry Number....: ")
+		printColored(color.FgHiWhite, fmt.Sprintf("%d\n", entry.Number))
+		printColored(color.FgGreen, "L2 Block Number.: ")
+		printColored(color.FgHiWhite, fmt.Sprintf("%d\n", l2BlockEnd.Number))
+
 	case datastreamer.EntryType(datastream.EntryType_ENTRY_TYPE_BATCH_START):
 		batch := &datastream.BatchStart{}
 		err := proto.Unmarshal(entry.Data, batch)

From a774dc9bb0aa7bd23ff6f3c0db21960d9b69e1fd Mon Sep 17 00:00:00 2001
From: agnusmor <100322135+agnusmor@users.noreply.github.com>
Date: Wed, 7 Aug 2024 11:45:00 +0200
Subject: [PATCH 15/20] Fix timestamp when querying zkevm_getBatchByNumer and
 the batch is only in trusted state (#3750)

* fix timestamp when querying zkevm_getBatchByNumer and the batch is only in trusted state

* control timestamp to be returned for a batch in GetBatchTimestamp

* fix ErrNotFound

* fix state.ErrNotFound check

* fix comments

* fix GetRawBatchTimestamps

* fix comments

* fix GetRawBatchTimestamps return err
---
 state/batch.go                | 23 ++++++++++++++++++++---
 state/pgstatestorage/batch.go |  2 +-
 2 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/state/batch.go b/state/batch.go
index f5325a08c7..c52d2eb278 100644
--- a/state/batch.go
+++ b/state/batch.go
@@ -568,10 +568,13 @@ func (s *State) GetLastBatch(ctx context.Context, dbTx pgx.Tx) (*Batch, error) {
 	return batches[0], nil
 }
 
-// GetBatchTimestamp returns the batch timestamp.
+// GetBatchTimestamp returns the batch timestamp
+// If batch >= etrog
 //
-//	   for >= etrog is stored on virtual_batch.batch_timestamp
-//		  previous batches is stored on batch.timestamp
+//	if the batch it's virtualized it will return virtual_batch.timestamp_batch_etrog field value
+//	if the batch if's only trusted and it has L2 blocks it will return the timestamp of the last L2 block, otherwise it will return batchTimestamp
+//
+// If batch < etrog it will return batchTimestamp value
 func (s *State) GetBatchTimestamp(ctx context.Context, batchNumber uint64, forcedForkId *uint64, dbTx pgx.Tx) (*time.Time, error) {
 	var forkid uint64
 	if forcedForkId != nil {
@@ -584,6 +587,20 @@ func (s *State) GetBatchTimestamp(ctx context.Context, batchNumber uint64, force
 		return nil, err
 	}
 	if forkid >= FORKID_ETROG {
+		if virtualTimestamp == nil {
+			lastL2Block, err := s.GetLastL2BlockByBatchNumber(ctx, batchNumber, dbTx)
+			if err != nil && !errors.Is(err, ErrNotFound) {
+				return nil, err
+			}
+
+			// If the batch has L2 blocks we will return the timestamp of the last L2 block as the timestamp of the batch
+			// else we will return the batchTimestamp value (timestamp of batch creation)
+			if lastL2Block != nil {
+				return &lastL2Block.ReceivedAt, nil
+			}
+
+			return batchTimestamp, nil
+		}
 		return virtualTimestamp, nil
 	}
 	return batchTimestamp, nil
diff --git a/state/pgstatestorage/batch.go b/state/pgstatestorage/batch.go
index b0b1aa6389..bbe12a355a 100644
--- a/state/pgstatestorage/batch.go
+++ b/state/pgstatestorage/batch.go
@@ -995,7 +995,7 @@ func (p *PostgresStorage) BuildChangeL2Block(deltaTimestamp uint32, l1InfoTreeIn
 }
 
 // GetRawBatchTimestamps returns the timestamp of the batch with the given number.
-// it returns batch_num.tstamp and virtual_batch.batch_timestamp
+// it returns batch.timestamp and virtual_batch.timestamp_batch_etrog
 func (p *PostgresStorage) GetRawBatchTimestamps(ctx context.Context, batchNumber uint64, dbTx pgx.Tx) (*time.Time, *time.Time, error) {
 	const sql = `
 	SELECT b.timestamp AS batch_timestamp, v.timestamp_batch_etrog AS virtual_batch_timestamp

From 64de8c9711c948ca1ab6cf410fc35af3c8cc63c1 Mon Sep 17 00:00:00 2001
From: chengzhinei 
Date: Fri, 9 Aug 2024 17:32:28 +0800
Subject: [PATCH 16/20] support special project in xlayer for free gas (#240)

* support special project in xlayer for free gas

* fmt code

* fmt code

* fix ci

* add enable flag; config use list

* fix json

* fix comment

* fix lint

* fix comment
---
 docs/config-file/node-config-doc.html    |  2 +-
 docs/config-file/node-config-doc.md      | 74 ++++++++++++++++++++++--
 docs/config-file/node-config-schema.json | 40 +++++++++++++
 pool/apollo_xlayer.go                    | 65 +++++++++++++++++++--
 pool/config.go                           | 13 +++++
 pool/pool_xlayer.go                      | 29 +++++++++-
 sequencer/sequencer.go                   | 13 +++--
 sequencer/sequencer_xlayer.go            | 18 +++++-
 test/Makefile                            |  2 +-
 9 files changed, 235 insertions(+), 21 deletions(-)

diff --git a/docs/config-file/node-config-doc.html b/docs/config-file/node-config-doc.html
index 67e8abca6b..7a8fab3a3d 100644
--- a/docs/config-file/node-config-doc.html
+++ b/docs/config-file/node-config-doc.html
@@ -14,7 +14,7 @@
 
"300ms"
 

Default: "15s"Type: string

PollMinAllowedGasPriceInterval is the interval to poll the suggested min gas price for a tx


Examples:

"1m"
 
"300ms"
-

Default: 64Type: integer

AccountQueue represents the maximum number of non-executable transaction slots permitted per account


Default: 1024Type: integer

GlobalQueue represents the maximum number of non-executable transaction slots for all accounts


EffectiveGasPrice is the config for the effective gas price calculation
Default: falseType: boolean

Enabled is a flag to enable/disable the effective gas price


Default: 0.25Type: number

L1GasPriceFactor is the percentage of the L1 gas price that will be used as the L2 min gas price


Default: 16Type: integer

ByteGasCost is the gas cost per byte that is not 0


Default: 4Type: integer

ZeroByteGasCost is the gas cost per byte that is 0


Default: 1Type: number

NetProfit is the profit margin to apply to the calculated breakEvenGasPrice


Default: 1.1Type: number

BreakEvenFactor is the factor to apply to the calculated breakevenGasPrice when comparing it with the gasPriceSigned of a tx


Default: 10Type: integer

FinalDeviationPct is the max allowed deviation percentage BreakEvenGasPrice on re-calculation


Default: 0Type: integer

EthTransferGasPrice is the fixed gas price returned as effective gas price for txs tha are ETH transfers (0 means disabled)
Only one of EthTransferGasPrice or EthTransferL1GasPriceFactor params can be different than 0. If both params are set to 0, the sequencer will halt and log an error


Default: 0Type: number

EthTransferL1GasPriceFactor is the percentage of L1 gas price returned as effective gas price for txs tha are ETH transfers (0 means disabled)
Only one of EthTransferGasPrice or EthTransferL1GasPriceFactor params can be different than 0. If both params are set to 0, the sequencer will halt and log an error


Default: 0.5Type: number

L2GasPriceSuggesterFactor is the factor to apply to L1 gas price to get the suggested L2 gas price used in the
calculations when the effective gas price is disabled (testing/metrics purposes)


Default: 0Type: integer

ForkID is the current fork ID of the chain


Default: 1Type: number

TxFeeCap is the global transaction fee(price * gaslimit) cap for
send-transaction variants. The unit is ether. 0 means no cap.


Type: array of string

XLayer config
BlockedList is the blocked address list

Each item of this array must be:


Default: ["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"]Type: array of string

FreeGasAddress is the default free gas address

Each item of this array must be:


Default: 150000Type: integer

FreeClaimGasLimit is the max gas allowed use to do a free claim


Type: array of string

BridgeClaimMethodSignature for tracking BridgeClaimMethodSignature method

Each item of this array must be:


Default: falseType: boolean

EnableFreeGasByNonce enable free gas


Type: array of string

FreeGasExAddress is the ex address which can be free gas for the transfer receiver

Each item of this array must be:


Default: 0Type: integer

FreeGasCountPerAddr is the count limit of free gas tx per address


Default: 0Type: integer

FreeGasLimit is the max gas allowed use to do a free gas tx


Configuration for RPC service. THis one offers a extended Ethereum JSON-RPC API interface to interact with the node
Default: "0.0.0.0"Type: string

Host defines the network adapter that will be used to serve the HTTP requests


Default: 8545Type: integer

Port defines the port to serve the endpoints via HTTP


Default: "1m0s"Type: string

ReadTimeout is the HTTP server read timeout
check net/http.server.ReadTimeout and net/http.server.ReadHeaderTimeout


Examples:

"1m"
+

Default: 64Type: integer

AccountQueue represents the maximum number of non-executable transaction slots permitted per account


Default: 1024Type: integer

GlobalQueue represents the maximum number of non-executable transaction slots for all accounts


EffectiveGasPrice is the config for the effective gas price calculation
Default: falseType: boolean

Enabled is a flag to enable/disable the effective gas price


Default: 0.25Type: number

L1GasPriceFactor is the percentage of the L1 gas price that will be used as the L2 min gas price


Default: 16Type: integer

ByteGasCost is the gas cost per byte that is not 0


Default: 4Type: integer

ZeroByteGasCost is the gas cost per byte that is 0


Default: 1Type: number

NetProfit is the profit margin to apply to the calculated breakEvenGasPrice


Default: 1.1Type: number

BreakEvenFactor is the factor to apply to the calculated breakevenGasPrice when comparing it with the gasPriceSigned of a tx


Default: 10Type: integer

FinalDeviationPct is the max allowed deviation percentage BreakEvenGasPrice on re-calculation


Default: 0Type: integer

EthTransferGasPrice is the fixed gas price returned as effective gas price for txs tha are ETH transfers (0 means disabled)
Only one of EthTransferGasPrice or EthTransferL1GasPriceFactor params can be different than 0. If both params are set to 0, the sequencer will halt and log an error


Default: 0Type: number

EthTransferL1GasPriceFactor is the percentage of L1 gas price returned as effective gas price for txs tha are ETH transfers (0 means disabled)
Only one of EthTransferGasPrice or EthTransferL1GasPriceFactor params can be different than 0. If both params are set to 0, the sequencer will halt and log an error


Default: 0.5Type: number

L2GasPriceSuggesterFactor is the factor to apply to L1 gas price to get the suggested L2 gas price used in the
calculations when the effective gas price is disabled (testing/metrics purposes)


Default: 0Type: integer

ForkID is the current fork ID of the chain


Default: 1Type: number

TxFeeCap is the global transaction fee(price * gaslimit) cap for
send-transaction variants. The unit is ether. 0 means no cap.


Type: array of string

XLayer config
BlockedList is the blocked address list

Each item of this array must be:


Default: ["0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"]Type: array of string

FreeGasAddress is the default free gas address

Each item of this array must be:


Default: 150000Type: integer

FreeClaimGasLimit is the max gas allowed use to do a free claim


Type: array of string

BridgeClaimMethodSignature for tracking BridgeClaimMethodSignature method

Each item of this array must be:


Default: falseType: boolean

EnableFreeGasByNonce enable free gas


Type: array of string

FreeGasExAddress is the ex address which can be free gas for the transfer receiver

Each item of this array must be:


Default: 0Type: integer

FreeGasCountPerAddr is the count limit of free gas tx per address


Default: 0Type: integer

FreeGasLimit is the max gas allowed use to do a free gas tx


Default: falseType: boolean

EnableFreeGasList enable the special project of XLayer for free gas


Type: array of object

FreeGasList is the special project of XLayer

Each item of this array must be:


Configuration for RPC service. THis one offers a extended Ethereum JSON-RPC API interface to interact with the node
Default: "0.0.0.0"Type: string

Host defines the network adapter that will be used to serve the HTTP requests


Default: 8545Type: integer

Port defines the port to serve the endpoints via HTTP


Default: "1m0s"Type: string

ReadTimeout is the HTTP server read timeout
check net/http.server.ReadTimeout and net/http.server.ReadHeaderTimeout


Examples:

"1m"
 
"300ms"
 

Default: "1m0s"Type: string

WriteTimeout is the HTTP server write timeout
check net/http.server.WriteTimeout


Examples:

"1m"
 
"300ms"
diff --git a/docs/config-file/node-config-doc.md b/docs/config-file/node-config-doc.md
index 607bda00b9..8c8281c85c 100644
--- a/docs/config-file/node-config-doc.md
+++ b/docs/config-file/node-config-doc.md
@@ -715,6 +715,8 @@ SecretKey=""
 | - [FreeGasExAddress](#Pool_FreeGasExAddress )                                   | No      | array of string | No         | -          | FreeGasExAddress is the ex address which can be free gas for the transfer receiver                                                  |
 | - [FreeGasCountPerAddr](#Pool_FreeGasCountPerAddr )                             | No      | integer         | No         | -          | FreeGasCountPerAddr is the count limit of free gas tx per address                                                                   |
 | - [FreeGasLimit](#Pool_FreeGasLimit )                                           | No      | integer         | No         | -          | FreeGasLimit is the max gas allowed use to do a free gas tx                                                                         |
+| - [EnableFreeGasList](#Pool_EnableFreeGasList )                                 | No      | boolean         | No         | -          | EnableFreeGasList enable the special project of XLayer for free gas                                                                 |
+| - [FreeGasList](#Pool_FreeGasList )                                             | No      | array of object | No         | -          | FreeGasList is the special project of XLayer                                                                                        |
 
 ### 7.1. `Pool.IntervalToRefreshBlockedAddresses`
 
@@ -1321,6 +1323,70 @@ FreeGasCountPerAddr=0
 FreeGasLimit=0
 ```
 
+### 7.24. `Pool.EnableFreeGasList`
+
+**Type:** : `boolean`
+
+**Default:** `false`
+
+**Description:** EnableFreeGasList enable the special project of XLayer for free gas
+
+**Example setting the default value** (false):
+```
+[Pool]
+EnableFreeGasList=false
+```
+
+### 7.25. `Pool.FreeGasList`
+
+**Type:** : `array of object`
+**Description:** FreeGasList is the special project of XLayer
+
+|                      | Array restrictions |
+| -------------------- | ------------------ |
+| **Min items**        | N/A                |
+| **Max items**        | N/A                |
+| **Items unicity**    | False              |
+| **Additional items** | False              |
+| **Tuple validation** | See below          |
+
+| Each item of this array must be              | Description                                                 |
+| -------------------------------------------- | ----------------------------------------------------------- |
+| [FreeGasList items](#Pool_FreeGasList_items) | FreeGasInfo contains the details for what tx should be free |
+
+#### 7.25.1. [Pool.FreeGasList.FreeGasList items]
+
+**Type:** : `object`
+**Description:** FreeGasInfo contains the details for what tx should be free
+
+| Property                                                        | Pattern | Type            | Deprecated | Definition | Title/Description |
+| --------------------------------------------------------------- | ------- | --------------- | ---------- | ---------- | ----------------- |
+| - [Name](#Pool_FreeGasList_items_Name )                         | No      | string          | No         | -          | -                 |
+| - [FromList](#Pool_FreeGasList_items_FromList )                 | No      | array of string | No         | -          | -                 |
+| - [ToList](#Pool_FreeGasList_items_ToList )                     | No      | array of string | No         | -          | -                 |
+| - [MethodSigs](#Pool_FreeGasList_items_MethodSigs )             | No      | array of string | No         | -          | -                 |
+| - [GasPriceMultiple](#Pool_FreeGasList_items_GasPriceMultiple ) | No      | number          | No         | -          | -                 |
+
+##### 7.25.1.1. `Pool.FreeGasList.FreeGasList items.Name`
+
+**Type:** : `string`
+
+##### 7.25.1.2. `Pool.FreeGasList.FreeGasList items.FromList`
+
+**Type:** : `array of string`
+
+##### 7.25.1.3. `Pool.FreeGasList.FreeGasList items.ToList`
+
+**Type:** : `array of string`
+
+##### 7.25.1.4. `Pool.FreeGasList.FreeGasList items.MethodSigs`
+
+**Type:** : `array of string`
+
+##### 7.25.1.5. `Pool.FreeGasList.FreeGasList items.GasPriceMultiple`
+
+**Type:** : `number`
+
 ## 8. `[RPC]`
 
 **Type:** : `object`
@@ -2080,7 +2146,7 @@ SpecialApis=[]
 | ----------------------------------------------------- | ---------------------------------------------------------- |
 | [SpecialApis items](#RPC_RateLimit_SpecialApis_items) | RateLimitItem defines the special rate limit for some apis |
 
-##### 8.25.5.1. [RPC.RateLimit.SpecialApis.SpecialApis items]
+##### 8.25.5.1. [RPC.RateLimit.SpecialApis.SpecialApis items]
 
 **Type:** : `object`
 **Description:** RateLimitItem defines the special rate limit for some apis
@@ -2315,7 +2381,7 @@ ApiKeys=[]
 | ----------------------------------------------------- | --------------------------- |
 | [ApiKeys items](#RPC_ApiAuthentication_ApiKeys_items) | KeyItem is the api key item |
 
-##### 8.29.2.1. [RPC.ApiAuthentication.ApiKeys.ApiKeys items]
+##### 8.29.2.1. [RPC.ApiAuthentication.ApiKeys.ApiKeys items]
 
 **Type:** : `object`
 **Description:** KeyItem is the api key item
@@ -4633,7 +4699,7 @@ RollupManagerBlockNumber=0
 | ----------------------------------------------------- | ------------------------------------------------------------------------- |
 | [Actions items](#NetworkConfig_Genesis_Actions_items) | GenesisAction represents one of the values set on the SMT during genesis. |
 
-##### 13.3.4.1. [NetworkConfig.Genesis.Actions.Actions items]
+##### 13.3.4.1. [NetworkConfig.Genesis.Actions.Actions items]
 
 **Type:** : `object`
 **Description:** GenesisAction represents one of the values set on the SMT during genesis.
@@ -5513,7 +5579,7 @@ ChainID=0
 | ----------------------------------------------------- | ------------------------------------ |
 | [ForkIDIntervals items](#State_ForkIDIntervals_items) | ForkIDInterval is a fork id interval |
 
-#### 20.3.1. [State.ForkIDIntervals.ForkIDIntervals items]
+#### 20.3.1. [State.ForkIDIntervals.ForkIDIntervals items]
 
 **Type:** : `object`
 **Description:** ForkIDInterval is a fork id interval
diff --git a/docs/config-file/node-config-schema.json b/docs/config-file/node-config-schema.json
index 847d43b296..9414fe86d0 100644
--- a/docs/config-file/node-config-schema.json
+++ b/docs/config-file/node-config-schema.json
@@ -505,6 +505,46 @@
 					"type": "integer",
 					"description": "FreeGasLimit is the max gas allowed use to do a free gas tx",
 					"default": 0
+				},
+				"EnableFreeGasList": {
+					"type": "boolean",
+					"description": "EnableFreeGasList enable the special project of XLayer for free gas",
+					"default": false
+				},
+				"FreeGasList": {
+					"items": {
+						"properties": {
+							"Name": {
+								"type": "string"
+							},
+							"FromList": {
+								"items": {
+									"type": "string"
+								},
+								"type": "array"
+							},
+							"ToList": {
+								"items": {
+									"type": "string"
+								},
+								"type": "array"
+							},
+							"MethodSigs": {
+								"items": {
+									"type": "string"
+								},
+								"type": "array"
+							},
+							"GasPriceMultiple": {
+								"type": "number"
+							}
+						},
+						"additionalProperties": false,
+						"type": "object",
+						"description": "FreeGasInfo contains the details for what tx should be free"
+					},
+					"type": "array",
+					"description": "FreeGasList is the special project of XLayer"
 				}
 			},
 			"additionalProperties": false,
diff --git a/pool/apollo_xlayer.go b/pool/apollo_xlayer.go
index bad98fad87..16ea4953cd 100644
--- a/pool/apollo_xlayer.go
+++ b/pool/apollo_xlayer.go
@@ -21,6 +21,11 @@ type apolloConfig struct {
 	FreeGasCountPerAddr  uint64
 	FreeGasLimit         uint64
 
+	// for special project
+	EnableFreeGasList  bool
+	FreeGasFromNameMap map[string]string       // map[from]projectName
+	FreeGasList        map[string]*FreeGasInfo // map[projectName]FreeGasInfo
+
 	BlockedList []string
 
 	sync.RWMutex
@@ -43,6 +48,21 @@ func (c *apolloConfig) enable() bool {
 	return c.EnableApollo
 }
 
+func (c *apolloConfig) setFreeGasList(freeGasList []FreeGasInfo) {
+	if c == nil || !c.EnableApollo {
+		return
+	}
+	c.FreeGasFromNameMap = make(map[string]string)
+	c.FreeGasList = make(map[string]*FreeGasInfo, len(freeGasList))
+	for _, info := range freeGasList {
+		for _, from := range info.FromList {
+			c.FreeGasFromNameMap[from] = info.Name
+		}
+		infoCopy := info
+		c.FreeGasList[info.Name] = &infoCopy
+	}
+}
+
 func (c *apolloConfig) setFreeGasAddresses(freeGasAddrs []string) {
 	if c == nil || !c.EnableApollo {
 		return
@@ -95,6 +115,8 @@ func UpdateConfig(apolloConfig Config) {
 	getApolloConfig().setFreeGasExAddresses(apolloConfig.FreeGasExAddress)
 	getApolloConfig().FreeGasCountPerAddr = apolloConfig.FreeGasCountPerAddr
 	getApolloConfig().FreeGasLimit = apolloConfig.FreeGasLimit
+	getApolloConfig().EnableFreeGasList = apolloConfig.EnableFreeGasList
+	getApolloConfig().setFreeGasList(apolloConfig.FreeGasList)
 
 	getApolloConfig().Unlock()
 }
@@ -119,10 +141,10 @@ func isFreeGasAddress(localFreeGasAddrs []string, address common.Address) bool {
 	if getApolloConfig().enable() {
 		getApolloConfig().RLock()
 		defer getApolloConfig().RUnlock()
-		return contains(getApolloConfig().FreeGasAddresses, address)
+		return Contains(getApolloConfig().FreeGasAddresses, address)
 	}
 
-	return contains(localFreeGasAddrs, address)
+	return Contains(localFreeGasAddrs, address)
 }
 
 func getEnableFreeGasByNonce(enableFreeGasByNonce bool) bool {
@@ -139,10 +161,10 @@ func isFreeGasExAddress(localFreeGasExAddrs []string, address common.Address) bo
 	if getApolloConfig().enable() {
 		getApolloConfig().RLock()
 		defer getApolloConfig().RUnlock()
-		return contains(getApolloConfig().FreeGasExAddress, address)
+		return Contains(getApolloConfig().FreeGasExAddress, address)
 	}
 
-	return contains(localFreeGasExAddrs, address)
+	return Contains(localFreeGasExAddrs, address)
 }
 
 func getFreeGasCountPerAddr(localFreeGasCountPerAddr uint64) uint64 {
@@ -197,8 +219,39 @@ func isBlockedAddress(localBlockedList []string, address common.Address) bool {
 	if getApolloConfig().enable() {
 		getApolloConfig().RLock()
 		defer getApolloConfig().RUnlock()
-		return contains(getApolloConfig().BlockedList, address)
+		return Contains(getApolloConfig().BlockedList, address)
+	}
+
+	return Contains(localBlockedList, address)
+}
+
+// GetEnableSpecialFreeGasList returns enable flag of FreeGasList
+func GetEnableSpecialFreeGasList(enableFreeGasList bool) bool {
+	if getApolloConfig().enable() {
+		getApolloConfig().RLock()
+		defer getApolloConfig().RUnlock()
+		return getApolloConfig().EnableFreeGasList
+	}
+	return enableFreeGasList
+}
+
+// GetSpecialFreeGasList returns the special project in XLayer for free gas
+func GetSpecialFreeGasList(freeGasList []FreeGasInfo) (map[string]string, map[string]*FreeGasInfo) {
+	if getApolloConfig().enable() {
+		getApolloConfig().RLock()
+		defer getApolloConfig().RUnlock()
+		return getApolloConfig().FreeGasFromNameMap, getApolloConfig().FreeGasList
+	}
+
+	freeGasFromNameMap := make(map[string]string)
+	freeGasMap := make(map[string]*FreeGasInfo, len(freeGasList))
+	for _, info := range freeGasList {
+		for _, from := range info.FromList {
+			freeGasFromNameMap[from] = info.Name
+		}
+		infoCopy := info
+		freeGasMap[info.Name] = &infoCopy
 	}
 
-	return contains(localBlockedList, address)
+	return freeGasFromNameMap, freeGasMap
 }
diff --git a/pool/config.go b/pool/config.go
index 283788a706..a7cd61baa1 100644
--- a/pool/config.go
+++ b/pool/config.go
@@ -71,6 +71,19 @@ type Config struct {
 	FreeGasCountPerAddr uint64 `mapstructure:"FreeGasCountPerAddr"`
 	// FreeGasLimit is the max gas allowed use to do a free gas tx
 	FreeGasLimit uint64 `mapstructure:"FreeGasLimit"`
+	// EnableFreeGasList enable the special project of XLayer for free gas
+	EnableFreeGasList bool `mapstructure:"EnableFreeGasList"`
+	// FreeGasList is the special project of XLayer
+	FreeGasList []FreeGasInfo `mapstructure:"FreeGasList"`
+}
+
+// FreeGasInfo contains the details for what tx should be free
+type FreeGasInfo struct {
+	Name             string   `mapstructure:"Name"`
+	FromList         []string `mapstructure:"FromList"`
+	ToList           []string `mapstructure:"ToList"`
+	MethodSigs       []string `mapstructure:"MethodSigs"`
+	GasPriceMultiple float64  `mapstructure:"GasPriceMultiple"`
 }
 
 // EffectiveGasPriceCfg contains the configuration properties for the effective gas price
diff --git a/pool/pool_xlayer.go b/pool/pool_xlayer.go
index ce7b4f1f3a..e6d2e16713 100644
--- a/pool/pool_xlayer.go
+++ b/pool/pool_xlayer.go
@@ -31,7 +31,8 @@ const (
 	MainnetBridgeURL = "https://www.okx.com/xlayer/bridge"
 )
 
-func contains(s []string, ele common.Address) bool {
+// Contains returns if string[] contains ele string
+func Contains(s []string, ele common.Address) bool {
 	for _, e := range s {
 		if common.HexToAddress(e) == ele {
 			return true
@@ -40,6 +41,16 @@ func contains(s []string, ele common.Address) bool {
 	return false
 }
 
+// ContainsMethod returns if data has prefix of method sig
+func ContainsMethod(data string, methods []string) bool {
+	for _, m := range methods {
+		if strings.HasPrefix(data, m) {
+			return true
+		}
+	}
+	return false
+}
+
 // StartRefreshingWhiteAddressesPeriodically will make this instance of the pool
 // to check periodically(accordingly to the configuration) for updates regarding
 // the white address and update the in memory blocked addresses
@@ -113,9 +124,23 @@ func (p *Pool) GetDynamicGasPrice() *big.Int {
 }
 
 func (p *Pool) checkFreeGp(ctx context.Context, poolTx Transaction, from common.Address) (bool, error) {
-	if isFreeGasAddress(p.cfg.FreeGasAddress, from) && poolTx.IsClaims { // claim tx
+	// claim tx
+	if isFreeGasAddress(p.cfg.FreeGasAddress, from) && poolTx.IsClaims {
 		return true, nil
 	}
+
+	// special project
+	if GetEnableSpecialFreeGasList(p.cfg.EnableFreeGasList) {
+		fromToName, freeGpList := GetSpecialFreeGasList(p.cfg.FreeGasList)
+		info := freeGpList[fromToName[from.String()]]
+		if info != nil &&
+			Contains(info.ToList, *poolTx.To()) &&
+			ContainsMethod("0x"+common.Bytes2Hex(poolTx.Data()), info.MethodSigs) {
+			return true, nil
+		}
+	}
+
+	// new bridge address
 	if getEnableFreeGasByNonce(p.cfg.EnableFreeGasByNonce) && poolTx.GasPrice().Cmp(big.NewInt(0)) == 0 { // free-gas tx by count
 		isFreeAddr, err := p.storage.IsFreeGasAddr(ctx, from)
 		if err != nil {
diff --git a/sequencer/sequencer.go b/sequencer/sequencer.go
index 2ba8dfb96d..c99ef4f661 100644
--- a/sequencer/sequencer.go
+++ b/sequencer/sequencer.go
@@ -231,18 +231,19 @@ func (s *Sequencer) addTxToWorker(ctx context.Context, tx pool.Transaction) erro
 		return err
 	}
 
-	// XLayer claim tx
-	freeGp, isClaimTx := s.checkFreeGas(tx, txTracker)
+	// XLayer free gas tx
+	freeGp, isClaimTx, gp := s.checkFreeGas(tx, txTracker)
 	if freeGp {
 		defaultGp := s.pool.GetDynamicGasPrice()
-		baseGp := s.worker.getBaseClaimGp(defaultGp)
-		copyBaseGp := new(big.Int).Set(baseGp)
+		copyBaseGp := new(big.Int)
 		if isClaimTx {
 			txTracker.IsClaimTx = true
-			txTracker.GasPrice = copyBaseGp.Mul(copyBaseGp, new(big.Int).SetUint64(uint64(getGasPriceMultiple(s.cfg.GasPriceMultiple))))
+			baseGp := s.worker.getBaseClaimGp(defaultGp)
+			copyBaseGp.Set(baseGp)
 		} else {
-			txTracker.GasPrice = defaultGp.Mul(defaultGp, new(big.Int).SetUint64(uint64(getInitGasPriceMultiple(s.cfg.InitGasPriceMultiple))))
+			copyBaseGp.Set(defaultGp)
 		}
+		txTracker.GasPrice = copyBaseGp.Mul(copyBaseGp, new(big.Int).SetUint64(uint64(gp)))
 	}
 
 	replacedTx, dropReason := s.worker.AddTxTracker(ctx, txTracker)
diff --git a/sequencer/sequencer_xlayer.go b/sequencer/sequencer_xlayer.go
index 838c9a8e4e..3a27452f22 100644
--- a/sequencer/sequencer_xlayer.go
+++ b/sequencer/sequencer_xlayer.go
@@ -9,6 +9,7 @@ import (
 	"github.com/0xPolygonHermez/zkevm-node/pool"
 	pmetric "github.com/0xPolygonHermez/zkevm-node/sequencer/metrics"
 	"github.com/0xPolygonHermez/zkevm-node/state"
+	"github.com/ethereum/go-ethereum/common"
 )
 
 var countinterval = 10
@@ -36,14 +37,29 @@ func (s *Sequencer) countReadyTx() {
 	state.InfiniteSafeRun(s.updateReadyTxCount, "error counting ready tx", time.Second)
 }
 
-func (s *Sequencer) checkFreeGas(tx pool.Transaction, txTracker *TxTracker) (freeGp, claimTx bool) {
+func (s *Sequencer) checkFreeGas(tx pool.Transaction, txTracker *TxTracker) (freeGp, claimTx bool, gpMul float64) {
 	// check if tx is init-free-gas and if it can be prior pack
 	freeGp = tx.GasPrice().Cmp(big.NewInt(0)) == 0
+	gpMul = getInitGasPriceMultiple(s.cfg.InitGasPriceMultiple)
 
 	// check if tx is bridge-claim
 	addrs := getPackBatchSpacialList(s.cfg.PackBatchSpacialList)
 	if addrs[txTracker.FromStr] {
 		claimTx = true
+		gpMul = getGasPriceMultiple(s.cfg.GasPriceMultiple)
+		return
+	}
+
+	// check if tx is from special project
+	if pool.GetEnableSpecialFreeGasList(s.poolCfg.EnableFreeGasList) {
+		fromToName, freeGpList := pool.GetSpecialFreeGasList(s.poolCfg.FreeGasList)
+		info := freeGpList[fromToName[txTracker.FromStr]]
+		if info != nil &&
+			pool.Contains(info.ToList, *tx.To()) &&
+			pool.ContainsMethod("0x"+common.Bytes2Hex(tx.Data()), info.MethodSigs) {
+			gpMul = info.GasPriceMultiple
+			return
+		}
 	}
 
 	return
diff --git a/test/Makefile b/test/Makefile
index d1df75cd76..01b7da898c 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,4 +1,4 @@
-DOCKERCOMPOSE := docker-compose -f docker-compose.yml
+DOCKERCOMPOSE := docker compose -f docker-compose.yml
 DOCKERCOMPOSEAPPSEQ := xlayer-sequencer
 DOCKERCOMPOSEAPPSEQSENDER := xlayer-sequence-sender
 DOCKERCOMPOSEAPPSIGNER := xlayer-signer

From 3e5f8c4373d928530e9b8694a4dac496db9079d1 Mon Sep 17 00:00:00 2001
From: zhangkai 
Date: Mon, 12 Aug 2024 11:22:13 +0800
Subject: [PATCH 17/20] GetFilterChanges return a empty object instead of null
 when no changes. (#242)

* if no blocks return object instead of null

* fix compile error

* logs return object instead of null

* return object install null
---
 jsonrpc/endpoints_eth.go | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/jsonrpc/endpoints_eth.go b/jsonrpc/endpoints_eth.go
index ca03f7b194..3fe3c373c9 100644
--- a/jsonrpc/endpoints_eth.go
+++ b/jsonrpc/endpoints_eth.go
@@ -473,7 +473,7 @@ func (e *EthEndpoints) GetFilterChanges(filterID string) (interface{}, types.Err
 				return nil, rpcErr
 			}
 			if len(res) == 0 {
-				return nil, nil
+				return []common.Hash{}, nil
 			}
 			return res, nil
 		}
@@ -488,7 +488,7 @@ func (e *EthEndpoints) GetFilterChanges(filterID string) (interface{}, types.Err
 				return nil, rpcErr
 			}
 			if len(res) == 0 {
-				return nil, nil
+				return []common.Hash{}, nil
 			}
 			return res, nil
 		}
@@ -511,7 +511,7 @@ func (e *EthEndpoints) GetFilterChanges(filterID string) (interface{}, types.Err
 			}
 			res := resInterface.([]types.Log)
 			if len(res) == 0 {
-				return nil, nil
+				return []types.Log{}, nil
 			}
 			return res, nil
 		}

From fa51e9de85f6282ec11d1355605735c7362e4929 Mon Sep 17 00:00:00 2001
From: zhangkai 
Date: Tue, 13 Aug 2024 14:09:35 +0800
Subject: [PATCH 18/20] add go.mod and go.sum

---
 go.mod | 2 +-
 go.sum | 2 --
 2 files changed, 1 insertion(+), 3 deletions(-)

diff --git a/go.mod b/go.mod
index d4ea562a2a..7859439cf6 100644
--- a/go.mod
+++ b/go.mod
@@ -24,7 +24,7 @@ require (
 	github.com/spf13/afero v1.11.0
 	github.com/spf13/viper v1.18.2
 	github.com/stretchr/testify v1.9.0
-	github.com/umbracle/ethgo v0.1.3
+	github.com/umbracle/ethgo v0.1.4-0.20230712173909-df37dddf16f0
 	github.com/urfave/cli/v2 v2.27.1
 	go.uber.org/zap v1.27.0
 	golang.org/x/crypto v0.18.0
diff --git a/go.sum b/go.sum
index abc12a96d9..325ccd703e 100644
--- a/go.sum
+++ b/go.sum
@@ -43,8 +43,6 @@ github.com/0xPolygon/agglayer v0.0.1 h1:J6/DUo9rNUncDifquanouRCo2g7g069yvz0aFtu7
 github.com/0xPolygon/agglayer v0.0.1/go.mod h1:UYp5O8THULoXVrUfzkRjVBzxHR5DxBdUN/Iq0EgxNxM=
 github.com/0xPolygon/cdk-data-availability v0.0.5 h1://vg1oR/5tw2XfEIorpP+wIxLfNUmoKrdmX8YZvBKX4=
 github.com/0xPolygon/cdk-data-availability v0.0.5/go.mod h1:aGwqHiJhL+mJbdepl3s58wsY18EuViDa9vZCpPuIYGw=
-github.com/0xPolygonHermez/zkevm-data-streamer v0.2.3-RC4 h1:+4K+xSzv0ImbK30B/T9FauNTrTFUmWcNKYhIgwsE4C4=
-github.com/0xPolygonHermez/zkevm-data-streamer v0.2.3-RC4/go.mod h1:0QkAXcFa92mFJrCbN3UPUJGJYes851yEgYHLONnaosE=
 github.com/0xPolygonHermez/zkevm-data-streamer v0.2.3 h1:zJ06KCGLMDOap4slop/QmiMUO+VPsKSS3+944SY06ww=
 github.com/0xPolygonHermez/zkevm-data-streamer v0.2.3/go.mod h1:bv7DjATsczN2WvFt26jv34TWv6rfvYM1SqegrgrFwfI=
 github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=

From 3f5badb809b8259912a63056190c9e40dde20d6e Mon Sep 17 00:00:00 2001
From: oker 
Date: Wed, 14 Aug 2024 11:07:21 +0800
Subject: [PATCH 19/20] format doc

---
 docs/config-file/node-config-doc.html |  3 +-
 docs/config-file/node-config-doc.md   | 96 +++++++++++++--------------
 2 files changed, 49 insertions(+), 50 deletions(-)

diff --git a/docs/config-file/node-config-doc.html b/docs/config-file/node-config-doc.html
index 524e4c82f5..e825ebd042 100644
--- a/docs/config-file/node-config-doc.html
+++ b/docs/config-file/node-config-doc.html
@@ -66,12 +66,11 @@
 
"300ms"
 

Default: trueType: boolean

EnableLog is a flag to enable/disable metrics logs


StreamServerCfg is the config for the stream server
Default: 0Type: integer

Port to listen on


Default: ""Type: string

Filename of the binary data file


Default: 0Type: integer

Version of the binary data file


Default: 0Type: integer

ChainID is the chain ID


Default: falseType: boolean

Enabled is a flag to enable/disable the data streamer


Log is the log configuration
Default: ""Type: enum (of string)

Must be one of:

  • "production"
  • "development"

Default: ""Type: enum (of string)

Must be one of:

  • "debug"
  • "info"
  • "warn"
  • "error"
  • "dpanic"
  • "panic"
  • "fatal"

Type: array of string

Each item of this array must be:


Default: 0Type: integer

UpgradeEtrogBatchNumber is the batch number of the upgrade etrog


Default: "5s"Type: string

WriteTimeout is the TCP write timeout when sending data to a datastream client


Examples:

"1m"
 
"300ms"
-

Type: array of string

XLayer config
PackBatchSpacialList is the list of addresses that will have a special gas price

Each item of this array must be:

Type: string

Default: 0Type: number

GasPriceMultiple is the multiple of the gas price


Default: 0Type: number

InitGasPriceMultiple is the multiple of the gas price for init free gas tx


Default: 0Type: integer

QueryPendingTxsLimit is used to limit amount txs from the db


Configuration of the sequence sender service
Default: "5s"Type: string

WaitPeriodSendSequence is the time the sequencer waits until
trying to send a sequence to L1


Examples:

"1m"
 

Default: "2m0s"Type: string

InactivityTimeout is the timeout to kill an inactive datastream client connection


Examples:

"1m"
 
"300ms"
 

Default: "5s"Type: string

InactivityCheckInterval is the time interval to check for datastream client connections that have reached the inactivity timeout to kill them


Examples:

"1m"
 
"300ms"
-

Configuration of the sequence sender service
Default: "5s"Type: string

WaitPeriodSendSequence is the time the sequencer waits until
trying to send a sequence to L1


Examples:

"1m"
+

Type: array of string

XLayer config
PackBatchSpacialList is the list of addresses that will have a special gas price

Each item of this array must be:

Type: string

Default: 0Type: number

GasPriceMultiple is the multiple of the gas price


Default: 0Type: number

InitGasPriceMultiple is the multiple of the gas price for init free gas tx


Default: 0Type: integer

QueryPendingTxsLimit is used to limit amount txs from the db


Configuration of the sequence sender service
Default: "5s"Type: string

WaitPeriodSendSequence is the time the sequencer waits until
trying to send a sequence to L1


Examples:

"1m"
 
"300ms"
 

Default: "5s"Type: string

LastBatchVirtualizationTimeMaxWaitPeriod is time since sequences should be sent


Examples:

"1m"
 
"300ms"
diff --git a/docs/config-file/node-config-doc.md b/docs/config-file/node-config-doc.md
index 5a4b9ed286..cf6cba6a3a 100644
--- a/docs/config-file/node-config-doc.md
+++ b/docs/config-file/node-config-doc.md
@@ -3808,54 +3808,6 @@ UpgradeEtrogBatchNumber=0
 WriteTimeout="5s"
 ```
 
-### 10.10. `Sequencer.PackBatchSpacialList`
-
-**Type:** : `array of string`
-**Description:** XLayer config
-PackBatchSpacialList is the list of addresses that will have a special gas price
-
-### 10.11. `Sequencer.GasPriceMultiple`
-
-**Type:** : `number`
-
-**Default:** `0`
-
-**Description:** GasPriceMultiple is the multiple of the gas price
-
-**Example setting the default value** (0):
-```
-[Sequencer]
-GasPriceMultiple=0
-```
-
-### 10.12. `Sequencer.InitGasPriceMultiple`
-
-**Type:** : `number`
-
-**Default:** `0`
-
-**Description:** InitGasPriceMultiple is the multiple of the gas price for init free gas tx
-
-**Example setting the default value** (0):
-```
-[Sequencer]
-InitGasPriceMultiple=0
-```
-
-### 10.13. `Sequencer.QueryPendingTxsLimit`
-
-**Type:** : `integer`
-
-**Default:** `0`
-
-**Description:** QueryPendingTxsLimit is used to limit amount txs from the db
-
-**Example setting the default value** (0):
-```
-[Sequencer]
-QueryPendingTxsLimit=0
-```
-
 #### 10.9.9. `Sequencer.StreamServer.InactivityTimeout`
 
 **Title:** Duration
@@ -3908,6 +3860,54 @@ InactivityTimeout="2m0s"
 InactivityCheckInterval="5s"
 ```
 
+### 10.10. `Sequencer.PackBatchSpacialList`
+
+**Type:** : `array of string`
+**Description:** XLayer config
+PackBatchSpacialList is the list of addresses that will have a special gas price
+
+### 10.11. `Sequencer.GasPriceMultiple`
+
+**Type:** : `number`
+
+**Default:** `0`
+
+**Description:** GasPriceMultiple is the multiple of the gas price
+
+**Example setting the default value** (0):
+```
+[Sequencer]
+GasPriceMultiple=0
+```
+
+### 10.12. `Sequencer.InitGasPriceMultiple`
+
+**Type:** : `number`
+
+**Default:** `0`
+
+**Description:** InitGasPriceMultiple is the multiple of the gas price for init free gas tx
+
+**Example setting the default value** (0):
+```
+[Sequencer]
+InitGasPriceMultiple=0
+```
+
+### 10.13. `Sequencer.QueryPendingTxsLimit`
+
+**Type:** : `integer`
+
+**Default:** `0`
+
+**Description:** QueryPendingTxsLimit is used to limit amount txs from the db
+
+**Example setting the default value** (0):
+```
+[Sequencer]
+QueryPendingTxsLimit=0
+```
+
 ## 11. `[SequenceSender]`
 
 **Type:** : `object`

From 938ad5c3b0d821397de6127530fce515f46f4ab8 Mon Sep 17 00:00:00 2001
From: zibuyu28 <36945916+zibuyu28@users.noreply.github.com>
Date: Tue, 27 Aug 2024 17:54:00 +0800
Subject: [PATCH 20/20] Create image-build.yml

---
 .github/workflows/image-build.yml | 61 +++++++++++++++++++++++++++++++
 1 file changed, 61 insertions(+)
 create mode 100644 .github/workflows/image-build.yml

diff --git a/.github/workflows/image-build.yml b/.github/workflows/image-build.yml
new file mode 100644
index 0000000000..cf2c406df4
--- /dev/null
+++ b/.github/workflows/image-build.yml
@@ -0,0 +1,61 @@
+name: image-builder
+
+on:
+  workflow_dispatch:
+    inputs:
+      branch:
+        description: 'Branch to build'
+        required: false
+      tag:
+        description: 'Tag to build'
+        required: false
+
+jobs:
+  docker:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v4
+        id: checkout
+        with:
+          ref: ${{ github.event.inputs.branch || github.event.inputs.tag }}
+
+      - name: check param
+        run: |
+          branch=${{ github.event.inputs.branch }}
+          tag=${{ github.event.inputs.tag }}
+          if [ -z "$branch" ] && [ -z "$tag" ]; then
+            echo "Both branch and tag are empty."
+            exit 1
+          elif [ -n "$branch" ] && [ -n "$tag" ]; then
+            echo "Both branch and tag are provided. Please provide only one."
+            exit 1
+          else
+            echo "Correct! One of branch or tag is provided."
+          fi
+
+      - name: Get current date
+        id: date
+        run: echo "DATE=$(date +'%Y%m%d%H%M%S')" >> $GITHUB_ENV
+
+      - name: Get commit hash
+        id: commit
+        run: echo "HASH=$(git rev-parse --short HEAD)" >> $GITHUB_ENV
+
+      - name: Generate image tag
+        id: tag
+        run: |
+          BRANCH_TAG=$(echo "${{ github.event.inputs.branch || github.event.inputs.tag }}" | sed 's/\//_/g')
+          IMAGE_TAG="${BRANCH_TAG}_${DATE}_${HASH}"
+          echo "IMAGE_TAG=${IMAGE_TAG}" >> $GITHUB_ENV
+
+      - name: Log in to Docker Hub
+        uses: docker/login-action@v3
+        with:
+          username: ${{ secrets.DOCKERHUB_USERNAME }}
+          password: ${{ secrets.DOCKERHUB_TOKEN }}
+
+      - name: Build and Push Docker image
+        run: |
+          docker build -t "xlayerdev/xlayer-node:${{ env.IMAGE_TAG }}" .
+          docker push "xlayerdev/xlayer-node:${{ env.IMAGE_TAG }}"