core/blockchain_mess_test.go — Version Comparison
|
v1.16.8 |
v1.17.3 |
| Branch |
etc/v1.16.8-full-node |
etc/v1.17.3-full-node |
| Delta |
+620 -0 |
+700 -0 |
Diff between branches
diff --git a/core/blockchain_mess_test.go b/core/blockchain_mess_test.go
index d589906e3..3e2fb0455 100644
--- a/core/blockchain_mess_test.go
+++ b/core/blockchain_mess_test.go
@@ -524,6 +524,86 @@ func TestMESSKnownBlock(t *testing.T) {
}
}
+// TestMESSFailClosed verifies that MESS rejects (fail-closed) a reorg whose common
+// ancestor cannot be found, instead of silently allowing it. Regression test for the
+// previous fail-open behaviour where findCommonAncestor errors returned nil (allow).
+func TestMESSFailClosed(t *testing.T) {
+ engine := ethash.NewFaker()
+ db := rawdb.NewMemoryDatabase()
+ genesis := messTestGenesis() // ECBP1100 active from block 11
+ genesisB := genesis.MustCommit(db, triedb.NewDatabase(db, nil))
+
+ chain, err := NewBlockChain(db, genesis, engine, DefaultConfig())
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer chain.Stop()
+ chain.EnableMESS(true, "test")
+
+ blocks, _ := GenerateChain(genesis.Config, genesisB, engine, db, 20, func(i int, gen *BlockGen) {})
+ if _, err := chain.InsertChain(blocks); err != nil {
+ t.Fatal(err)
+ }
+
+ current := chain.CurrentHeader() // block 20 → ECBP1100 active
+ if !chain.chainConfig.IsECBP1100(current.Number) {
+ t.Fatal("ECBP1100 should be active at the test height")
+ }
+
+ // An "extern" header that is not part of the chain: its parent (and itself) are
+ // unknown, so findCommonAncestor cannot resolve a common ancestor.
+ orphan := &types.Header{
+ ParentHash: common.HexToHash("0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef"),
+ Number: new(big.Int).Add(current.Number, big.NewInt(1)),
+ Difficulty: big.NewInt(1),
+ GasLimit: current.GasLimit,
+ Time: current.Time + 1,
+ }
+
+ fc := NewForkChoiceWithMESS(chain, nil)
+ if err := fc.reorgFilter(current, orphan); err == nil {
+ t.Error("MESS allowed a reorg whose common ancestor could not be found (fail-open); expected rejection")
+ }
+}
+
+// TestMESSPerChainIsolation verifies that MESS runtime state is per-BlockChain, not global:
+// enabling MESS on one chain must not affect another chain in the same process.
+func TestMESSPerChainIsolation(t *testing.T) {
+ newChain := func() *BlockChain {
+ engine := ethash.NewFaker()
+ db := rawdb.NewMemoryDatabase()
+ genesis := messTestGenesis()
+ genesis.MustCommit(db, triedb.NewDatabase(db, nil))
+ bc, err := NewBlockChain(db, genesis, engine, DefaultConfig())
+ if err != nil {
+ t.Fatal(err)
+ }
+ return bc
+ }
+
+ chainA := newChain()
+ defer chainA.Stop()
+ chainB := newChain()
+ defer chainB.Stop()
+
+ if chainA.IsMESSEnabled() || chainB.IsMESSEnabled() {
+ t.Fatal("MESS should start disabled on both chains")
+ }
+
+ chainA.EnableMESS(true, "test")
+ if !chainA.IsMESSEnabled() {
+ t.Error("chainA: MESS should be enabled after EnableMESS(true)")
+ }
+ if chainB.IsMESSEnabled() {
+ t.Error("chainB: MESS leaked from chainA — runtime state is not per-chain")
+ }
+
+ chainA.EnableMESS(false, "test")
+ if chainA.IsMESSEnabled() {
+ t.Error("chainA: MESS should be disabled after EnableMESS(false)")
+ }
+}
+
// TestEcbp1100ConfigActivation tests the IsECBP1100 config method.
func TestEcbp1100ConfigActivation(t *testing.T) {
tests := []struct {
← Back to Version Comparison