Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BFT Testing] Reducing load of BFT tests and improving test packages #4652

Merged
merged 50 commits into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
cfb85bd
adds test for node config filter
yhassanzadeh13 Aug 22, 2023
1f42d81
removes redundant nodes
yhassanzadeh13 Aug 22, 2023
69d5000
reduces the number of messages sent on topic validation test
yhassanzadeh13 Aug 22, 2023
8049091
changes block list to disallow list
yhassanzadeh13 Aug 22, 2023
f582994
reduces the load of tests
yhassanzadeh13 Aug 22, 2023
f66d6f5
adds readme
yhassanzadeh13 Aug 22, 2023
5273868
improves topic validator test
yhassanzadeh13 Aug 22, 2023
ed252b8
improves signature requirements test
yhassanzadeh13 Aug 22, 2023
4c8a158
extends the readme for gossipsub package
yhassanzadeh13 Aug 22, 2023
546cfd5
adds readme
yhassanzadeh13 Aug 22, 2023
30c9b78
fixes lint
yhassanzadeh13 Aug 22, 2023
05822c7
Merge branch 'master' into yahya/6857-bft-testing-ci-fix-2
yhassanzadeh13 Aug 23, 2023
e606490
Update integration/tests/bft/protocol/README.md
yhassanzadeh13 Aug 25, 2023
8793102
Merge branch 'master' into yahya/6857-bft-testing-ci-fix-2
yhassanzadeh13 Aug 25, 2023
0694f38
Update integration/tests/bft/base_suite.go
yhassanzadeh13 Aug 28, 2023
b84c87f
Update integration/tests/bft/base_suite.go
yhassanzadeh13 Aug 28, 2023
ea84b9e
Update integration/tests/bft/protocol/disallowlisting/admin_command_d…
yhassanzadeh13 Aug 28, 2023
bf44848
Update integration/tests/bft/protocol/disallowlisting/admin_command_d…
yhassanzadeh13 Aug 28, 2023
62cac9c
Update integration/testnet/node_config_test.go
yhassanzadeh13 Aug 28, 2023
8edf28b
Update integration/tests/bft/protocol/README.md
yhassanzadeh13 Aug 28, 2023
abb1572
Update integration/tests/bft/protocol/README.md
yhassanzadeh13 Aug 28, 2023
ca62488
Update integration/tests/bft/gossipsub/README.md
yhassanzadeh13 Aug 28, 2023
40c825f
Update integration/tests/bft/gossipsub/README.md
yhassanzadeh13 Aug 28, 2023
0eabca5
Update integration/tests/bft/gossipsub/README.md
yhassanzadeh13 Aug 28, 2023
44c0894
Update integration/testnet/node_config_test.go
yhassanzadeh13 Aug 28, 2023
3ea2a69
Update integration/tests/bft/framework/README.md
yhassanzadeh13 Aug 28, 2023
2c0ae3f
Update integration/tests/bft/gossipsub/README.md
yhassanzadeh13 Aug 28, 2023
d8acfb9
Update integration/tests/bft/gossipsub/README.md
yhassanzadeh13 Aug 28, 2023
5af3a49
Update integration/tests/bft/framework/README.md
yhassanzadeh13 Aug 28, 2023
47e54c8
Update integration/tests/bft/framework/README.md
yhassanzadeh13 Aug 28, 2023
d49533c
extends the godoc of base suite
yhassanzadeh13 Aug 28, 2023
53a2434
adds a comment for number of (un)authorized events
yhassanzadeh13 Aug 28, 2023
7ac2c2b
adds a comment for number of (un)authorized events
yhassanzadeh13 Aug 28, 2023
51c29ea
adds a comment for number of (un)authorized events
yhassanzadeh13 Aug 28, 2023
57687af
Merge branch 'master' into yahya/6857-bft-testing-ci-fix-2
yhassanzadeh13 Aug 29, 2023
a49f39c
extends startup duration and removes it as a parameter
yhassanzadeh13 Aug 30, 2023
51c1308
relaxes the geometric decay test
yhassanzadeh13 Aug 30, 2023
e4390a1
fixes unknown identity tests
yhassanzadeh13 Aug 30, 2023
6f2ece4
removes run parallel
yhassanzadeh13 Aug 30, 2023
2ad6e35
wip
yhassanzadeh13 Aug 30, 2023
21d627d
Revert "wip"
yhassanzadeh13 Aug 30, 2023
86d6d22
quarantines flakey tests
yhassanzadeh13 Aug 30, 2023
2d837eb
quarantines more tests
yhassanzadeh13 Aug 30, 2023
52a8ab8
quarantines more tests
yhassanzadeh13 Aug 30, 2023
edd5519
Update connection_gater_test.go
kc1116 Aug 31, 2023
4cb2d49
fixes mock with connection gater
yhassanzadeh13 Aug 31, 2023
f7580cf
Update connection_gater_test.go
kc1116 Aug 31, 2023
f972fab
Merge branch 'yahya/6857-bft-testing-ci-fix-2' of github.com:onflow/f…
kc1116 Aug 31, 2023
26f70c3
skips entire echo engine test suite
yhassanzadeh13 Aug 31, 2023
573dea1
skips entire meshnet engine test suite
yhassanzadeh13 Aug 31, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions integration/testnet/node_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,15 @@ type NodeConfig struct {
func (n NodeConfigs) Filter(filters ...NodeConfigFilter) NodeConfigs {
nodeConfigs := make(NodeConfigs, 0)
for _, config := range n {
filter := false
passedAllFilters := true
for _, f := range filters {
filter = f(config)
if !f(config) {
passedAllFilters = false
break
}
}

if filter {
if passedAllFilters {
nodeConfigs = append(nodeConfigs, config)
}
}
Expand Down
47 changes: 47 additions & 0 deletions integration/testnet/node_config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package testnet_test

import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/onflow/flow-go/integration/testnet"
"github.com/onflow/flow-go/model/flow"
)

func TestFilter(t *testing.T) {
t.Run("filters by role", func(t *testing.T) {
configs := testnet.NewNodeConfigSet(5, flow.RoleAccess)

yhassanzadeh13 marked this conversation as resolved.
Show resolved Hide resolved
filters := configs.Filter(func(n testnet.NodeConfig) bool { return n.Role == flow.RoleAccess })

yhassanzadeh13 marked this conversation as resolved.
Show resolved Hide resolved
for _, config := range filters {
assert.Equal(t, flow.RoleAccess, config.Role)
}
})

t.Run("filters by multiple conditions", func(t *testing.T) {
configs := testnet.NodeConfigs{
testnet.NewNodeConfig(flow.RoleAccess, testnet.WithDebugImage(true)),
testnet.NewNodeConfig(flow.RoleExecution, testnet.WithDebugImage(true)),
}

filters := configs.Filter(
func(n testnet.NodeConfig) bool { return n.Role == flow.RoleAccess },
func(n testnet.NodeConfig) bool {
return n.Debug
},
)

assert.Len(t, filters, 1) // should exclude execution node
assert.True(t, filters[0].Debug)
})

t.Run("no matching filters", func(t *testing.T) {
configs := testnet.NewNodeConfigSet(5, flow.RoleConsensus)

filters := configs.Filter(func(n testnet.NodeConfig) bool { return n.Role == flow.RoleAccess })

assert.Len(t, filters, 0)
})
}
12 changes: 5 additions & 7 deletions integration/tests/bft/base_suite.go
gomisha marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,16 @@ type BaseSuite struct {

// Ghost returns a client to interact with the Ghost node on testnet.
func (b *BaseSuite) Ghost() *client.GhostClient {
client, err := b.Net.ContainerByID(b.GhostID).GhostClient()
c, err := b.Net.ContainerByID(b.GhostID).GhostClient()
require.NoError(b.T(), err, "could not get ghost client")
return client
return c
}

// AccessClient returns a client to interact with the access node api on testnet.
func (b *BaseSuite) AccessClient() *testnet.Client {
client, err := b.Net.ContainerByName(testnet.PrimaryAN).TestnetClient()
c, err := b.Net.ContainerByName(testnet.PrimaryAN).TestnetClient()
require.NoError(b.T(), err, "could not get access client")
return client
return c
}

// SetupSuite sets up node configs to run a bare minimum Flow network to function correctly.
Expand All @@ -51,11 +51,10 @@ func (b *BaseSuite) SetupSuite() {
// setup access nodes
yhassanzadeh13 marked this conversation as resolved.
Show resolved Hide resolved
b.NodeConfigs = append(b.NodeConfigs,
testnet.NewNodeConfig(flow.RoleAccess, testnet.WithLogLevel(zerolog.FatalLevel)),
testnet.NewNodeConfig(flow.RoleAccess, testnet.WithLogLevel(zerolog.FatalLevel)),
)

// setup consensus nodes
for _, nodeID := range unittest.IdentifierListFixture(4) {
for _, nodeID := range unittest.IdentifierListFixture(3) {
nodeConfig := testnet.NewNodeConfig(flow.RoleConsensus,
testnet.WithID(nodeID),
testnet.WithLogLevel(zerolog.FatalLevel),
Expand All @@ -69,7 +68,6 @@ func (b *BaseSuite) SetupSuite() {
// setup verification nodes
yhassanzadeh13 marked this conversation as resolved.
Show resolved Hide resolved
b.NodeConfigs = append(b.NodeConfigs,
testnet.NewNodeConfig(flow.RoleVerification, testnet.WithLogLevel(zerolog.FatalLevel)),
testnet.NewNodeConfig(flow.RoleVerification, testnet.WithLogLevel(zerolog.FatalLevel)),
)

// setup execution nodes
Expand Down
10 changes: 10 additions & 0 deletions integration/tests/bft/framework/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Framework BFT Tests
The framework BFT tests are designed to assess the health of the BFT testing framework.

## Passthrough Sealing and Verification Test
The `PassThroughTestSuite` test within the `framework` package and includes a specific test method `TestSealingAndVerificationPassThrough`.
yhassanzadeh13 marked this conversation as resolved.
Show resolved Hide resolved
This test evaluates the health of the BFT testing framework for Byzantine Fault Tolerance (BFT) testing.
1. **Simulates a Scenario**: It sets up a scenario with two corrupted execution nodes and one corrupted verification node, controlled by a dummy orchestrator that lets all incoming events pass through.
yhassanzadeh13 marked this conversation as resolved.
Show resolved Hide resolved
2. **Deploys Transaction and Verifies Chunks**: Deploys a transaction leading to an execution result with multiple chunks, assigns them to a verification node, and verifies the generation of result approvals for all chunks.
3. **Sealing and Verification**: Enables sealing based on result approvals and verifies the sealing of a block with a specific multi-chunk execution result.
4. **Evaluates Events**: The test also assesses whether critical sealing-and-verification-related events from corrupted nodes are passed through the orchestrator, by checking both egress and ingress events.
yhassanzadeh13 marked this conversation as resolved.
Show resolved Hide resolved
32 changes: 32 additions & 0 deletions integration/tests/bft/gossipsub/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# GossipSub BFT Tests
GossipSub BFT tests are designed to test the behavior of the GossipSub protocol in a network environment with Byzantine nodes.

## Topic Validator Test
The `TopicValidatorTestSuite` in the `topicvalidator` package is specifically designed to test the functionality of the
libp2p topic validator within a network scenario.
This suite includes an end-to-end test to verify the topic validator's behavior in different situations,
focusing on both unauthorized and authorized message handling.
The method `TestTopicValidatorE2E` is a comprehensive test that mimics an environment with a corrupted byzantine attacker node
yhassanzadeh13 marked this conversation as resolved.
Show resolved Hide resolved
attempting to send unauthorized messages to a victim node.
These messages should be dropped by the topic validator, as they fail the message authorization validation.
The test simultaneously sends authorized messages to the victim node, ensuring that they are processed correctly,
demonstrating the validator's correct operation.
The test confirms two main aspects:
1. Unauthorized messages must be dropped, and the victim node should not receive any of them.
2. Authorized messages should be correctly delivered and processed by the victim node.

## Signature Requirement Test
The `TestGossipSubSignatureRequirement` method sets up a test environment consisting of three corrupted nodes:two attackers and one victim.
yhassanzadeh13 marked this conversation as resolved.
Show resolved Hide resolved
One attacker is configured without message signing, intending to send unsigned messages that should be rejected by the victim.
yhassanzadeh13 marked this conversation as resolved.
Show resolved Hide resolved
The other attacker sends valid signed messages that should be received by the victim.
yhassanzadeh13 marked this conversation as resolved.
Show resolved Hide resolved
The test is broken down into the following main parts:
1. **Unauthorized Messages Testing**: The victim node should not receive any messages sent without correct signatures from the unauthorized attacker. The test checks for zero unauthorized messages received by the victim.
2. **Authorized Messages Testing**: Messages sent by the authorized attacker, with the correct signature, must pass the libp2p signature verification process and be delivered to the victim. The test checks for all authorized messages received by the victim within a certain time frame.

## RPC Inspector False Positive Test
The `GossipsubRPCInspectorFalsePositiveNotificationsTestSuite` test within the `rpc_inspector` package test suite aims to ensure that the underlying libp2p libraries related to gossip sub RPC control message inspection do not trigger false positives during their validation processes.
yhassanzadeh13 marked this conversation as resolved.
Show resolved Hide resolved
Here's a breakdown of the `TestGossipsubRPCInspectorFalsePositiveNotifications` method:
1. **Configuration and Context Setup**: A specific duration for loading and intervals is defined, and a context with a timeout is created for the test scenario.
2. **Simulating Network Activity**: The method triggers a "loader loop" with a specific number of test accounts and intervals, intending to create artificial network activity. It does this by submitting transactions to create Flow accounts, waiting for them to be sealed.
3. **State Commitments**: The method waits for 20 state commitment changes, ensuring that the simulated network load behaves as expected.
4. **Verification of Control Messages**: After simulating network activity, the method checks to ensure that no node in the network has disseminated an invalid control message notification. This is done by collecting metrics from the network containers and verifying that no false notifications are detected.
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ const (
// The numOfAuthorizedEvents allows us to wait for a certain number of authorized messages to be received, this should
// give the network enough time to process the unauthorized messages. This ensures us that the unauthorized messages
// were indeed dropped and not unprocessed.
numOfAuthorizedEvents = 50
gomisha marked this conversation as resolved.
Show resolved Hide resolved
numOfAuthorizedEvents = 5

// numOfUnauthorizedEvents the number of unauthorized events to send by the test orchestrator.
numOfUnauthorizedEvents = 10
numOfUnauthorizedEvents = 5
)

// Orchestrator represents a simple `insecure.AttackOrchestrator` that tracks any unsigned messages received by victim nodes as well as the typically expected messages.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,7 @@ func (s *GossipSubSignatureRequirementTestSuite) TestGossipSubSignatureRequireme
require.Equal(s.T(), int64(0), s.Orchestrator.unauthorizedEventsReceived.Load(), fmt.Sprintf("expected to not receive any unauthorized messages instead got: %d", s.Orchestrator.unauthorizedEventsReceived.Load()))

// messages with correct message signatures are expected to always pass libp2p signature verification and be delivered to the victim EN.
require.Equal(s.T(), int64(numOfAuthorizedEvents), s.Orchestrator.authorizedEventsReceived.Load(), fmt.Sprintf("expected to receive %d authorized events got: %d", numOfAuthorizedEvents, s.Orchestrator.unauthorizedEventsReceived.Load()))
require.Eventually(s.T(), func() bool {
return s.Orchestrator.authorizedEventsReceived.Load() == int64(numOfAuthorizedEvents)
}, 5*time.Second, 500*time.Millisecond, fmt.Sprintf("expected to receive %d authorized events got: %d", numOfAuthorizedEvents, s.Orchestrator.unauthorizedEventsReceived.Load()))
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ const (
// The numOfAuthorizedEvents allows us to wait for a certain number of authorized messages to be received, this should
// give the network enough time to process the unauthorized messages. This ensures us that the unauthorized messages
// were indeed dropped and not unprocessed.
numOfAuthorizedEvents = 100
gomisha marked this conversation as resolved.
Show resolved Hide resolved
numOfAuthorizedEvents = 5

// numOfUnauthorizedEvents the number of unauthorized events per type to send by the test orchestrator.
numOfUnauthorizedEvents = 10
numOfUnauthorizedEvents = 5
)

// Orchestrator represents an insecure.AttackOrchestrator track incoming unauthorized messages and authorized messages received by victim nodes.
Expand Down
2 changes: 0 additions & 2 deletions integration/tests/bft/gossipsub/topicvalidator/suite.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ func (s *Suite) SetupSuite() {
return n.Role != flow.RoleExecution && n.Role != flow.RoleVerification && n.Role != flow.RoleAccess
})

s.NodeConfigs = append(s.NodeConfigs, testnet.NewNodeConfig(flow.RoleAccess, testnet.WithLogLevel(zerolog.FatalLevel)))

// create corrupt access node
s.attackerANID = unittest.IdentifierFixture()
s.NodeConfigs = append(s.NodeConfigs, testnet.NewNodeConfig(flow.RoleAccess,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,23 @@ func TestTopicValidator(t *testing.T) {
func (s *TopicValidatorTestSuite) TestTopicValidatorE2E() {
s.Orchestrator.sendUnauthorizedMsgs(s.T())
s.Orchestrator.sendAuthorizedMsgs(s.T())
unittest.RequireReturnsBefore(s.T(), s.Orchestrator.authorizedEventReceivedWg.Wait, 5*time.Second, "could not send authorized messages on time")
unittest.RequireReturnsBefore(
s.T(),
s.Orchestrator.authorizedEventReceivedWg.Wait,
5*time.Second,
"could not send authorized messages on time")

// Victim nodes are configured with the topic validator enabled, therefore they should not have
// received any of the unauthorized messages.
require.Equal(s.T(), 0, len(s.Orchestrator.unauthorizedEventsReceived), fmt.Sprintf("expected to not receive any unauthorized messages instead got: %d", len(s.Orchestrator.unauthorizedEventsReceived)))
require.Equal(
s.T(),
0,
len(s.Orchestrator.unauthorizedEventsReceived),
fmt.Sprintf("expected to not receive any unauthorized messages instead got: %d", len(s.Orchestrator.unauthorizedEventsReceived)))

// Victim nodes should receive all the authorized events sent.
require.Equal(s.T(), numOfAuthorizedEvents, len(s.Orchestrator.authorizedEventsReceived), fmt.Sprintf("expected to receive %d authorized events got: %d", numOfAuthorizedEvents, len(s.Orchestrator.unauthorizedEventsReceived)))
require.Eventually(s.T(), func() bool {
return len(s.Orchestrator.authorizedEventsReceived) == numOfAuthorizedEvents
}, 5*time.Second, 500*time.Millisecond,
fmt.Sprintf("expected to receive %d authorized events got: %d", numOfAuthorizedEvents, len(s.Orchestrator.unauthorizedEventsReceived)))
}
22 changes: 22 additions & 0 deletions integration/tests/bft/protocol/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Protocol BFT Tests
This package contains BFT tests concerning the core Flow protocol. These tests are run as part of the integration test suite.


## Admin Command Disallow List Test
The `AdminCommandDisallowListTestSuite` in the `disallowlisting` package is designed to test the functionality of the disallow-list admin command within a network context.
It ensures that connections to a blocked node are immediately pruned and incoming connection requests are blocked.
The test simulates the setup of two corrupt nodes (a sender and a receiver) and examines the behavior of the network before and after the sender node is disallowed.
It includes steps to send authorized messages to verify normal behavior, implement disallow-listing, send unauthorized messages, and validate the expectation that no unauthorized messages are received.
Various timing controls are put in place to handle asynchronous processes and potential race conditions.
The entire suite assures that the disallow-listing command behaves as intended, safeguarding network integrity.

## Wintermute Attack Test
The `WintermuteTestSuite` in the `wintermute` package is focused on validating a specific attack scenario within the network, termed the "wintermute attack."
This attack involves an orchestrator corrupting an execution result and then leveraging corrupted verification nodes to verify it.
yhassanzadeh13 marked this conversation as resolved.
Show resolved Hide resolved
The suite includes a constant timeout to define the attack window and a detailed test sequence.
The `TestWintermuteAttack` method carries out the attack process.
It first waits for an execution result to be corrupted and identifies the corresponding victim block.
It ensures that the corrupted execution nodes generate the correct result for the victim block and then waits for a specific number of approvals from corrupted verification nodes for each chunk of the corrupted result.
yhassanzadeh13 marked this conversation as resolved.
Show resolved Hide resolved
Further, the test waits for a block height equal to the victim block height to be sealed and verifies that the original victim block is correctly identified.
Additional methods and logging information assist in detailing and controlling the flow of the attack.
The entire suite is instrumental in evaluating the system's behavior under this specific attack condition and ensuring that the expected actions and responses are observed.
Loading
Loading