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 → Bitcoin: Commit hash tweaks the pubkey via BIP-341 TapTweak, recorded on-chain
- Bitcoin → Git: TXO URI in repository points to the UTXO
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:
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:
tagged_hash(tag, msg) = sha256(sha256(tag) || sha256(tag) || msg)x_only(P)extracts the 32-byte x-coordinatecommit_hashis the 20-byte git commit hash (padded or used as-is)nis the secp256k1 curve order
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>]
| Field | Type | Description |
|---|---|---|
| network | string | Bitcoin network (mainnet, tbtc4, signet) |
| txid | hex64 | Transaction ID (64 hex characters) |
| vout | integer | Output index |
| amount | integer | Value in satoshis |
| pubkey | hex64 | X-only pubkey (64 hex characters) |
| commit | hex40 | Git 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
4.2 Making a Transition
- Create git commit with state changes
- Compute new pubkey:
P_new = P_current + scalar(P_current, commit) × G - Spend current UTXO to new pubkey
- Append new TXO URI to
txo.json - 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:
- Genesis: First TXO pubkey =
P_base + scalar(P_base, genesis_commit) × G - Continuity: Each subsequent
pubkey = prev_pubkey + scalar(prev_pubkey, commit) × G - On-chain: Each UTXO exists (or existed) on Bitcoin
- 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:
- Marked commits SHOULD be in ancestral order (each marked commit is a descendant of the previous)
- The TXO chain records the order commits were marked
- Verifiers SHOULD confirm referenced commits exist in the repository
- Verifiers MAY check that commits form a valid ancestral chain in git
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
| Aspect | Git-mark | Monochrome |
|---|---|---|
| Tweak derivation | BIP-341 TapTweak with commit hash | BIP-341 TapTweak with sha256(JCS(state)) |
| State storage | Git tree objects | JSON state array |
| State format | Any git content | Structured JSON with ops |
| Linking | TXO URI in txo.json | State contains prev hash |
| Use case | Repository anchoring | Application 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
- Hash preimage resistance → commit binding
- Discrete log hardness → pubkey security
- Bitcoin consensus → spend ordering
8.2 Git-mark Specific
| Threat | Mitigation |
|---|---|
| Commit rewriting | Git's content-addressing; verifiers check commit exists |
| History divergence | TXO chain anchors specific commit sequence |
| UTXO availability | Bitcoin full node or SPV verification |
| txo.json tampering | Verify pubkey derivation matches recorded commits |
8.3 Trust Model
- Bitcoin: UTXO existence and spend ordering
- Git: Commit immutability (content-addressed)
- Client: Must verify EC_ADD chain and commit existence
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
- Blocktrails Core Specification
- Blocktrails Profiles
- Legacy gitmark
- BIP-340: Schnorr Signatures
- BIP-341: Taproot