From fe7420e6bede0983d7080831dd711ee3eead8833 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Tue, 31 Mar 2026 19:12:35 +0530 Subject: [PATCH 1/5] (feat): disable pending block creation loop via flag --- docs/cli/default_config.toml | 1 + docs/cli/example_config.toml | 15 +++++++------- docs/cli/server.md | 2 ++ internal/cli/server/config.go | 7 ++++++- internal/cli/server/flags.go | 7 +++++++ miner/miner.go | 4 ++++ miner/worker.go | 9 ++++++++- miner/worker_test.go | 37 +++++++++++++++++++++++++++++++++++ 8 files changed, 73 insertions(+), 9 deletions(-) diff --git a/docs/cli/default_config.toml b/docs/cli/default_config.toml index 022a277ef1..e9f1f865d7 100644 --- a/docs/cli/default_config.toml +++ b/docs/cli/default_config.toml @@ -105,6 +105,7 @@ devfakeauthor = false base-fee-change-denominator = 0 prefetch = false prefetch-gaslimit-percent = 100 + disable-pending-block = false [jsonrpc] ipcdisable = false diff --git a/docs/cli/example_config.toml b/docs/cli/example_config.toml index 33b6249046..006c878a42 100644 --- a/docs/cli/example_config.toml +++ b/docs/cli/example_config.toml @@ -79,13 +79,14 @@ bp-rpc-endpoints = [ ] # Comma separated rpc endpoints of all block producers lifetime = "3h0m0s" # Maximum amount of time non-executable transaction are queued [miner] - mine = false # Enable mining - etherbase = "" # Public address for block mining rewards - extradata = "" # Block extra data set by the miner (default = client version) - gaslimit = 50000000 # Target gas ceiling for mined blocks (used when dynamic gas limit is disabled) - gasprice = "25000000000" # Minimum gas price for mining a transaction. Regardless the value set, it will be enforced to 25000000000 for all networks - recommit = "2m5s" # The time interval for miner to re-create mining work - commitinterrupt = true # Interrupt the current mining work when time is exceeded and create partial blocks + mine = false # Enable mining + etherbase = "" # Public address for block mining rewards + extradata = "" # Block extra data set by the miner (default = client version) + gaslimit = 50000000 # Target gas ceiling for mined blocks (used when dynamic gas limit is disabled) + gasprice = "25000000000" # Minimum gas price for mining a transaction. Regardless the value set, it will be enforced to 25000000000 for all networks + recommit = "2m5s" # The time interval for miner to re-create mining work + commitinterrupt = true # Interrupt the current mining work when time is exceeded and create partial blocks + disable-pending-block = false # Disable the pending block creation loop. When set, RPC queries for 'pending' block will return nil # Dynamic gas limit configuration enableDynamicGasLimit = false # Enable dynamic gas limit adjustment based on base fee gasLimitMin = 50000000 # Minimum gas limit when dynamic gas limit is enabled diff --git a/docs/cli/server.md b/docs/cli/server.md index a8e4a3d595..85e45e1e24 100644 --- a/docs/cli/server.md +++ b/docs/cli/server.md @@ -336,6 +336,8 @@ The ```bor server``` command runs the Bor client. - ```miner.blocktime```: The block time defined by the miner. Needs to be larger or equal to the consensus block time. If not set (default = 0), the miner will use the consensus block time. (default: 0s) +- ```miner.disable-pending-block```: Disable the pending block creation loop. When set, RPC queries for 'pending' block will return nil (default: false) + - ```miner.enableDynamicGasLimit```: Enable dynamic gas limit adjustment based on base fee (default: false) - ```miner.enableDynamicTargetGas```: Enable dynamic EIP-1559 target gas percentage adjustment based on base fee (post-Lisovo, mutually exclusive with enableDynamicGasLimit) (default: false) diff --git a/internal/cli/server/config.go b/internal/cli/server/config.go index bc4e168cde..bc016a761c 100644 --- a/internal/cli/server/config.go +++ b/internal/cli/server/config.go @@ -449,6 +449,10 @@ type SealerConfig struct { // PrefetchGasLimitPercent is the gas limit percentage for prefetching (e.g., 100 = 100%, 110 = 110%) PrefetchGasLimitPercent uint64 `hcl:"prefetch-gaslimit-percent,optional" toml:"prefetch-gaslimit-percent,optional"` + + // DisablePendingBlock disables the pending block creation loop which currently works in all node types + // to create a block for serving rpc queries for 'pending' block. + DisablePendingBlock bool `hcl:"disable-pending-block,optional" toml:"disable-pending-block,optional"` } type JsonRPCConfig struct { @@ -866,7 +870,6 @@ func DefaultConfig() *Config { StateScheme: "path", Snapshot: true, BorLogs: false, - TxPool: &TxPoolConfig{ Locals: []string{}, NoLocals: false, @@ -906,6 +909,7 @@ func DefaultConfig() *Config { PrefetchGasLimitPercent: 100, TargetGasPercentage: 0, // Initialize to 0, will be set from CLI or remain 0 (meaning use default) BaseFeeChangeDenominator: 0, // Initialize to 0, will be set from CLI or remain 0 (meaning use default) + DisablePendingBlock: false, }, Gpo: &GpoConfig{ Blocks: 20, @@ -1277,6 +1281,7 @@ func (c *Config) buildEth(stack *node.Node, accountManager *accounts.Manager) (* n.Miner.BlockTime = c.Sealer.BlockTime n.Miner.EnablePrefetch = c.Sealer.EnablePrefetch n.Miner.PrefetchGasLimitPercent = c.Sealer.PrefetchGasLimitPercent + n.Miner.DisablePendingBlock = c.Sealer.DisablePendingBlock // Validate prefetch gas limit percentage if c.Sealer.EnablePrefetch && c.Sealer.PrefetchGasLimitPercent > 150 { diff --git a/internal/cli/server/flags.go b/internal/cli/server/flags.go index 270d9f6bde..aa30a557ee 100644 --- a/internal/cli/server/flags.go +++ b/internal/cli/server/flags.go @@ -508,6 +508,13 @@ func (c *Command) Flags(config *Config) *flagset.Flagset { Default: c.cliConfig.Sealer.TargetGasMaxPercentage, Group: "Sealer", }) + f.BoolFlag(&flagset.BoolFlag{ + Name: "miner.disable-pending-block", + Usage: "Disable the pending block creation loop. When set, RPC queries for 'pending' block will return nil", + Value: &c.cliConfig.Sealer.DisablePendingBlock, + Default: c.cliConfig.Sealer.DisablePendingBlock, + Group: "Sealer", + }) // ethstats f.StringFlag(&flagset.StringFlag{ diff --git a/miner/miner.go b/miner/miner.go index a919717cc2..60d1c6ac35 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -67,6 +67,8 @@ type Config struct { PendingFeeRecipient common.Address `toml:"-"` // Address for pending block rewards. EnablePrefetch bool // Enable transaction prefetching from pool during block building PrefetchGasLimitPercent uint64 // Gas limit percentage for prefetching (e.g., 100 = 100%, 110 = 110%) + + DisablePendingBlock bool // Disable the pending block creation loop } // DefaultConfig contains default settings for miner. @@ -89,6 +91,8 @@ var DefaultConfig = Config{ Recommit: 2 * time.Second, EnablePrefetch: true, PrefetchGasLimitPercent: 100, // 100% of header gas limit + + DisablePendingBlock: false, } // Miner is the main object which takes care of submitting new work to consensus diff --git a/miner/worker.go b/miner/worker.go index 6f9b05bc3a..58807109e7 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -829,6 +829,13 @@ func (w *worker) mainLoop() { for { select { case req := <-w.newWorkCh: + // When DisablePendingBlock is set and the worker is not actively producing + // blocks (non-validator), skip commitWork entirely — its only purpose in + // that case is to maintain the pending block snapshot for RPC. + if w.config.DisablePendingBlock && !w.IsRunning() { + continue + } + if w.chainConfig.ChainID.Cmp(params.BorMainnetChainConfig.ChainID) == 0 || w.chainConfig.ChainID.Cmp(params.MumbaiChainConfig.ChainID) == 0 || w.chainConfig.ChainID.Cmp(params.AmoyChainConfig.ChainID) == 0 { if w.eth.PeerCount() > 0 || devFakeAuthor { //nolint:contextcheck @@ -849,7 +856,7 @@ func (w *worker) mainLoop() { // already included in the current sealing block. These transactions will // be automatically eliminated. // nolint : nestif - if !w.IsRunning() && w.current != nil { + if !w.IsRunning() && !w.config.DisablePendingBlock && w.current != nil { // If block is already full, abort if gp := w.current.gasPool; gp != nil && gp.Gas() < params.TxGas { continue diff --git a/miner/worker_test.go b/miner/worker_test.go index 8da774b8e4..7b6d852c6a 100644 --- a/miner/worker_test.go +++ b/miner/worker_test.go @@ -2967,3 +2967,40 @@ func TestDelayFlagOffByOne(t *testing.T) { require.True(t, buggyDelayFlag(), "bug: last tx skipped, DAG hint incorrectly embedded") require.False(t, fixedDelayFlag(), "fix: last tx detected, DAG hint suppressed") } + +// TestDisablePendingBlock validates if setting `DisablePendingBlock` to true +// correctly prevents the creation of a pending block or not. +func TestDisablePendingBlock(t *testing.T) { + t.Run("pending block is nil when flag is enabled", func(t *testing.T) { + config := DefaultTestConfig() + config.DisablePendingBlock = true + + w, _, cleanup := newTestWorker(t, config, ethashChainConfig, ethash.NewFaker(), rawdb.NewMemoryDatabase(), false, 0) + defer cleanup() + + // Trigger the pending block build (non-validator path: worker is not started/running). + w.startCh <- struct{}{} + time.Sleep(500 * time.Millisecond) + + block, receipts, stateDB := w.pending() + require.Nil(t, block, "pending block should be nil when DisablePendingBlock is true") + require.Nil(t, receipts, "pending receipts should be nil when DisablePendingBlock is true") + require.Nil(t, stateDB, "pending state should be nil when DisablePendingBlock is true") + }) + + t.Run("pending block is created when flag is disabled", func(t *testing.T) { + config := DefaultTestConfig() + config.DisablePendingBlock = false + + w, _, cleanup := newTestWorker(t, config, ethashChainConfig, ethash.NewFaker(), rawdb.NewMemoryDatabase(), false, 0) + defer cleanup() + + // Trigger the pending block build (non-validator path: worker is not started/running). + w.startCh <- struct{}{} + time.Sleep(500 * time.Millisecond) + + block, _, stateDB := w.pending() + require.NotNil(t, block, "pending block should not be nil when DisablePendingBlock is false") + require.NotNil(t, stateDB, "pending state should not be nil when DisablePendingBlock is false") + }) +} From 51f0295a7b82f65ab5ec12f47f3e011fd5d448ad Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Fri, 3 Apr 2026 01:04:26 +0530 Subject: [PATCH 2/5] miner: update tests --- miner/worker_test.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/miner/worker_test.go b/miner/worker_test.go index 7b6d852c6a..15918141f4 100644 --- a/miner/worker_test.go +++ b/miner/worker_test.go @@ -2968,9 +2968,11 @@ func TestDelayFlagOffByOne(t *testing.T) { require.False(t, fixedDelayFlag(), "fix: last tx detected, DAG hint suppressed") } -// TestDisablePendingBlock validates if setting `DisablePendingBlock` to true -// correctly prevents the creation of a pending block or not. +// TestDisablePendingBlock validates if setting `DisablePendingBlock` affects the +// creation of pending block or not. func TestDisablePendingBlock(t *testing.T) { + t.Parallel() + t.Run("pending block is nil when flag is enabled", func(t *testing.T) { config := DefaultTestConfig() config.DisablePendingBlock = true @@ -2999,8 +3001,9 @@ func TestDisablePendingBlock(t *testing.T) { w.startCh <- struct{}{} time.Sleep(500 * time.Millisecond) - block, _, stateDB := w.pending() + block, receipts, stateDB := w.pending() require.NotNil(t, block, "pending block should not be nil when DisablePendingBlock is false") + require.NotNil(t, receipts, "pending receipts should not be nil when DisablePendingBlock is false") require.NotNil(t, stateDB, "pending state should not be nil when DisablePendingBlock is false") }) } From 82c089ee50af10ac7e5e32ed596f2096efd090f2 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Fri, 3 Apr 2026 01:14:48 +0530 Subject: [PATCH 3/5] update flag description --- docs/cli/server.md | 2 +- internal/cli/server/config.go | 5 +++-- internal/cli/server/flags.go | 2 +- miner/miner.go | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/cli/server.md b/docs/cli/server.md index 85e45e1e24..ee914f0b6e 100644 --- a/docs/cli/server.md +++ b/docs/cli/server.md @@ -336,7 +336,7 @@ The ```bor server``` command runs the Bor client. - ```miner.blocktime```: The block time defined by the miner. Needs to be larger or equal to the consensus block time. If not set (default = 0), the miner will use the consensus block time. (default: 0s) -- ```miner.disable-pending-block```: Disable the pending block creation loop. When set, RPC queries for 'pending' block will return nil (default: false) +- ```miner.disable-pending-block```: Disable the pending block creation loop. When set, RPC queries for 'pending' block will return nil on non block producer nodes (default: false) - ```miner.enableDynamicGasLimit```: Enable dynamic gas limit adjustment based on base fee (default: false) diff --git a/internal/cli/server/config.go b/internal/cli/server/config.go index bc016a761c..66f43bef36 100644 --- a/internal/cli/server/config.go +++ b/internal/cli/server/config.go @@ -450,8 +450,9 @@ type SealerConfig struct { // PrefetchGasLimitPercent is the gas limit percentage for prefetching (e.g., 100 = 100%, 110 = 110%) PrefetchGasLimitPercent uint64 `hcl:"prefetch-gaslimit-percent,optional" toml:"prefetch-gaslimit-percent,optional"` - // DisablePendingBlock disables the pending block creation loop which currently works in all node types - // to create a block for serving rpc queries for 'pending' block. + // DisablePendingBlock disables the pending block creation loop which primarily builds a 'pending' + // block to serve rpc queries. If enabled, all 'pending' block queries will return nil. This won't + // apply for block producer nodes. DisablePendingBlock bool `hcl:"disable-pending-block,optional" toml:"disable-pending-block,optional"` } diff --git a/internal/cli/server/flags.go b/internal/cli/server/flags.go index aa30a557ee..66c74943c4 100644 --- a/internal/cli/server/flags.go +++ b/internal/cli/server/flags.go @@ -510,7 +510,7 @@ func (c *Command) Flags(config *Config) *flagset.Flagset { }) f.BoolFlag(&flagset.BoolFlag{ Name: "miner.disable-pending-block", - Usage: "Disable the pending block creation loop. When set, RPC queries for 'pending' block will return nil", + Usage: "Disable the pending block creation loop. When set, RPC queries for 'pending' block will return nil on non block producer nodes", Value: &c.cliConfig.Sealer.DisablePendingBlock, Default: c.cliConfig.Sealer.DisablePendingBlock, Group: "Sealer", diff --git a/miner/miner.go b/miner/miner.go index 60d1c6ac35..dbd4607542 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -68,7 +68,7 @@ type Config struct { EnablePrefetch bool // Enable transaction prefetching from pool during block building PrefetchGasLimitPercent uint64 // Gas limit percentage for prefetching (e.g., 100 = 100%, 110 = 110%) - DisablePendingBlock bool // Disable the pending block creation loop + DisablePendingBlock bool // Disable the pending block creation loop on non block producer nodes } // DefaultConfig contains default settings for miner. From 32a87a82003d816d325249c66875d14d02312e8b Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Fri, 3 Apr 2026 11:53:48 +0530 Subject: [PATCH 4/5] address claude comments --- docs/cli/server.md | 2 +- internal/cli/server/flags.go | 2 +- miner/worker.go | 1 + miner/worker_test.go | 22 ++++++++++++---------- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/docs/cli/server.md b/docs/cli/server.md index ee914f0b6e..ac618eb7aa 100644 --- a/docs/cli/server.md +++ b/docs/cli/server.md @@ -336,7 +336,7 @@ The ```bor server``` command runs the Bor client. - ```miner.blocktime```: The block time defined by the miner. Needs to be larger or equal to the consensus block time. If not set (default = 0), the miner will use the consensus block time. (default: 0s) -- ```miner.disable-pending-block```: Disable the pending block creation loop. When set, RPC queries for 'pending' block will return nil on non block producer nodes (default: false) +- ```miner.disable-pending-block```: Disable the pending block creation loop on non block producer nodes. When set, RPC queries for 'pending' block will return an error (default: false) - ```miner.enableDynamicGasLimit```: Enable dynamic gas limit adjustment based on base fee (default: false) diff --git a/internal/cli/server/flags.go b/internal/cli/server/flags.go index 66c74943c4..5ff98824b2 100644 --- a/internal/cli/server/flags.go +++ b/internal/cli/server/flags.go @@ -510,7 +510,7 @@ func (c *Command) Flags(config *Config) *flagset.Flagset { }) f.BoolFlag(&flagset.BoolFlag{ Name: "miner.disable-pending-block", - Usage: "Disable the pending block creation loop. When set, RPC queries for 'pending' block will return nil on non block producer nodes", + Usage: "Disable the pending block creation loop on non block producer nodes. When set, RPC queries for 'pending' block will return an error", Value: &c.cliConfig.Sealer.DisablePendingBlock, Default: c.cliConfig.Sealer.DisablePendingBlock, Group: "Sealer", diff --git a/miner/worker.go b/miner/worker.go index ca5eb159c8..4a8c79bf29 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -836,6 +836,7 @@ func (w *worker) mainLoop() { // blocks (non-validator), skip commitWork entirely — its only purpose in // that case is to maintain the pending block snapshot for RPC. if w.config.DisablePendingBlock && !w.IsRunning() { + w.pendingWorkBlock.Store(0) continue } diff --git a/miner/worker_test.go b/miner/worker_test.go index 15918141f4..eaf87fe72d 100644 --- a/miner/worker_test.go +++ b/miner/worker_test.go @@ -2974,6 +2974,8 @@ func TestDisablePendingBlock(t *testing.T) { t.Parallel() t.Run("pending block is nil when flag is enabled", func(t *testing.T) { + t.Parallel() + config := DefaultTestConfig() config.DisablePendingBlock = true @@ -2982,15 +2984,16 @@ func TestDisablePendingBlock(t *testing.T) { // Trigger the pending block build (non-validator path: worker is not started/running). w.startCh <- struct{}{} - time.Sleep(500 * time.Millisecond) - block, receipts, stateDB := w.pending() - require.Nil(t, block, "pending block should be nil when DisablePendingBlock is true") - require.Nil(t, receipts, "pending receipts should be nil when DisablePendingBlock is true") - require.Nil(t, stateDB, "pending state should be nil when DisablePendingBlock is true") + require.Never(t, func() bool { + block, receipts, stateDB := w.pending() + return block != nil || receipts != nil || stateDB != nil + }, 500*time.Millisecond, 100*time.Millisecond, "pending block, receipts and state should be nil when DisablePendingBlock is true") }) t.Run("pending block is created when flag is disabled", func(t *testing.T) { + t.Parallel() + config := DefaultTestConfig() config.DisablePendingBlock = false @@ -2999,11 +3002,10 @@ func TestDisablePendingBlock(t *testing.T) { // Trigger the pending block build (non-validator path: worker is not started/running). w.startCh <- struct{}{} - time.Sleep(500 * time.Millisecond) - block, receipts, stateDB := w.pending() - require.NotNil(t, block, "pending block should not be nil when DisablePendingBlock is false") - require.NotNil(t, receipts, "pending receipts should not be nil when DisablePendingBlock is false") - require.NotNil(t, stateDB, "pending state should not be nil when DisablePendingBlock is false") + require.Eventually(t, func() bool { + block, receipts, stateDB := w.pending() + return block != nil && receipts != nil && stateDB != nil + }, 2*time.Second, 100*time.Millisecond, "pending block, receipts and state should not be nil when DisablePendingBlock is false") }) } From 6fa492ec126fbb1d39126283069dcbd9eac524d3 Mon Sep 17 00:00:00 2001 From: Manav Darji Date: Fri, 3 Apr 2026 16:45:15 +0530 Subject: [PATCH 5/5] change flag description --- docs/cli/example_config.toml | 2 +- docs/cli/server.md | 2 +- internal/cli/server/config.go | 6 +++--- internal/cli/server/flags.go | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/cli/example_config.toml b/docs/cli/example_config.toml index 006c878a42..5bac960687 100644 --- a/docs/cli/example_config.toml +++ b/docs/cli/example_config.toml @@ -86,7 +86,7 @@ bp-rpc-endpoints = [ ] # Comma separated rpc endpoints of all block producers gasprice = "25000000000" # Minimum gas price for mining a transaction. Regardless the value set, it will be enforced to 25000000000 for all networks recommit = "2m5s" # The time interval for miner to re-create mining work commitinterrupt = true # Interrupt the current mining work when time is exceeded and create partial blocks - disable-pending-block = false # Disable the pending block creation loop. When set, RPC queries for 'pending' block will return nil + disable-pending-block = false # Disable the pending block creation loop on non block producer nodes. When set, 'pending' block will be unavailable for RPC queries. # Dynamic gas limit configuration enableDynamicGasLimit = false # Enable dynamic gas limit adjustment based on base fee gasLimitMin = 50000000 # Minimum gas limit when dynamic gas limit is enabled diff --git a/docs/cli/server.md b/docs/cli/server.md index ac618eb7aa..11c63bfcc3 100644 --- a/docs/cli/server.md +++ b/docs/cli/server.md @@ -336,7 +336,7 @@ The ```bor server``` command runs the Bor client. - ```miner.blocktime```: The block time defined by the miner. Needs to be larger or equal to the consensus block time. If not set (default = 0), the miner will use the consensus block time. (default: 0s) -- ```miner.disable-pending-block```: Disable the pending block creation loop on non block producer nodes. When set, RPC queries for 'pending' block will return an error (default: false) +- ```miner.disable-pending-block```: Disable the pending block creation loop on non block producer nodes. When set, 'pending' block will be unavailable for RPC queries. (default: false) - ```miner.enableDynamicGasLimit```: Enable dynamic gas limit adjustment based on base fee (default: false) diff --git a/internal/cli/server/config.go b/internal/cli/server/config.go index 66f43bef36..0d86148b71 100644 --- a/internal/cli/server/config.go +++ b/internal/cli/server/config.go @@ -450,9 +450,9 @@ type SealerConfig struct { // PrefetchGasLimitPercent is the gas limit percentage for prefetching (e.g., 100 = 100%, 110 = 110%) PrefetchGasLimitPercent uint64 `hcl:"prefetch-gaslimit-percent,optional" toml:"prefetch-gaslimit-percent,optional"` - // DisablePendingBlock disables the pending block creation loop which primarily builds a 'pending' - // block to serve rpc queries. If enabled, all 'pending' block queries will return nil. This won't - // apply for block producer nodes. + // DisablePendingBlock disables the pending block creation loop on non block producer nodes. When + // set, 'pending' block will be unavailable for RPC queries. This won't apply for block producer + // nodes. DisablePendingBlock bool `hcl:"disable-pending-block,optional" toml:"disable-pending-block,optional"` } diff --git a/internal/cli/server/flags.go b/internal/cli/server/flags.go index 5ff98824b2..39e01ea7ab 100644 --- a/internal/cli/server/flags.go +++ b/internal/cli/server/flags.go @@ -510,7 +510,7 @@ func (c *Command) Flags(config *Config) *flagset.Flagset { }) f.BoolFlag(&flagset.BoolFlag{ Name: "miner.disable-pending-block", - Usage: "Disable the pending block creation loop on non block producer nodes. When set, RPC queries for 'pending' block will return an error", + Usage: "Disable the pending block creation loop on non block producer nodes. When set, 'pending' block will be unavailable for RPC queries.", Value: &c.cliConfig.Sealer.DisablePendingBlock, Default: c.cliConfig.Sealer.DisablePendingBlock, Group: "Sealer",