JAM is the anticipated future protocol for Polkadot, being implemented by multiple teams across different programming languages. The JAM Gray Paper outlines the protocol, and the Web3 Foundation has shared initial test vectors with participating teams here.
This repository serves as a collaborative space for teams to develop and test JAM TestNets independently and eventually work towards cross-team compatibility. See also docs.jamcha.in
To support testing in a wide variety of network sizes from "tiny" (V=6) to "full" (V=1023), we follow the W3F test vectors in having public secret keys derived deterministically from publicly known seeds for Ed25519, Bandersnatch, and BLS keys.
Using these seeds, secret and public keys can be programmatically generated, ensuring each JAM team can run the public testnet consistently. This is strictly for development purposes.
An open-source key
program is used to map seeds into Bandersnatch/Ed25519/BLS secret and public keys. See here showing how to map any seed.
See Dev Accounts 32-byte seeds (from 0x00...00 to 0x00...05 for tiny V=6
).
Chain specs for 8 network sizes have been modeled and published.
Sharing excerpts of blockchain state and validating state transitions is a valuable prerequisite before 2 or more teams can set up a JAM Testnet.
By using a public genesis state, teams can collaborate by sharing state transitions (pre-state, block, post-state). This allows for verifying that different implementations can read key objects and perform the identical state transitions in accordance with the GP Spec and prepare to pass "M1 Import Blocks".
- blocks:
$epoch_$phase.json
$epoch_$phase.bin
-- follows w3f block test vectors - state_snapshots:
$epoch_$phase.json
$epoch_$phase.bin
-- JSON + Codec developer-friendly states following w3f STF test vectors - state_transitions:
$epoch_$phase.json
$epoch_$phase.bin
-- JSON + Codec machine-friendly state transitions
In Go:
type StateTransition struct {
PreState StateSnapshotRaw `json:"pre_state"`
Block Block `json:"block"`
PostState StateSnapshotRaw `json:"post_state"`
}
type StateSnapshotRaw struct {
StateRoot common.Hash `json:"state_root"`
KeyVals KeyVals `json:"keyvals"`
}
type KeyVals []KeyVal
type KeyVal [2][]byte
The combination of JSON + codec is useful for debugging purposes.
Here is a sample output:
# ls safrole/blocks/
407402_000.bin 407402_004.bin 407402_008.bin 407403_000.bin 407403_004.bin 407403_008.bin 407404_000.bin 407404_004.bin 407404_008.bin 407405_000.bin 407405_004.bin 407405_008.bin 407406_000.bin
407402_000.json 407402_004.json 407402_008.json 407403_000.json 407403_004.json 407403_008.json 407404_000.json 407404_004.json 407404_008.json 407405_000.json 407405_004.json 407405_008.json 407406_000.json
407402_001.bin 407402_005.bin 407402_009.bin 407403_001.bin 407403_005.bin 407403_009.bin 407404_001.bin 407404_005.bin 407404_009.bin 407405_001.bin 407405_005.bin 407405_009.bin 407406_001.bin
407402_001.json 407402_005.json 407402_009.json 407403_001.json 407403_005.json 407403_009.json 407404_001.json 407404_005.json 407404_009.json 407405_001.json 407405_005.json 407405_009.json 407406_001.json
407402_002.bin 407402_006.bin 407402_010.bin 407403_002.bin 407403_006.bin 407403_010.bin 407404_002.bin 407404_006.bin 407404_010.bin 407405_002.bin 407405_006.bin 407405_010.bin
407402_002.json 407402_006.json 407402_010.json 407403_002.json 407403_006.json 407403_010.json 407404_002.json 407404_006.json 407404_010.json 407405_002.json 407405_006.json 407405_010.json
407402_003.bin 407402_007.bin 407402_011.bin 407403_003.bin 407403_007.bin 407403_011.bin 407404_003.bin 407404_007.bin 407404_011.bin 407405_003.bin 407405_007.bin 407405_011.bin
407402_003.json 407402_007.json 407402_011.json 407403_003.json 407403_007.json 407403_011.json 407404_003.json 407404_007.json 407404_011.json 407405_003.json 407405_007.json 407405_011.json
# ls safrole/state_snapshots/
407402_000.bin 407402_004.bin 407402_008.bin 407403_000.bin 407403_004.bin 407403_008.bin 407404_000.bin 407404_004.bin 407404_008.bin 407405_000.bin 407405_004.bin 407405_008.bin 407406_000.bin
407402_000.json 407402_004.json 407402_008.json 407403_000.json 407403_004.json 407403_008.json 407404_000.json 407404_004.json 407404_008.json 407405_000.json 407405_004.json 407405_008.json 407406_000.json
407402_001.bin 407402_005.bin 407402_009.bin 407403_001.bin 407403_005.bin 407403_009.bin 407404_001.bin 407404_005.bin 407404_009.bin 407405_001.bin 407405_005.bin 407405_009.bin 407406_001.bin
407402_001.json 407402_005.json 407402_009.json 407403_001.json 407403_005.json 407403_009.json 407404_001.json 407404_005.json 407404_009.json 407405_001.json 407405_005.json 407405_009.json 407406_001.json
407402_002.bin 407402_006.bin 407402_010.bin 407403_002.bin 407403_006.bin 407403_010.bin 407404_002.bin 407404_006.bin 407404_010.bin 407405_002.bin 407405_006.bin 407405_010.bin
407402_002.json 407402_006.json 407402_010.json 407403_002.json 407403_006.json 407403_010.json 407404_002.json 407404_006.json 407404_010.json 407405_002.json 407405_006.json 407405_010.json
407402_003.bin 407402_007.bin 407402_011.bin 407403_003.bin 407403_007.bin 407403_011.bin 407404_003.bin 407404_007.bin 407404_011.bin 407405_003.bin 407405_007.bin 407405_011.bin
407402_003.json 407402_007.json 407402_011.json 407403_003.json 407403_007.json 407403_011.json 407404_003.json 407404_007.json 407404_011.json 407405_003.json 407405_007.json 407405_011.json
# ls safrole/state_transitions/
407402_000.bin 407402_004.bin 407402_008.bin 407403_000.bin 407403_004.bin 407403_008.bin 407404_000.bin 407404_004.bin 407404_008.bin 407405_000.bin 407405_004.bin 407405_008.bin 407406_000.bin
407402_000.json 407402_004.json 407402_008.json 407403_000.json 407403_004.json 407403_008.json 407404_000.json 407404_004.json 407404_008.json 407405_000.json 407405_004.json 407405_008.json 407406_000.json
407402_001.bin 407402_005.bin 407402_009.bin 407403_001.bin 407403_005.bin 407403_009.bin 407404_001.bin 407404_005.bin 407404_009.bin 407405_001.bin 407405_005.bin 407405_009.bin
407402_001.json 407402_005.json 407402_009.json 407403_001.json 407403_005.json 407403_009.json 407404_001.json 407404_005.json 407404_009.json 407405_001.json 407405_005.json 407405_009.json
407402_002.bin 407402_006.bin 407402_010.bin 407403_002.bin 407403_006.bin 407403_010.bin 407404_002.bin 407404_006.bin 407404_010.bin 407405_002.bin 407405_006.bin 407405_010.bin
407402_002.json 407402_006.json 407402_010.json 407403_002.json 407403_006.json 407403_010.json 407404_002.json 407404_006.json 407404_010.json 407405_002.json 407405_006.json 407405_010.json
407402_003.bin 407402_007.bin 407402_011.bin 407403_003.bin 407403_007.bin 407403_011.bin 407404_003.bin 407404_007.bin 407404_011.bin 407405_003.bin 407405_007.bin 407405_011.bin
407402_003.json 407402_007.json 407402_011.json 407403_003.json 407403_007.json 407403_011.json 407404_003.json 407404_007.json 407404_011.json 407405_003.json 407405_007.json 407405_011.json
Based on JAM0 - JAM Implementers Meetup @ sub0/Devcon 7 we will build a Import Blocks tool, which we will post here in mid-December 2024 with support for 4 different modes:
mode |
fallback |
safrole |
assurance |
orderedaccumulation |
---|---|---|---|---|
Tickets: E_T | x | x | x | |
Guarantees: E_G | x | x | ||
Assurances: E_A | x | x | ||
Preimages: E_P | x | x | ||
Refine/Accumulate PVM | x | x | ||
Bootstrap Services | x | x | ||
Ordered Accumulation | x |
The importblocks tool is documented here.
Additional modes:
authorization
: same as assurances, but also adjusting C(1)+C(2)blessed
: same as assurances, but also adjusting C(5), C(12)basichostfunctions
: same as assurances, but using most common host functionsfinalization
: combines all of the above, adjusting everything in C(1)-C(15), except disputesdisputes
: combines all of the above, including dispute extrinsics
The presence of W3F test vectors will guide adjustments to the above.
The fallback
mode does not involve any PVM execution or extrinsics. See Sealing Test Vectors.
See fallback.txt for execution.
The safrole
mode adds extrinsic tickets. Here is a draft of the shape of mode=safrole
here:
See safrole.txt for execution.
The assurances
mode adds a few tiny services (bootstrap, fib) and requires E_G, E_A, E_P extrinsics as well as a basic PVM implementation with a few host functions implemented.
See services for bootstrap
and fib
code.
See assurances.txt for execution.
The orderedaccumulation
mode uses both cores to run through simple cases of package dependencies and ordered accumulation with "trib" and "megatron" services.
Nov 2024:
- added fallback based on JAM0 meeting
- genesis state fixes [thanks to Daniel from Jamixir]
- made the phases 3 digits (000, 001, ... 011) rather than variable (0, 1, .. 11) [thank you Boy Maas]
- fixed parent hash to be header hash rather than block hash [thank you Arjan, PyJAMaz]
Dec 2024:
- mode=orderedaccumulation added (C14+C15)
- C3 Recent Blocks support consistent with E.2 0.5.2 Beefy root and w3f STF reports test vectors
- 64-bit PVM support with new opcodes (with 96% coverage (see community test vectors))
- state_transitions output with service k,v metadata
Jan 2025:
Everyone must follow JAM Prize rules and can politely refuse collaboration with any team for any reason.
To contribute, submit a PR to:
- add additional state transitions:
${mode}/${team}
(e.g.safrole/jam-duna
). If you have a new mode, just describe it and add it - add your service code (in any language, including privileged services). Put it in
services/${team}/${servicename}
(e.g.services/strongly-web3/fib
)
- JAM Testnet on Telegram - Public, anyone can join
- JAM0 on Matrix/Element - Private, ask for an invite from a fellow JAM Implementer (e.g. @sourabhniyogi)