|
3 | 3 |
|
4 | 4 | package simplex_test |
5 | 5 |
|
6 | | -// func TestPoS(t *testing.T) { |
7 | | -// weights := map[int]uint64{ |
8 | | -// 1: 2, |
9 | | -// 2: 2, |
10 | | -// 3: 5, |
11 | | -// 4: 1, |
12 | | -// } |
13 | | - |
14 | | -// nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} |
15 | | - |
16 | | -// posSigAggregator := &testutil.TestSignatureAggregator{ |
17 | | -// IsQuorumFunc: func(signatures []simplex.NodeID) bool { |
18 | | -// var totalWeight uint64 |
19 | | -// for _, signer := range signatures { |
20 | | -// totalWeight += weights[int(signer[0])] |
21 | | -// } |
22 | | -// return totalWeight > 6 |
23 | | -// }, |
24 | | -// } |
25 | | -// testConf := &testutil.TestNodeConfig{SigAggregator: posSigAggregator, ReplicationEnabled: true} |
26 | | - |
27 | | -// net := testutil.NewInMemNetwork(t, nodes) |
28 | | -// testutil.NewSimplexNode(t, nodes[0], net, testConf) |
29 | | -// testutil.NewSimplexNode(t, nodes[1], net, testConf) |
30 | | -// testutil.NewSimplexNode(t, nodes[2], net, testConf) |
31 | | -// testutil.NewSimplexNode(t, nodes[3], net, testConf) |
32 | | - |
33 | | -// net.StartInstances() |
34 | | - |
35 | | -// // Totally order 4 blocks, each proposed by a different node |
36 | | - |
37 | | -// for seq := uint64(0); seq < 5; seq++ { |
38 | | -// net.TriggerLeaderBlockBuilder(seq) |
39 | | -// for _, n := range net.Instances { |
40 | | -// n.Storage.WaitForBlockCommit(seq) |
41 | | -// } |
42 | | -// } |
43 | | - |
44 | | -// for i := range net.Instances { |
45 | | -// require.Equal(t, uint64(5), net.Instances[i].E.Metadata().Round) |
46 | | -// } |
47 | | - |
48 | | -// // Next, disconnect the second node which has 20% of the stake |
49 | | -// net.Disconnect(nodes[1]) |
50 | | - |
51 | | -// net.AdvanceWithoutLeader(5, nodes[1]) |
52 | | - |
53 | | -// // Re-connect it and ensure it catches up |
54 | | -// net.Connect(nodes[1]) |
55 | | - |
56 | | -// net.TriggerLeaderBlockBuilder(6) |
57 | | -// for i, n := range net.Instances { |
58 | | -// if i == 1 { |
59 | | -// continue |
60 | | -// } |
61 | | -// n.Storage.WaitForBlockCommit(5) |
62 | | -// } |
63 | | - |
64 | | -// net.Instances[1].Storage.WaitForBlockCommit(5) |
65 | | - |
66 | | -// net.TriggerLeaderBlockBuilder(7) |
67 | | -// for _, n := range net.Instances { |
68 | | -// n.Storage.WaitForBlockCommit(6) |
69 | | -// } |
70 | | - |
71 | | -// net.TriggerLeaderBlockBuilder(8) |
72 | | -// for _, n := range net.Instances { |
73 | | -// n.Storage.WaitForBlockCommit(7) |
74 | | -// } |
75 | | - |
76 | | -// // Ensure the leader is the second node |
77 | | -// require.Equal(t, nodes[1], simplex.LeaderForRound(nodes, 9)) |
78 | | - |
79 | | -// // Take down the first node and the last node, leave only the second and third node. |
80 | | -// net.Disconnect(nodes[0]) |
81 | | -// net.Disconnect(nodes[3]) |
82 | | - |
83 | | -// // At this point the second node is blacklisted, so we skip this round. |
84 | | -// testutil.WaitToEnterRound(t, net.Instances[1].E, 10) |
85 | | -// testutil.WaitToEnterRound(t, net.Instances[2].E, 10) |
86 | | - |
87 | | -// net.TriggerLeaderBlockBuilder(10) |
88 | | -// for _, n := range net.Instances { |
89 | | -// if bytes.Equal(n.E.ID, nodes[0]) || bytes.Equal(n.E.ID, nodes[3]) { |
90 | | -// continue |
91 | | -// } |
92 | | -// n.Storage.WaitForBlockCommit(8) |
93 | | -// } |
94 | | - |
95 | | -// // Bring up the two nodes back. |
96 | | -// net.Connect(nodes[0]) |
97 | | -// net.Connect(nodes[3]) |
98 | | - |
99 | | -// // Have the nodes advance to round 14 where the leader is 2. |
100 | | - |
101 | | -// for net.Instances[1].E.Metadata().Round != 14 && net.Instances[2].E.Metadata().Round != 14 { |
102 | | -// for _, n := range net.Instances { |
103 | | -// if bytes.Equal(n.E.ID, nodes[0]) || bytes.Equal(n.E.ID, nodes[3]) { |
104 | | -// continue |
105 | | -// } |
106 | | -// n.TriggerBlockShouldBeBuilt() |
107 | | -// n.AdvanceTime(n.E.EpochConfig.MaxProposalWait / 4) |
108 | | -// } |
109 | | - |
110 | | -// time.Sleep(time.Millisecond * 100) |
111 | | -// } |
112 | | - |
113 | | -// net.TriggerLeaderBlockBuilder(14) |
114 | | -// for _, n := range net.Instances { |
115 | | -// if bytes.Equal(n.E.ID, nodes[0]) || bytes.Equal(n.E.ID, nodes[3]) { |
116 | | -// continue |
117 | | -// } |
118 | | -// n.Storage.WaitForBlockCommit(9) |
119 | | -// } |
120 | | - |
121 | | -// // Ensure all nodes including those that were offline, now caught up with the latest round. |
122 | | -// for _, n := range net.Instances { |
123 | | -// testutil.WaitToEnterRound(t, n.E, 15) |
124 | | -// } |
125 | | - |
126 | | -// fmt.Println(simplex.LeaderForRound(nodes, 15)) |
127 | | - |
128 | | -// // Now, disconnect the node with the highest stake (node 3) and observe the network is stuck |
129 | | -// net.Disconnect(nodes[2]) |
130 | | -// net.TriggerLeaderBlockBuilder(15) |
131 | | - |
132 | | -// timedOut := make(map[int]struct{}) |
133 | | - |
134 | | -// for len(timedOut) < 3 { |
135 | | -// for i, n := range net.Instances { |
136 | | -// if bytes.Equal(n.E.ID, nodes[2]) { |
137 | | -// continue |
138 | | -// } |
139 | | -// n.TriggerBlockShouldBeBuilt() |
140 | | -// n.AdvanceTime(n.E.EpochConfig.MaxProposalWait / 4) |
141 | | -// if n.WAL.ContainsEmptyVote(15) { |
142 | | -// timedOut[i] = struct{}{} |
143 | | -// } |
144 | | -// } |
145 | | -// time.Sleep(time.Millisecond * 100) |
146 | | -// } |
147 | | - |
148 | | -// for _, n := range net.Instances { |
149 | | -// require.False(t, n.WAL.ContainsEmptyNotarization(15)) |
150 | | -// } |
151 | | - |
152 | | -// } |
| 6 | +import ( |
| 7 | + "bytes" |
| 8 | + "fmt" |
| 9 | + "testing" |
| 10 | + "time" |
| 11 | + |
| 12 | + "github.com/ava-labs/simplex" |
| 13 | + "github.com/ava-labs/simplex/testutil" |
| 14 | + "github.com/stretchr/testify/require" |
| 15 | +) |
| 16 | + |
| 17 | +func TestPoS(t *testing.T) { |
| 18 | + weights := map[int]uint64{ |
| 19 | + 1: 2, |
| 20 | + 2: 2, |
| 21 | + 3: 5, |
| 22 | + 4: 1, |
| 23 | + } |
| 24 | + |
| 25 | + nodes := []simplex.NodeID{{1}, {2}, {3}, {4}} |
| 26 | + |
| 27 | + posSigAggregator := &testutil.TestSignatureAggregator{ |
| 28 | + IsQuorumFunc: func(signatures []simplex.NodeID) bool { |
| 29 | + var totalWeight uint64 |
| 30 | + for _, signer := range signatures { |
| 31 | + totalWeight += weights[int(signer[0])] |
| 32 | + } |
| 33 | + return totalWeight > 6 |
| 34 | + }, |
| 35 | + } |
| 36 | + testConf := &testutil.TestNodeConfig{SigAggregator: posSigAggregator, ReplicationEnabled: true} |
| 37 | + |
| 38 | + net := testutil.NewInMemNetwork(t, nodes) |
| 39 | + testutil.NewSimplexNode(t, nodes[0], net, testConf) |
| 40 | + testutil.NewSimplexNode(t, nodes[1], net, testConf) |
| 41 | + testutil.NewSimplexNode(t, nodes[2], net, testConf) |
| 42 | + testutil.NewSimplexNode(t, nodes[3], net, testConf) |
| 43 | + |
| 44 | + net.StartInstances() |
| 45 | + |
| 46 | + // Totally order 4 blocks, each proposed by a different node |
| 47 | + |
| 48 | + for seq := uint64(0); seq < 5; seq++ { |
| 49 | + net.TriggerLeaderBlockBuilder(seq) |
| 50 | + for _, n := range net.Instances { |
| 51 | + n.Storage.WaitForBlockCommit(seq) |
| 52 | + } |
| 53 | + } |
| 54 | + |
| 55 | + for i := range net.Instances { |
| 56 | + require.Equal(t, uint64(5), net.Instances[i].E.Metadata().Round) |
| 57 | + } |
| 58 | + |
| 59 | + // Next, disconnect the second node which has 20% of the stake |
| 60 | + net.Disconnect(nodes[1]) |
| 61 | + |
| 62 | + net.AdvanceWithoutLeader(5, nodes[1]) |
| 63 | + |
| 64 | + // Re-connect it and ensure it catches up |
| 65 | + net.Connect(nodes[1]) |
| 66 | + |
| 67 | + net.TriggerLeaderBlockBuilder(6) |
| 68 | + for i, n := range net.Instances { |
| 69 | + if i == 1 { |
| 70 | + continue |
| 71 | + } |
| 72 | + n.Storage.WaitForBlockCommit(5) |
| 73 | + } |
| 74 | + |
| 75 | + net.Instances[1].Storage.WaitForBlockCommit(5) |
| 76 | + |
| 77 | + net.TriggerLeaderBlockBuilder(7) |
| 78 | + for _, n := range net.Instances { |
| 79 | + n.Storage.WaitForBlockCommit(6) |
| 80 | + } |
| 81 | + |
| 82 | + net.TriggerLeaderBlockBuilder(8) |
| 83 | + for _, n := range net.Instances { |
| 84 | + n.Storage.WaitForBlockCommit(7) |
| 85 | + } |
| 86 | + |
| 87 | + // Ensure the leader is the second node |
| 88 | + require.Equal(t, nodes[1], simplex.LeaderForRound(nodes, 9)) |
| 89 | + |
| 90 | + // Take down the first node and the last node, leave only the second and third node. |
| 91 | + net.Disconnect(nodes[0]) |
| 92 | + net.Disconnect(nodes[3]) |
| 93 | + |
| 94 | + // At this point the second node is blacklisted, so we skip this round. |
| 95 | + testutil.WaitToEnterRound(t, net.Instances[1].E, 10) |
| 96 | + testutil.WaitToEnterRound(t, net.Instances[2].E, 10) |
| 97 | + |
| 98 | + net.TriggerLeaderBlockBuilder(10) |
| 99 | + for _, n := range net.Instances { |
| 100 | + if bytes.Equal(n.E.ID, nodes[0]) || bytes.Equal(n.E.ID, nodes[3]) { |
| 101 | + continue |
| 102 | + } |
| 103 | + n.Storage.WaitForBlockCommit(8) |
| 104 | + } |
| 105 | + |
| 106 | + // Bring up the two nodes back. |
| 107 | + net.Connect(nodes[0]) |
| 108 | + net.Connect(nodes[3]) |
| 109 | + |
| 110 | + // Have the nodes advance to round 14 where the leader is 2. |
| 111 | + |
| 112 | + for net.Instances[1].E.Metadata().Round != 14 && net.Instances[2].E.Metadata().Round != 14 { |
| 113 | + for _, n := range net.Instances { |
| 114 | + if bytes.Equal(n.E.ID, nodes[0]) || bytes.Equal(n.E.ID, nodes[3]) { |
| 115 | + continue |
| 116 | + } |
| 117 | + n.BB.TriggerBlockShouldBeBuilt() |
| 118 | + n.AdvanceTime(n.E.EpochConfig.MaxProposalWait / 4) |
| 119 | + } |
| 120 | + |
| 121 | + time.Sleep(time.Millisecond * 100) |
| 122 | + } |
| 123 | + |
| 124 | + net.TriggerLeaderBlockBuilder(14) |
| 125 | + for _, n := range net.Instances { |
| 126 | + if bytes.Equal(n.E.ID, nodes[0]) || bytes.Equal(n.E.ID, nodes[3]) { |
| 127 | + continue |
| 128 | + } |
| 129 | + n.Storage.WaitForBlockCommit(9) |
| 130 | + } |
| 131 | + |
| 132 | + // Ensure all nodes including those that were offline, now caught up with the latest round. |
| 133 | + for _, n := range net.Instances { |
| 134 | + testutil.WaitToEnterRound(t, n.E, 15) |
| 135 | + } |
| 136 | + |
| 137 | + fmt.Println(simplex.LeaderForRound(nodes, 15)) |
| 138 | + |
| 139 | + // Now, disconnect the node with the highest stake (node 3) and observe the network is stuck |
| 140 | + net.Disconnect(nodes[2]) |
| 141 | + net.TriggerLeaderBlockBuilder(15) |
| 142 | + |
| 143 | + timedOut := make(map[int]struct{}) |
| 144 | + |
| 145 | + for len(timedOut) < 3 { |
| 146 | + for i, n := range net.Instances { |
| 147 | + if bytes.Equal(n.E.ID, nodes[2]) { |
| 148 | + continue |
| 149 | + } |
| 150 | + n.BB.TriggerBlockShouldBeBuilt() |
| 151 | + n.AdvanceTime(n.E.EpochConfig.MaxProposalWait / 4) |
| 152 | + if n.WAL.ContainsEmptyVote(15) { |
| 153 | + timedOut[i] = struct{}{} |
| 154 | + } |
| 155 | + } |
| 156 | + time.Sleep(time.Millisecond * 100) |
| 157 | + } |
| 158 | + |
| 159 | + for _, n := range net.Instances { |
| 160 | + require.False(t, n.WAL.ContainsEmptyNotarization(15)) |
| 161 | + } |
| 162 | + |
| 163 | +} |
0 commit comments