Skip to content

Getting Started

  • Java Development Kit (JDK) 17 or higher

    Terminal window
    # Check Java version
    java -version
    # Install via SDKMAN (recommended)
    curl -s "https://get.sdkman.io" | bash
    sdk install java 17.0.9-tem
  • Scala Build Tool (sbt) 1.9+

    Terminal window
    # macOS
    brew install sbt
    # Linux
    curl -fL https://github.com/sbt/sbt/releases/download/v1.9.7/sbt-1.9.7.tgz | tar xz
    # Check version
    sbt --version
  • Rust toolchain (for native libraries)

    Terminal window
    # Install Rust
    curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
    # Check installation
    cargo --version
    rustc --version
Terminal window
# Clone with submodules (includes graypaper and jamtestvectors)
cd /jam
git submodule update --init --recursive

The first build will:

  1. Download Scala compiler and dependencies
  2. Build native Rust libraries (Bandersnatch VRF, Ed25519, Erasure Coding)
  3. Compile all Scala modules
Terminal window
# Full build
sbt compile
# Build and run all tests
sbt test
jam/
├── build.sbt # Main build configuration
├── project/ # sbt build definitions
│ ├── build.properties # sbt version
│ └── plugins.sbt # sbt plugins
├── modules/
│ ├── core/ # Core types and encoding
│ │ └── src/
│ │ ├── main/scala/ # Source code
│ │ └── test/scala/ # Tests
│ ├── crypto/ # Cryptography
│ │ ├── src/
│ │ └── native/ # Rust native libraries
│ │ ├── bandersnatch-vrfs-wrapper/
│ │ ├── ed25519-zebra-wrapper/
│ │ └── erasure-coding-wrapper/
│ ├── pvm/ # PolkaVM virtual machine
│ ├── protocol/ # State transition functions
│ └── conformance/ # Conformance testing
├── graypaper/ # Gray Paper (submodule)
├── jamtestvectors/ # Official test vectors (submodule)
└── jam-conformance/ # Conformance testing tools (submodule)

The project uses Scalafmt for code formatting:

Terminal window
# Format all source files
sbt scalafmtAll
# Check formatting without modifying
sbt scalafmtCheckAll

Configuration in .scalafmt.conf:

  • 2-space indentation
  • 100-character line width
  • Scala 3 syntax
Terminal window
# Run all tests
sbt test
# Run tests for a specific module
sbt "core/test"
# Run a single test class
sbt "core/testOnly io.forge.jam.core.codec.BlockCodecTest"
# Run tests matching a pattern
sbt "protocol/testOnly *SafroleTest"
# Run with increased logging
sbt "set Test / logLevel := Level.Debug" test

Native libraries are automatically rebuilt if missing. To force a rebuild:

Terminal window
# Remove existing libraries
rm -rf modules/crypto/native/build/
# Rebuild
sbt crypto/compile
Terminal window
# Build manually with debug output
cd modules/crypto/native/bandersnatch-vrfs-wrapper
cargo clean
cargo build --release --verbose
# Check library is loadable (macOS)
otool -L target/release/libbandersnatch_vrfs_wrapper.dylib
# Check library is loadable (Linux)
ldd target/release/libbandersnatch_vrfs_wrapper.so

Set RUST_LOG environment variable for Rust library debug output:

Terminal window
RUST_LOG=debug sbt test

Test vectors are in the jamtestvectors submodule:

Terminal window
# Update to latest test vectors
cd jamtestvectors
git pull origin main
cd ..
# Run tests with new vectors
sbt test

Run performance benchmarks:

Terminal window
# Run benchmark suite
sbt benchmark
# The benchmark runs TracesBenchmark which measures STF performance

Create a standalone JAR with all dependencies:

modules/conformance/target/scala-3.3.7/jam-conformance.jar
# Build fat JAR
sbt "conformance/assembly"
# Run the server
java -jar modules/conformance/target/scala-3.3.7/jam-conformance.jar
Terminal window
# Build Docker image
docker build -t jam-scala:latest .
# Run container
docker run -v /path/to/socket:/var/run/jam jam-scala:latest
Terminal window
# Start the conformance server
sbt "conformance/run"
# In another terminal, run fuzzing tests
cd jam-conformance
python3 scripts/fuzz-workflow.py --target jam-forge --mode exploratory

Set log level in src/main/resources/logback.xml or via environment:

Terminal window
# Run with debug logging
LOG_LEVEL=debug sbt test
# Or set in test code
System.setProperty("org.slf4j.simpleLogger.defaultLogLevel", "debug")