From 817ca2a2ba47c8663806608e70c59da3a51b655a Mon Sep 17 00:00:00 2001 From: Arpit Temani Date: Sun, 13 Nov 2022 17:28:47 +0530 Subject: [PATCH] add 2 node testcase --- tests/bor/bor_sprint_length_change_test.go | 289 ++++++++++++++++++--- 1 file changed, 257 insertions(+), 32 deletions(-) diff --git a/tests/bor/bor_sprint_length_change_test.go b/tests/bor/bor_sprint_length_change_test.go index e2d30f078b..8d2760de5f 100644 --- a/tests/bor/bor_sprint_length_change_test.go +++ b/tests/bor/bor_sprint_length_change_test.go @@ -209,53 +209,83 @@ func TestProducerDelay(t *testing.T) { } var keys_21val = []map[string]string{ - // 2 - { - "address": "0x73E033779C9030D4528d86FbceF5B02e97488921", - "priv_key": "61eb51cf8936309151ab7b931841ea033b6a09931f6a100b464fbbd74f3e0bd7", - "pub_key": "0x04f9a5e9bf76b45ac58f1b018ccba4b83b3531010cdadf42174c18a9db9879ef1dcb5d1254ce834bc108b110cd8d0186ed69a0387528a142bdb5936faf58bf98c9", - }, - // 1 { "address": "0x5C3E1B893B9315a968fcC6bce9EB9F7d8E22edB3", "priv_key": "c19fac8e538447124ad2408d9fbaeda2bb686fee763dca7a6bab58ea12442413", "pub_key": "0x0495421933eda03dcc37f9186c24e255b569513aefae71e96d55d0db3df17502e24e86297b01a167fab9ce1174f06ee3110510ac242e39218bd964de5b345edbd6", }, - // 5 { - "address": "0xb005bc07015170266Bd430f3EC1322938603be20", - "priv_key": "17cd9b38c2b3a639c7d97ccbf2bb6c7140ab8f625aec4c249bc8e4cfd3bf9a96", - "pub_key": "0x04435a70d343aa569e6f3386c73e39a1aa6f88c30e5943baedda9618b55cc944a2de1d114aff6d0e9fa002bebc780b04ef6c1b8a06bbf0d41c10d1efa55390f198", + "address": "0x73E033779C9030D4528d86FbceF5B02e97488921", + "priv_key": "61eb51cf8936309151ab7b931841ea033b6a09931f6a100b464fbbd74f3e0bd7", + "pub_key": "0x04f9a5e9bf76b45ac58f1b018ccba4b83b3531010cdadf42174c18a9db9879ef1dcb5d1254ce834bc108b110cd8d0186ed69a0387528a142bdb5936faf58bf98c9", }, - // 4 - { - "address": "0xA464DC4810Bc79B956810759e314d85BcE35cD1c", - "priv_key": "3efcf3f7014a6257f4a443119851414111820c681b27525dab3f35e72e28e51e", - "pub_key": "0x040180920306bf598ea050e258f2c7e50804a77a64f5a11705e08d18ee71eb0a80fafc95d0a42b92371ded042edda16c1f0b5f2fef7c4113ad66c59a71c29d977e", - }, - // 6 - { - "address": "0xE8d02Da3dFeeB3e755472D95D666BD6821D92129", - "priv_key": "45c9ef66361a2283cef14184f128c41949103b791aa622ead3c0bc844648b835", - "pub_key": "0x04a14651ddc80467eb589d72d95153fa695e4cb2e4bb99edeb912e840d309d61313b6f4676081b099f29e6598ecf98cb7b44bb862d019920718b558f27ba94ca51", - }, - // 7 - { - "address": "0xF93B54Cf36E917f625B48e1e3C9F93BC2344Fb06", - "priv_key": "93788a1305605808df1f9a96b5e1157da191680cf08bc15e077138f517563cd5", - "pub_key": "0x045eee11dceccd9cccc371ca3d96d74c848e785223f1e5df4d1a7f08efdfeb90bd8f0035342a9c26068cf6c7ab395ca3ceea555541325067fc187c375390efa57d", - }, - // 3 { "address": "0x751eC4877450B8a4D652d0D70197337FC38a42e6", "priv_key": "6e7f48d012c9c0baadbdc88af32521e2e477fd6898a9b65e6abe19fd6652cb2e", "pub_key": "0x0479db4c0b757bf0e5d9b8954b078ab7c0e91d6c19697904d23d07ea4853c8584382de91174929ba5c598214b8a991471ae051458ea787cdc15a4e435a55ef8059", }, + { + "address": "0xA464DC4810Bc79B956810759e314d85BcE35cD1c", + "priv_key": "3efcf3f7014a6257f4a443119851414111820c681b27525dab3f35e72e28e51e", + "pub_key": "0x040180920306bf598ea050e258f2c7e50804a77a64f5a11705e08d18ee71eb0a80fafc95d0a42b92371ded042edda16c1f0b5f2fef7c4113ad66c59a71c29d977e", + }, + { + "address": "0xb005bc07015170266Bd430f3EC1322938603be20", + "priv_key": "17cd9b38c2b3a639c7d97ccbf2bb6c7140ab8f625aec4c249bc8e4cfd3bf9a96", + "pub_key": "0x04435a70d343aa569e6f3386c73e39a1aa6f88c30e5943baedda9618b55cc944a2de1d114aff6d0e9fa002bebc780b04ef6c1b8a06bbf0d41c10d1efa55390f198", + }, + { + "address": "0xE8d02Da3dFeeB3e755472D95D666BD6821D92129", + "priv_key": "45c9ef66361a2283cef14184f128c41949103b791aa622ead3c0bc844648b835", + "pub_key": "0x04a14651ddc80467eb589d72d95153fa695e4cb2e4bb99edeb912e840d309d61313b6f4676081b099f29e6598ecf98cb7b44bb862d019920718b558f27ba94ca51", + }, + { + "address": "0xF93B54Cf36E917f625B48e1e3C9F93BC2344Fb06", + "priv_key": "93788a1305605808df1f9a96b5e1157da191680cf08bc15e077138f517563cd5", + "pub_key": "0x045eee11dceccd9cccc371ca3d96d74c848e785223f1e5df4d1a7f08efdfeb90bd8f0035342a9c26068cf6c7ab395ca3ceea555541325067fc187c375390efa57d", + }, +} + +func getTestSprintLengthReorgCases2Nodes() []map[string]interface{} { + sprintSizes := []uint64{64, 32, 16, 8} + faultyNodes := [][]uint64{[]uint64{0, 1}, []uint64{1, 2}, []uint64{0, 2}} + reorgsLengthTests := make([]map[string]interface{}, 0) + + for i := uint64(0); i < uint64(len(sprintSizes)); i++ { + maxReorgLength := sprintSizes[i] * 4 + for j := uint64(3); j <= maxReorgLength; j = j + 4 { + maxStartBlock := sprintSizes[i] - 1 + for k := sprintSizes[i] / 2; k <= maxStartBlock; k = k + 4 { + for l := uint64(0); l < uint64(len(faultyNodes)); l++ { + if j+k < sprintSizes[i] { + continue + } + + reorgsLengthTest := map[string]interface{}{ + "reorgLength": j, + "startBlock": k, + "sprintSize": sprintSizes[i], + "faultyNodes": faultyNodes[i], // node 1(index) is primary validator of the first sprint + } + reorgsLengthTests = append(reorgsLengthTests, reorgsLengthTest) + } + } + } + } + // reorgsLengthTests := []map[string]uint64{ + // { + // "reorgLength": 3, + // "startBlock": 7, + // "sprintSize": 8, + // "faultyNode": 1, + // }, + // } + return reorgsLengthTests } func getTestSprintLengthReorgCases() []map[string]uint64 { sprintSizes := []uint64{64, 32, 16, 8} - faultyNodes := []uint64{1, 0} + faultyNodes := []uint64{0, 1} reorgsLengthTests := make([]map[string]uint64, 0) for i := uint64(0); i < uint64(len(sprintSizes)); i++ { @@ -307,6 +337,64 @@ func SprintLengthReorgIndividual(t *testing.T, index int, tt map[string]uint64) return tt["reorgLength"], tt["startBlock"], tt["sprintSize"], tt["faultyNode"], faultyOldChainLength, observerOldChainLength } +func SprintLengthReorgIndividual2Nodes(t *testing.T, index int, tt map[string]interface{}) (uint64, uint64, uint64, []uint64, uint64, uint64) { + t.Helper() + + log.Warn("Case ----- ", "Index", index, "InducedReorgLength", tt["reorgLength"], "BlockStart", tt["startBlock"], "SprintSize", tt["sprintSize"], "DisconnectedNode", tt["faultyNodes"]) + observerOldChainLength, faultyOldChainLength := SetupValidatorsAndTest2Nodes(t, tt) + + if observerOldChainLength > 0 { + log.Warn("Observer", "Old Chain length", observerOldChainLength) + } + + if faultyOldChainLength > 0 { + log.Warn("Faulty", "Old Chain length", faultyOldChainLength) + } + fNodes, _ := tt["faultyNodes"].([]uint64) + + return tt["reorgLength"].(uint64), tt["startBlock"].(uint64), tt["sprintSize"].(uint64), fNodes, faultyOldChainLength, observerOldChainLength +} + +func TestSprintLengthReorg2Nodes(t *testing.T) { + t.Skip() + t.Parallel() + + reorgsLengthTests := getTestSprintLengthReorgCases2Nodes() + f, err := os.Create("sprintReorg2Nodes.csv") + + defer func() { + err = f.Close() + + if err != nil { + panic(err) + } + }() + + if err != nil { + _log.Fatalln("failed to open file", err) + } + + w := csv.NewWriter(f) + err = w.Write([]string{"Induced Reorg Length", "Start Block", "Sprint Size", "Disconnected Node Ids", "Disconnected Node Id's Reorg Length", "Observer Node Id's Reorg Length"}) + w.Flush() + + if err != nil { + panic(err) + } + + var wg sync.WaitGroup + + for index, tt := range reorgsLengthTests { + if index%4 == 0 { + wg.Wait() + } + + wg.Add(1) + + go SprintLengthReorgIndividual2NodesHelper(t, index, tt, w, &wg) + } +} + func TestSprintLengthReorg(t *testing.T) { t.Skip() t.Parallel() @@ -361,6 +449,20 @@ func SprintLengthReorgIndividualHelper(t *testing.T, index int, tt map[string]ui (*wg).Done() } +func SprintLengthReorgIndividual2NodesHelper(t *testing.T, index int, tt map[string]interface{}, w *csv.Writer, wg *sync.WaitGroup) { + t.Helper() + + r1, r2, r3, r4, r5, r6 := SprintLengthReorgIndividual2Nodes(t, index, tt) + err := w.Write([]string{fmt.Sprint(r1), fmt.Sprint(r2), fmt.Sprint(r3), fmt.Sprint(r4), fmt.Sprint(r5), fmt.Sprint(r6)}) + + if err != nil { + panic(err) + } + + w.Flush() + (*wg).Done() +} + // nolint: gocognit func SetupValidatorsAndTest(t *testing.T, tt map[string]uint64) (uint64, uint64) { t.Helper() @@ -421,7 +523,7 @@ func SetupValidatorsAndTest(t *testing.T, tt map[string]uint64) (uint64, uint64) var observerOldChainLength, faultyOldChainLength uint64 faultyProducerIndex := tt["faultyNode"] // node causing reorg :: faulty :: - subscribedNodeIndex := 5 // node on different partition, produces 7th sprint but our testcase does not run till 7th sprint. :: observer :: + subscribedNodeIndex := 6 // node on different partition, produces 7th sprint but our testcase does not run till 7th sprint. :: observer :: nodes[subscribedNodeIndex].BlockChain().SubscribeChain2HeadEvent(chain2HeadChObserver) nodes[faultyProducerIndex].BlockChain().SubscribeChain2HeadEvent(chain2HeadChFaulty) @@ -486,3 +588,126 @@ func SetupValidatorsAndTest(t *testing.T, tt map[string]uint64) (uint64, uint64) return 0, 0 } + +func SetupValidatorsAndTest2Nodes(t *testing.T, tt map[string]interface{}) (uint64, uint64) { + t.Helper() + + log.Root().SetHandler(log.LvlFilterHandler(3, log.StreamHandler(os.Stderr, log.TerminalFormat(true)))) + + _, err := fdlimit.Raise(2048) + + if err != nil { + panic(err) + } + + // Create an Ethash network based off of the Ropsten config + genesis := InitGenesis(t, nil, "./testdata/genesis_7val.json", tt["sprintSize"]) + + nodes := make([]*eth.Ethereum, len(keys_21val)) + enodes := make([]*enode.Node, len(keys_21val)) + stacks := make([]*node.Node, len(keys_21val)) + pkeys_21val := make([]*ecdsa.PrivateKey, len(keys_21val)) + + for index, signerdata := range keys_21val { + pkeys_21val[index], _ = crypto.HexToECDSA(signerdata["priv_key"]) + } + + for i := 0; i < len(keys_21val); i++ { + // Start the node and wait until it's up + stack, ethBackend, err := InitMiner(genesis, pkeys_21val[i], true) + if err != nil { + panic(err) + } + defer stack.Close() + + for stack.Server().NodeInfo().Ports.Listener == 0 { + time.Sleep(250 * time.Millisecond) + } + // Connect the node to all the previous ones + for _, n := range enodes { + stack.Server().AddPeer(n) + } + // Start tracking the node and its enode + nodes[i] = ethBackend + enodes[i] = stack.Server().Self() + stacks[i] = stack + } + + // 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) + } + } + + chain2HeadChObserver := make(chan core.Chain2HeadEvent, 64) + chain2HeadChFaulty := make(chan core.Chain2HeadEvent, 64) + + var observerOldChainLength, faultyOldChainLength uint64 + + faultyProducerIndex := tt["faultyNodes"].([]uint64)[0] // node causing reorg :: faulty :: + subscribedNodeIndex := 6 // node on different partition, produces 7th sprint but our testcase does not run till 7th sprint. :: observer :: + + nodes[subscribedNodeIndex].BlockChain().SubscribeChain2HeadEvent(chain2HeadChObserver) + nodes[faultyProducerIndex].BlockChain().SubscribeChain2HeadEvent(chain2HeadChFaulty) + + stacks[faultyProducerIndex].Server().NoDiscovery = true + + for { + blockHeaderObserver := nodes[subscribedNodeIndex].BlockChain().CurrentHeader() + blockHeaderFaulty := nodes[faultyProducerIndex].BlockChain().CurrentHeader() + + log.Warn("Current Observer block", "number", blockHeaderObserver.Number, "hash", blockHeaderObserver.Hash()) + log.Warn("Current Faulty block", "number", blockHeaderFaulty.Number, "hash", blockHeaderFaulty.Hash()) + + if blockHeaderObserver.Number.Uint64() >= tt["startBlock"].(uint64) && blockHeaderObserver.Number.Uint64() < tt["startBlock"].(uint64)+tt["reorgLength"].(uint64) { + for _, n := range tt["faultyNodes"].([]uint64) { + stacks[n].Server().MaxPeers = 1 + for n, enode := range enodes { + stacks[n].Server().RemovePeer(enode) + } + for _, m := range tt["faultyNodes"].([]uint64) { + stacks[m].Server().AddPeer(enodes[n]) + } + } + } + + if blockHeaderObserver.Number.Uint64() == tt["startBlock"].(uint64)+tt["reorgLength"].(uint64) { + 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: + if ev.Type == core.Chain2HeadReorgEvent { + if len(ev.OldChain) > 1 { + observerOldChainLength = uint64(len(ev.OldChain)) + return observerOldChainLength, 0 + } + } + + case ev := <-chain2HeadChFaulty: + if ev.Type == core.Chain2HeadReorgEvent { + if len(ev.OldChain) > 1 { + faultyOldChainLength = uint64(len(ev.OldChain)) + return 0, faultyOldChainLength + } + } + + default: + time.Sleep(500 * time.Millisecond) + } + } + + return 0, 0 +}