← Blocktrails Profiles

Git-mark Profile (v0.2)

Git commits anchored to Bitcoin via Blocktrails output-key commitments.

Abstract

Git-mark binds Bitcoin UTXOs to Git commits using BIP-341 TapTweak derivation. Each commit hash is combined with the current pubkey to derive a new pubkey, creating a cryptographic chain linking repository history to Bitcoin.

1. Introduction

Git-mark creates a two-way binding between Git and Bitcoin:

Git-mark uses Git commit hashes as the state data, combined with BIP-341 tagged hashes for pubkey-dependent derivation.

2. Cryptographic Model

2.1 Chained Key Derivation

Git-mark follows the Blocktrails v0.2 chained derivation model with BIP-341 pubkey-dependent tweaks:

Genesis: P₀ = P_base + scalar(P_base, commit₀) × G (tweaked by genesis commit) Commit 1: P₁ = P₀ + scalar(P₀, commit₁) × G (tweaked by first commit) Commit 2: P₂ = P₁ + scalar(P₁, commit₂) × G (tweaked by second commit) ... Commit n: Pₙ = Pₙ₋₁ + scalar(Pₙ₋₁, commitₙ) × G

Note: Each tweak depends on the current pubkey, not just the commit hash. The same commit at different positions produces different tweaks.

2.2 Scalar Function (BIP-341 TapTweak)

Git-mark uses the BIP-341 TapTweak derivation with the git commit hash as data:

scalar(P, commit):
  t = tagged_hash("TapTweak", x_only(P) || commit_hash)
  return int(t, big-endian) mod n

Where:

If scalar(P, commit) = 0, the commit MUST be rejected (probability ~2-256).

2.3 Private Key Derivation

The spending key for any state, where each tweak tᵢ = scalar(Pᵢ₋₁, commitᵢ):

d_n = d₀ + t₀ + t₁ + ... + tₙ  (mod n)

where t₀ = scalar(P_base, commit₀), t₁ = scalar(P₀, commit₁), etc.

3. TXO URI Format

Git-mark uses TXO URIs to record the on-chain state:

txo:<network>:<txid>:<vout>?amount=<sats>&pubkey=<hex>[&commit=<git_hash>]
FieldTypeDescription
networkstringBitcoin network (mainnet, tbtc4, signet)
txidhex64Transaction ID (64 hex characters)
voutintegerOutput index
amountintegerValue in satoshis
pubkeyhex64X-only pubkey (64 hex characters)
commithex40Git commit hash (absent for genesis)

3.1 Genesis TXO

The genesis TXO has no commit parameter. Its pubkey is the base pubkey P₀:

txo:tbtc4:34cea31b...e854be0e:0?amount=1000000&pubkey=3e458cc6...a5c8cf

3.2 Subsequent TXOs

Each subsequent TXO includes the commit that tweaked to this pubkey:

txo:tbtc4:45fbcbd7...81a9f7d:0?amount=999000&pubkey=b5bc388c...5266c&commit=cf97baba...83d17d

4. State Transitions

4.1 Transition Flow

┌─────────────┐ │ Git Commit │ │ (state Δ) │ └──────┬──────┘ │ hash ▼ ┌──────────┐ tweak ┌──────────┐ │ P_old │────────────→│ P_new │ │ (UTXO₁) │ │ (UTXO₂) │ └──────────┘ └──────────┘ │ │ │ spend │ new output ▼ ▼ ┌────────────────────────────────────┐ │ Bitcoin Transaction │ └────────────────────────────────────┘

4.2 Making a Transition

  1. Create git commit with state changes
  2. Compute new pubkey: P_new = P_current + scalar(P_current, commit) × G
  3. Spend current UTXO to new pubkey
  4. Append new TXO URI to txo.json
  5. Push to git remote

5. Directory Structure

Git-mark state is stored in the repository:

.well-known/
└── txo/
    └── txo.json      # Array of TXO URIs

5.1 txo.json Format

Simple JSON array of TXO URI strings:

[
  "txo:tbtc4:<txid>:0?amount=1000000&pubkey=<genesis_pubkey>",
  "txo:tbtc4:<txid>:0?amount=999000&pubkey=<pubkey>&commit=<hash>",
  "txo:tbtc4:<txid>:0?amount=998000&pubkey=<pubkey>&commit=<hash>"
]

6. Verification

6.1 Chain Validity

A git-mark chain is valid if:

  1. Genesis: First TXO pubkey = P_base + scalar(P_base, genesis_commit) × G
  2. Continuity: Each subsequent pubkey = prev_pubkey + scalar(prev_pubkey, commit) × G
  3. On-chain: Each UTXO exists (or existed) on Bitcoin
  4. Git validity: Commit hashes correspond to actual git commits

6.2 Verification Algorithm

function verify(txoUris):
  txos = parse(txoUris)

  // Genesis check - first TXO is base pubkey (no commit)
  if txos[0].commit != null:
    return { valid: false, error: "genesis has commit" }

  // Try both Y parities (x-only loses parity)
  for prefix in [0x02, 0x03]:
    basePubkey = prefix || txos[0].pubkey
    P = basePubkey

    valid = true
    for i = 1 to txos.length - 1:
      commit = txos[i].commit
      // BIP-341 TapTweak: tweak depends on current pubkey
      t = scalar(P, commit)
      P = P + t × G
      if xonly(P) != txos[i].pubkey:
        valid = false
        break

    if valid:
      return { valid: true }

  return { valid: false, error: "pubkey mismatch" }

6.3 Commit Selection and Ordering

Commits anchored to the TXO chain need not be consecutive in git history. Any commit may be selected for marking. However:

The EC_ADD verification ensures pubkey chain integrity. Git ancestry verification is an additional check that confirms the logical ordering of state transitions.

7. Comparison with Monochrome

AspectGit-markMonochrome
Tweak derivationBIP-341 TapTweak with commit hashBIP-341 TapTweak with sha256(JCS(state))
State storageGit tree objectsJSON state array
State formatAny git contentStructured JSON with ops
LinkingTXO URI in txo.jsonState contains prev hash
Use caseRepository anchoringApplication state machines

Both profiles use BIP-341 TapTweak for pubkey-dependent derivation. Git-mark leverages Git's existing content-addressed storage and commit graph. Monochrome defines its own state schema with explicit operations.

8. Security Considerations

8.1 Inherited from Blocktrails

8.2 Git-mark Specific

ThreatMitigation
Commit rewritingGit's content-addressing; verifiers check commit exists
History divergenceTXO chain anchors specific commit sequence
UTXO availabilityBitcoin full node or SPV verification
txo.json tamperingVerify pubkey derivation matches recorded commits

8.3 Trust Model

9. Implementation

Reference implementation: blocktrails/git-mark

npm install git-seal

git mark init
git mark genesis --txid <txid> --vout 0 --amount 1000000
git commit -m "state change"
git mark advance --txid <txid> --vout 0 --amount 999000
git mark verify

10. References