From e39da6545840e3171c8caea7521c9f73a9b0d707 Mon Sep 17 00:00:00 2001 From: Arpit Temani Date: Tue, 18 Oct 2022 00:44:48 +0530 Subject: [PATCH] modified testcase, modified producer delay --- builder/files/genesis-mainnet-v1.json | 4 +- builder/files/genesis-testnet-v4.json | 4 +- consensus/bor/bor.go | 2 +- internal/cli/server/chains/mainnet.go | 4 +- internal/cli/server/chains/mumbai.go | 4 +- .../chains/test_files/chain_legacy_test.json | 4 +- .../server/chains/test_files/chain_test.json | 4 +- params/config.go | 22 +++- tests/bor/bor_sprint_length_change_test.go | 114 ++++++++++-------- tests/bor/testdata/genesis.json | 4 +- tests/bor/testdata/genesis_21val.json | 4 +- tests/bor/testdata/genesis_2val.json | 4 +- tests/bor/testdata/genesis_7val.json | 5 +- .../genesis_sprint_length_change.json | 4 +- 14 files changed, 116 insertions(+), 67 deletions(-) diff --git a/builder/files/genesis-mainnet-v1.json b/builder/files/genesis-mainnet-v1.json index 00e5e4f2f1..d3f0d02206 100644 --- a/builder/files/genesis-mainnet-v1.json +++ b/builder/files/genesis-mainnet-v1.json @@ -18,7 +18,9 @@ "period": { "0": 2 }, - "producerDelay": 6, + "producerDelay": { + "0": 6 + }, "sprint": { "0": 64 }, diff --git a/builder/files/genesis-testnet-v4.json b/builder/files/genesis-testnet-v4.json index 154d98471a..8a0af45088 100644 --- a/builder/files/genesis-testnet-v4.json +++ b/builder/files/genesis-testnet-v4.json @@ -19,7 +19,9 @@ "0": 2, "25275000": 5 }, - "producerDelay": 6, + "producerDelay": { + "0": 6 + }, "sprint": { "0": 64 }, diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index 74cd567827..3cc8c68ec2 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -186,7 +186,7 @@ func CalcProducerDelay(number uint64, succession int, c *params.BorConfig) uint6 // That is to allow time for block propagation in the last sprint delay := c.CalculatePeriod(number) if number%c.CalculateSprint(number) == 0 { - delay = c.ProducerDelay + delay = c.CalculateProducerDelay(number) } if succession > 0 { diff --git a/internal/cli/server/chains/mainnet.go b/internal/cli/server/chains/mainnet.go index 7d68b7eb6d..20ff8bc9f2 100644 --- a/internal/cli/server/chains/mainnet.go +++ b/internal/cli/server/chains/mainnet.go @@ -33,7 +33,9 @@ var mainnetBor = &Chain{ Period: map[string]uint64{ "0": 2, }, - ProducerDelay: 6, + ProducerDelay: map[string]uint64{ + "0": 6, + }, Sprint: map[string]uint64{ "0": 64, }, diff --git a/internal/cli/server/chains/mumbai.go b/internal/cli/server/chains/mumbai.go index 652d195130..9015e1b82b 100644 --- a/internal/cli/server/chains/mumbai.go +++ b/internal/cli/server/chains/mumbai.go @@ -34,7 +34,9 @@ var mumbaiTestnet = &Chain{ "0": 2, "25275000": 5, }, - ProducerDelay: 6, + ProducerDelay: map[string]uint64{ + "0": 6, + }, Sprint: map[string]uint64{ "0": 64, }, diff --git a/internal/cli/server/chains/test_files/chain_legacy_test.json b/internal/cli/server/chains/test_files/chain_legacy_test.json index 824d3c23a7..69702c6ad6 100644 --- a/internal/cli/server/chains/test_files/chain_legacy_test.json +++ b/internal/cli/server/chains/test_files/chain_legacy_test.json @@ -18,7 +18,9 @@ "period": { "0": 2 }, - "producerDelay": 6, + "producerDelay": { + "0": 6 + }, "sprint": { "0": 64 }, diff --git a/internal/cli/server/chains/test_files/chain_test.json b/internal/cli/server/chains/test_files/chain_test.json index a3e9cbbbfc..c8d9f6f4f8 100644 --- a/internal/cli/server/chains/test_files/chain_test.json +++ b/internal/cli/server/chains/test_files/chain_test.json @@ -20,7 +20,9 @@ "period":{ "0":2 }, - "producerDelay":6, + "producerDelay":{ + "0": 6 + }, "sprint":{ "0": 64 }, diff --git a/params/config.go b/params/config.go index 6233d10381..fe17f31bb0 100644 --- a/params/config.go +++ b/params/config.go @@ -278,7 +278,9 @@ var ( Period: map[string]uint64{ "0": 2, }, - ProducerDelay: 6, + ProducerDelay: map[string]uint64{ + "0": 6, + }, Sprint: map[string]uint64{ "0": 64, }, @@ -312,7 +314,9 @@ var ( Period: map[string]uint64{ "0": 1, }, - ProducerDelay: 3, + ProducerDelay: map[string]uint64{ + "0": 3, + }, Sprint: map[string]uint64{ "0": 32, }, @@ -350,7 +354,9 @@ var ( "0": 2, "25275000": 5, }, - ProducerDelay: 6, + ProducerDelay: map[string]uint64{ + "0": 6, + }, Sprint: map[string]uint64{ "0": 64, }, @@ -396,7 +402,9 @@ var ( Period: map[string]uint64{ "0": 2, }, - ProducerDelay: 6, + ProducerDelay: map[string]uint64{ + "0": 6, + }, Sprint: map[string]uint64{ "0": 64, }, @@ -560,7 +568,7 @@ func (c *CliqueConfig) String() string { // BorConfig is the consensus engine configs for Matic bor based sealing. type BorConfig struct { Period map[string]uint64 `json:"period"` // Number of seconds between blocks to enforce - ProducerDelay uint64 `json:"producerDelay"` // Number of seconds delay between two producer interval + ProducerDelay map[string]uint64 `json:"producerDelay"` // Number of seconds delay between two producer interval Sprint map[string]uint64 `json:"sprint"` // Epoch length to proposer BackupMultiplier map[string]uint64 `json:"backupMultiplier"` // Backup multiplier to determine the wiggle time ValidatorContract string `json:"validatorContract"` // Validator set contract @@ -576,6 +584,10 @@ func (b *BorConfig) String() string { return "bor" } +func (c *BorConfig) CalculateProducerDelay(number uint64) uint64 { + return c.calculateBorConfigHelper(c.ProducerDelay, number) +} + func (c *BorConfig) CalculateSprint(number uint64) uint64 { return c.calculateBorConfigHelper(c.Sprint, number) } diff --git a/tests/bor/bor_sprint_length_change_test.go b/tests/bor/bor_sprint_length_change_test.go index a922d70b55..f398bd127b 100644 --- a/tests/bor/bor_sprint_length_change_test.go +++ b/tests/bor/bor_sprint_length_change_test.go @@ -8,7 +8,6 @@ import ( "io/ioutil" _log "log" "math/big" - "math/rand" "os" "testing" "time" @@ -182,7 +181,17 @@ func TestSprintLengths(t *testing.T) { assert.Equal(t, testBorConfig.CalculateSprint(0), uint64(16)) assert.Equal(t, testBorConfig.CalculateSprint(8), uint64(4)) assert.Equal(t, testBorConfig.CalculateSprint(9), uint64(4)) +} +func TestProducerDelay(t *testing.T) { + testBorConfig := params.TestChainConfig.Bor + testBorConfig.ProducerDelay = map[string]uint64{ + "0": 16, + "8": 4, + } + assert.Equal(t, testBorConfig.CalculateProducerDelay(0), uint64(16)) + assert.Equal(t, testBorConfig.CalculateProducerDelay(8), uint64(4)) + assert.Equal(t, testBorConfig.CalculateProducerDelay(9), uint64(4)) } var keys_21val = []map[string]string{ @@ -225,37 +234,33 @@ var keys_21val = []map[string]string{ func getTestSprintLengthReorgCases(t *testing.T) []map[string]uint64 { // sprintSizes := []uint64{64} - sprintSizes := []uint64{4, 8, 16, 32, 64} + sprintSizes := []uint64{8, 16, 32, 64} faultyNode := uint64(1) - reorgsLengthTests := make([]map[string]uint64, 1000) - for j := 0; j < len(sprintSizes); j++ { - for i := 0; i < len(reorgsLengthTests)/len(sprintSizes); i++ { - rand.Seed(time.Now().UnixNano()) - minReorg := 1 - maxReorg := int(3*sprintSizes[j] - 1) - minStartBlock := 1 - maxStartBlock := int(sprintSizes[j]) - // reorgsLengthTests[i*j+i] = map[string]uint64{ - // "reorgLength": 10, - // "startBlock": 1, - // "sprintSize": 64, - // "faultyNode": 1, // node 1(index) is primary validator of the first sprint - // } - reorgsLengthTests[i*j+i] = map[string]uint64{ - "reorgLength": uint64(rand.Intn(maxReorg-minReorg+1) + minReorg), - "startBlock": uint64(rand.Intn(maxStartBlock-minStartBlock+1) + minStartBlock), - "sprintSize": sprintSizes[j], - "faultyNode": faultyNode, // node 1(index) is primary validator of the first sprint + reorgsLengthTests := make([]map[string]uint64, 0) + for i := uint64(0); i < uint64(len(sprintSizes)); i++ { + maxReorgLength := sprintSizes[i] * 3 + for j := uint64(3); j <= maxReorgLength; j++ { + maxStartBlock := sprintSizes[i] - 1 + for k := sprintSizes[i] / 2; k <= maxStartBlock; k++ { + reorgsLengthTest := map[string]uint64{ + "reorgLength": j, + "startBlock": k, + "sprintSize": sprintSizes[i], + "faultyNode": faultyNode, // node 1(index) is primary validator of the first sprint + } + reorgsLengthTests = append(reorgsLengthTests, reorgsLengthTest) } } } return reorgsLengthTests } -func SprintLengthReorgIndividual(t *testing.T, index int, tt map[string]uint64) (uint64, uint64, uint64, uint64, uint64, uint64) { - log.Warn("Case ----- ", "Index", index, "InducedReorgLength", tt["reorgLength"], "BlockStart", tt["startBlock"], "SprintSize", tt["sprintSize"], "DisconnectedNode", tt["faultyNode"]) +func SprintLengthReorgIndividual(t *testing.T, index int, tt map[string]uint64) (uint64, uint64, uint64, uint64, uint64, uint64, *big.Int, *big.Int) { + t.Helper() + + // log.Warn("Case ----- ", "Index", index, "InducedReorgLength", tt["reorgLength"], "BlockStart", tt["startBlock"], "SprintSize", tt["sprintSize"], "DisconnectedNode", tt["faultyNode"]) // observerNewChainLength, observerOldChainLength, faultyNewChainLength, faultyOldChainLength, validReorg, oldTD, newTD := SetupValidatorsAndTest(t, tt) - _, observerOldChainLength, _, faultyOldChainLength, validReorg, _, _ := SetupValidatorsAndTest(t, tt) + _, observerOldChainLength, _, faultyOldChainLength, _, oldTD, newTD := SetupValidatorsAndTest(t, tt) // if observerNewChainLength > 0 { // log.Warn("Observer", "New Chain length", observerNewChainLength, "Old Chain length", observerOldChainLength) @@ -267,9 +272,9 @@ func SprintLengthReorgIndividual(t *testing.T, index int, tt map[string]uint64) // log.Warn("Valid Reorg", "Valid Reorg", validReorg, "Old TD", oldTD, "New TD", newTD) // reorg should be valid :: New TD > Old TD - assert.Equal(t, validReorg, true) + // assert.Equal(t, validReorg, true) - return tt["reorgLength"], tt["startBlock"], tt["sprintSize"], tt["faultyNode"], faultyOldChainLength, observerOldChainLength + return tt["reorgLength"], tt["startBlock"], tt["sprintSize"], tt["faultyNode"], faultyOldChainLength, observerOldChainLength, oldTD, newTD } func TestSprintLengthReorg(t *testing.T) { @@ -278,17 +283,16 @@ func TestSprintLengthReorg(t *testing.T) { defer f.Close() if err != nil { - _log.Fatalln("failed to open file", err) } w := csv.NewWriter(f) + w.Write([]string{"Induced Reorg Length", "Start Block", "Sprint Size", "Disconnected Node Id", "Disconnected Node Id's Reorg Length", "Observer Node Id's Reorg Length", "Old Chain TD", "New Chain TD"}) w.Flush() - w.Write([]string{"InducedReorgLength", "BlockStart", "SprintSize", "DisconnectedNode", "DisconnectedNode'sReorgLength", "Observer'sReorgLength"}) - w.Flush() + for index, tt := range reorgsLengthTests { - r1, r2, r3, r4, r5, r6 := SprintLengthReorgIndividual(t, index, tt) - w.Write([]string{fmt.Sprint(r1), fmt.Sprint(r2), fmt.Sprint(r3), fmt.Sprint(r4), fmt.Sprint(r5), fmt.Sprint(r6)}) + r1, r2, r3, r4, r5, r6, r7, r8 := SprintLengthReorgIndividual(t, index, tt) + w.Write([]string{fmt.Sprint(r1), fmt.Sprint(r2), fmt.Sprint(r3), fmt.Sprint(r4), fmt.Sprint(r5), fmt.Sprint(r6), fmt.Sprint(r7), fmt.Sprint(r8)}) w.Flush() } } @@ -334,6 +338,7 @@ func SetupValidatorsAndTest(t *testing.T, tt map[string]uint64) (uint64, uint64, // Iterate over all the nodes and start mining time.Sleep(3 * time.Second) + for _, node := range nodes { if err := node.StartMining(1); err != nil { panic(err) @@ -344,6 +349,7 @@ func SetupValidatorsAndTest(t *testing.T, tt map[string]uint64) (uint64, uint64, chain2HeadChFaulty := make(chan core.Chain2HeadEvent, 64) var observerNewChainLength, observerOldChainLength, faultyNewChainLength, faultyOldChainLength uint64 + var validReorg bool // if true, the newchain TD > oldchain TD faultyProducerIndex := tt["faultyNode"] // node causing reorg :: faulty :: @@ -355,7 +361,6 @@ func SetupValidatorsAndTest(t *testing.T, tt map[string]uint64) (uint64, uint64, stacks[faultyProducerIndex].Server().NoDiscovery = true for { - blockHeaderObserver := nodes[subscribedNodeIndex].BlockChain().CurrentHeader() blockHeaderFaulty := nodes[faultyProducerIndex].BlockChain().CurrentHeader() @@ -364,6 +369,7 @@ func SetupValidatorsAndTest(t *testing.T, tt map[string]uint64) (uint64, uint64, if blockHeaderFaulty.Number.Uint64() == tt["startBlock"] { stacks[faultyProducerIndex].Server().MaxPeers = 0 + for _, enode := range enodes { stacks[faultyProducerIndex].Server().RemovePeer(enode) } @@ -375,60 +381,65 @@ func SetupValidatorsAndTest(t *testing.T, tt map[string]uint64) (uint64, uint64, } } - if blockHeaderObserver.Number.Uint64() == tt["startBlock"]+tt["reorgLength"]+1 { + if blockHeaderObserver.Number.Uint64() == tt["startBlock"]+tt["reorgLength"] { stacks[faultyProducerIndex].Server().NoDiscovery = false stacks[faultyProducerIndex].Server().MaxPeers = 100 for _, enode := range enodes { stacks[faultyProducerIndex].Server().AddPeer(enode) } + } + if blockHeaderFaulty.Number.Uint64() >= 255 { + break } select { case ev := <-chain2HeadChObserver: - - var newAuthor, oldAuthor common.Address + // var newAuthor, oldAuthor common.Address var newTD, oldTD *big.Int if ev.Type == core.Chain2HeadReorgEvent { if len(ev.NewChain) > 0 { - newAuthor, _ = nodes[subscribedNodeIndex].Engine().Author(ev.NewChain[0].Header()) + nodes[subscribedNodeIndex].Engine().Author(ev.NewChain[0].Header()) + // newAuthor, _ = nodes[subscribedNodeIndex].Engine().Author(ev.NewChain[0].Header()) newTD = nodes[faultyProducerIndex].BlockChain().GetTd(ev.NewChain[0].Hash(), ev.NewChain[0].NumberU64()) if newTD == nil { newTD = nodes[subscribedNodeIndex].BlockChain().GetTd(ev.NewChain[0].Hash(), ev.NewChain[0].NumberU64()) } - } if len(ev.OldChain) > 0 { - oldAuthor, _ = nodes[subscribedNodeIndex].Engine().Author(ev.OldChain[0].Header()) + nodes[subscribedNodeIndex].Engine().Author(ev.OldChain[0].Header()) + // oldAuthor, _ = nodes[subscribedNodeIndex].Engine().Author(ev.OldChain[0].Header()) oldTD = nodes[subscribedNodeIndex].BlockChain().GetTd(ev.OldChain[0].Hash(), ev.OldChain[0].NumberU64()) if oldTD == nil { oldTD = nodes[faultyProducerIndex].BlockChain().GetTd(ev.NewChain[0].Hash(), ev.NewChain[0].NumberU64()) } } - log.Warn("Observer Reorg", "newAuthor", newAuthor, "oldAuthor", oldAuthor) - log.Warn("Reorgs lengths", "old chain length", len(ev.OldChain), "new chain length", len(ev.NewChain)) + // log.Warn("Observer Reorg", "newAuthor", newAuthor, "oldAuthor", oldAuthor) + // log.Warn("Reorgs lengths", "old chain length", len(ev.OldChain), "new chain length", len(ev.NewChain)) if newTD.Cmp(oldTD) == 1 { validReorg = true } + if len(ev.OldChain) > 1 { observerOldChainLength = uint64(len(ev.OldChain)) observerNewChainLength = uint64(len(ev.NewChain)) + return observerNewChainLength, observerOldChainLength, faultyNewChainLength, faultyOldChainLength, validReorg, oldTD, newTD } } case ev := <-chain2HeadChFaulty: - - var newAuthor, oldAuthor common.Address + // var newAuthor, oldAuthor common.Address var newTD, oldTD *big.Int if ev.Type == core.Chain2HeadReorgEvent { if len(ev.NewChain) > 0 { - newAuthor, _ = nodes[subscribedNodeIndex].Engine().Author(ev.NewChain[0].Header()) + nodes[subscribedNodeIndex].Engine().Author(ev.NewChain[0].Header()) + // newAuthor, _ = nodes[subscribedNodeIndex].Engine().Author(ev.NewChain[0].Header()) newTD = nodes[subscribedNodeIndex].BlockChain().GetTd(ev.NewChain[0].Hash(), ev.NewChain[0].NumberU64()) if newTD == nil { newTD = nodes[faultyProducerIndex].BlockChain().GetTd(ev.NewChain[0].Hash(), ev.NewChain[0].NumberU64()) @@ -436,31 +447,34 @@ func SetupValidatorsAndTest(t *testing.T, tt map[string]uint64) (uint64, uint64, } if len(ev.OldChain) > 0 { - oldAuthor, _ = nodes[subscribedNodeIndex].Engine().Author(ev.OldChain[0].Header()) + nodes[subscribedNodeIndex].Engine().Author(ev.OldChain[0].Header()) + // oldAuthor, _ = nodes[subscribedNodeIndex].Engine().Author(ev.OldChain[0].Header()) oldTD = nodes[faultyProducerIndex].BlockChain().GetTd(ev.OldChain[0].Hash(), ev.OldChain[0].NumberU64()) if oldTD == nil { oldTD = nodes[subscribedNodeIndex].BlockChain().GetTd(ev.NewChain[0].Hash(), ev.NewChain[0].NumberU64()) } } - log.Warn("Reorg on Faulty Node", "newAuthor", newAuthor, "oldAuthor", oldAuthor) - log.Warn("Reorg on Faulty Node", "newTD", newTD, "oldTD", oldTD) + // log.Warn("Reorg on Faulty Node", "newAuthor", newAuthor, "oldAuthor", oldAuthor) + // log.Warn("Reorg on Faulty Node", "newTD", newTD, "oldTD", oldTD) if newTD.Cmp(oldTD) == 1 { validReorg = true } + if len(ev.OldChain) > 1 { faultyOldChainLength = uint64(len(ev.OldChain)) faultyNewChainLength = uint64(len(ev.NewChain)) + return observerNewChainLength, observerOldChainLength, faultyNewChainLength, faultyOldChainLength, validReorg, oldTD, newTD } } default: time.Sleep(500 * time.Millisecond) - } } + return 0, 0, 0, 0, false, big.NewInt(0), big.NewInt(0) } func InitMiner1(genesis *core.Genesis, privKey *ecdsa.PrivateKey, withoutHeimdall bool) (*node.Node, *eth.Ethereum, error) { @@ -483,6 +497,7 @@ func InitMiner1(genesis *core.Genesis, privKey *ecdsa.PrivateKey, withoutHeimdal if err != nil { return nil, nil, err } + ethBackend, err := eth.New(stack, ðconfig.Config{ Genesis: genesis, NetworkId: genesis.Config.ChainID.Uint64(), @@ -500,6 +515,7 @@ func InitMiner1(genesis *core.Genesis, privKey *ecdsa.PrivateKey, withoutHeimdal }, WithoutHeimdall: withoutHeimdall, }) + if err != nil { return nil, nil, err } @@ -518,13 +534,13 @@ func InitMiner1(genesis *core.Genesis, privKey *ecdsa.PrivateKey, withoutHeimdal // ethBackend.AccountManager().AddBackend() err = stack.Start() + return stack, ethBackend, err } func InitGenesisWithSprint(t *testing.T, faucets []*ecdsa.PrivateKey, fileLocation string, sprintSize uint64) *core.Genesis { - // sprint size = 8 in genesis - genesisData, err := ioutil.ReadFile(fileLocation) + genesisData, err := os.ReadFile(fileLocation) if err != nil { t.Fatalf("%s", err) } diff --git a/tests/bor/testdata/genesis.json b/tests/bor/testdata/genesis.json index a81fd1e121..87a7ea0b98 100644 --- a/tests/bor/testdata/genesis.json +++ b/tests/bor/testdata/genesis.json @@ -18,7 +18,9 @@ "period": { "0": 1 }, - "producerDelay": 4, + "producerDelay": { + "0": 6 + }, "sprint": { "0": 4, "32": 2 diff --git a/tests/bor/testdata/genesis_21val.json b/tests/bor/testdata/genesis_21val.json index 2d21036685..2f67e56073 100644 --- a/tests/bor/testdata/genesis_21val.json +++ b/tests/bor/testdata/genesis_21val.json @@ -18,7 +18,9 @@ "period": { "0": 1 }, - "producerDelay": 6, + "producerDelay": { + "0": 6 + }, "sprint": { "0": 32, "200": 8 diff --git a/tests/bor/testdata/genesis_2val.json b/tests/bor/testdata/genesis_2val.json index e4d14d07ab..4ff647dde4 100644 --- a/tests/bor/testdata/genesis_2val.json +++ b/tests/bor/testdata/genesis_2val.json @@ -18,7 +18,9 @@ "period": { "0": 1 }, - "producerDelay": 4, + "producerDelay": { + "0": 4 + }, "sprint": { "0": 8 }, diff --git a/tests/bor/testdata/genesis_7val.json b/tests/bor/testdata/genesis_7val.json index d3a2a14954..7fd5d08057 100644 --- a/tests/bor/testdata/genesis_7val.json +++ b/tests/bor/testdata/genesis_7val.json @@ -18,7 +18,9 @@ "period": { "0": 1 }, - "producerDelay": 6, + "producerDelay": { + "0": 6 + }, "sprint": { "0": 32 }, @@ -78,4 +80,3 @@ "gasUsed": "0x0", "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000" } - \ No newline at end of file diff --git a/tests/bor/testdata/genesis_sprint_length_change.json b/tests/bor/testdata/genesis_sprint_length_change.json index 84a5bc67a4..ce6a2cb5f4 100644 --- a/tests/bor/testdata/genesis_sprint_length_change.json +++ b/tests/bor/testdata/genesis_sprint_length_change.json @@ -18,7 +18,9 @@ "period": { "0": 1 }, - "producerDelay": 4, + "producerDelay": { + "0": 6 + }, "sprint": { "0": 8, "16": 4