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

Gas Dos #722

Merged
merged 3 commits into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
33 changes: 28 additions & 5 deletions .github/workflows/checks-all.yml
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,11 @@ jobs:
CELESTIA_LOG_LEVEL: FATAL # adjust the log level while debugging
run: |
nix develop --command bash -c "just suzuka-full-node native build.setup.eth-local.celestia-local.test -t=false"
nix develop --command bash -c "just suzuka-full-node native build.setup.eth-local.celestia-local.test -t=false"

suzuka-full-node-malicious:
if: github.event.label.name == 'cicd:suzuka-full-node-malicious' || github.ref == 'refs/heads/main'

suzuka-multi-node-local:
if: github.event.label.name == 'cicd:suzuka-multi-node-local' || github.ref == 'refs/heads/main'
strategy:
matrix:
include:
Expand All @@ -122,10 +124,31 @@ jobs:
- name: Install Nix
uses: DeterminateSystems/nix-installer-action@main

- uses: cachix/cachix-action@v15
- name: Run Suzuka Full Node Gas DoS Test
env:
CELESTIA_LOG_LEVEL: FATAL # adjust the log level while debugging
run: |
nix develop --command bash -c "just suzuka-full-node native build.setup.eth-local.celestia-local.gas-dos -t=false"

suzuka-multi-node-local:
if: github.event.label.name == 'cicd:suzuka-multi-node-local' || github.ref == 'refs/heads/main'
strategy:
matrix:
include:
- os: ubuntu-22.04
arch: x86_64
runs-on: buildjet-16vcpu-ubuntu-2204

runs-on: ${{ matrix.runs-on }}

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
name: movementlabs
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
submodules: true

- name: Install Nix
uses: DeterminateSystems/nix-installer-action@main

- name: Run Suzuka Full Node Tests Against Local ETH and Local Celestia
env:
Expand Down
Empty file modified docker/README.md
100644 → 100755
Empty file.
Empty file modified docker/build/bridge-service/Dockerfile
100644 → 100755
Empty file.
Empty file modified docker/build/bridge-setup/Dockerfile
100644 → 100755
Empty file.
Empty file modified docker/build/helios/Dockerfile
100644 → 100755
Empty file.
Empty file modified docker/build/m1-da-light-node-celestia-appd/Dockerfile
100644 → 100755
Empty file.
Empty file modified docker/build/m1-da-light-node-celestia-bridge/Dockerfile
100644 → 100755
Empty file.
Empty file modified docker/build/m1-da-light-node/Dockerfile
100644 → 100755
Empty file.
Empty file.
Empty file modified docker/build/suzuka-client-e2e-simple-interaction/Dockerfile
100644 → 100755
Empty file.
Empty file modified docker/build/suzuka-config/Dockerfile
100644 → 100755
Empty file.
Empty file modified docker/build/suzuka-faucet-service/Dockerfile
100644 → 100755
Empty file.
Empty file modified docker/build/suzuka-full-node-setup/Dockerfile
100644 → 100755
Empty file.
Empty file modified docker/build/suzuka-full-node/Dockerfile
100644 → 100755
Empty file.
Empty file modified docker/build/suzuka-indexer/Dockerfile
100644 → 100755
Empty file.
Empty file modified docker/build/wait-for-celestia-light-node/Dockerfile
100644 → 100755
Empty file.
Empty file modified docker/compose/bridge/docker-compose.helios.yml
100644 → 100755
Empty file.
Empty file modified docker/compose/bridge/docker-compose.mvt-remote.yml
100644 → 100755
Empty file.
Empty file modified docker/compose/bridge/docker-compose.setup.yml
100644 → 100755
Empty file.
Empty file modified docker/compose/bridge/docker-compose.yml
100644 → 100755
Empty file.
Empty file modified docker/compose/grafana-alloy/README.md
100644 → 100755
Empty file.
Empty file modified docker/compose/grafana-alloy/config.alloy
100644 → 100755
Empty file.
Empty file modified docker/compose/grafana-alloy/docker-compose.yml
100644 → 100755
Empty file.
Empty file modified docker/compose/grafana-alloy/img/1.png
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified docker/compose/grafana-alloy/img/2.png
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified docker/compose/grafana-alloy/img/3.png
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file modified docker/compose/grafana-alloy/img/4.png
100644 → 100755
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Empty file.
Empty file modified docker/compose/suzuka-full-node/docker-compose.follower.yml
100644 → 100755
Empty file.
Empty file modified docker/compose/suzuka-full-node/docker-compose.leader.yml
100644 → 100755
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
services:

# This service checks if the ledger version has increased every LEDGER_INCREASE_PERIOD_SECONDS
ledger-should-progress:
image: alpine:latest
container_name: ledger-should-progress
command: >
sh -c '
l-monninger marked this conversation as resolved.
Show resolved Hide resolved
# install jq and curl for busybox
apk add --no-cache jq curl
l-monninger marked this conversation as resolved.
Show resolved Hide resolved

# sleep a little to allow the full node to get through some startup
sleep 20

LAST_LEDGER_VERSION=0
# check the ledger version has increased every LEDGER_INCREASE_PERIOD_SECONDS
while true; do
sleep $${LEDGER_INCREASE_PERIOD_SECONDS}

# Get the current ledger version from the response using curl and busybox-friendly parsing
echo "$$(curl -s $${SUZUKA_FULL_NODE_CONNECTION}/v1)"
CURRENT_LEDGER_VERSION=$$(curl -s $${SUZUKA_FULL_NODE_CONNECTION}/v1 | jq -r ".ledger_version" | tr -d "\"")

# Check if we got a valid ledger version
if [ -z "$$CURRENT_LEDGER_VERSION" ]; then
echo "Failed to retrieve the current ledger version."
exit 1
fi

# Compare the current ledger version with the last one
if [ "$$CURRENT_LEDGER_VERSION" -le "$$LAST_LEDGER_VERSION" ]; then
echo "Ledger version has not increased in the last $${LEDGER_INCREASE_PERIOD_SECONDS} seconds."
exit 1
else
echo "Ledger version has increased from $$LAST_LEDGER_VERSION to $$CURRENT_LEDGER_VERSION."
fi

# Update the last ledger version to the current one
LAST_LEDGER_VERSION=$$CURRENT_LEDGER_VERSION
done
'
environment:
DOT_MOVEMENT_PATH: /.movement
LEDGER_INCREASE_PERIOD_SECONDS: ${LEDGER_INCREASE_PERIOD_SECONDS-300}
SUZUKA_FULL_NODE_CONNECTION: http://suzuka-full-node:30731
volumes:
- ${DOT_MOVEMENT_PATH}:/.movement
depends_on:
suzuka-full-node:
condition: service_healthy
healthcheck:
test: ["CMD", "echo", "true"]
interval: 1m30s
timeout: 30s
retries: 5
start_period: 30s

# Here we use a dependent service to trigger application crash, i.e., throughout docker-compose
ledger-should-progress-watcher:
image: busybox
container_name: ledger-should-progress-watcher
command: >
sh -c '
while true; do
sleep 1000
done
'
depends_on:
ledger-should-progress:
condition: service_healthy
Empty file modified docker/compose/suzuka-full-node/docker-compose.local.yml
100644 → 100755
Empty file.
Empty file.
Empty file modified docker/compose/suzuka-full-node/docker-compose.test.yml
100644 → 100755
Empty file.
Empty file modified docker/compose/suzuka-full-node/docker-compose.yml
100644 → 100755
Empty file.
32 changes: 32 additions & 0 deletions docker/compose/suzuka-full-node/ledger-should-progress.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# install jq if in busybox
if [ -f /etc/alpine-release ]; then
echo "Installing jq using apk (Alpine Linux environment)..."
apk add --no-cache jq
else
echo "BusyBox detected, but not Alpine Linux. Manual jq installation required."
fi

LAST_LEDGER_VERSION=0
# check the ledger version has increased every LEDGER_INCREASE_PERIOD_SECONDS
while true; do
sleep ${LEDGER_INCREASE_PERIOD_SECONDS}

# Get the current ledger version from the response using curl and busybox-friendly parsing
echo $(curl -s ${SUZUKA_FULL_NODE_CONNECTION}/v1 | jq -r '.ledger_version' | tr -d '"')
CURRENT_LEDGER_VERSION=$(curl -s ${SUZUKA_FULL_NODE_CONNECTION}/v1 | jq -r '.ledger_version' | tr -d '"')

# Check if we got a valid ledger version
if [ -z "$CURRENT_LEDGER_VERSION" ]; then
echo "Failed to retrieve the current ledger version."
exit 1
fi

# Compare the current ledger version with the last one
if [ "$CURRENT_LEDGER_VERSION" -le "$LAST_LEDGER_VERSION" ]; then
echo "Ledger version has not increased in the last ${LEDGER_INCREASE_PERIOD_SECONDS} seconds."
exit 1
fi

# Update the last ledger version to the current one
LAST_LEDGER_VERSION=$CURRENT_LEDGER_VERSION
done
Empty file modified docker/compose/suzuka-indexer/.remote-suzuka-node.env
100644 → 100755
Empty file.
Empty file modified docker/compose/suzuka-indexer/README.md
100644 → 100755
Empty file.
Empty file modified docker/compose/suzuka-indexer/docker-compose.hasura.yml
100644 → 100755
Empty file.
Empty file modified docker/compose/suzuka-indexer/docker-compose.indexer.yml
100644 → 100755
Empty file.
Empty file.
Empty file modified docker/compose/suzuka-indexer/indexer-config.json
100644 → 100755
Empty file.
1 change: 1 addition & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
gcc
rust
postgresql
tesseract4
l-monninger marked this conversation as resolved.
Show resolved Hide resolved
ansible
];

Expand Down
2 changes: 2 additions & 0 deletions networks/suzuka/setup/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ async fn main() -> Result<(), anyhow::Error> {
}
});

info!("Starting Suzuka Full Node Setup");

// get the config file
let dot_movement = dot_movement::DotMovement::try_from_env()?;

Expand Down
6 changes: 5 additions & 1 deletion networks/suzuka/suzuka-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ rust-version = { workspace = true }
### define here all scenarios execution binaries
[[bin]]
name = "demo_scenario"
path = "bin/demo_scenario.rs"
path = "src/bin/e2e/demo_scenario.rs"
#[[bin]]
# name = "basic_alice_bob"
# path = "bin/basic_alice_bob.rs"
Expand All @@ -23,6 +23,10 @@ path = "bin/demo_scenario.rs"
name = "suzuka-client-e2e-simple-interaction"
path = "src/bin/e2e/simple_interaction.rs"

[[bin]]
name = "suzuka-client-gas-dos"
l-monninger marked this conversation as resolved.
Show resolved Hide resolved
path = "src/bin/e2e/gas_dos.rs"

[[bin]]
name = "suzuka-client-e2e-followers-consistent"
path = "src/bin/e2e/followers_consistent.rs"
Expand Down
174 changes: 174 additions & 0 deletions networks/suzuka/suzuka-client/src/bin/e2e/basic_alice_bob.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
use anyhow::{Context, Result};
use aptos_sdk::{
coin_client::CoinClient,
rest_client::{Client, FaucetClient},
types::LocalAccount,
};
use std::str::FromStr;
use std::sync::Arc;
use suzuka_client::load_soak_testing::{execute_test, init_test, ExecutionConfig, Scenario};
use url::Url;

fn main() {
// Define the Test config. Use the default parameters.
let config = ExecutionConfig::default();

// Init the Test before execution
if let Err(err) = init_test(&config) {
println!("Test init fail ; {err}",);
}

// Execute the test.
let result = execute_test(config, Arc::new(create_scenario));
tracing::info!("End Test with result {result:?}",);
}

// Scenario constructor function use by the Test runtime to create new scenarios.
fn create_scenario(id: usize) -> Box<dyn Scenario> {
Box::new(BasicScenario { id })
}

pub struct BasicScenario {
id: usize,
}

impl BasicScenario {
pub fn new(id: usize) -> Self {
BasicScenario { id }
}
}

#[async_trait::async_trait]
impl Scenario for BasicScenario {
async fn run(self: Box<Self>) -> Result<()> {
let suzuka_config = maptos_execution_util::config::Config::try_from_env()
.context("Failed to create the suzuka_config")?;
let node_url = Url::from_str(
format!("http://{}", suzuka_config.aptos_config.aptos_rest_listen_url.as_str())
.as_str(),
)?;

let faucet_url = Url::from_str(
format!("http://{}", suzuka_config.aptos_config.aptos_faucet_listen_url.as_str())
.as_str(),
)?;

let rest_client = Client::new(node_url.clone());
let faucet_client = FaucetClient::new(faucet_url.clone(), node_url.clone()); // <:!:section_1a

let coin_client = CoinClient::new(&rest_client); // <:!:section_1b

// Create two accounts locally, Alice and Bob.
let mut alice = LocalAccount::generate(&mut rand::rngs::OsRng);
let bob = LocalAccount::generate(&mut rand::rngs::OsRng); // <:!:section_2

// Print account addresses.
tracing::info!(
"Scenario:{}\n=== Addresses ===\nAlice: {}\nBob: {}",
self.id,
alice.address().to_hex_literal(),
bob.address().to_hex_literal()
);

tracing::info!("{} Before alice fund", self.id);
self.log_exec_info(&format!("{} Before alice fund", self.id));
// Create the accounts on chain, but only fund Alice.
faucet_client.fund(alice.address(), 100_000_000).await?;
tracing::info!("{} Before Bod create_account", self.id);
self.log_exec_info(&format!("{} Before Bod create_account", self.id));
faucet_client.create_account(bob.address()).await?;
tracing::info!("{} After Bod create_account", self.id);
self.log_exec_info(&format!("{} After Bod create_account", self.id));

// Print initial balances.
tracing::info!(
"Scenario:{}\n=== Initial Balances ===\nAlice: {:?}\nBob: {:?}",
self.id,
coin_client
.get_account_balance(&alice.address())
.await
.context("Failed to get Alice's account balance")?,
coin_client
.get_account_balance(&bob.address())
.await
.context("Failed to get Bob's account balance")?
);

// Have Alice send Bob some coins.
let txn_hash = coin_client
.transfer(&mut alice, bob.address(), 1_000, None)
.await
.context("Failed to submit transaction to transfer coins")?;
rest_client
.wait_for_transaction(&txn_hash)
.await
.context("Failed when waiting for the transfer transaction")?;

// Print intermediate balances.
tracing::info!(
"Scenario:{}\n=== Intermediate Balances ===\nAlice: {:?}\nBob: {:?}",
self.id,
coin_client
.get_account_balance(&alice.address())
.await
.context("Failed to get Alice's account balance the second time")?,
coin_client
.get_account_balance(&bob.address())
.await
.context("Failed to get Bob's account balance the second time")?
);

self.log_exec_info(&format!("Scenario:{} ended", self.id));

// Have Alice send Bob some coins.
let txn_hash = coin_client
.transfer(&mut alice, bob.address(), 1_000, None)
.await
.context("Failed to submit transaction to transfer coins")?;
rest_client
.wait_for_transaction(&txn_hash)
.await
.context("Failed when waiting for the transfer transaction")?;

// Print intermediate balances.
tracing::info!(
"Scenario:{}\n=== Intermediate Balances ===\n Alice: {:?}\n Bob: {:?}",
self.id,
coin_client
.get_account_balance(&alice.address())
.await
.context("Failed to get Alice's account balance the second time")?,
coin_client
.get_account_balance(&bob.address())
.await
.context("Failed to get Bob's account balance the second time")?
);

// Have Alice send Bob some more coins.
let txn_hash = coin_client
.transfer(&mut alice, bob.address(), 1_000, None)
.await
.context("Failed to submit transaction to transfer coins")?; // <:!:section_5
// :!:>section_6
rest_client
.wait_for_transaction(&txn_hash)
.await
.context("Failed when waiting for the transfer transaction")?; // <:!:section_6

// Print final balances.
tracing::info!(
"Scenario:{}\n=== Final Balances ===\n Alice: {:?}\n Bob: {:?}",
self.id,
coin_client
.get_account_balance(&alice.address())
.await
.context("Failed to get Alice's account balance the second time")?,
coin_client
.get_account_balance(&bob.address())
.await
.context("Failed to get Bob's account balance the second time")?
);

Ok(())
}
}
Loading
Loading