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

feat: Move bootstrap node into collator #727

Merged
merged 21 commits into from
Feb 11, 2025
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
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