mirror of
https://github.com/pezkuwichain/pezkuwi-wallet-utils.git
synced 2026-11-06 01:01:07 +00:00
- signed_config.py root drafts a later root in docs/root-signing/proposals/, where wallets never look, and keeps the current targets key by default. - docs/root-signing/: a page for the Pezkuwi Wallet DApp browser that shows the proposal and its fingerprint, has the holder's wallet sign <Bytes>payload</Bytes>, checks every signature as the wallet will, collects signature codes and offers root.N.json once two current and two new holders have signed. Crypto bundles are served beside it. - scripts/root/verify_root.mjs checks every published signed/root.N.json the way installed wallets do; Code Quality runs it. Wallet 1.3.0 accepts sr25519 only under the substrate signing context, and a root it cannot verify stops its config refresh, so such a root must never reach master. - Draft root 2: three new holder accounts, threshold 2, five years.
203 lines
6.3 KiB
YAML
203 lines
6.3 KiB
YAML
name: Code Quality
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
pull_request:
|
|
branches: [main]
|
|
# Weekly, so a signature running out shows here a month before the wallet stops trusting it.
|
|
schedule:
|
|
- cron: '0 7 * * 1'
|
|
|
|
|
|
# Read-only token: Code Quality never writes through GITHUB_TOKEN.
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
python-lint:
|
|
name: Python Lint
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Python
|
|
uses: actions/setup-python@v5
|
|
with:
|
|
python-version: '3.12'
|
|
|
|
- name: Install ruff
|
|
run: pip install ruff
|
|
|
|
- name: Run ruff linter
|
|
run: ruff check scripts/
|
|
continue-on-error: true
|
|
|
|
- name: Run ruff formatter check
|
|
run: ruff format --check scripts/
|
|
continue-on-error: true
|
|
|
|
json-validation:
|
|
name: JSON Validation
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
submodules: true
|
|
|
|
- name: Validate JSON files
|
|
run: |
|
|
ERRORS=0
|
|
echo "Validating chain config JSON files..."
|
|
|
|
for f in chains/v22/android/chains.json chains/v22/chains.json chains/v22/chains_dev.json pezkuwi-overlay/chains/pezkuwi-chains.json; do
|
|
if [ -f "$f" ]; then
|
|
if python3 -m json.tool "$f" > /dev/null 2>&1; then
|
|
echo " $f: valid"
|
|
else
|
|
echo "::error file=$f::Invalid JSON: $f"
|
|
ERRORS=$((ERRORS + 1))
|
|
fi
|
|
fi
|
|
done
|
|
|
|
exit $ERRORS
|
|
|
|
signed-config:
|
|
name: Signed Config
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Setup Python
|
|
uses: actions/setup-python@v5
|
|
with:
|
|
python-version: '3.12'
|
|
|
|
- name: Install cryptography
|
|
run: pip install cryptography
|
|
|
|
# The wallet refuses a config file whose sha256 signed/targets.json does not give, so
|
|
# a change that was not re-signed must not reach master.
|
|
- name: Targets signed and matching every served file
|
|
run: python3 scripts/signed_config.py check
|
|
|
|
# A wallet that never fell back to its light client has no saved state, so its first fallback
|
|
# starts from this checkpoint; refreshed specifications reach wallets through the signed config.
|
|
- name: Light client checkpoint not stale
|
|
run: python3 scripts/light_client_specs.py --relay-rpc https://zagros-rpc.pezkuwichain.io --check-age 60
|
|
|
|
- name: Setup Node
|
|
uses: actions/setup-node@v4
|
|
with:
|
|
node-version: '22'
|
|
|
|
# A wallet that finds a root it cannot verify stops refreshing its config, so every published
|
|
# signed/root.N.json is checked here exactly as installed wallets check it.
|
|
- name: Root chain verifies as installed wallets check it
|
|
run: |
|
|
npm ci --prefix scripts/root --ignore-scripts --no-audit --no-fund
|
|
node scripts/root/verify_root.mjs docs/root-signing/proposals/*.json
|
|
|
|
chain-integrity:
|
|
name: Chain Config Integrity
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
submodules: true
|
|
|
|
- name: Setup Python
|
|
uses: actions/setup-python@v5
|
|
with:
|
|
python-version: '3.11'
|
|
|
|
# Refuses the regressions this repo has already had: assets declared that do not
|
|
# exist on chain, sufficiency left undeclared, assets served from a working
|
|
# branch, and a published fixture drifting from its source.
|
|
- name: Pezkuwi integrity
|
|
run: python3 scripts/check_pezkuwi_integrity.py
|
|
|
|
- name: Verify Pezkuwi chains are present
|
|
run: |
|
|
CHAINS_FILE="chains/v22/android/chains.json"
|
|
if [ ! -f "$CHAINS_FILE" ]; then
|
|
echo "::error::$CHAINS_FILE not found"
|
|
exit 1
|
|
fi
|
|
|
|
ERRORS=0
|
|
|
|
# Pezkuwi Relay
|
|
if ! python3 -c "import json; chains=json.load(open('$CHAINS_FILE')); assert any(c['chainId'].startswith('1aa94987') for c in chains), 'Missing Pezkuwi Relay'"; then
|
|
echo "::error::Pezkuwi Relay chain missing from $CHAINS_FILE"
|
|
ERRORS=$((ERRORS + 1))
|
|
else
|
|
echo "Pezkuwi Relay: present"
|
|
fi
|
|
|
|
# Pezkuwi Asset Hub
|
|
if ! python3 -c "import json; chains=json.load(open('$CHAINS_FILE')); assert any(c['chainId'].startswith('e7c15092') for c in chains), 'Missing Asset Hub'"; then
|
|
echo "::error::Pezkuwi Asset Hub missing from $CHAINS_FILE"
|
|
ERRORS=$((ERRORS + 1))
|
|
else
|
|
echo "Pezkuwi Asset Hub: present"
|
|
fi
|
|
|
|
# Pezkuwi People
|
|
if ! python3 -c "import json; chains=json.load(open('$CHAINS_FILE')); assert any(c['chainId'].startswith('69a8d025') for c in chains), 'Missing People Chain'"; then
|
|
echo "::error::Pezkuwi People chain missing from $CHAINS_FILE"
|
|
ERRORS=$((ERRORS + 1))
|
|
else
|
|
echo "Pezkuwi People: present"
|
|
fi
|
|
|
|
# Verify Pezkuwi chains are first in array
|
|
FIRST_CHAIN=$(python3 -c "import json; print(json.load(open('$CHAINS_FILE'))[0]['chainId'][:8])")
|
|
if [ "$FIRST_CHAIN" != "1aa94987" ]; then
|
|
echo "::warning::Pezkuwi Relay is not the first chain (found: $FIRST_CHAIN)"
|
|
else
|
|
echo "Pezkuwi Relay is first chain: OK"
|
|
fi
|
|
|
|
exit $ERRORS
|
|
|
|
sync-script-test:
|
|
name: Sync Script Dry Run
|
|
runs-on: ubuntu-latest
|
|
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
with:
|
|
submodules: true
|
|
|
|
- name: Setup Python
|
|
uses: actions/setup-python@v5
|
|
with:
|
|
python-version: '3.12'
|
|
|
|
- name: Run sync script
|
|
run: python3 scripts/sync_from_nova.py
|
|
|
|
- name: Verify output was generated
|
|
run: |
|
|
if [ ! -f "chains/v22/android/chains.json" ]; then
|
|
echo "::error::Sync script failed to generate chains/v22/android/chains.json"
|
|
exit 1
|
|
fi
|
|
COUNT=$(python3 -c "import json; print(len(json.load(open('chains/v22/android/chains.json'))))")
|
|
echo "Generated $COUNT chains"
|
|
if [ "$COUNT" -lt 4 ]; then
|
|
echo "::error::Expected at least 4 chains, got $COUNT"
|
|
exit 1
|
|
fi
|