Skip to content

Commit

Permalink
feat: Move bootstrap node into collator (#727)
Browse files Browse the repository at this point in the history
  • Loading branch information
aidan46 authored Feb 11, 2025
1 parent 324ecb9 commit 7e775f7
Show file tree
Hide file tree
Showing 22 changed files with 243 additions and 163 deletions.
9 changes: 7 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 8 additions & 1 deletion Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,12 @@ release: lint
release-testnet:
cargo build --release --features polka-storage-runtime/testnet --bin polka-storage-node

# Run the testnet without building
# Generate a private key for the P2P network and
# run the testnet without building
run-testnet:
mkdir -p /tmp/zombienet
openssl genpkey -algorithm ED25519 -out /tmp/zombienet/private.pem
openssl pkey -in /tmp/zombienet/private.pem -pubout -out /tmp/zombienet/public.pem # Generate public key so script can get the Peer ID
zombienet -p native spawn zombienet/local-testnet.toml

# Run the testing building it before
Expand Down Expand Up @@ -152,6 +156,9 @@ load-to-minikube:
minikube image load ghcr.io/polka-storage-node:"$(cargo metadata --format-version=1 --no-deps | jq -r '.packages[] | select(.name == "polka-storage-node") | .version')"

kube-testnet:
mkdir -p /tmp/zombienet
openssl genpkey -algorithm ED25519 -out /tmp/zombienet/private.pem
openssl pkey -in /tmp/zombienet/private.pem -pubout -out /tmp/zombienet/public.pem # Generate public key so script can get the Peer ID
zombienet -p kubernetes spawn zombienet/local-kube-testnet.toml

# The tarpaulin calls for test coverage have the following options:
Expand Down
2 changes: 2 additions & 0 deletions docs/src/storage-provider-cli/server.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ This chapter covers the Polka Storage Provider server.
## P2P Key generation

The Polka Storage Provider server runs a p2p node that is used to map Peer ID's to Multi-addresses.
The generated Peer ID is used for on-chain registration and inside the P2P network.
Both these Peer ID's must be the same.
The server can run either a bootstrap node, used to aid in discovery,
or a registration node, which registers to a bootstrap node with their Peer ID to Multi-address mapping.
For both of these node types, the server needs an ed25519 private key.
Expand Down
12 changes: 8 additions & 4 deletions examples/rpc_publish.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,20 @@ INPUT_TMP_FILE="/tmp/$INPUT_FILE_NAME.car"
# Config file location
CONFIG="/tmp/config.toml"
# P2P Node variables
P2P_PUBLIC_KEY="/tmp/public.pem"
P2P_PRIVATE_KEY="/tmp/private.pem"
P2P_PUBLIC_KEY="/tmp/polka-storage/public.pem"
P2P_PRIVATE_KEY="/tmp/polka-storage/private.pem"
P2P_ADDRESS="/ip4/127.0.0.1/tcp/62649"

# Generate ED25519 private key to be replaced with a polka-storage-provider-client command
# Generate ED25519 private key
mkdir -p /tmp/storage-provider
openssl genpkey -algorithm ED25519 -out "$P2P_PRIVATE_KEY"
# -outpubkey is only available in OpenSSL 3.4.0 onwards
# https://github.com/openssl/openssl/commit/6c03fa21ed4bbc9fd6d3013fdf9f4646d231f831
openssl pkey -in "$P2P_PRIVATE_KEY" -pubout -out "$P2P_PUBLIC_KEY"

# Generate Peer ID
P2P_BOOTSTRAP_PEER_ID="$(target/release/polka-storage-provider-client generate-peer-id --pubkey "$P2P_PUBLIC_KEY")"

# Convert file to CARv2 format
target/release/mater-cli convert -q --overwrite "$INPUT_FILE" "$INPUT_TMP_FILE" &&

Expand All @@ -54,7 +57,8 @@ post_proof = '2KiB'
porep_parameters = '2KiB.porep.params'
post_parameters = '2KiB.post.params'
rendezvous_point_address = '$P2P_ADDRESS'
p2p_key = '@$P2P_PRIVATE_KEY'" > "$CONFIG"
p2p_key = '@$P2P_PRIVATE_KEY'
rendezvous_point = '$P2P_BOOTSTRAP_PEER_ID'" > "$CONFIG"


# Setup balances
Expand Down
42 changes: 26 additions & 16 deletions examples/start_sp.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,29 @@ export DISABLE_XT_WAIT_WARNING=1

CLIENT="//Alice"
PROVIDER="//Charlie"
P2P_PUBLIC_KEY="/tmp/public.pem"
P2P_PRIVATE_KEY="/tmp/private.pem"
P2P_ADDRESS="/ip4/127.0.0.1/tcp/62649"
P2P_PUBLIC_KEY="/tmp/polka-storage/public.pem"
P2P_PRIVATE_KEY="/tmp/polka-storage/private.pem"
P2P_BOOTSTRAP_PUBLIC_KEY="/tmp/zombienet/public.pem"
# Config file location
CONFIG="/tmp/storage-provider/config.toml"

# Generate ED25519 private key
mkdir -p /tmp/storage-provider
openssl genpkey -algorithm ED25519 -out "$P2P_PRIVATE_KEY"
# -outpubkey is only available in OpenSSL 3.4.0 onwards
# https://github.com/openssl/openssl/commit/6c03fa21ed4bbc9fd6d3013fdf9f4646d231f831
openssl pkey -in "$P2P_PRIVATE_KEY" -pubout -out "$P2P_PUBLIC_KEY"

# Generate Peer ID
PEER_ID="$(target/release/polka-storage-provider-client generate-peer-id --pubkey "$P2P_PUBLIC_KEY")"
P2P_SP_PEER_ID="$(target/release/polka-storage-provider-client generate-peer-id --pubkey "$P2P_PUBLIC_KEY")"

echo "Generated new peer ID for $PROVIDER: $P2P_SP_PEER_ID"

# Get bootstrap P2P Peer ID. This works after running zombienet locally or in kubernetes
P2P_BOOTSTRAP_PEER_ID="$(target/release/polka-storage-provider-client generate-peer-id --pubkey "$P2P_BOOTSTRAP_PUBLIC_KEY")"

echo "Peer ID for bootstrap node: $P2P_BOOTSTRAP_PEER_ID"

# Setup balances
RUST_LOG=debug target/release/storagext-cli --sr25519-key "$CLIENT" market add-balance 250000000000 &
Expand All @@ -31,22 +42,21 @@ wait
# It's a test setup based on the local verifying keys, everyone can run those extrinsics currently.
# Each of the keys is different, because the processes are running in parallel.
# If they were running in parallel on the same account, they'd conflict with each other on the transaction nonce.
RUST_LOG=debug target/release/storagext-cli --sr25519-key "//Charlie" storage-provider register "$PEER_ID" &
RUST_LOG=debug target/release/storagext-cli --sr25519-key "//Charlie" storage-provider register "$P2P_SP_PEER_ID" &
RUST_LOG=debug target/release/storagext-cli --sr25519-key "//Alice" proofs set-porep-verifying-key @2KiB.porep.vk.scale &
RUST_LOG=debug target/release/storagext-cli --sr25519-key "//Bob" proofs set-post-verifying-key @2KiB.post.vk.scale &
wait

echo '{
"seal_proof": "2KiB",
"post_proof": "2KiB",
"porep_parameters": "2KiB.porep.params",
"post_parameters": "2KiB.post.params",
"p2p_key": "@/tmp/private.pem",
"rendezvous_point_address": "/ip4/127.0.0.1/tcp/62649",
"sealing_configuration": {
"fill_percentage": 75
}
}' > /tmp/storage_provider.config.json
echo "seal_proof = '2KiB'
post_proof = '2KiB'
porep_parameters = '2KiB.porep.params'
post_parameters = '2KiB.post.params'
rendezvous_point_address = '$P2P_ADDRESS'
p2p_key = '@$P2P_PRIVATE_KEY'
rendezvous_point = '$P2P_BOOTSTRAP_PEER_ID'
[sealing_configuration]
fill_percentage = 75" > "$CONFIG"

RUST_LOG=debug target/release/polka-storage-provider-server \
--sr25519-key "$PROVIDER" \
--config /tmp/storage_provider.config.json
--config "$CONFIG"
5 changes: 2 additions & 3 deletions maat/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ bls12_381 = { workspace = true }
bs58.workspace = true
cid.workspace = true
codec = { workspace = true }
ed25519-dalek = { workspace = true, features = ["pem"] }
futures.workspace = true
hex = { workspace = true }
libp2p = { workspace = true, features = ["ecdsa", "identify"] }
Expand All @@ -33,6 +34,7 @@ serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true, features = ["std"] }
storagext = { workspace = true }
subxt = { workspace = true, features = ["substrate-compat"] }
tempfile = { workspace = true }
thiserror.workspace = true
tokio = { workspace = true, features = ["full"] }
tokio-util = { workspace = true, features = ["rt"] }
Expand All @@ -43,8 +45,5 @@ zombienet-configuration.workspace = true
zombienet-sdk.workspace = true
zombienet-support.workspace = true

[dev-dependencies]
tempfile = { workspace = true }

[lints]
workspace = true
23 changes: 22 additions & 1 deletion maat/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
use std::path::PathBuf;
use std::{
fs::File,
io::Write,
path::{Path, PathBuf},
};

use ed25519_dalek::{
pkcs8::{spki::der::pem::LineEnding, EncodePrivateKey},
SigningKey,
};
use storagext::PolkaStorageConfig;
use subxt::{
ext::{
Expand All @@ -8,6 +16,7 @@ use subxt::{
},
tx::PairSigner,
};
use tempfile::tempdir;
use tracing::level_filters::LevelFilter;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter, Layer};
use zombienet_configuration::shared::node::{Buildable, Initial, NodeConfigBuilder};
Expand Down Expand Up @@ -92,6 +101,9 @@ pub fn local_testnet_config() -> NetworkConfig {
.display()
.to_string();
let polka_storage_node_binary_path = binding.as_str();
let temp_dir = tempdir().unwrap();
let file_path = temp_dir.path().join("private_key.pem");
generate_pem_file(&file_path);

NetworkConfigBuilder::new()
.with_relaychain(|relaychain| {
Expand All @@ -111,6 +123,8 @@ pub fn local_testnet_config() -> NetworkConfig {
.with_args(vec![
("--pool-type", "fork-aware").into(),
("-lruntime=trace,parachain=debug").into(),
("--p2p-listen-address=/ip4/127.0.0.1/tcp/62649").into(),
(format!("--p2p-key={}", file_path.display()).as_str()).into(),
])
})
})
Expand Down Expand Up @@ -138,3 +152,10 @@ where
let keypair = Pair::from_string(s, None).unwrap();
PairSigner::<PolkaStorageConfig, P>::new(keypair)
}

fn generate_pem_file<P: AsRef<Path>>(path: P) {
let signing_key = SigningKey::from([0; 32]);
let pem = signing_key.to_pkcs8_pem(LineEnding::default()).unwrap();
let mut file = File::create(path).unwrap();
write!(file, "{}", *pem).unwrap();
}
3 changes: 3 additions & 0 deletions node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ name = "polka-storage-node"

[dependencies]
polka-storage-runtime.workspace = true
primitives = { workspace = true, features = ["std"] }

clap = { features = ["derive"], workspace = true }
codec = { workspace = true, default-features = true }
Expand All @@ -33,6 +34,7 @@ frame-benchmarking = { workspace = true, default-features = true }
frame-benchmarking-cli = { workspace = true, default-features = true }
futures = { workspace = true }
jsonrpsee = { features = ["server"], workspace = true }
libp2p = { workspace = true, features = ["identify", "macros", "noise", "rendezvous", "tcp", "tokio", "yamux"] }
log = { workspace = true, default-features = true }
pallet-transaction-payment-rpc = { workspace = true, default-features = true }
polkadot-cli = { features = ["rococo-native"], workspace = true, default-features = true }
Expand Down Expand Up @@ -66,6 +68,7 @@ sp-keystore = { workspace = true, default-features = true }
sp-runtime = { workspace = true, default-features = true }
sp-timestamp = { workspace = true, default-features = true }
substrate-frame-rpc-system = { workspace = true, default-features = true }
thiserror = { workspace = true }
xcm.workspace = true

[build-dependencies]
Expand Down
23 changes: 22 additions & 1 deletion node/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use std::path::PathBuf;

use libp2p::{identity::Keypair, Multiaddr};
use primitives::p2p::keypair_value_parser;

/// Sub-commands supported by the collator.
#[derive(Debug, clap::Subcommand)]
#[allow(clippy::large_enum_variant)]
Expand Down Expand Up @@ -64,7 +67,7 @@ pub struct Cli {
pub subcommand: Option<Subcommand>,

#[command(flatten)]
pub run: cumulus_client_cli::RunCmd,
pub run: RunCmd,

/// Disable automatic hardware benchmarks.
///
Expand Down Expand Up @@ -109,3 +112,21 @@ impl RelayChainCli {
}
}
}

#[derive(Debug, clap::Parser)]
#[group(skip)]
pub struct RunCmd {
#[clap(flatten)]
pub base: cumulus_client_cli::RunCmd,

/// Key used in the P2P network of Storage Providers and Collators.
/// This key generates the Peer ID that storage providers use to register.
/// It must be an ED25519 private key, either in PEM format or passed in directly.
#[arg(long, value_parser = keypair_value_parser, required = false)]
pub p2p_key: Option<Keypair>,

/// Listen address in the P2P network of Storage Providers and Collators
/// that the bootstrap node binds to.
#[arg(long, required = false)]
pub p2p_listen_address: Option<Multiaddr>,
}
25 changes: 22 additions & 3 deletions node/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use sc_service::config::{BasePath, PrometheusConfig};
use crate::{
chain_spec,
cli::{Cli, RelayChainCli, Subcommand},
service::new_partial,
service::{new_partial, p2p::BootstrapConfig},
};

fn load_spec(id: &str) -> std::result::Result<Box<dyn ChainSpec>, String> {
Expand Down Expand Up @@ -221,10 +221,28 @@ pub fn run() -> Result<()> {
}
}
None => {
let runner = cli.create_runner(&cli.run.normalize())?;
let collator_options = cli.run.collator_options();
let runner = cli.create_runner(&cli.run.base.normalize())?;
let collator_options = cli.run.base.collator_options();

runner.run_node_until_exit(|config| async move {
let bootstrap_config = if config.role.is_authority() {
let p2p_key = cli
.run
.p2p_key
.ok_or(
"This node is configured as authority, so it will be used as Bootstrap node for Storage Provider & Collator network, but the key is missing. Set the --p2p-key argument of the node."
)?;
let p2p_listen_address = cli
.run
.p2p_listen_address
.ok_or(
"This node is configured as authority, so it will be used as Bootstrap node for Storage Provider & Collator network, but the listen address is missing. Set the --p2p-listen-address argument of the node."
)?;
Some(BootstrapConfig::new(p2p_key, p2p_listen_address))
} else {
None
};

let hwbench = (!cli.no_hardware_benchmarks)
.then_some(config.database.path().map(|database_path| {
let _ = std::fs::create_dir_all(database_path);
Expand Down Expand Up @@ -268,6 +286,7 @@ pub fn run() -> Result<()> {
collator_options,
id,
hwbench,
bootstrap_config,
)
.await
.map(|r| r.0)
Expand Down
Loading

0 comments on commit 7e775f7

Please sign in to comment.