Lektion 3 / 6 · 25 Minuten
Proof of Existence programmatisch
In der Foundation-Lektion ging es darum, was ein Existenznachweis beweist. Jetzt bauen wir ihn in eigene Software ein.
Der Ablauf
- Hash lokal berechnen. Das Dokument verlässt nie den eigenen Rechner.
- Verankern mit
POST /v1/poeund einem Schlüssel der Stufepoeoderwrite. - Auf die Bestätigung warten, im Mittel zehn Minuten, bei Blockpausen auch länger.
- Prüfen mit
GET /v1/poe/{hash}, ohne Schlüssel.
import hashlib, requests
API, KEY = "https://doi-api.sendlabs.de/v1", "<poe-schluessel>"
h = hashlib.sha256(open("vertrag.pdf", "rb").read()).hexdigest()
r = requests.post(f"{API}/poe", json={"hash": h, "note": "meine-app:v1"},
headers={"X-API-Key": KEY}, timeout=30)
print(r.status_code, r.json()) # 201 mit txid und status "pending"
# später
st = requests.get(f"{API}/poe/{h}", timeout=10).json()
if st["status"] in ("confirmed", "expired"):
print("verankert seit", st["first_anchored"]["block_time_iso"])
else:
print("Status:", st["status"]) # unknown oder pending, first_anchored fehlt dann
Große Dateien in Blöcken einlesen (hashlib.sha256().update(...)), statt sie ganz in den Speicher zu laden.
Felder beim Anlegen
| Feld | Bedeutung |
|---|---|
hash |
SHA-256, 64 Hex-Zeichen, Pflicht |
filename |
optional, höchstens 80 Zeichen, öffentlich auf der Kette |
note |
optional, höchstens 160 Zeichen, öffentlich auf der Kette |
reanchor |
nur für abgelaufene Hashes, Standard false |
Notiz und Dateiname nie mit personenbezogenen Daten füllen. Eine kurze maschinenlesbare Kennung wie meine-app:v1 reicht.
Antworten beim Anlegen
| Code | Bedeutung |
|---|---|
| 201 | angenommen, status: pending, die Transaktion liegt im Mempool |
| 400 | Hash ungültig, etwa nicht 64 Hex-Zeichen |
| 402 | das Node-Wallet hat nicht genug Guthaben, später erneut versuchen |
| 409 | Hash ist bereits aktiv verankert, wartet schon im Mempool oder ist abgelaufen |
| 429 | Kontingent oder Ratenbegrenzung erreicht |
Ein 409 ist bei einem schon verankerten Hash kein Fehler im Sinne der Anwendung: Der Nachweis existiert bereits. Die Anwendung übernimmt dann einfach den Status aus GET /v1/poe/{hash}.
Status beim Prüfen
status |
Bedeutung |
|---|---|
unknown |
nie registriert |
pending |
wartet im Mempool |
confirmed |
aktiv in der Kette |
expired |
Name abgelaufen, der Nachweis bleibt in der Historie gültig |
Maßgeblich für Dritte ist immer first_anchored: Block, Blockzeit und Transaktion der ersten Verankerung. Läuft ein Name ab und registriert ihn jemand neu, gehören Notiz und Inhaber auf oberster Ebene zu dieser späteren Registrierung. first_anchored verweist weiter auf den ursprünglichen Nachweis.
reanchor: true erzeugt für einen abgelaufenen Hash bewusst eine zusätzliche, spätere Registrierung. Sie verbessert den ursprünglichen Nachweis nicht.
Strukturierte Daten verankern
Oft soll kein Dokument, sondern ein Datensatz bewiesen werden, etwa ein Messwert oder ein Zertifikat. Dann gilt:
- Kanonisch serialisieren. Gleiche Daten müssen immer dieselben Bytes ergeben, sonst passt der Hash später nicht. Bei JSON zum Beispiel: Schlüssel sortieren, feste Trennzeichen, UTF-8.
- Zufallswert beimischen, wenn der Datensatz erratbar ist, damit niemand ihn durch Ausprobieren aus dem Hash zurückgewinnen kann.
- Original aufbewahren. Ohne die exakten Bytes lässt sich der Nachweis nicht mehr führen.
So arbeitet auch diese Academy: Jedes Zertifikat ist ein kanonisches JSON mit Zufallswert nonce. Sein SHA-256 steht als poe/<hash> in der Doichain.
import json
raw = json.dumps(daten, sort_keys=True, separators=(",", ":"), ensure_ascii=False).encode("utf-8")
h = hashlib.sha256(raw).hexdigest()
Merksätze
- Hash lokal berechnen, nie das Dokument verschicken.
- 201 heißt angenommen, endgültig erst nach der Bestätigung.
- Für Dritte zählt
first_anchored. - Strukturierte Daten kanonisch serialisieren und bei Bedarf salzen.
Bitte anmelden, um den Fortschritt zu speichern und die Prüfung abzulegen. Registrieren
Weiter →