Skip to content

Commit 5227d91

Browse files
committed
miner: add malicious miner feature for test
1 parent 5e1ded9 commit 5227d91

File tree

10 files changed

+278
-7
lines changed

10 files changed

+278
-7
lines changed

consensus/parlia/parlia.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1699,6 +1699,23 @@ func (p *Parlia) Delay(chain consensus.ChainReader, header *types.Header, leftOv
16991699
return &delay
17001700
}
17011701

1702+
// AssembleSignature assemble the signature for block header
1703+
func (p *Parlia) AssembleSignature(block *types.Block) (*types.Block, error) {
1704+
header := block.Header()
1705+
// Don't hold the val fields for the entire sealing procedure
1706+
p.lock.RLock()
1707+
val, signFn := p.val, p.signFn
1708+
p.lock.RUnlock()
1709+
sig, err := signFn(accounts.Account{Address: val}, accounts.MimetypeParlia, ParliaRLP(header, p.chainConfig.ChainID))
1710+
if err != nil {
1711+
log.Error("Sign for the block header failed when sealing", "err", err)
1712+
return nil, err
1713+
}
1714+
copy(header.Extra[len(header.Extra)-extraSeal:], sig)
1715+
block = block.WithSeal(header)
1716+
return block, nil
1717+
}
1718+
17021719
// Seal implements consensus.Engine, attempting to create a sealed block using
17031720
// the local signing credentials.
17041721
func (p *Parlia) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error {

core/blockchain.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1997,18 +1997,18 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
19971997

19981998
// WriteBlockAndSetHead writes the given block and all associated state to the database,
19991999
// and applies the block as the new chain head.
2000-
func (bc *BlockChain) WriteBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, sealedBlockSender *event.TypeMux) (status WriteStatus, err error) {
2000+
func (bc *BlockChain) WriteBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, sealedBlockSender *event.TypeMux, delayBroadcast bool) (status WriteStatus, err error) {
20012001
if !bc.chainmu.TryLock() {
20022002
return NonStatTy, errChainStopped
20032003
}
20042004
defer bc.chainmu.Unlock()
20052005

2006-
return bc.writeBlockAndSetHead(block, receipts, logs, state, sealedBlockSender)
2006+
return bc.writeBlockAndSetHead(block, receipts, logs, state, sealedBlockSender, delayBroadcast)
20072007
}
20082008

20092009
// writeBlockAndSetHead is the internal implementation of WriteBlockAndSetHead.
20102010
// This function expects the chain mutex to be held.
2011-
func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, sealedBlockSender *event.TypeMux) (status WriteStatus, err error) {
2011+
func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, sealedBlockSender *event.TypeMux, delayBroadcast bool) (status WriteStatus, err error) {
20122012
currentBlock := bc.CurrentBlock()
20132013
reorg, err := bc.forker.ReorgNeededWithFastFinality(currentBlock, block.Header())
20142014
if err != nil {
@@ -2017,7 +2017,7 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types
20172017
if reorg {
20182018
bc.highestVerifiedBlock.Store(types.CopyHeader(block.Header()))
20192019
bc.highestVerifiedBlockFeed.Send(HighestVerifiedBlockEvent{Header: block.Header()})
2020-
if sealedBlockSender != nil {
2020+
if sealedBlockSender != nil && !delayBroadcast {
20212021
// If the local DB is corrupted, writeBlockWithState may fail.
20222022
// It's fine — other nodes will persist the block.
20232023
//
@@ -2628,7 +2628,7 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s
26282628
// Don't set the head, only insert the block
26292629
err = bc.writeBlockWithState(block, res.Receipts, statedb)
26302630
} else {
2631-
status, err = bc.writeBlockAndSetHead(block, res.Receipts, res.Logs, statedb, nil)
2631+
status, err = bc.writeBlockAndSetHead(block, res.Receipts, res.Logs, statedb, nil, false)
26322632
}
26332633
if err != nil {
26342634
return nil, err

core/types/block.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package types
2020
import (
2121
"crypto/sha256"
2222
"encoding/binary"
23+
"encoding/json"
2324
"fmt"
2425
"io"
2526
"math/big"
@@ -785,6 +786,14 @@ func (b *Block) WithWitness(witness *ExecutionWitness) *Block {
785786
}
786787
}
787788

789+
func (b *Block) DeepCopySidecars(sidecars BlobSidecars) {
790+
b.sidecars = make(BlobSidecars, len(sidecars))
791+
if len(sidecars) != 0 {
792+
buffer, _ := json.Marshal(sidecars)
793+
json.Unmarshal(buffer, &b.sidecars)
794+
}
795+
}
796+
788797
// Hash returns the keccak256 hash of b's header.
789798
// The hash is computed on the first call and cached thereafter.
790799
func (b *Block) Hash() common.Hash {

core/vote/vote_manager.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ var notContinuousJustified = metrics.NewRegisteredCounter("votesManager/notConti
3535
// Backend wraps all methods required for voting.
3636
type Backend interface {
3737
IsMining() bool
38+
VoteEnabled() bool
3839
EventMux() *event.TypeMux
3940
}
4041

@@ -140,6 +141,11 @@ func (voteManager *VoteManager) loop() {
140141
log.Debug("skip voting because mining is disabled, continue")
141142
continue
142143
}
144+
if !voteManager.eth.VoteEnabled() {
145+
log.Debug("skip voting because voting is disabled, continue")
146+
continue
147+
}
148+
143149
blockCountSinceMining++
144150
if blockCountSinceMining <= blocksNumberSinceMining {
145151
log.Debug("skip voting", "blockCountSinceMining", blockCountSinceMining, "blocksNumberSinceMining", blocksNumberSinceMining)

core/vote/vote_pool_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ func newTestBackend() *testBackend {
7676
return &testBackend{eventMux: new(event.TypeMux)}
7777
}
7878
func (b *testBackend) IsMining() bool { return true }
79+
func (b *testBackend) VoteEnabled() bool { return true }
7980
func (b *testBackend) EventMux() *event.TypeMux { return b.eventMux }
8081

8182
func (mp *mockPOSA) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, headers []*types.Header) (uint64, common.Hash, error) {

eth/api_miner.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"math/big"
2121
"time"
2222

23+
"github.com/ethereum/go-ethereum/miner/minerconfig"
2324
"github.com/ethereum/go-ethereum/params"
2425

2526
"github.com/ethereum/go-ethereum/common"
@@ -117,3 +118,37 @@ func (api *MinerAPI) AddBuilder(builder common.Address, url string) error {
117118
func (api *MinerAPI) RemoveBuilder(builder common.Address) error {
118119
return api.e.APIBackend.RemoveBuilder(builder)
119120
}
121+
122+
func (api *MinerAPI) MBConfig() minerconfig.MBConfig {
123+
return api.e.Miner().MBConfig()
124+
}
125+
126+
func (api *MinerAPI) ResetMaliciousBehavior() minerconfig.MBConfig {
127+
api.e.Miner().ResetMaliciousBehavior()
128+
return api.e.Miner().MBConfig()
129+
}
130+
131+
func (api *MinerAPI) SetDoubleSign(on bool) minerconfig.MBConfig {
132+
api.e.Miner().SetDoubleSign(on)
133+
return api.e.Miner().MBConfig()
134+
}
135+
136+
func (api *MinerAPI) SetVoteDisable(on bool) minerconfig.MBConfig {
137+
api.e.Miner().SetVoteDisable(on)
138+
return api.e.Miner().MBConfig()
139+
}
140+
141+
func (api *MinerAPI) SetSkipOffsetInturn(offset uint64) minerconfig.MBConfig {
142+
api.e.Miner().SetSkipOffsetInturn(offset)
143+
return api.e.Miner().MBConfig()
144+
}
145+
146+
func (api *MinerAPI) SetBroadcastDelayBlocks(num uint64) minerconfig.MBConfig {
147+
api.e.Miner().SetBroadcastDelayBlocks(num)
148+
return api.e.Miner().MBConfig()
149+
}
150+
151+
func (api *MinerAPI) SetLastBlockMiningTime(time uint64) minerconfig.MBConfig {
152+
api.e.Miner().SetLastBlockMiningTime(time)
153+
return api.e.Miner().MBConfig()
154+
}

eth/backend.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,7 @@ func (s *Ethereum) StopMining() {
806806
}
807807

808808
func (s *Ethereum) IsMining() bool { return s.miner.Mining() }
809+
func (s *Ethereum) VoteEnabled() bool { return s.miner.VoteEnabled() }
809810
func (s *Ethereum) Miner() *miner.Miner { return s.miner }
810811

811812
func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager }

miner/miner.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,10 @@ func (miner *Miner) Mining() bool {
170170
return miner.worker.isRunning()
171171
}
172172

173+
func (miner *Miner) VoteEnabled() bool {
174+
return miner.worker.config.VoteEnable && !miner.worker.config.MB.VoteDisable
175+
}
176+
173177
func (miner *Miner) InTurn() bool {
174178
return miner.worker.inTurn()
175179
}
@@ -227,6 +231,34 @@ func (miner *Miner) SetGasCeil(ceil uint64) {
227231
miner.worker.setGasCeil(ceil)
228232
}
229233

234+
func (miner *Miner) MBConfig() minerconfig.MBConfig {
235+
return miner.worker.config.MB
236+
}
237+
238+
func (miner *Miner) ResetMaliciousBehavior() {
239+
miner.worker.config.MB = minerconfig.DefaultMBConfig
240+
}
241+
242+
func (miner *Miner) SetDoubleSign(on bool) {
243+
miner.worker.config.MB.DoubleSign = on
244+
}
245+
246+
func (miner *Miner) SetVoteDisable(on bool) {
247+
miner.worker.config.MB.VoteDisable = on
248+
}
249+
250+
func (miner *Miner) SetSkipOffsetInturn(offset uint64) {
251+
miner.worker.config.MB.SkipOffsetInturn = &offset
252+
}
253+
254+
func (miner *Miner) SetBroadcastDelayBlocks(num uint64) {
255+
miner.worker.config.MB.BroadcastDelayBlocks = num
256+
}
257+
258+
func (miner *Miner) SetLastBlockMiningTime(time uint64) {
259+
miner.worker.config.MB.LastBlockMiningTime = time
260+
}
261+
230262
// BuildPayload builds the payload according to the provided parameters.
231263
func (miner *Miner) BuildPayload(args *BuildPayloadArgs, witness bool) (*Payload, error) {
232264
return miner.worker.buildPayload(args, witness)

miner/minerconfig/config.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ type Config struct {
6363
DisableVoteAttestation bool // Whether to skip assembling vote attestation
6464

6565
Mev MevConfig // Mev configuration
66+
MB MBConfig // Malicious behavior configuration
6667
}
6768

6869
// DefaultConfig contains default settings for miner.
@@ -82,6 +83,7 @@ var DefaultConfig = Config{
8283
MaxWaitProposalInSecs: &defaultMaxWaitProposalInSecs,
8384

8485
Mev: DefaultMevConfig,
86+
MB: DefaultMBConfig,
8587
}
8688

8789
type BuilderConfig struct {
@@ -163,3 +165,24 @@ func ApplyDefaultMinerConfig(cfg *Config) {
163165
log.Info("ApplyDefaultMinerConfig", "Mev.MaxBidsPerBuilder", *cfg.Mev.MaxBidsPerBuilder)
164166
}
165167
}
168+
169+
//go:generate go run github.com/fjl/gencodec -type MBConfig -formats toml -out gen_mb_config.go
170+
type MBConfig struct {
171+
// Generate two consecutive blocks for the same parent block
172+
DoubleSign bool
173+
// Disable voting for Fast Finality
174+
VoteDisable bool
175+
// Skip block production for in-turn validators at a specified offset
176+
SkipOffsetInturn *uint64 `toml:",omitempty"`
177+
// Delay broadcasting mined blocks by a specified number of blocks, only for in turn validators
178+
BroadcastDelayBlocks uint64
179+
// Mining time (milliseconds) for the last block in every turn
180+
LastBlockMiningTime uint64
181+
}
182+
183+
var DefaultMBConfig = MBConfig{
184+
DoubleSign: false,
185+
VoteDisable: false,
186+
BroadcastDelayBlocks: 0,
187+
LastBlockMiningTime: 0,
188+
}

0 commit comments

Comments
 (0)