ChainLaunch Pro Feature
Pro Sharing requires ChainLaunch Pro. Learn more about Pro features.
Pro Sharing is a peer-to-peer protocol that lets two or more ChainLaunch Pro instances exchange resources directly — keys, networks, chaincode, and governance proposals — without a central authority. It's the foundation for true multi-organization consortiums where every party runs their own ChainLaunch.
For just sharing node connection metadata (IP/port/cert), see Node Sharing. This page covers the broader P2P system that builds on top of it.
What you can share
| Resource | Direction | Use case |
|---|---|---|
| Keys | A → B | A generates an MSP signing key in their HSM and shares the public material so B can include them in a channel config. |
| Networks (Fabric & Besu) | A → B | A defines a network template; B receives an invitation, accepts it, and joins as a participating org. |
| Chaincode | A → B | Source code, package, or installed chaincode is shared so all orgs run identical bytecode. |
| Configuration proposals | A → B (multi-sig) | A drafts a channel-config update; signers in B and C approve before A submits. |
| Node metadata | bidirectional | IP/port/TLS-cert info — see Node Sharing. |
What never leaves a host: private keys (only public material is exchanged), database contents, audit logs, and any data on chain.
Architecture
Pro Sharing rides on a WebSocket-based mesh between paired instances:
┌──────────────────┐ WSS (mTLS) ┌──────────────────┐
│ ChainLaunch A │ ◄─────────────────────────► │ ChainLaunch B │
│ pkg/pro │ pro_shares + dual- │ pkg/pro │
│ pkg/communica… │ table receiver pattern │ pkg/communica… │
└──────────────────┘ └──────────────────┘
│ │
▼ ▼
pro_shares ─────► connection_items ─────► connected_peers
Each paired peer is a row in connected_peers. Every shared resource gets a row in pro_shares plus a row in a resource-specific table (e.g. received_keys, received_networks). The connection_id column on every share links back to the originating peer for audit and revocation.
Step 1 — Pair two instances
Pairing creates a mutual-TLS WebSocket trust link. Use the CLI on either instance:
# Instance A — generate an invitation
chainlaunch nodesharing generate-node-invitation --bidirectional
# → Invitation JWT: eyJhbGciOi...# Instance B — accept it
chainlaunch nodesharing accept-node-invitation \
--invitation_jwt "eyJhbGciOi..."
# → Connected peer #1 ✓Bidirectional pairings let both sides see each other's resources. One-way pairings restrict the flow to A → B only. The full mechanics — including external URL setup so the WebSocket callback works behind NAT — are in Node Sharing.
Verify the pair under Settings → Connected Peers or:
chainlaunch nodesharing list-connected-peersStep 2 — Share keys
Pick a key (database-backed, AWS KMS, or HashiCorp Vault) and share it:
chainlaunch pro share-key --key_id 42 --peer_id 1 \
--metadata 'Org2 MSP signing key'The peer receives an entry in their Inbox → Shared Keys. They can:
- Accept — the key is persisted as a
received_keysrow, with the public material visible everywhere a local key would be (network configs, chaincode endorsements, MSP definitions). - Reject — the share is marked rejected and an audit event is appended on both sides.
Inbox / actions:
# Keys shared with me
chainlaunch pro get-keys-shared-with-me
# Accept (or otherwise process) a shared key
chainlaunch pro receive-key --shareId 17Only public key material crosses the wire. Private keys remain in the originating ChainLaunch (or the underlying HSM/Vault). See Vault and AWS KMS for HSM details.
Step 3 — Share a Fabric or Besu network
Share an entire network — including consortium definition, channel config, and orderer endpoints:
# Fabric
chainlaunch pro share-network --networkId 5 --recipients 1,2
# Besu
chainlaunch pro share-besu-network --networkId 7 --recipients 1The receiver sees the share under Networks → Shared with me:
# List
chainlaunch pro list-shared-networks
# Inspect
chainlaunch pro get-shared-network --networkId 5
# Accept (joins the network with the proposed role)
chainlaunch pro accept-shared-network --shareId {shareId}
# Reject
chainlaunch pro reject-shared-network --shareId {shareId}
# Remove a previously accepted share
chainlaunch pro delete-shared-network --shareId {shareId}On accept, the receiver's ChainLaunch:
- Imports the network definition into its local DB.
- Joins the channel(s) using local nodes (or external nodes — see Node Sharing).
- Subscribes to live events for that channel and starts indexing.
Step 4 — Share chaincode
Sharing chaincode keeps all orgs running identical bytecode. You can share at three levels:
| Level | What's exchanged |
|---|---|
| Source | Original source tree — receiver builds locally |
| Package | Pre-built .tar.gz chaincode package |
| Installed | Reference to an already-installed chaincode for cross-instance discovery |
chainlaunch pro share-chaincode \
--chaincodeId 12 --recipients 1,2 \
--version 1.0 --sequence 1 \
--dockerImage kfsoftware/external-chaincode:v1.0Receiver inbox:
chainlaunch pro list-shared-chaincodes
chainlaunch pro get-shared-chaincode --chaincodeId {chaincodeId}After accept, the chaincode shows up in the receiver's chaincode list as Source: shared from Org A. Lifecycle events (install, approve, commit) for that chaincode are mirrored back to the source org via the audit channel.
Step 5 — Share configuration proposals (multi-sig governance)
For any change that requires multiple-org approval (Fabric channel-config updates, Besu validator rotation), use a shared configuration proposal:
chainlaunch pro share-config-proposal \
--proposalId proposal-add-org3 \
--channelName mychannel \
--recipients 1,2 \
--metadata 'Add Org3 to channel mychannel'Each receiver:
- Reviews the proposed config in Governance → Pending Proposals.
- Signs (or rejects) under their own RBAC rules.
- Once the policy threshold is reached, the originator can submit the signed update.
For the full governance workflow, including reviewer assignment, expiration, and audit, see Governance and automating_governance.md.
Database model (for operators)
If you operate ChainLaunch and need to debug a share that "looks stuck":
| Table | Role |
|---|---|
connected_peers |
One row per paired instance. Holds the cached external URL and pairing JWT material. |
pro_shares |
The central log of every share event (resource type, status, timestamps). Use it to answer "did this share actually reach B?" |
received_keys |
Keys received from other peers. |
connection_items |
Peer nodes (Fabric peers/orderers, Besu validators) referenced by shares. |
pro_share_status enum |
pending, accepted, rejected, revoked, expired. |
-- All shares originating from this instance
SELECT id, resource_type, target_peer_id, status, created_at
FROM pro_shares
WHERE direction = 'outgoing'
ORDER BY created_at DESC LIMIT 50;Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| "Peer offline" on share | The other instance can't be reached on its external URL | Verify each instance was started with --external-url https://... and that URL resolves & TLS-validates from the other side. |
Share stuck in pending |
Receiver hasn't connected since share was issued | Check connected_peers.last_seen_at — peers reconnect on a heartbeat. |
| Network share accepted but channel doesn't appear | Receiver has no nodes assigned to that channel yet | After accepting, run Networks → (the shared network) → Add Nodes on the receiver. |
403 forbidden on share |
Caller lacks PRO_SHARE_CREATE permission |
Grant the user OPERATOR or ADMIN role. See RBAC. |
Chaincode share at package level fails |
Package size exceeds the configured WS frame limit | Either use source level (smaller) or raise the per-instance --max-share-size flag. |
| Receiver sees a key but can't endorse | They accepted the share but the local MSP isn't using that key as signing identity | Edit the local MSP definition to reference the received key by its share ID. |
Security model
- Pairing: Both sides hold each other's pinned TLS cert hash from the invitation JWT. A man-in-the-middle proxy can't insert itself after pairing.
- Authorization: RBAC permissions gate every endpoint (
PRO_SHARE_CREATE,PRO_SHARE_ACCEPT,PRO_SHARE_REVOKE). - Replay: Each share has a monotonic
share_idper peer; receivers reject duplicates. - Audit: Every share, accept, reject, and revoke is recorded in Audit Logging on both sides.
- Revocation: An originator can
DELETE /pro/shared-networks/{shareId}(and equivalent for keys/chaincode) at any time. The receiver retains the resource if already accepted but is notified that the source org has revoked the link — useful for offboarding a partner without breaking active workloads.
Best practices
- Pair bidirectionally for active partnerships, one-way for read-only observers.
- Use one connected peer per partner org, not per environment — environment isolation should come from separate channels, not separate peers.
- Encrypt the master key with Encryption at Rest so the pairing material on disk is safe from cold-storage attacks.
- Audit pro_shares weekly during early consortium ramp-up — it's the fastest way to spot mis-shares before they become governance issues.
- Tag shares with the change ticket in
purposeso audit trails are self-explanatory months later.
Next steps
- Node Sharing — pairing fundamentals.
- Governance — multi-sig configuration proposals in depth.
- Multi-Org Fabric Network — end-to-end consortium walkthrough.
- Audit Logging — review every share and accept.
- RBAC & Permissions — who can share what.