From 392ee723c3cf626d0e5281aa94771d7133bb345e Mon Sep 17 00:00:00 2001 From: Otto Date: Sat, 7 Mar 2026 16:18:48 +0100 Subject: [PATCH] Initial commit with OTS hook --- README.md | 1 + generate-proof.sh | 102 ++++++++++++++++++++++++++++++++++++++++++++ install-ots-hook.sh | 75 ++++++++++++++++++++++++++++++++ 3 files changed, 178 insertions(+) create mode 100644 README.md create mode 100755 generate-proof.sh create mode 100755 install-ots-hook.sh diff --git a/README.md b/README.md new file mode 100644 index 0000000..8657695 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# Git OpenTimestamp Test diff --git a/generate-proof.sh b/generate-proof.sh new file mode 100755 index 0000000..e1ae44f --- /dev/null +++ b/generate-proof.sh @@ -0,0 +1,102 @@ +#!/bin/bash +# generate-proof.sh - Generate OpenTimestamp proof for a git commit +# Usage: generate-proof.sh [output-file] + +set -e + +COMMIT_HASH="${1:-}" +OUTPUT_FILE="${2:-.ots/proof.ots}" + +if [ -z "$COMMIT_HASH" ]; then + echo "Error: commit hash required" >&2 + echo "Usage: $0 [output-file]" >&2 + exit 1 +fi + +# Ensure .ots directory exists +mkdir -p "$(dirname "$OUTPUT_FILE")" + +# Function to generate proof using ots CLI +generate_with_ots_cli() { + local hash="$1" + local output="$2" + + # Create a temporary file with the hash + local temp_file=$(mktemp) + echo -n "$hash" | xxd -r -p > "$temp_file" + + # Generate timestamp + ots stamp "$temp_file" -o "$output" + + # Cleanup + rm -f "$temp_file" + + echo "Generated proof with ots CLI: $output" +} + +# Function to generate proof using opentimestamps-nodejs +generate_with_node() { + local hash="$1" + local output="$2" + + # Use nodejs opentimestamps library + # This requires @opentimestamps/ots to be installed globally + node -e " +const ots = require('@opentimestamps/ots'); +const fs = require('fs'); +const crypto = require('crypto'); + +const hash = '$hash'; +const output = '$output'; + +// Convert hex hash to buffer +const hashBuffer = Buffer.from(hash, 'hex'); + +// Create timestamp +ots.Timestamp.hash(hashBuffer).then(timestamp => { + // In a real implementation, this would contact the calendar server + // For now, we create a minimal proof structure + console.log('Warning: nodejs fallback creates local proof only'); + console.log('Install ots CLI for full functionality: https://github.com/opentimestamps/opentimestamps-client'); + + // Create a simple proof file (this is a placeholder - real impl needs calendar) + const proof = { + hash: hash, + timestamp: new Date().toISOString(), + status: 'pending' + }; + + fs.writeFileSync(output, JSON.stringify(proof, null, 2)); + console.log('Generated local proof: ' + output); +}).catch(err => { + console.error('Error generating timestamp:', err); + process.exit(1); +}); +" +} + +# Check if ots CLI is available +if command -v ots &> /dev/null; then + echo "Using ots CLI..." + generate_with_ots_cli "$COMMIT_HASH" "$OUTPUT_FILE" +elif command -v node &> /dev/null && node -e "require('@opentimestamps/ots')" &> /dev/null; then + echo "Using opentimestamps-nodejs fallback..." + generate_with_node "$COMMIT_HASH" "$OUTPUT_FILE" +else + echo "Error: Neither ots CLI nor @opentimestamps/ots node package found" >&2 + echo "Install one of:" >&2 + echo " - ots CLI: https://github.com/opentimestamps/opentimestamps-client" >&2 + echo " - Node package: npm install -g @opentimestamps/ots" >&2 + exit 1 +fi + +# Append previous commit hash to the proof file for chaining +if [ -f "$OUTPUT_FILE" ]; then + PREV_COMMIT=$(git rev-parse HEAD^1 2>/dev/null || echo "") + if [ -n "$PREV_COMMIT" ]; then + echo "" >> "$OUTPUT_FILE" + echo "# Previous commit: $PREV_COMMIT" >> "$OUTPUT_FILE" + fi +fi + +echo "Proof generated for commit: $COMMIT_HASH" diff --git a/install-ots-hook.sh b/install-ots-hook.sh new file mode 100755 index 0000000..ff425a5 --- /dev/null +++ b/install-ots-hook.sh @@ -0,0 +1,75 @@ +#!/bin/bash +# install-ots-hook.sh - Install OpenTimestamp post-commit hook +# Usage: install-ots-hook.sh [repository-path] + +set -e + +REPO_PATH="${1:-.}" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +cd "$REPO_PATH" + +# Verify we're in a git repository +if ! git rev-parse --git-dir > /dev/null 2>&1; then + echo "Error: not a git repository" >&2 + exit 1 +fi + +HOOKS_DIR="$(git rev-parse --git-dir)/hooks" +POST_COMMIT_HOOK="$HOOKS_DIR/post-commit" + +echo "Installing OpenTimestamp hook in: $REPO_PATH" + +# Create the post-commit hook +cat > "$POST_COMMIT_HOOK" << 'HOOK_SCRIPT' +#!/bin/bash +# Post-commit hook: generate OpenTimestamp proof for each commit + +set -e + +# Get the commit hash +COMMIT_HASH=$(git rev-parse HEAD) + +# Find the generate-proof.sh script +# Try relative paths first, then check common locations +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +GENERATE_SCRIPT="" + +# Check if generate-proof.sh is in the same directory as this hook +if [ -f "$SCRIPT_DIR/generate-proof.sh" ]; then + GENERATE_SCRIPT="$SCRIPT_DIR/generate-proof.sh" +# Check in .git/hooks directory +elif [ -f ".git/hooks/generate-proof.sh" ]; then + GENERATE_SCRIPT=".git/hooks/generate-proof.sh" +# Check in repository root +elif [ -f "generate-proof.sh" ]; then + GENERATE_SCRIPT="./generate-proof.sh" +# Check if skill is installed globally (common OpenClaw path) +elif [ -f "$HOME/.openclaw/workspace/skills/git-ots-hook/scripts/generate-proof.sh" ]; then + GENERATE_SCRIPT="$HOME/.openclaw/workspace/skills/git-ots-hook/scripts/generate-proof.sh" +else + echo "Warning: generate-proof.sh not found, skipping OpenTimestamp proof" >&2 + exit 0 +fi + +# Make sure the script is executable +chmod +x "$GENERATE_SCRIPT" + +# Generate the proof +echo "[ots] Generating proof for commit: $COMMIT_HASH" +"$GENERATE_SCRIPT" "$COMMIT_HASH" + +echo "[ots] Proof generated successfully" +HOOK_SCRIPT + +# Make the hook executable +chmod +x "$POST_COMMIT_HOOK" + +echo "✓ Post-commit hook installed successfully" +echo "" +echo "Next steps:" +echo "1. Ensure generate-proof.sh is accessible (copy to repo root or install skill globally)" +echo "2. Verify ots CLI or @opentimestamps/ots is installed" +echo "3. Make a test commit to verify the hook works" +echo "" +echo "To uninstall, run: rm $POST_COMMIT_HOOK"