Skip to content

REPRODUCIBLE.MD issues/comments #329

Description

@TomBanks0912944

I was able to successfully compile the firmware and verify the release but discovered some issues along the way. I documented the steps I took below (highlighting the differences from the instructions in bold) as it may help others:

Compile and Compare Instructions

Initial instructions are here: https://github.com/Blockstream/Jade/blob/master/REPRODUCIBLE.md

Below assumes docker is installed and user added to docker group (so "sudo docker" is not needed)

Compile the firmware from the source

  1. Clone Jade master repository here: https://github.com/Blockstream/Jade/tree/master
cd
git clone https://github.com/Blockstream/Jade.git
  1. Checkout release tag to be verified (https://github.com/Blockstream/Jade/tags)
cd Jade
git checkout 1.0.40 
  1. Pull in missing dependances (change from instructions)
git submodule update --init --recursive
  1. Create docker image
DOCKER_BUILDKIT=1 docker build -f ./Dockerfile -t jade_builder .
  1. Run docker image (added rm option from instructions to delete container when done)
docker run --rm -v ${PWD}:/builds/blockstream/jade --name jade_builder -it jade_builder bash
  1. Prepare the environment inside docker container

(Note command ". /root/esp/esp-idf/export.sh" no longer works but is not needed)

cd /builds/blockstream/jade
git config --global --add safe.directory /builds/blockstream/jade
  1. Confirm "git describe" now works
git describe
1.0.40
  1. Generate config file for hardware / build type. From instructions:
Jade Hardware Type Configuration Command
Jade 1.0 (true wheel) BLE-enabled ./tools/switch_to.sh jade
no-radio ./tools/switch_to.sh jade --noradio
Jade 1.1 (rocker/jog-wheel) BLE-enabled ./tools/switch_to.sh jade_v1_1
no-radio ./tools/switch_to.sh jade_v1_1 --noradio
Jade 2.0 (two buttons) BLE-enabled ./tools/switch_to.sh jade_v2
no-radio ./tools/switch_to.sh jade_v2 --noradio

For example, execute:

./tools/switch_to.sh jade_v2
  1. Build firmware (target will be here: ./build/jade.bin)
idf.py fullclean all
  1. Sign target and exit container (note signin key filename change from instructions)
espsecure.py sign_data --keyfile ./release/scripts/dev_fw_signing_key_A.pem --version 2 --output ./build/jade_signed.bin ./build/jade.bin
exit
  1. Compare signed and unsigned to understand signing block location
cd
xxd ./Jade/build/jade.bin ./jade.xxd
xxd ./Jade/build/jade_signed.bin ./jade_signed.xxd
diff -C 0 jade.xxd jade_signed.xxd 

Diff shows only difference is added data end of file

Output snippet example:

*** jade.xxd	2026-08-17 10:03:54.425821995 -0500
--- jade_signed.xxd	2026-08-17 10:04:02.499384205 -0500
***************
*** 81920 ****
--- 81921,82176 ----
+ 00140000: e702 0000 0869 ac1f 08c1 b344 9ae3 b1f3  .....i.....D....

Note location of new data (e.g. lines 81921 to 82176 for above example).

Download official firmware to check vs compiled code.

  1. Get expected hashes from offical json

Use from HW table in instructions and note hw-target value

Jade Hardware Type flag
Jade 1.0 (true wheel) --hw-target jade
Jade 1.1 (rocker/jog-wheel) --hw-target jade1.1
Jade 2.0 (two buttons) --hw-target jade2.0
Jade 2.0c (2.0, no camera/battery) --hw-target jade2.0c

Display stable versions available and checksums (note URL has hw-target). For example:

curl https://jadefw.blockstream.com/bin/jade2.0/index.json | jq ".stable" 

Copy built version info desired (e.g. jade2.0 above was the following for latest ble stable):

      {
        "filename": "1.0.40_ble_1314816_fw.bin",
        "version": "1.0.40",
        "config": "ble",
        "fwsize": 1314816,
        "cmphash": "6623dadf8090b3debc9e47902ab8d927109ccfa58662f7d5e6bde4b46fb8e64e",
        "fwhash": "6c1a0f4e932bfb05b8876bb3e6a4a541b55377db75453999b346d6dad1bcfff9"
      }
  1. Download firmware

Two options to download the firmware:

  • Option 1: Download firmware directly from server using the above file name in step 12 (note hw-target is in URL)
curl -O https://jadefw.blockstream.com/bin/jade2.0/1.0.40_ble_1314816_fw.bin
  • Option 2: Download firmware using jade_ota.py per instructions (Note latest jade_ota.py does not work)

Use 1.0.36 version of jade_ota.py to download firmware:

cd Jade
git checkout 1.0.36
docker run --rm -v ${PWD}:/builds/blockstream/jade --name jade_builder -it jade_builder bash

Run jade_ota.py (Note hw-target as described above in step 12):

cd /builds/blockstream/jade
python ./jade_ota.py --skipserial --skipble --write-compressed --download-firmware --release stable --hw-target jade2.0

Output:

The fw file will be downloaded/verified but the actual OTA will be skipped
Downloading firmware index file https://jadefw.blockstream.com/bin/jade2.0/index.json
Full firmwares
1)  1.0.40 - noradio
2)  1.0.40 - ble
-
Delta patches
-
Select firmware: 2
Downloading firmware https://jadefw.blockstream.com/bin/jade2.0/1.0.40_ble_1314816_fw.bin
Downloaded 892251 byte firmware
Downloaded file hash verified
Written file build/1.0.40_ble_1314816_fw.bin
Written file build/1.0.40_ble_1314816_fw.bin.hash
Got fw file of length 892251 with expected uncompressed final fw length 1314816
Final fw hash: 6c1a0f4e932bfb05b8876bb3e6a4a541b55377db75453999b346d6dad1bcfff9

Exit docker container:

exit

Copy firmware into home directory:

cd
cp ./Jade/build/1.0.40_ble_1314816_fw.bin .
  • After either Option 1 or Option 2, continue to the next step
  1. Compute compressed fm hash:
sha256sum 1.0.40_ble_1314816_fw.bin
6623dadf8090b3debc9e47902ab8d927109ccfa58662f7d5e6bde4b46fb8e64e  1.0.40_ble_1314816_fw.bin

Compare output with cmphash downloaded above in step 12

  1. Compute uncompressed hash

install pigz if needed per instructions

apt update && apt install pigz

Uncompress firmware

cp 1.0.40_ble_1314816_fw.bin downloaded.bin.gz
pigz -z -d downloaded.bin.gz

Compute uncompressed hash:

sha256sum downloaded.bin
6c1a0f4e932bfb05b8876bb3e6a4a541b55377db75453999b346d6dad1bcfff9  downloaded.bin

Compare output with fwhash above in step 12

  1. Compare signed downloaded with unsigned compiled
xxd downloaded.bin downloaded.xxd
diff -C 0 jade.xxd downloaded.xxd 

Example output snippet:

*** jade.xxd	2026-08-17 10:03:54.425821995 -0500
--- downloaded.xxd	2026-08-18 10:31:24.209831450 -0500
***************
*** 81920 ****
--- 81921,82176 ----
+ 00140000: e702 0000 0869 ac1f 08c1 b344 9ae3 b1f3  .....i.....D....

Diff shows new data at 81921 to 82176 (just like signed and unsigned diff above in step 11)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions