Skip to content

Commit 3c044e5

Browse files
authored
Merge pull request #60 from crytic/additional-planner-faults
Cut release v0.3
2 parents 4cbb714 + 70b2a92 commit 3c044e5

File tree

20 files changed

+356
-799
lines changed

20 files changed

+356
-799
lines changed

README.md

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,18 @@
22

33
## Getting started
44

5+
Ahead of public release, please add _any_ issues discovered with Attacknet to this Github tracker: https://github.com/crytic/attacknet/issues/59
6+
Adding issues there will help guide the development of the tool and avoid time wasted on features that don't find good bugs.
7+
58
### Installation/Building
69

7-
1. Install Go 1.20 or newer
10+
1. Install Go 1.21 or newer
811
2. In the project root, run `go build ./cmd/attacknet`
912
3. Copy the "attacknet" binary to your PATH or directly invoke it.
1013

1114
### Setting up the other bits
1215

13-
1. Set up a containerd k8s cluster. (1.26 or older) (todo: recommended resourcing. Also note that auto-scaling can
16+
1. Set up a containerd k8s cluster. (1.27 or older) (todo: recommended resourcing. Also note that auto-scaling can
1417
sometimes be too slow, and kurtosis will time out before the nodes for its workload can be provisioned.)
1518
2. Authenticate to the cluster for kubectl
1619
3. Install chaos-mesh
@@ -34,13 +37,14 @@ There are three workflows in attacknet:
3437
## Manually creating/configuring test suites
3538

3639
Attacknet is configured using "test suites". These are yaml files found under `./test-suites` that define everything
37-
Attacknet needs to genesis a network, test the network, and determine the health of the network.
40+
Attacknet needs to genesis a network, test the network, and determine the health of the network. You may have to manually add/remove
41+
targeting criteria from these configs depending on the network being tested.
3842

3943
Test suite configuration is broken into 3 sections:
4044
- Attacknet configuration.
4145
- Harness configuration. This is used to configure the Kurtosis package that will be used to genesis the network.
4246
- Test configuration. This is used to determine which tests should be run against the devnet and how those tests
43-
should be configured. As of right now, only the first test in the array is run before exiting.
47+
should be configured.
4448

4549
Here is an annotated test suite configuration that explains what each bit is for:
4650
```yaml
@@ -86,9 +90,11 @@ testConfig:
8690
description: wait for faults to terminate
8791
```
8892
93+
Over the long term, expect manual fault configuration to be deprecated in favor of the fault planner.
94+
8995
## Automatically creating test suites/network configs using the planner
9096
91-
Attacknet can automatically create test suites based off a pre-defined test plan. This can be used to create large, comprehensive test suites that test against a variety of different client combos.
97+
Attacknet can automatically create test suites based off a pre-defined test plan. This can be used to create large, comprehensive test suites that test against a variety of different client combos. This feature is highly experimental at this time.
9298
9399
An example test plan can be found in the `planner-configs/` directory
94100
Here's an annotated version:
@@ -114,6 +120,8 @@ fault_config:
114120
fault_type: ClockSkew # which fault to use. A list of faults currently supported by the planner can be found in pkg/plan/suite/types.go in FaultTypeEnum
115121
target_client: reth # which client to test. this can be an exec client or a consensus client. must show up in the client definitions above.
116122
wait_before_first_test: 300s # how long to wait before running the first test. Set this to 25 minutes to test against a finalized network.
123+
bootnode_el: geth
124+
bootnode_cl: prysm
117125
fault_config_dimensions: # the different fault configurations to use when creating tests. At least one config dimension is required.
118126
- skew: -2m # these configs differ for each fault
119127
duration: 1m
@@ -178,21 +186,31 @@ Once you've got your configuration set up, you can run Attacknet:
178186
If your suite config is located at `./test-suites/suite.yaml`, you would run `attacknet start suite`. This will
179187
probably be changed.
180188

181-
At this time, health checks will be run in perpetuity once the fault has concluded. Simply ctrl+c to terminate.
189+
Depending on the state of the Kurtosis package and tons of other variables, a lot of the example test suites/networks might not work out of the box.
190+
If you're just trying to test things out, use `attacknet start suite`. This refers to a demo test suite that was tested on Jan 30.
182191

183192
## Changelog
184193

185194
**Dec 15, 2023 version v0.1 (internal)**
186195
- Initial internal release
187196

188-
**Jan 11, 2023 version v0.2 (internal)**
197+
**Jan 11, 2024 version v0.2 (internal)**
189198
- Updated to kurtosis v0.86.1
190199
- Updated to Go 1.21
191200
- Grafana port-forwarding has been temporarily disabled
192201
- Introduces multi-step tests. This allows multiple faults and other actions to be composed into a single test.
193202
- Introduces the suite planner. The suite planner allows the user to define a set of testing criteria/dimensions, which the planner turns into a suite containing multiple tests.
194203
- Successful & failed test suites now emit test artifacts summarizing the results of the test.
195-
-
204+
205+
**Jan 30, 2024 version v0.3 (internal)**
206+
- Fixed the demo example suite
207+
- Fixed issues with the test planner and pod-restart faults.
208+
- Added bootnode configuration for the test planner.
209+
- Attack sizes in the test planner now refer to size in the context of the entire network.
210+
- A supermajority-sized attack will try to target 66%+ nodes in the entire network, not just 66% of the nodes that match the test target criteria.
211+
- Peer scoring is now disabled for all planner-generated network configurations.
212+
- Bootnodes are no longer targetable by planner-generated test suites.
213+
196214
## Developing (wip)
197215

198216
1. Install pre-commit

network-configs/default.yaml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
participants:
2-
- el_client_type: nethermind
3-
el_client_image: nethermindeth/nethermind:master
2+
- el_client_type: geth
3+
el_client_image: ethereum/client-go:latest
44
cl_client_type: lighthouse
5-
cl_client_image: ethpandaops/lighthouse:stable
5+
cl_client_image: sigp/lighthouse:latest
66
el_min_cpu: 1000
77
el_max_cpu: 1000
88
el_min_mem: 1024
@@ -15,9 +15,9 @@ participants:
1515
v_max_cpu: 1000
1616
v_min_mem: 1028
1717
v_max_mem: 1028
18-
count: 2
19-
- el_client_type: nethermind
20-
el_client_image: nethermindeth/nethermind:master
18+
count: 1
19+
- el_client_type: geth
20+
el_client_image: ethereum/client-go:latest
2121
cl_client_type: prysm
2222
cl_client_image: prysmaticlabs/prysm-beacon-chain:latest,prysmaticlabs/prysm-validator:latest
2323
el_min_cpu: 1000
@@ -26,8 +26,8 @@ participants:
2626
el_max_mem: 1024
2727
bn_min_cpu: 2000
2828
bn_max_cpu: 3000
29-
bn_min_mem: 3072
30-
bn_max_mem: 3072
29+
bn_min_mem: 2048
30+
bn_max_mem: 2048
3131
v_min_cpu: 1000
3232
v_max_cpu: 1000
3333
v_min_mem: 1028
@@ -40,4 +40,4 @@ network_params:
4040
additional_services:
4141
- prometheus_grafana
4242
- dora
43-
persistent: true
43+
persistent: false

network-configs/plan/testing.yaml

Lines changed: 0 additions & 88 deletions
This file was deleted.

pkg/plan/network/clients.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ func buildNode(index int, execConf, consensusConf ClientVersion) *Node {
1212
}
1313
}
1414

15-
func composeBootnode(execClients, consensusClients map[string]ClientVersion) (*Node, error) {
16-
execConf, ok := execClients["geth"]
15+
func composeBootnode(bootEl, bootCl string, execClients, consensusClients map[string]ClientVersion) (*Node, error) {
16+
execConf, ok := execClients[bootEl]
1717
if !ok {
18-
return nil, stacktrace.NewError("unable to load configuration for exec client geth")
18+
return nil, stacktrace.NewError("unable to load configuration for exec client %s", bootEl)
1919
}
20-
consConf, ok := consensusClients["lighthouse"]
20+
consConf, ok := consensusClients[bootCl]
2121
if !ok {
22-
return nil, stacktrace.NewError("unable to load configuration for exec client lighthouse")
22+
return nil, stacktrace.NewError("unable to load configuration for exec client %s", bootCl)
2323
}
24-
return buildNode(0, execConf, consConf), nil
24+
return buildNode(1, execConf, consConf), nil
2525
}

pkg/plan/network/consensus.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const defaultValCpu = 1000
1111
const defaultClMem = 2048
1212
const defaultValMem = 1024
1313

14-
func composeConsensusTesterNetwork(consensusClient string, execClients, consClients []ClientVersion) ([]*Node, error) {
14+
func composeConsensusTesterNetwork(bootEl, bootCl, consensusClient string, execClients, consClients []ClientVersion) ([]*Node, error) {
1515
execClientMap, consClientMap, err := clientListsToMaps(execClients, consClients)
1616
if err != nil {
1717
return nil, err
@@ -25,7 +25,7 @@ func composeConsensusTesterNetwork(consensusClient string, execClients, consClie
2525

2626
var nodes []*Node
2727
index := 1
28-
bootnode, err := composeBootnode(execClientMap, consClientMap)
28+
bootnode, err := composeBootnode(bootEl, bootCl, execClientMap, consClientMap)
2929
if err != nil {
3030
return nil, err
3131
}

pkg/plan/network/execution.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
const defaultElCpu = 1000
88
const defaultElMem = 1024
99

10-
func composeExecTesterNetwork(execClient string, execClients, consClients []ClientVersion) ([]*Node, error) {
10+
func composeExecTesterNetwork(bootEl, bootCl, execClient string, execClients, consClients []ClientVersion) ([]*Node, error) {
1111
execClientMap, consClientMap, err := clientListsToMaps(execClients, consClients)
1212
if err != nil {
1313
return nil, err
@@ -21,7 +21,7 @@ func composeExecTesterNetwork(execClient string, execClients, consClients []Clie
2121

2222
var nodes []*Node
2323
index := 1
24-
bootnode, err := composeBootnode(execClientMap, consClientMap)
24+
bootnode, err := composeBootnode(bootEl, bootCl, execClientMap, consClientMap)
2525
if err != nil {
2626
return nil, err
2727
}

pkg/plan/network/network_builder.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ func clientListsToMaps(execClients, consClients []ClientVersion) (execClientMap,
3030
return execClientMap, consClientMap, nil
3131
}
3232

33-
func ComposeNetworkTopology(client string, execClients, consClients []ClientVersion) ([]*Node, error) {
33+
func ComposeNetworkTopology(bootEl, bootCl, client string, execClients, consClients []ClientVersion) ([]*Node, error) {
3434
if client == "all" {
3535
return nil, stacktrace.NewError("target client 'all' not supported yet")
3636
}
@@ -44,8 +44,8 @@ func ComposeNetworkTopology(client string, execClients, consClients []ClientVers
4444
}
4545
// assume already checked client is a member of consClients or execClients
4646
if isExecutionClient {
47-
return composeExecTesterNetwork(client, execClients, consClients)
47+
return composeExecTesterNetwork(bootEl, bootCl, client, execClients, consClients)
4848
} else {
49-
return composeConsensusTesterNetwork(client, execClients, consClients)
49+
return composeConsensusTesterNetwork(bootEl, bootCl, client, execClients, consClients)
5050
}
5151
}

pkg/plan/plan.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,21 @@ func BuildPlan(planName string, config *PlannerConfig) error {
1414
return err
1515
}
1616

17-
nodes, err := network.ComposeNetworkTopology(config.FaultConfig.TargetClient, config.ExecutionClients, config.ConsensusClients)
17+
nodes, err := network.ComposeNetworkTopology(
18+
config.FaultConfig.BootnodeEL,
19+
config.FaultConfig.BootnodeCl,
20+
config.FaultConfig.TargetClient,
21+
config.ExecutionClients,
22+
config.ConsensusClients,
23+
)
1824
if err != nil {
1925
return err
2026
}
2127

2228
isExecTarget := config.IsTargetExecutionClient()
23-
tests, err := suite.ComposeTestSuite(config.FaultConfig, isExecTarget, nodes)
29+
// exclude the bootnode from test targeting
30+
potentialNodesUnderTest := nodes[1:]
31+
tests, err := suite.ComposeTestSuite(config.FaultConfig, isExecTarget, potentialNodesUnderTest)
2432
if err != nil {
2533
return err
2634
}

pkg/plan/serialization.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ func SerializeNetworkTopology(nodes []*network.Node, config *network.GenesisConf
1919
"dora",
2020
},
2121
ParallelKeystoreGen: false,
22-
Persistent: true,
22+
Persistent: false,
23+
DisablePeerScoring: true,
2324
}
2425

2526
bs, err := yaml.Marshal(netConfig)

pkg/plan/suite/faults.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ type PodChaosSpec struct {
4646
Selector `yaml:"selector"`
4747
Mode string `yaml:"mode"`
4848
Duration string `yaml:"duration"`
49+
Action string `yaml:"action"`
4950
}
5051

5152
type PodChaosFault struct {
@@ -131,8 +132,9 @@ func buildPodRestartFault(description string, expressionSelectors []ChaosExpress
131132
Kind: "PodChaos",
132133
ApiVersion: "chaos-mesh.org/v1alpha1",
133134
Spec: PodChaosSpec{
134-
Duration: "1s",
135+
Duration: "5s",
135136
Mode: "all",
137+
Action: "pod-failure",
136138
Selector: Selector{
137139
ExpressionSelectors: expressionSelectors,
138140
},

0 commit comments

Comments
 (0)