-
Notifications
You must be signed in to change notification settings - Fork 6
Fixed smoldot westend integration test #170
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
Changes from 21 commits
127abe3
61b1cfd
fdf53b5
7f476bf
52a7003
c70f80b
7bbf142
89b2543
febf06b
a9e328b
aa1d499
afb4d05
f8b807e
72b6e8f
daa9723
f331210
b898eac
d79ebf8
f16cc74
1df17b9
2ce5c2b
dd9dde8
eb7aad9
51b6165
36c297d
acdd70d
cd23abf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,19 +5,68 @@ import { createClient } from 'polkadot-api'; | |
| import { getSmProvider } from 'polkadot-api/sm-provider'; | ||
| import { cryptoWaitReady } from '@polkadot/util-crypto'; | ||
| import { authorizeAccount, fetchCid, store } from './api.js'; | ||
| import { setupKeyringAndSigners } from './common.js'; | ||
| import { setupKeyringAndSigners, waitForChainReady } from './common.js'; | ||
| import { cidFromBytes } from "./cid_dag_metadata.js"; | ||
| import { bulletin } from './.papi/descriptors/dist/index.mjs'; | ||
|
|
||
| // Constants | ||
| const SYNC_WAIT_SEC = 15; | ||
| const SMOLDOT_LOG_LEVEL = 3; // 0=off, 1=error, 2=warn, 3=info, 4=debug, 5=trace | ||
| const SMOLDOT_LOG_LEVEL = 4; // 0=off, 1=error, 2=warn, 3=info, 4=debug, 5=trace | ||
bkontur marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| const HTTP_IPFS_API = 'http://127.0.0.1:8080' // Local IPFS HTTP gateway | ||
|
|
||
| /** | ||
| * Converts TCP bootnodes to WebSocket bootnodes for smoldot compatibility. | ||
| * Uses convention: WebSocket port = TCP p2p_port + 1 | ||
| * | ||
| * Example: /ip4/127.0.0.1/tcp/30333/p2p/PEER_ID | ||
| * -> /ip4/127.0.0.1/tcp/30334/ws/p2p/PEER_ID | ||
| */ | ||
| function convertBootNodesToWebSocket(bootNodes) { | ||
| if (!bootNodes || bootNodes.length === 0) { | ||
| return []; | ||
| } | ||
|
|
||
| const wsBootNodes = []; | ||
| for (const addr of bootNodes) { | ||
| // Parse multiaddr: /ip4/HOST/tcp/PORT/p2p/PEER_ID or /ip4/HOST/tcp/PORT/ws/p2p/PEER_ID | ||
| const tcpMatch = addr.match(/^(\/ip[46]\/[^/]+)\/tcp\/(\d+)\/p2p\/(.+)$/); | ||
| if (tcpMatch) { | ||
| const [, hostPart, portStr, peerId] = tcpMatch; | ||
| const tcpPort = parseInt(portStr, 10); | ||
| const wsPort = tcpPort + 1; // Convention: WS port = TCP port + 1 | ||
|
||
| const wsAddr = `${hostPart}/tcp/${wsPort}/ws/p2p/${peerId}`; | ||
| wsBootNodes.push(wsAddr); | ||
| console.log(` 📡 Converted: tcp/${tcpPort} -> tcp/${wsPort}/ws`); | ||
| } | ||
| // Check if already a WebSocket address | ||
| const wsMatch = addr.match(/\/tcp\/\d+\/ws\/p2p\//); | ||
| if (wsMatch) { | ||
| wsBootNodes.push(addr); | ||
| console.log(` ✅ Already WebSocket: ${addr.substring(0, 50)}...`); | ||
| } | ||
| } | ||
| return wsBootNodes; | ||
| } | ||
|
|
||
| function readChainSpec(chainspecPath) { | ||
| const chainSpecContent = readFileSync(chainspecPath, 'utf8'); | ||
| const chainSpecObj = JSON.parse(chainSpecContent); | ||
| chainSpecObj.protocolId = null; | ||
|
|
||
| // Convert TCP bootnodes to WebSocket for smoldot | ||
| if (chainSpecObj.bootNodes && chainSpecObj.bootNodes.length > 0) { | ||
| console.log(`🔄 Converting ${chainSpecObj.bootNodes.length} bootnode(s) to WebSocket for smoldot...`); | ||
| const wsBootNodes = convertBootNodesToWebSocket(chainSpecObj.bootNodes); | ||
| if (wsBootNodes.length > 0) { | ||
| chainSpecObj.bootNodes = wsBootNodes; | ||
| console.log(`✅ Using ${wsBootNodes.length} WebSocket bootnode(s)`); | ||
| } else { | ||
| console.log(`⚠️ No bootnodes could be converted to WebSocket`); | ||
| } | ||
| } else { | ||
| console.log(`⚠️ No bootnodes found in chain spec: ${chainspecPath}`); | ||
| } | ||
|
|
||
| return JSON.stringify(chainSpecObj); | ||
| } | ||
|
|
||
|
|
@@ -33,34 +82,55 @@ function initSmoldot() { | |
| return sd; | ||
| } | ||
|
|
||
| async function createSmoldotClient(chainspecPath) { | ||
| const chainSpec = readChainSpec(chainspecPath); | ||
| async function createSmoldotClient(chainSpecPath, parachainSpecPath = null) { | ||
| const sd = initSmoldot(); | ||
| const chain = await sd.addChain({ chainSpec }); | ||
| const client = createClient(getSmProvider(chain)); | ||
|
|
||
| const chainSpec = readChainSpec(chainSpecPath); | ||
| const mainChain = await sd.addChain({ chainSpec }); | ||
| console.log(`✅ Added main chain: ${chainSpecPath}`); | ||
|
|
||
| if (parachainSpecPath) { | ||
| const parachainSpec = readChainSpec(parachainSpecPath); | ||
| const parachain = await sd.addChain({ | ||
| chainSpec: parachainSpec, | ||
| potentialRelayChains: [mainChain] | ||
| }); | ||
| console.log(`✅ Added parachain: ${parachainSpecPath}`); | ||
| const client = createClient(getSmProvider(parachain)); | ||
| return { client, sd }; | ||
| } | ||
|
|
||
| const client = createClient(getSmProvider(mainChain)); | ||
| return { client, sd }; | ||
| } | ||
|
|
||
| async function main() { | ||
| await cryptoWaitReady(); | ||
|
|
||
| // Get chainspec path from command line argument | ||
| const chainspecPath = process.argv[2]; | ||
| if (!chainspecPath) { | ||
| console.error('❌ Error: Chainspec path is required as first argument'); | ||
| console.error('Usage: node authorize_and_store_papi_smoldot.js <chainspec-path>'); | ||
| // Get chainspec path from command line argument (required - main chain: relay for para, or solo) | ||
| const chainSpecPath = process.argv[2]; | ||
| if (!chainSpecPath) { | ||
| console.error('❌ Error: Chain spec path is required as first argument'); | ||
| console.error('Usage: node authorize_and_store_papi_smoldot.js <chain-spec-path> [parachain-spec-path]'); | ||
| console.error(' For parachains: <relay-chain-spec-path> <parachain-spec-path>'); | ||
| console.error(' For solochains: <solo-chain-spec-path>'); | ||
| process.exit(1); | ||
| } | ||
|
|
||
| // Optional parachain chainspec path (only needed for parachains) | ||
| const parachainSpecPath = process.argv[3] || null; | ||
|
|
||
| let sd, client, resultCode; | ||
| try { | ||
| // Init Smoldot PAPI client and typed api. | ||
| ({ client, sd } = await createSmoldotClient(chainspecPath)); | ||
| ({ client, sd } = await createSmoldotClient(chainSpecPath, parachainSpecPath)); | ||
| console.log(`⏭️ Waiting ${SYNC_WAIT_SEC} seconds for smoldot to sync...`); | ||
| // TODO: check better way, when smoldot is synced, maybe some RPC/runtime api that checks best vs finalized block? | ||
| await new Promise(resolve => setTimeout(resolve, SYNC_WAIT_SEC * 1000)); | ||
|
|
||
| console.log('🔍 Checking if chain is ready...'); | ||
| const bulletinAPI = client.getTypedApi(bulletin); | ||
| await waitForChainReady(bulletinAPI); | ||
|
|
||
| // Signers. | ||
| const { sudoSigner, whoSigner, whoAddress } = setupKeyringAndSigners('//Alice', '//Alice'); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,14 +15,20 @@ chain = "westend-local" | |
| [[relaychain.nodes]] | ||
| name = "alice" | ||
| validator = true | ||
| p2p_port = 30333 | ||
| rpc_port = 9942 | ||
| balance = 2000000000000 | ||
| # WebSocket P2P on p2p_port + 1 for smoldot light client support | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. comments to be moved or removed |
||
| args = ["--listen-addr", "/ip4/0.0.0.0/tcp/30334/ws"] | ||
bkontur marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| [[relaychain.nodes]] | ||
| name = "bob" | ||
| validator = true | ||
| p2p_port = 30433 | ||
| rpc_port = 9943 | ||
| balance = 2000000000000 | ||
| # WebSocket P2P on p2p_port + 1 for smoldot light client support | ||
| args = ["--listen-addr", "/ip4/0.0.0.0/tcp/30434/ws"] | ||
|
|
||
| [[parachains]] | ||
| id = 1006 | ||
|
|
@@ -38,6 +44,9 @@ rpc_port = 10000 | |
| args = [ | ||
| "--ipfs-server", | ||
| "-lparachain=debug,runtime=trace,xcm=trace,bitswap=trace,sub-libp2p::bitswap=trace", | ||
| # WebSocket P2P on p2p_port + 1 for smoldot light client support | ||
| "--listen-addr", | ||
| "/ip4/0.0.0.0/tcp/10002/ws", | ||
| ] | ||
|
|
||
| [[parachains.collators]] | ||
|
|
@@ -49,4 +58,7 @@ rpc_port = 12346 | |
| args = [ | ||
| "--ipfs-server", | ||
| "-lparachain=debug,runtime=trace,xcm=trace,bitswap=trace,sub-libp2p::bitswap=trace", | ||
| # WebSocket P2P on p2p_port + 1 for smoldot light client support | ||
| "--listen-addr", | ||
| "/ip4/0.0.0.0/tcp/12348/ws", | ||
| ] | ||
Uh oh!
There was an error while loading. Please reload this page.