Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
335ce60
feat(tbtc/signer): mirror FROST/ROAST Rust signer from tBTC monorepo
mswilkison May 26, 2026
bfd7658
extraction: apply allowlisted-divergence transformations to signer sc…
mswilkison May 26, 2026
551bd42
ci(tbtc-signer): add formal verification workflow (moved from tbtc-v2)
mswilkison May 26, 2026
d1a1424
extraction: fix signer formal-verification CI (chmod + vector path)
mswilkison May 26, 2026
adb6f64
extraction: mirror p2tr-signature-fraud-v0 vector + fix test path
mswilkison May 26, 2026
220cff2
fix(tbtc-signer): harden signer validation and retries
mswilkison May 27, 2026
c12c593
ci(tbtc-signer): update tla tools checksum
mswilkison May 27, 2026
2e61c26
ci(tbtc-signer): add full rust checks
mswilkison May 27, 2026
2930091
fix(tbtc-signer): preserve cached build tx retries
mswilkison May 27, 2026
9cfcde6
fix(tbtc-signer): harden production defaults
mswilkison May 28, 2026
c1e72f5
fix(tbtc-signer): close hardening follow-ups
mswilkison May 28, 2026
506959d
Expose interactive FROST DKG signer ABI
mswilkison Jun 4, 2026
2e0a054
Support Taproot tweaked signer rounds
mswilkison Jun 5, 2026
3a259ec
Support seeded tbtc-signer DKG
mswilkison Jun 5, 2026
4c9c654
Reuse signer rounds across member identifiers
mswilkison Jun 5, 2026
8f5aec7
Harden Taproot signer aggregation
mswilkison Jun 6, 2026
a62cb26
Preserve legacy signer round fingerprints
mswilkison Jun 6, 2026
797417f
Clarify signer exported key boundary
mswilkison Jun 6, 2026
e5b4f16
Stabilize signer round reuse fingerprints
mswilkison Jun 6, 2026
815ea72
Classify malformed DKG seeds as validation errors
mswilkison Jun 6, 2026
64d9d64
Assert signer round retry idempotency
mswilkison Jun 6, 2026
2380c8c
Support Taproot tweaked signer rounds (#4018)
mswilkison Jun 6, 2026
4f775b9
Document interactive FROST nonce contract
mswilkison Jun 6, 2026
57461c3
Zeroize interactive FROST secret buffers
mswilkison Jun 6, 2026
6179a3f
Merge signer mirror updates into interactive FROST ABI
mswilkison Jun 6, 2026
abdae01
Expose interactive FROST DKG signer ABI (#4011)
mswilkison Jun 6, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions .github/workflows/tbtc-signer-formal.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
name: tBTC Signer Formal Verification

on:
pull_request:
paths:
- pkg/tbtc/signer/**
- .github/workflows/tbtc-signer-formal.yml
schedule:
- cron: "23 5 * * *"
workflow_dispatch:

permissions:
contents: read

concurrency:
group: tbtc-signer-formal-${{ github.ref }}
cancel-in-progress: true

jobs:
signer-rust-checks:
name: Signer Rust checks
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
components: rustfmt, clippy

- name: Check formatting
run: cargo fmt --manifest-path pkg/tbtc/signer/Cargo.toml -- --check

- name: Run clippy
run: cargo clippy --manifest-path pkg/tbtc/signer/Cargo.toml --all-targets -- -D warnings

- name: Run signer tests
env:
TBTC_SIGNER_STATE_PATH: /tmp/tbtc-signer-ci-state-${{ github.run_id }}-${{ github.run_attempt }}.json
run: cargo test --manifest-path pkg/tbtc/signer/Cargo.toml

signer-formal-invariants:
name: Signer formal invariants
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout
uses: actions/checkout@v4
Comment on lines +49 to +50
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE=".github/workflows/tbtc-signer-formal.yml"
echo "== File exists? =="
ls -l "$FILE"
echo "== Lines 1-120 with numbers =="
nl -ba "$FILE" | sed -n '1,120p'

Repository: threshold-network/keep-core

Length of output: 272


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE=".github/workflows/tbtc-signer-formal.yml"
echo "== File exists? =="
ls -l "$FILE"
echo "== Lines 1-120 with numbers =="
nl -ba "$FILE" | sed -n '1,120p'

Repository: threshold-network/keep-core

Length of output: 272


🏁 Script executed:

#!/bin/bash
set -euo pipefail
FILE=".github/workflows/tbtc-signer-formal.yml"

echo "== Showing lines 1-80 =="
awk 'NR>=1 && NR<=80 {printf "%4d: %s\n", NR, $0}' "$FILE"

echo "== Showing checkout-related lines (search) =="
rg -n "name:\s*Checkout|uses:\s*actions/checkout|persist-credentials" "$FILE" || true

Repository: threshold-network/keep-core

Length of output: 2302


Set persist-credentials: false on both actions/checkout@v4 steps

The current workflow checks out without disabling persisted git credentials; add with: persist-credentials: false to reduce credential exposure.

Suggested patch
       - name: Checkout
         uses: actions/checkout@v4
+        with:
+          persist-credentials: false
@@
       - name: Checkout
         uses: actions/checkout@v4
+        with:
+          persist-credentials: false
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- name: Checkout
uses: actions/checkout@v4
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: false
🧰 Tools
🪛 zizmor (1.25.2)

[warning] 25-26: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 26-26: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/tbtc-signer-formal.yml around lines 25 - 26, The checkout
steps using actions/checkout@v4 persist git credentials by default; update each
Checkout step (the uses: actions/checkout@v4 entries) to add with:
persist-credentials: false so credentials are not stored in the runner after
checkout. Ensure both occurrences of actions/checkout@v4 in the workflow are
modified accordingly.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

for repo in actions/checkout actions/setup-java dtolnay/rust-toolchain; do
  echo "=== $repo ==="
  git ls-remote "https://github.com/${repo}.git" | head -n 5
  echo
done

Repository: threshold-network/keep-core

Length of output: 535


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Inspect workflow around the referenced lines
echo "=== Workflow file context ==="
nl -ba .github/workflows/tbtc-signer-formal.yml | sed -n '1,120p'

# 2) Resolve refs to commit SHAs (avoid SIGPIPE by capturing then slicing)
resolve_ref() {
  local repo="$1" ref="$2"
  local url="https://github.com/${repo}.git"
  local tmp="/tmp/lsremote_${repo//\//_}_${ref//\//_}"
  git ls-remote "$url" "$ref" > "$tmp" 2>/dev/null || true
  echo "--- ${repo} ${ref} ---"
  cat "$tmp" || true
  echo
  rm -f "$tmp" || true
}

echo "=== Resolve action refs to SHAs ==="
resolve_ref "actions/checkout" "refs/tags/v4"
resolve_ref "actions/checkout" "refs/heads/v4"
resolve_ref "actions/setup-java" "refs/tags/v4"
resolve_ref "actions/setup-java" "refs/heads/v4"
resolve_ref "dtolnay/rust-toolchain" "refs/heads/stable"
resolve_ref "dtolnay/rust-toolchain" "refs/tags/stable"

Repository: threshold-network/keep-core

Length of output: 162


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Workflow file context (numbered) ==="
python3 - <<'PY'
from pathlib import Path
p = Path(".github/workflows/tbtc-signer-formal.yml")
lines = p.read_text().splitlines()
start, end = 1, min(len(lines), 140)
for i in range(start, end+1):
    print(f"{i}\t{lines[i-1]}")
PY

echo
echo "=== Resolve action refs to commit SHAs ==="
resolve_ref() {
  local repo="$1" ref="$2"
  local url="https://github.com/${repo}.git"
  echo "--- ${repo} ${ref} ---"
  git ls-remote "$url" "$ref" || true
  echo
}

resolve_ref "actions/checkout" "refs/tags/v4"
resolve_ref "actions/checkout" "refs/heads/v4"
resolve_ref "actions/setup-java" "refs/tags/v4"
resolve_ref "actions/setup-java" "refs/heads/v4"
resolve_ref "dtolnay/rust-toolchain" "refs/heads/stable"
resolve_ref "dtolnay/rust-toolchain" "refs/tags/stable"

Repository: threshold-network/keep-core

Length of output: 2438


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Total lines: $(python3 - <<'PY'\nimport pathlib\np=pathlib.Path('.github/workflows/tbtc-signer-formal.yml')\nprint(len(p.read_text().splitlines()))\nPY)"

echo
echo "=== uses: occurrences ==="
rg -n "uses:" .github/workflows/tbtc-signer-formal.yml || true

echo
echo "=== persist-credentials occurrences ==="
rg -n "persist-credentials" .github/workflows/tbtc-signer-formal.yml || true

Repository: threshold-network/keep-core

Length of output: 133


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Total lines: $(python3 - <<'PY'
import pathlib
p=pathlib.Path('.github/workflows/tbtc-signer-formal.yml')
print(len(p.read_text().splitlines()))
PY)"

echo
echo "=== uses: occurrences ==="
rg -n "uses:" .github/workflows/tbtc-signer-formal.yml || true

echo
echo "=== persist-credentials occurrences ==="
rg -n "persist-credentials" .github/workflows/tbtc-signer-formal.yml || true

Repository: threshold-network/keep-core

Length of output: 424


Pin GitHub Actions to commit SHAs and harden checkout credentials.

  • actions/checkout@v4 (lines 26, 44) -> actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5; also add with: persist-credentials: false to both checkout steps.
  • dtolnay/rust-toolchain@stable (line 29) -> dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8.
  • actions/setup-java@v4 (line 47) -> actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9.
🧰 Tools
🪛 zizmor (1.25.2)

[warning] 25-26: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)


[error] 26-26: unpinned action reference (unpinned-uses): action is not pinned to a hash (required by blanket policy)

(unpinned-uses)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/tbtc-signer-formal.yml at line 26, Update the GitHub
Actions workflow to pin action versions and harden checkout credentials: replace
occurrences of actions/checkout@v4 with
actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 and add with:
persist-credentials: false to both checkout steps that use checkout, replace
dtolnay/rust-toolchain@stable with
dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8, and replace
actions/setup-java@v4 with
actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 so the workflow pins
SHA-based commits and disables persisting credentials on checkout.


- name: Setup Rust
uses: dtolnay/rust-toolchain@stable

- name: Run signer formal invariant tests
# Filters cargo test by the formal_verification_ prefix so only
# the formal-invariant test cases run (faster + clearer signal
# than the full suite). Matches the convention used in the
# source monorepo's ci-formal-verification.yml.
run: cargo test --manifest-path pkg/tbtc/signer/Cargo.toml formal_verification_

tla-model-checks:
name: TLA model checks
runs-on: ubuntu-latest
timeout-minutes: 20
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Java
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: "17"

- name: Run TLA model checks
# Iterates over every .cfg under pkg/tbtc/signer/docs/formal/models/
# and runs TLC against the matching .tla module. MODELS_PATH defaults
# to the canonical signer-relative path; override via env var for
# alternate environments (set in extraction/frost-signer-mirror PR).
run: pkg/tbtc/signer/scripts/formal/run_tla_models.sh
1 change: 1 addition & 0 deletions pkg/tbtc/signer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target/
Loading
Loading