Extend CI action to enforce encodable fuzzing
What changed, and why it matters
This commit only changes a CI (continuous integration) shell script that checks whether all types implementing a certain encoding trait are covered by fuzz tests. It adds a second check for roundtrip fuzz targets and updates comments and variable names. There is no change to the actual Bitcoin library code, cryptography, network handling, or any user-facing behavior. It is purely a testing/quality-assurance improvement.
No security action required. This is a benign CI tooling change. Normal code review and merge procedures apply.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff modifies contrib/check-encodable-coverage.sh to extend an existing coverage check. Previously the script verified that all types implementing encoding::Encodable appear in fuzz/fuzz_targets/bitcoin/compare_consensus_encoding.rs. Now it also verifies coverage against fuzz/generate-encoding-roundtrip.sh. The script logic is refactored to run two checks with separate exclusion lists and aggregate failure status. No Rust source code, no consensus logic, no serialization/deserialization implementation, and no API surface are changed.
Changed components
contrib/check-encodable-coverage.shInspect captured patch +55 / −15
diff --git a/contrib/check-encodable-coverage.sh b/contrib/check-encodable-coverage.sh
index fa35260f..ee46963f 100755
--- a/contrib/check-encodable-coverage.sh
+++ b/contrib/check-encodable-coverage.sh
@@ -1,15 +1,18 @@
#!/usr/bin/env bash
#
# Check that all types implementing encoding::Encodable are covered in the fuzz
-# test that compares encoding between old and new bitcoin crates.
+# tests:
+# 1. compare_consensus_encoding.rs - compares encoding between old and new bitcoin crates.
+# 2. fuzz/generate-encoding-roundtrip.sh - generates per-type roundtrip fuzz targets.
set -euo pipefail
REPO_DIR=$(git rev-parse --show-toplevel)
-FUZZ_FILE="$REPO_DIR/fuzz/fuzz_targets/bitcoin/compare_consensus_encoding.rs"
+COMPARE_FUZZ_FILE="$REPO_DIR/fuzz/fuzz_targets/bitcoin/compare_consensus_encoding.rs"
+ROUNDTRIP_FUZZ_SCRIPT="$REPO_DIR/fuzz/generate-encoding-roundtrip.sh"
TRAIT_IMPL_JS="$REPO_DIR/target/doc/trait.impl/bitcoin_consensus_encoding/encode/trait.Encode.js"
-# Known exclusions (types that don't exist in old_bitcoin 0.32 or are generic).
+# Known exclusions for compare_consensus_encoding (types that don't exist in old_bitcoin 0.32 or are generic).
# Add types here that have new Encodable but no old_bitcoin equivalent.
# - CommandString has very different decoding functionality in new bitcoin.
# - HeadersMessage has no type in 0.32 bitcoin. Vec<(Header, u8)> is not Decodable.
@@ -23,20 +26,45 @@ main() {
generate_docs
check_trait_impl_file
- local new_types fuzz_types missing
+ local new_types
new_types=$(extract_new_types)
- fuzz_types=$(extract_fuzz_types)
- missing=$(find_missing_types "$new_types" "$fuzz_types")
- if [ -n "$missing" ]; then
- echo "The following types implement encoding::Encode but are not in the fuzz test:" >&2
- for type in $missing; do
+ local failed=0
+
+ # Check compare_consensus_encoding.rs (with exclusions)
+ local compare_types compare_missing
+ compare_types=$(extract_compare_fuzz_types)
+ compare_missing=$(find_missing_types "$new_types" "$compare_types" "$EXCLUSIONS")
+
+ if [ -n "$compare_missing" ]; then
+ echo "The following types implement encoding::Encode but are not in compare_consensus_encoding.rs:" >&2
+ for type in $compare_missing; do
+ echo " - $type" >&2
+ done
+ echo "Either add them to compare_consensus_encoding.rs or add to EXCLUSIONS in this script" >&2
+ failed=1
+ fi
+
+ # Check generate-encoding-roundtrip.sh
+ local roundtrip_types roundtrip_missing exclusions
+ exclusions="Script Validation NetworkMessage V2NetworkMessage"
+ roundtrip_types=$(extract_roundtrip_fuzz_types)
+ roundtrip_missing=$(find_missing_types "$new_types" "$roundtrip_types" "$exclusions")
+
+ if [ -n "$roundtrip_missing" ]; then
+ echo "The following types implement encoding::Encode but are not in fuzz/generate-encoding-roundtrip.sh:" >&2
+ for type in $roundtrip_missing; do
echo " - $type" >&2
done
- err "Either add them to compare_consensus_encoding.rs or add to EXCLUSIONS in this script"
+ echo "Add them to ROUNDTRIP_TYPES or SCRIPT_ROUNDTRIP_TYPES in fuzz/generate-encoding-roundtrip.sh" >&2
+ failed=1
fi
- echo "All encoding::Encode types are covered (or excluded)"
+ if [ "$failed" -ne 0 ]; then
+ exit 1
+ fi
+
+ echo "All encoding::Encode types are covered"
}
generate_docs() {
@@ -60,9 +88,9 @@ extract_new_types() {
| sort -u
}
-# Extract types from the fuzz test file.
-extract_fuzz_types() {
- grep -E 'compare_encoding!' "$FUZZ_FILE" \
+# Extract types from compare_consensus_encoding.rs.
+extract_compare_fuzz_types() {
+ grep -E 'compare_encoding!' "$COMPARE_FUZZ_FILE" \
| grep -v '//' \
| sed -E 's/.*compare_encoding!\s*\(\s*data\s*,\s*//' \
| sed -E 's/\s*\);.*//' \
@@ -72,15 +100,27 @@ extract_fuzz_types() {
| sort -u
}
+# Extract types from generate-encoding-roundtrip.sh.
+# Types are listed as quoted Rust paths in the ROUNDTRIP_TYPES and SCRIPT_ROUNDTRIP_TYPES arrays,
+# e.g. "bitcoin::block::Header" or "p2p::Magic". Extract the last path component (the type name).
+extract_roundtrip_fuzz_types() {
+ grep -E '^\s+"[a-z]' "$ROUNDTRIP_FUZZ_SCRIPT" \
+ | sed -E 's/.*"([^"]+)".*/\1/' \
+ | sed -E 's/.*:://' \
+ | grep -E '^[A-Z]' \
+ | sort -u
+}
+
# Find types that are in new_types but not in fuzz_types or exclusions.
find_missing_types() {
local new_types=$1
local fuzz_types=$2
+ local exclusions=$3
local missing=""
for type in $new_types; do
if ! echo "$fuzz_types" | grep -qw "$type"; then
- if ! echo "$EXCLUSIONS" | grep -qw "$type"; then
+ if [ -z "$exclusions" ] || ! echo "$exclusions" | grep -qw "$type"; then
missing="$missing $type"
fi
fi
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.