Skip to content
Draft
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
69 changes: 69 additions & 0 deletions examples/assign_cores.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { createClient } from 'polkadot-api';
import { getWsProvider } from 'polkadot-api/ws-provider';
import { Enum } from '@polkadot-api/substrate-bindings';
import { cryptoWaitReady } from '@polkadot/util-crypto';
import { newSigner } from './common.js';
import { westend } from './.papi/descriptors/dist/index.mjs';

// Command line arguments: [relay_ws_url] [para_id] [num_cores] [seed]
const args = process.argv.slice(2);
const RELAY_WS = args[0] || 'ws://localhost:9942';
const PARA_ID = parseInt(args[1] || '2487');
const NUM_CORES = parseInt(args[2] || '3');
const SEED = args[3] || '//Alice';

async function main() {
await cryptoWaitReady();

console.log(`Connecting to relay chain at ${RELAY_WS}...`);
const client = createClient(getWsProvider(RELAY_WS));
const api = client.getTypedApi(westend);

const { signer } = newSigner(SEED);

// Build assignCore calls for each core
const calls = [];
for (let core = 0; core < NUM_CORES; core++) {
const call = api.tx.Coretime.assign_core({
core,
begin: 0,
assignment: [
[Enum("Task", PARA_ID), 57600]
],
end_hint: undefined,
}).decodedCall;
calls.push(call);
console.log(` Prepared assignCore(core=${core}, paraId=${PARA_ID}, parts=57600)`);
}

// Batch all assign calls and wrap in sudo
const batch = api.tx.Utility.batch_all({ calls });
const sudoTx = api.tx.Sudo.sudo({ call: batch.decodedCall });

console.log(`Submitting sudo batchAll to assign ${NUM_CORES} cores to para ${PARA_ID}...`);

await new Promise((resolve, reject) => {
const sub = sudoTx.signSubmitAndWatch(signer).subscribe({
next: (ev) => {
console.log(` Event: ${ev.type}`);
if (ev.type === "txBestBlocksState" && ev.found) {
console.log(`Included in block: ${ev.block.hash}`);
console.log(`Successfully assigned ${NUM_CORES} cores to para ${PARA_ID}`);
sub.unsubscribe();
resolve();
}
},
error: (err) => {
sub.unsubscribe();
reject(err);
},
});
});

client.destroy();
}

main().catch((err) => {
console.error('Error:', err.message || err);
process.exit(1);
});
29 changes: 29 additions & 0 deletions examples/justfile
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,19 @@ bulletin-westend-parachain-zombienet-start test_dir runtime="bulletin-westend-ru
echo " Waiting for chain to start (180 seconds)..."
sleep 180

# Assign multiple coretime cores to a parachain on the relay chain via sudo.
# Requires PAPI descriptors for the relay chain (run papi-generate-relay first).
# Parameters:
# relay_ws_url - WebSocket URL of the relay chain node (default: ws://localhost:9942)
# para_id - Parachain ID to assign cores to (default: 2487)
# num_cores - Number of cores to assign (default: 3)
# seed - Sudo account seed (default: //Alice)
assign-cores relay_ws_url="ws://localhost:9942" para_id="2487" num_cores="3" seed="//Alice": npm-install
#!/usr/bin/env bash
set -e
echo "Assigning {{ num_cores }} coretime cores to para {{ para_id }} on {{ relay_ws_url }}..."
node assign_cores.js "{{ relay_ws_url }}" "{{ para_id }}" "{{ num_cores }}" "{{ seed }}"

# Check if Docker is available and running
_check-docker:
#!/usr/bin/env bash
Expand Down Expand Up @@ -355,6 +368,16 @@ papi-generate ws_url="ws://localhost:10000": npm-install
echo "🔧 Generating PAPI descriptors from {{ ws_url }}..."
npx papi add -w "{{ ws_url }}" bulletin

# Generate PAPI descriptors for the relay chain (needed for assign-cores)
# Parameters:
# relay_ws_url - WebSocket URL of the relay chain node (default: ws://localhost:9942)
papi-generate-relay relay_ws_url="ws://localhost:9942": npm-install
#!/usr/bin/env bash
set -e

echo "🔧 Generating PAPI descriptors for relay chain from {{ relay_ws_url }}..."
npx papi add -w "{{ relay_ws_url }}" westend

# Setup all services using Docker for IPFS
# Parameters:
# runtime - Runtime to build and run (e.g., "bulletin-polkadot-runtime", "bulletin-westend-runtime")
Expand All @@ -375,6 +398,12 @@ setup-services test_dir runtime: npm-install
# Generate PAPI descriptors from running node.
just papi-generate

# For parachain: generate relay chain descriptors and assign coretime cores
if [ "{{ runtime }}" = "bulletin-westend-runtime" ]; then
just papi-generate-relay
just assign-cores
fi

# Start IPFS
echo "🔧 Tearing down Docker services if they are running..."
just ipfs-shutdown "{{ test_dir }}"
Expand Down
11 changes: 10 additions & 1 deletion runtimes/bulletin-westend/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,11 @@ use sp_runtime::{
#[cfg(feature = "std")]
use sp_version::NativeVersion;
use sp_version::RuntimeVersion;
use testnet_parachains_constants::westend::{consensus::*, currency::*, fee::WeightToFee, time::*};
use testnet_parachains_constants::westend::{currency::*, fee::WeightToFee, time::*};
// Import consensus constants but override the ones we need for elastic scaling (3 cores, 2s blocks).
use testnet_parachains_constants::westend::consensus::{
MAXIMUM_BLOCK_WEIGHT, RELAY_CHAIN_SLOT_DURATION_MILLIS,
};
use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight};
use xcm::{prelude::*, Version as XcmVersion};
#[cfg(feature = "runtime-benchmarks")]
Expand All @@ -91,6 +95,11 @@ use xcm_runtime_apis::{
fees::Error as XcmPaymentApiError,
};

// Override consensus constants for elastic scaling (3 cores, 2s blocks).
const SLOT_DURATION: u64 = 2000;
const BLOCK_PROCESSING_VELOCITY: u32 = 3;
const UNINCLUDED_SEGMENT_CAPACITY: u32 = 6;

/// The address format for describing accounts.
pub type Address = MultiAddress<AccountId, ()>;

Expand Down
26 changes: 26 additions & 0 deletions zombienet/bulletin-westend-local.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ default_command = "{{POLKADOT_BINARY_PATH}}"
default_args = ["-lruntime=debug,xcm=trace"]
chain = "westend-local"

[relaychain.genesis.runtimeGenesis.patch.configuration.config.scheduler_params]
num_cores = 3

[relaychain.genesis.runtimeGenesis.patch.configuration.config.async_backing_params]
allowed_ancestry_len = 6
max_candidate_depth = 6

[[relaychain.nodes]]
name = "alice"
validator = true
Expand All @@ -30,10 +37,27 @@ balance = 2000000000000
# WebSocket P2P on p2p_port + 1 for smoldot light client support
args = ["--listen-addr", "/ip4/0.0.0.0/tcp/30434/ws"]

[[relaychain.nodes]]
name = "charlie"
validator = true

[[relaychain.nodes]]
name = "dave"
validator = true

[[relaychain.nodes]]
name = "eve"
validator = true

[[relaychain.nodes]]
name = "ferdie"
validator = true

[[parachains]]
id = 2487
chain_spec_path = "./zombienet/bulletin-westend-spec.json"
cumulus_based = true
num_cores = 3

[[parachains.collators]]
name = "bulletin-westend-collator-1"
Expand All @@ -42,6 +66,7 @@ validator = true
p2p_port = 10001
rpc_port = 10000
args = [
"--authoring=slot-based",
"--ipfs-server",
# Increase tx pool from 20->64 MiB
# "--pool-kbytes 65536",
Expand All @@ -58,6 +83,7 @@ validator = true
p2p_port = 12347
rpc_port = 12346
args = [
"--authoring=slot-based",
"--ipfs-server",
# Increase tx pool from 20->64 MiB
# "--pool-kbytes 65536",
Expand Down
Loading