Skip to content

Commit a9dbdad

Browse files
chore: make extra signers auditable in dlog metadata
In both IssueMetadata and TransferMetadata, the ExtraSigners field was typed as []Identity. This created an auditability gap - any third party with access to the metadata could not resolve or audit these identities, unlike Issuer, Senders, and Receivers which already carry full AuditableIdentity (identity + audit info). - Change ExtraSigners to []*AuditableIdentity in both IssueMetadata and TransferMetadata - Add V3 metadata proto types (IssueMetadataV3, TransferMetadataV3) with AuditableIdentity for ExtraSigners and Issuer - Add ProtocolV3 constant and backward-compatible FromProtos/ToProtos - Add SetMinProtocolVersion to Validator interface for protocol enforcement - Add regression tests for V1/V2/V3 metadata serialization - Fix lint errors: remove wastedassign, fix import grouping, fix integer conversion in getVersion() Closes #993 Signed-off-by: SurbhiAgarwal1 <agarwalsurbhi1807@gmail.com>
1 parent 3e90aa3 commit a9dbdad

237 files changed

Lines changed: 14913 additions & 4089 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/tests.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,3 +206,32 @@ jobs:
206206
- name: Compile benchmarks (do not run)
207207
run: go test ./... -run=^$ -bench=^$
208208

209+
# Guard: the tokengen / artifactgen binaries must build without cgo so
210+
# they can be distributed in scratch / alpine images and on hosts
211+
# without a C toolchain. See #1445.
212+
cgo-check:
213+
runs-on: ubuntu-latest
214+
215+
steps:
216+
- name: Checkout code
217+
uses: actions/checkout@v4
218+
219+
- name: Set up Go
220+
uses: actions/setup-go@v5
221+
with:
222+
go-version-file: "go.mod"
223+
cache-dependency-path: "**/*.sum"
224+
225+
- name: Download dependencies
226+
run: go mod download
227+
228+
- name: Build tokengen without cgo
229+
env:
230+
CGO_ENABLED: "0"
231+
run: go build -o /dev/null ./cmd/tokengen
232+
233+
- name: Build artifactgen without cgo
234+
env:
235+
CGO_ENABLED: "0"
236+
run: go build -o /dev/null ./cmd/artifactgen
237+

MAINTAINERS.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ Maintainers
88
| Angelo De Caro | [adecaro][adecaro] | adecaro | <adc@zurich.ibm.com> |
99
| Kaoutar Elkhiyaoui | [KElkhiyaoui][KElkhiyaoui] | KElkhiyaoui | <kao@zurich.ibm.com> |
1010
| Arne Rutjes | [arner][arner] | arner | <arne.rutjesISC@nl.ibm.com> |
11-
| Alexandros Filios | [alexandrosfilios][alexandrosfilios] | lio | <alexandros.filios@ibm.com> |
11+
| Alexandros Filios | [alexandrosfilios][alexandrosfilios] | lio | <alexandros.filios@alumni.ethz.ch> |
12+
| Akram Bitar | [AkramBitar][AkramBitar] | akrambitar | <akram@il.ibm.com> |
1213

1314
**Emeritus Maintainers**
1415

@@ -25,3 +26,4 @@ Maintainers
2526
[ale-linux]: https://github.com/ale-linux
2627
[arner]: https://github.com/arner
2728
[alexandrosfilios]: https://github.com/alexandrosfilios
29+
[AkramBitar]: https://github.com/AkramBitar

Makefile

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,14 @@ clean-fabric-peer-images:
156156
docker images -a | grep "_peer_" | awk '{print $3}' | xargs docker rmi
157157

158158
.PHONY: tokengen
159-
# install tokengen tool
159+
# install tokengen tool (must build without cgo; see #1445)
160160
tokengen:
161-
@go install ./cmd/tokengen
161+
@CGO_ENABLED=0 go install ./cmd/tokengen
162+
163+
.PHONY: artifactgen
164+
# install artifactgen tool (must build without cgo; see #1445)
165+
artifactgen:
166+
@CGO_ENABLED=0 go install ./cmd/artifactgen
162167

163168
.PHONY: traceinspector
164169
# install traceinspector tool

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Fabric Token SDK
22
[![License](https://img.shields.io/badge/license-Apache%202-blue)](LICENSE)
33
[![Go Report Card](https://goreportcard.com/badge/github.com/hyperledger-labs/fabric-token-sdk)](https://goreportcard.com/badge/github.com/hyperledger-labs/fabric-token-sdk)
4-
[![Go](https://github.com/hyperledger-labs/fabric-token-sdk/actions/workflows/tests.yml/badge.svg)](https://github.com/hyperledger-labs/fabric-token-sdk/actions/workflows/go.yml)
5-
[![CodeQL](https://github.com/hyperledger-labs/fabric-token-sdk/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/hyperledger-labs/fabric-token-sdk/actions/workflows/codeql-analysis.yml)
4+
[![Tests](https://github.com/hyperledger-labs/fabric-token-sdk/actions/workflows/tests.yml/badge.svg?branch=main)](https://github.com/hyperledger-labs/fabric-token-sdk/actions/workflows/tests.yml)
5+
[![CodeQL](https://github.com/hyperledger-labs/fabric-token-sdk/actions/workflows/codeql-analysis.yml/badge.svg?branch=main)](https://github.com/hyperledger-labs/fabric-token-sdk/actions/workflows/codeql-analysis.yml)
66
[![Coverage Status](https://coveralls.io/repos/github/hyperledger-labs/fabric-token-sdk/badge.svg?branch=main)](https://coveralls.io/github/hyperledger-labs/fabric-token-sdk?branch=main)
77

88
The `Fabric Token SDK` provides a collection of APIs and services that streamline development for token-based distributed applications.
@@ -15,7 +15,7 @@ The project will be subject to rapid changes to complete the open-sourcing proce
1515
# Useful Links
1616

1717
- [`Documentation`](docs/README.md): The entry point for the Fabric Token SDK documentation.
18-
- [`Code Wiki`](https://codewiki.google/repo/hyperledger-labs/fabric-token-sdk): AI-powered documentation, architecture overviews, and interactive exploration of the Fabric Token-SDK codebase.
18+
- [`Code Wiki`](https://codewiki.google/github.com/hyperledger-labs/fabric-token-sdk): AI-powered documentation, architecture overviews, and interactive exploration of the Fabric Token SDK codebase.
1919
- [`Development`](docs/development/development.md): All about the development guidelines.
2020
- [`Contributing`](CONTRIBUTING.md): How to contribute to the project.
2121
- [`Fabric Samples`](https://github.com/hyperledger/fabric-samples/tree/main/token-sdk) Token SDK sample application is the

ci/scripts/contributors.sh

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
#!/usr/bin/env bash
2+
# fetch_contributors.sh — Run from inside your token-sdk folder
3+
4+
set -euo pipefail
5+
6+
REPO=$(gh repo view --json nameWithOwner -q .nameWithOwner)
7+
8+
echo "📦 Contributors for: $REPO"
9+
echo ""
10+
echo "| Name (@username) | Company | Location | Email | Twitter | Followers | Public Repos | Commits |"
11+
echo "|------------------|---------|----------|-------|---------|-----------|--------------|---------|"
12+
13+
# Step 1: Get contributor stats (additions, deletions, commits per week)
14+
STATS=$(gh api --cache 1h "/repos/$REPO/stats/contributors")
15+
16+
# Step 2: Get paginated contributor list and enrich each with user profile
17+
# Using process substitution to avoid subshell issues with variable scope
18+
CONTRIBUTOR_LOGINS=()
19+
COUNT=0
20+
21+
while read -r LOGIN; do
22+
CONTRIBUTOR_LOGINS+=("$LOGIN")
23+
((COUNT++))
24+
25+
# Fetch full user profile
26+
USER=$(gh api "/users/$LOGIN")
27+
28+
# Fetch per-contributor stats from cached stats payload
29+
# Handle case where stats might be empty or not available
30+
if [ "$STATS" != "[]" ] && [ "$STATS" != "{}" ]; then
31+
CONTRIB_STATS=$(echo "$STATS" | jq --arg login "$LOGIN" '
32+
.[] | select(.author.login == $login) | {
33+
commits: ([.weeks[].c] | add // 0),
34+
additions: ([.weeks[].a] | add // 0),
35+
deletions: ([.weeks[].d] | add // 0)
36+
}')
37+
38+
COMMITS=$(echo "$CONTRIB_STATS" | jq -r '.commits // 0')
39+
ADDITIONS=$(echo "$CONTRIB_STATS" | jq -r '.additions // 0')
40+
DELETIONS=$(echo "$CONTRIB_STATS" | jq -r '.deletions // 0')
41+
else
42+
# Fallback: get contributor data from the contributors list and extract contributions count
43+
# We need to get the contributors list again to find this specific user
44+
CONTRIB_DATA=$(gh api --paginate \
45+
-H "Accept: application/vnd.github+json" \
46+
"/repos/$REPO/contributors" \
47+
--jq ".[] | select(.login == \"$LOGIN\")")
48+
49+
COMMITS=$(echo "$CONTRIB_DATA" | jq -r '.contributions // 0')
50+
ADDITIONS="N/A" # These aren't available without stats
51+
DELETIONS="N/A" # These aren't available without stats
52+
fi
53+
54+
# Extract user information
55+
NAME=$(echo "$USER" | jq -r '.name // .login')
56+
COMPANY=$(echo "$USER" | jq -r '.company // "N/A"')
57+
LOCATION=$(echo "$USER" | jq -r '.location // "N/A"')
58+
EMAIL=$(echo "$USER" | jq -r '.email // "N/A"')
59+
TWITTER=$(echo "$USER" | jq -r '.twitter_username // "N/A"')
60+
if [ "$TWITTER" != "N/A" ]; then
61+
TWITTER="@$TWITTER"
62+
fi
63+
FOLLOWERS=$(echo "$USER" | jq -r '.followers')
64+
PUBLIC_REPOS=$(echo "$USER" | jq -r '.public_repos')
65+
66+
# Print main row
67+
echo "| $NAME (@$LOGIN) | $COMPANY | $LOCATION | $EMAIL | $TWITTER | $FOLLOWERS | $PUBLIC_REPOS | $COMMITS |"
68+
69+
# Print social links if available (indented below the row)
70+
BLOG=$(echo "$USER" | jq -r '.blog // empty')
71+
LINKEDIN_URL=""
72+
73+
# Check for LinkedIn in blog field
74+
if [ -n "$BLOG" ] && [ "$BLOG" != "N/A" ]; then
75+
if [[ "$BLOG" == *"linkedin.com"* ]]; then
76+
LINKEDIN_URL="$BLOG"
77+
fi
78+
fi
79+
80+
# Fetch social accounts to find LinkedIn if not found in blog
81+
if [ -z "$LINKEDIN_URL" ]; then
82+
SOCIAL_ACCOUNTS=$(gh api "/users/$LOGIN/social_accounts")
83+
LINKEDIN_URL=$(echo "$SOCIAL_ACCOUNTS" | jq -r '.[] | select(.provider == "linkedin") | .url // empty')
84+
fi
85+
86+
if [ -n "$LINKEDIN_URL" ]; then
87+
echo "| *💼 LinkedIn:* $LINKEDIN_URL | | | | | | | |"
88+
fi
89+
90+
if [ "$TWITTER" != "N/A" ]; then
91+
echo "| *🐦 Twitter:* https://twitter.com/${TWITTER#@} | | | | | | | |"
92+
fi
93+
94+
if [ -n "$BLOG" ] && [ "$BLOG" != "N/A" ] && [ -z "$LINKEDIN_URL" ]; then
95+
echo "| *🌐 Website:* $BLOG | | | | | | | |"
96+
fi
97+
98+
done < <(gh api --paginate \
99+
-H "Accept: application/vnd.github+json" \
100+
"/repos/$REPO/contributors" \
101+
--jq '.[] | select(.login != "dependabot[bot]") | .login')
102+
103+
# Summary section
104+
echo ""
105+
echo "📊 SUMMARY"
106+
echo ""
107+
echo "**Total Contributors:** $COUNT"
108+
109+
# Identify IBM contributors (using already fetched data to avoid extra API calls)
110+
IBM_CONTRIBUTORS=()
111+
for LOGIN in "${CONTRIBUTOR_LOGINS[@]}"; do
112+
# We need to fetch user data to check company/email
113+
USER_DATA=$(gh api "/users/$LOGIN")
114+
COMPANY=$(echo "$USER_DATA" | jq -r '.company // ""')
115+
EMAIL=$(echo "$USER_DATA" | jq -r '.email // ""')
116+
NAME=$(echo "$USER_DATA" | jq -r '.name // .login')
117+
118+
# Check if company, email, or name indicates IBM affiliation
119+
if [[ "$COMPANY" == *"IBM"* ]] || [[ "$COMPANY" == *"ibm"* ]] || [[ "$EMAIL" == *"ibm.com"* ]] || [[ "$EMAIL" == *"zurich.ibm.com"* ]] || [[ "$NAME" == *"IBM"* ]] || [[ "$NAME" == *"ibm"* ]]; then
120+
IBM_CONTRIBUTORS+=("$NAME (@$LOGIN)")
121+
fi
122+
done
123+
124+
IBM_COUNT=${#IBM_CONTRIBUTORS[@]}
125+
echo "**IBM Contributors:** $IBM_COUNT"
126+
127+
if [ $IBM_COUNT -gt 0 ]; then
128+
echo ""
129+
echo "**IBM Contributor List:**"
130+
for contributor in "${IBM_CONTRIBUTORS[@]}"; do
131+
echo "- $contributor"
132+
done
133+
fi
134+
135+
echo ""
136+
echo "✅ Done"

ci/scripts/extract_signoffs.sh

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#!/bin/bash
2+
3+
# Target the repository path (defaults to the current directory if not provided)
4+
REPO_PATH="${1:-.}"
5+
6+
# Verify if the target directory is a valid git repository
7+
if ! git -C "$REPO_PATH" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
8+
echo "Error: '$REPO_PATH' is not a valid git repository."
9+
exit 1
10+
fi
11+
12+
echo "Extracting deduplicated Signed-off-by emails with counts from: $REPO_PATH"
13+
echo "------------------------------------------------------------"
14+
15+
# Fetch logs, filter sign-offs, extract emails, count duplicates, and sort by count descending
16+
git -C "$REPO_PATH" log | \
17+
grep -i "^[[:space:]]*Signed-off-by:" | \
18+
sed -n 's/.*<\([^>]*\)>.*/\1/p' | \
19+
sort | \
20+
uniq -c | \
21+
sort -nr

ci/scripts/generate-repo-stats.sh

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
#!/bin/bash
2+
3+
REPO="hyperledger-labs/fabric-token-sdk"
4+
API_URL="https://api.github.com/repos/$REPO"
5+
SEARCH_API_URL="https://api.github.com/search/issues"
6+
7+
# Require jq and gh for JSON parsing and GitHub API
8+
if ! command -v jq &> /dev/null; then
9+
echo "Error: jq is required but not installed. Please install it (e.g., brew install jq or apt install jq)." >&2
10+
exit 1
11+
fi
12+
13+
if ! command -v gh &> /dev/null; then
14+
echo "Error: gh (GitHub CLI) is required but not installed. Please install it (e.g., brew install gh)." >&2
15+
exit 1
16+
fi
17+
18+
# Function to format numbers with commas (Cross-platform pure bash)
19+
format_num() {
20+
local num=$1
21+
while [[ $num =~ ^([0-9]+)([0-9]{3})(.*)$ ]]; do
22+
num="${BASH_REMATCH[1]},${BASH_REMATCH[2]}${BASH_REMATCH[3]}"
23+
done
24+
echo "$num"
25+
}
26+
27+
# Helper to call GitHub API using gh (handles authentication automatically)
28+
call_api() {
29+
local endpoint="$1"
30+
gh api "$endpoint" --jq '.'
31+
}
32+
33+
# Helper to fetch total counts using the paginated Link header
34+
get_paginated_count() {
35+
local endpoint="$1"
36+
37+
# Fetch headers only using gh
38+
local header_file=$(mktemp)
39+
gh api "$endpoint" -i > "$header_file" 2>/dev/null
40+
41+
local link_header=$(grep -i '^link:' "$header_file")
42+
if [[ -n "$link_header" ]]; then
43+
# Extract the exact page number from the 'last' rel link
44+
grep -i '^link:' "$header_file" | sed -E 's/.*<([^>]+)>; rel="last".*/\1/' | sed -E 's/.*page=([0-9]+).*/\1/'
45+
else
46+
# Fallback to counting the JSON array length if there is only 1 page
47+
local items=$(call_api "$endpoint" | jq -r 'length // 0')
48+
echo "$items"
49+
fi
50+
rm -f "$header_file"
51+
}
52+
53+
# Helper to get issues/PRs counts from Search API
54+
get_search_count() {
55+
local query="$1"
56+
gh api "$SEARCH_API_URL?q=repo:$REPO+$query" --jq '.total_count // 0'
57+
}
58+
59+
echo "Fetching repository metrics..." >&2
60+
REPO_DATA=$(call_api "$API_URL")
61+
62+
# 1. Repository Metrics
63+
REPO_URL=$(echo "$REPO_DATA" | jq -r '.html_url // ""')
64+
LANGUAGE=$(echo "$REPO_DATA" | jq -r '.language // "Unknown"')
65+
LICENSE=$(echo "$REPO_DATA" | jq -r '.license.name // "None"')
66+
STARS=$(echo "$REPO_DATA" | jq -r '.stargazers_count // 0')
67+
FORKS=$(echo "$REPO_DATA" | jq -r '.forks_count // 0')
68+
WATCHERS=$(echo "$REPO_DATA" | jq -r '.subscribers_count // 0')
69+
DEFAULT_BRANCH=$(echo "$REPO_DATA" | jq -r '.default_branch // "main"')
70+
71+
echo "Fetching contributors count..." >&2
72+
CONTRIBUTORS=$(get_paginated_count "$API_URL/contributors?per_page=1&anon=true")
73+
74+
# 2. Community Standards Compliance
75+
echo "Checking community standards..." >&2
76+
check_file() {
77+
local file=$1
78+
local status=$(curl -s -o /dev/null -w "%{http_code}" "https://raw.githubusercontent.com/$REPO/$DEFAULT_BRANCH/$file")
79+
if [[ "$status" == "200" ]]; then
80+
# Output status with a Markdown link to the file on GitHub
81+
echo "✅ [Complete](https://github.com/$REPO/blob/$DEFAULT_BRANCH/$file)"
82+
else
83+
echo "❌ Missing"
84+
fi
85+
}
86+
87+
README_STATUS=$(check_file "README.md")
88+
CONTRIBUTING_STATUS=$(check_file "CONTRIBUTING.md")
89+
CODE_OF_CONDUCT_STATUS=$(check_file "CODE_OF_CONDUCT.md")
90+
LICENSE_STATUS=$(check_file "LICENSE")
91+
SECURITY_STATUS=$(check_file "SECURITY.md")
92+
93+
# 3. Development Activity
94+
echo "Fetching development activity metrics..." >&2
95+
96+
# Cross-platform date parsing (macOS/BSD vs GNU Linux)
97+
if date --version >/dev/null 2>&1; then
98+
SINCE_DATE=$(date -d "30 days ago" -u +"%Y-%m-%dT%H:%M:%SZ")
99+
else
100+
SINCE_DATE=$(date -v-30d -u +"%Y-%m-%dT%H:%M:%SZ")
101+
fi
102+
103+
COMMITS_30D=$(get_paginated_count "$API_URL/commits?since=$SINCE_DATE&per_page=1")
104+
OPEN_ISSUES=$(get_search_count "type:issue+state:open")
105+
CLOSED_ISSUES=$(get_search_count "type:issue+state:closed")
106+
OPEN_PRS=$(get_search_count "type:pr+state:open")
107+
CLOSED_PRS=$(get_search_count "type:pr+state:closed")
108+
109+
# Get current date for the header
110+
CURRENT_DATE=$(date +"%B %d, %Y at %H:%M %Z")
111+
112+
# Output Final Markdown
113+
echo ""
114+
cat <<EOF
115+
## Project Statistics
116+
117+
The following metrics demonstrate the project's maturity, active development, and community engagement ($CURRENT_DATE):
118+
119+
### Repository Metrics
120+
121+
| Metric | Value |
122+
|--------|-------|
123+
| **Repository** | [github.com/$REPO]($REPO_URL) |
124+
| **Primary Language** | $LANGUAGE |
125+
| **License** | $LICENSE |
126+
| **Stars** | $(format_num "$STARS") |
127+
| **Forks** | $(format_num "$FORKS") |
128+
| **Watchers** | $(format_num "$WATCHERS") |
129+
| **Total Contributors** | $(format_num "$CONTRIBUTORS") |
130+
131+
### Community Standards Compliance
132+
| Standard | Status |
133+
|----------|--------|
134+
| README | $README_STATUS |
135+
| CONTRIBUTING | $CONTRIBUTING_STATUS |
136+
| CODE_OF_CONDUCT | $CODE_OF_CONDUCT_STATUS |
137+
| LICENSE | $LICENSE_STATUS |
138+
| SECURITY Policy | $SECURITY_STATUS |
139+
140+
### Development Activity
141+
| Metric | Count |
142+
|--------|-------|
143+
| **Commits (Last 30 Days)** | $(format_num "$COMMITS_30D") |
144+
| **Open Issues** | $(format_num "$OPEN_ISSUES") |
145+
| **Closed Issues** | $(format_num "$CLOSED_ISSUES") |
146+
| **Open Pull Requests** | $(format_num "$OPEN_PRS") |
147+
| **Closed Pull Requests** | $(format_num "$CLOSED_PRS") |
148+
EOF

0 commit comments

Comments
 (0)