From 45c03acf0c6209fb3c4593ac2034dd26267d9897 Mon Sep 17 00:00:00 2001 From: Buffrr Date: Tue, 7 Apr 2026 23:58:32 +0200 Subject: [PATCH] Update libveritas and include examples --- .github/workflows/snippets.yml | 64 + Cargo.lock | 36 +- fabric/examples/extract-snippets.sh | 65 + fabric/examples/go/go.mod | 13 + fabric/examples/go/main.go | 325 ++ fabric/examples/js/index.mjs | 206 ++ fabric/examples/kotlin/Example.kt | 206 ++ fabric/examples/python/example.py | 198 ++ fabric/examples/rust/Cargo.lock | 2833 +++++++++++++++++ fabric/examples/rust/Cargo.toml | 17 + fabric/examples/rust/src/main.rs | 228 ++ fabric/examples/swift/Example.swift | 213 ++ fabric/examples/test-example.sh | 63 + fabric/go/fabric.go | 9 +- fabric/go/go.mod | 2 +- fabric/go/go.sum | 4 +- fabric/go/libveritas.go | 22 - fabric/js/fabric-react-native/package.json | 2 +- fabric/js/fabric-web/package.json | 2 +- fabric/js/package-lock.json | 16 +- fabric/kotlin/build.gradle.kts | 4 +- .../org/spacesprotocol/fabric/Fabric.kt | 2 +- .../org/spacesprotocol/fabric/Libveritas.kt | 1 + fabric/python/pyproject.toml | 2 +- fabric/rust/src/client.rs | 89 +- fabric/swift/Package.swift | 2 +- fabric/swift/Sources/Fabric/Fabric.swift | 3 +- relay/src/handler.rs | 24 +- 28 files changed, 4547 insertions(+), 104 deletions(-) create mode 100644 .github/workflows/snippets.yml create mode 100755 fabric/examples/extract-snippets.sh create mode 100644 fabric/examples/go/go.mod create mode 100644 fabric/examples/go/main.go create mode 100644 fabric/examples/js/index.mjs create mode 100644 fabric/examples/kotlin/Example.kt create mode 100644 fabric/examples/python/example.py create mode 100644 fabric/examples/rust/Cargo.lock create mode 100644 fabric/examples/rust/Cargo.toml create mode 100644 fabric/examples/rust/src/main.rs create mode 100644 fabric/examples/swift/Example.swift create mode 100755 fabric/examples/test-example.sh delete mode 100644 fabric/go/libveritas.go diff --git a/.github/workflows/snippets.yml b/.github/workflows/snippets.yml new file mode 100644 index 0000000..f76b2b7 --- /dev/null +++ b/.github/workflows/snippets.yml @@ -0,0 +1,64 @@ +name: Extract code snippets + +on: + push: + paths: + - "fabric/examples/**" + workflow_dispatch: + +permissions: + contents: read + pages: write + id-token: write + +jobs: + extract: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Extract snippets + run: | + cd fabric/examples + mkdir -p /tmp/snippets + + for lang_file in \ + rust/src/main.rs \ + js/index.mjs \ + go/main.go \ + python/example.py \ + kotlin/Example.kt \ + swift/Example.swift; do + + lang=$(dirname "$lang_file" | cut -d/ -f1) + mkdir -p "/tmp/snippets/$lang" + ./extract-snippets.sh "$lang_file" "/tmp/snippets/$lang" + done + + # Create index + echo "# Code Snippets" > /tmp/snippets/index.md + echo "" >> /tmp/snippets/index.md + for lang in rust js go python kotlin swift; do + echo "## $lang" >> /tmp/snippets/index.md + for f in /tmp/snippets/$lang/*.txt; do + name=$(basename "$f" .txt) + echo "- [$name]($lang/$name.txt)" >> /tmp/snippets/index.md + done + echo "" >> /tmp/snippets/index.md + done + + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + with: + path: /tmp/snippets + + deploy: + needs: extract + runs-on: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 diff --git a/Cargo.lock b/Cargo.lock index 840de17..f3d5a29 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -692,7 +692,7 @@ dependencies = [ [[package]] name = "borsh_utils" version = "0.1.0" -source = "git+https://github.com/spacesprotocol/spaces.git?branch=subspaces#e8df2856d5034fcbece10a33eb93da4de6d04baf" +source = "git+https://github.com/spacesprotocol/spaces.git?branch=subspaces#8bfdffc02d7a49c07f7bf7da77d63a606a502515" dependencies = [ "bitcoin", "borsh", @@ -744,9 +744,9 @@ checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "cc" -version = "1.2.58" +version = "1.2.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1e928d4b69e3077709075a938a05ffbedfa53a84c8f766efbf8220bb1ff60e1" +checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" dependencies = [ "find-msvc-tools", "shlex", @@ -1746,9 +1746,9 @@ checksum = "4ee796ad498c8d9a1d68e477df8f754ed784ef875de1414ebdaf169f70a6a784" [[package]] name = "indexmap" -version = "2.13.0" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" dependencies = [ "equivalent", "hashbrown 0.16.1", @@ -2008,7 +2008,7 @@ dependencies = [ [[package]] name = "libveritas" version = "0.1.0" -source = "git+https://github.com/spacesprotocol/libveritas.git#c040c016837900bb36cc3d85452f8f6494d9552d" +source = "git+https://github.com/spacesprotocol/libveritas.git#a7d86225bac32cf26383cd8b9d2fcff6d8ce7829" dependencies = [ "base64 0.22.1", "borsh", @@ -2026,7 +2026,7 @@ dependencies = [ [[package]] name = "libveritas_testutil" version = "0.1.0" -source = "git+https://github.com/spacesprotocol/libveritas.git#c040c016837900bb36cc3d85452f8f6494d9552d" +source = "git+https://github.com/spacesprotocol/libveritas.git#a7d86225bac32cf26383cd8b9d2fcff6d8ce7829" dependencies = [ "bitcoin", "borsh", @@ -2044,7 +2044,7 @@ dependencies = [ [[package]] name = "libveritas_zk" version = "0.1.0" -source = "git+https://github.com/spacesprotocol/libveritas.git#c040c016837900bb36cc3d85452f8f6494d9552d" +source = "git+https://github.com/spacesprotocol/libveritas.git#a7d86225bac32cf26383cd8b9d2fcff6d8ce7829" dependencies = [ "borsh", "serde", @@ -3241,9 +3241,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" dependencies = [ "serde", "serde_core", @@ -3373,7 +3373,7 @@ checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" [[package]] name = "sip7" version = "0.1.0" -source = "git+https://github.com/spacesprotocol/spaces.git?branch=subspaces#e8df2856d5034fcbece10a33eb93da4de6d04baf" +source = "git+https://github.com/spacesprotocol/spaces.git?branch=subspaces#8bfdffc02d7a49c07f7bf7da77d63a606a502515" dependencies = [ "base64 0.22.1", "hex", @@ -3445,7 +3445,7 @@ dependencies = [ [[package]] name = "spaces_checkpoint" version = "0.1.0" -source = "git+https://github.com/spacesprotocol/spaces.git?branch=subspaces#e8df2856d5034fcbece10a33eb93da4de6d04baf" +source = "git+https://github.com/spacesprotocol/spaces.git?branch=subspaces#8bfdffc02d7a49c07f7bf7da77d63a606a502515" dependencies = [ "anyhow", "clap", @@ -3464,7 +3464,7 @@ dependencies = [ [[package]] name = "spaces_client" version = "0.0.7" -source = "git+https://github.com/spacesprotocol/spaces.git?branch=subspaces#e8df2856d5034fcbece10a33eb93da4de6d04baf" +source = "git+https://github.com/spacesprotocol/spaces.git?branch=subspaces#8bfdffc02d7a49c07f7bf7da77d63a606a502515" dependencies = [ "anyhow", "base64 0.22.1", @@ -3498,7 +3498,7 @@ dependencies = [ [[package]] name = "spaces_nums" version = "0.1.0" -source = "git+https://github.com/spacesprotocol/spaces.git?branch=subspaces#e8df2856d5034fcbece10a33eb93da4de6d04baf" +source = "git+https://github.com/spacesprotocol/spaces.git?branch=subspaces#8bfdffc02d7a49c07f7bf7da77d63a606a502515" dependencies = [ "bech32", "bitcoin", @@ -3513,7 +3513,7 @@ dependencies = [ [[package]] name = "spaces_protocol" version = "0.0.7" -source = "git+https://github.com/spacesprotocol/spaces.git?branch=subspaces#e8df2856d5034fcbece10a33eb93da4de6d04baf" +source = "git+https://github.com/spacesprotocol/spaces.git?branch=subspaces#8bfdffc02d7a49c07f7bf7da77d63a606a502515" dependencies = [ "bitcoin", "borsh", @@ -3524,7 +3524,7 @@ dependencies = [ [[package]] name = "spaces_wallet" version = "0.0.7" -source = "git+https://github.com/spacesprotocol/spaces.git?branch=subspaces#e8df2856d5034fcbece10a33eb93da4de6d04baf" +source = "git+https://github.com/spacesprotocol/spaces.git?branch=subspaces#8bfdffc02d7a49c07f7bf7da77d63a606a502515" dependencies = [ "anyhow", "bdk_wallet", @@ -4506,9 +4506,9 @@ checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" [[package]] name = "writeable" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] name = "xattr" diff --git a/fabric/examples/extract-snippets.sh b/fabric/examples/extract-snippets.sh new file mode 100755 index 0000000..e01f330 --- /dev/null +++ b/fabric/examples/extract-snippets.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash +set -eo pipefail +# +# Extract code snippets from example files. +# +# Snippets are delimited by and tags. +# Output: one file per snippet in the output directory. +# +# Usage: +# ./extract-snippets.sh rust/src/main.rs snippets/rust +# ./extract-snippets.sh js/index.mjs snippets/js +# + +INPUT="${1:?Usage: extract-snippets.sh }" +OUTDIR="${2:?Usage: extract-snippets.sh }" + +mkdir -p "$OUTDIR" + +# Detect language from file extension +EXT="txt" + +# Extract each ... block +current_tag="" +current_file="" + +while IFS= read -r line; do + # Check for opening tag + if [[ "$line" =~ \ ]]; then + current_tag="${BASH_REMATCH[1]}" + current_file="$OUTDIR/${current_tag}.${EXT}" + > "$current_file" # truncate + continue + fi + + # Check for closing tag + if [[ "$line" =~ \ $current_file" + fi + current_tag="" + current_file="" + continue + fi + + # Write line to current snippet (strip common leading whitespace) + if [ -n "$current_file" ]; then + echo "$line" >> "$current_file" + fi +done < "$INPUT" + +# Clean up: strip common leading whitespace from each snippet +for f in "$OUTDIR"/*."$EXT"; do + [ -f "$f" ] || continue + # Find minimum indentation (ignoring blank lines) + min_indent=$(sed -n '/[^ ]/{ s/^\( *\).*/\1/; p; }' "$f" | awk '{ print length }' | sort -n | head -1) + if [ -n "$min_indent" ] && [ "$min_indent" -gt 0 ]; then + if sed -i '' "s/^ \{1,$min_indent\}//" "$f" 2>/dev/null; then + : # macOS sed + else + sed -i "s/^ \{1,$min_indent\}//" "$f" # Linux sed + fi + fi +done + +echo "Done: $(ls "$OUTDIR"/*."$EXT" 2>/dev/null | wc -l | tr -d ' ') snippets extracted" \ No newline at end of file diff --git a/fabric/examples/go/go.mod b/fabric/examples/go/go.mod new file mode 100644 index 0000000..c95635f --- /dev/null +++ b/fabric/examples/go/go.mod @@ -0,0 +1,13 @@ +module example-go + +go 1.22 + +require github.com/spacesprotocol/fabric-go v0.0.0-dev.20260401232107 + +require ( + github.com/spacesprotocol/libveritas-go v0.0.0-dev.20260401232107 // indirect + github.com/btcsuite/btcd/btcec/v2 v2.3.6 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect + github.com/decred/dcrd/crypto/blake256 v1.0.0 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect +) diff --git a/fabric/examples/go/main.go b/fabric/examples/go/main.go new file mode 100644 index 0000000..728278b --- /dev/null +++ b/fabric/examples/go/main.go @@ -0,0 +1,325 @@ +package main + +import ( + "encoding/hex" + "fmt" + "log" + + fabric "github.com/spacesprotocol/fabric-go" + lv "github.com/spacesprotocol/libveritas-go" +) + +/// Resolve a single handle +func exampleResolve() error { + // + f := fabric.New() + resolved, err := f.Resolve("alice@bitcoin") + if err != nil { + return err + } + if resolved == nil { + fmt.Println("handle not found") + return nil + } + + fmt.Printf("Handle found: %s\n", resolved.Zone.Handle) + // + + return nil +} + +/// Verification +func exampleTrustAndVerification() error { + f := fabric.New() + + // + // Before pinning a trust id: resolve uses observed (peer) state + // badge() returns Unverified + resolved, err := f.Resolve("alice@bitcoin") + if err != nil { + return err + } + + f.Badge(resolved) // Unverified + + // Pin trust from a QR scan + qr := "veritas://scan?id=14ef902621df01bdeee0b23fedf67458563a20df600af8979a4748dcd9d1b9f9" + + // For highest level of trust (scan QR code from Veritas desktop) + if err := f.TrustFromQr(qr); err != nil { + return err + } + + // Does not require re-resolving, badge now checks + // whether resolved was against a trusted root + f.Badge(resolved) // Orange if handle is sovereign (final certificate) + + // Or from a semi-trusted source (e.g. an explorer you trust with qr scanned over HTTPS) + // .Badge() will not show Orange for roots in this trust pool, + // but it will not report it as "Unverified". + if err := f.SemiTrustFromQr(qr); err != nil { + return err + } + + // Check current trust ids + f.Trusted() // pinned id from local verification + f.SemiTrusted() // pinned id from semi-trusted source + f.Observed() // latest from peers + + // Clear trusted state + f.ClearTrusted() + f.ClearSemiTrusted() + + // + + return nil +} + +/// Unpack records from a resolved handle +func exampleUnpackRecords() error { + f := fabric.New() + resolved, err := f.Resolve("alice@bitcoin") + if err != nil { + return err + } + + // + records, err := resolved.Zone.Records.Unpack() + if err != nil { + return err + } + + for _, record := range records { + switch r := record.(type) { + case lv.ParsedRecordTxt: + fmt.Printf("txt %s=%s\n", r.Key, joinStrings(r.Value)) + case lv.ParsedRecordAddr: + fmt.Printf("addr %s=%s\n", r.Key, joinStrings(r.Value)) + } + } + // + + return nil +} + +/// Resolve multiple handles +func exampleResolveAll() error { + f := fabric.New() + + // + batch, err := f.ResolveAll([]string{"alice@bitcoin", "bob@bitcoin"}) + if err != nil { + return err + } + + for _, zone := range batch.Zones { + fmt.Printf("%s: %s\n", zone.Handle, zone.Sovereignty) + } + // + + return nil +} + +/// Pack records into a RecordSet +func examplePackRecords() error { + // + records, err := lv.RecordSetPack([]lv.Record{ + lv.RecordSeq{Version: 1}, + lv.RecordTxt{Key: "website", Value: []string{"https://example.com"}}, + lv.RecordAddr{Key: "btc", Value: []string{"bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"}}, + lv.RecordAddr{Key: "nostr", Value: []string{ + "npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6", + "wss://relay.example.com", + }}, + }) + // + + if err != nil { + return err + } + _ = records + return nil +} + +/// Publish signed records +func examplePublish() error { + f := fabric.New() + secretKey, err := hex.DecodeString( + "0000000000000000000000000000000000000000000000000000000000000001", + ) + if err != nil { + return err + } + + rs, err := lv.RecordSetPack([]lv.Record{ + lv.RecordSeq{Version: 1}, + lv.RecordTxt{Key: "website", Value: []string{"https://example.com"}}, + lv.RecordAddr{Key: "btc", Value: []string{"bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"}}, + }) + if err != nil { + return err + } + + // + cert, err := f.Export("alice@bitcoin") + if err != nil { + return err + } + err = f.Publish(cert, rs, secretKey, true) + if err != nil { + return err + } + // + + return nil +} + +/// Resolve by numeric ID +func exampleResolveById() error { + f := fabric.New() + + // + resolved, err := f.ResolveById("num1qx8dtlzq...") + if err != nil { + return err + } + if resolved == nil { + fmt.Println("handle not found") + return nil + } + + fmt.Printf("Handle found: %s\n", resolved.Zone.Handle) + // + + return nil +} + +/// Search by address +func exampleSearchAddr() error { + f := fabric.New() + + // + batch, err := f.SearchAddr("btc", "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4") + if err != nil { + return err + } + + for _, zone := range batch.Zones { + fmt.Printf("%s: %s\n", zone.Handle, zone.Sovereignty) + } + // + + return nil +} + +/// Advanced: Build and broadcast a message manually +func exampleMessageBuilder() error { + f := fabric.New() + secretKey, err := hex.DecodeString( + "0000000000000000000000000000000000000000000000000000000000000001", + ) + if err != nil { + return err + } + + certBytes, err := f.Export("alice@bitcoin") + if err != nil { + return err + } + records, err := lv.RecordSetPack([]lv.Record{ + lv.RecordSeq{Version: 1}, + lv.RecordAddr{Key: "btc", Value: []string{"bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"}}, + }) + if err != nil { + return err + } + + // + builder := lv.NewMessageBuilder() + if err := builder.AddHandle(certBytes, records.ToBytes()); err != nil { + return err + } + + proofReq, err := builder.ChainProofRequest() + if err != nil { + return err + } + proofBytes, err := f.Prove([]byte(proofReq)) + if err != nil { + return err + } + + result, err := builder.Build(proofBytes) + if err != nil { + return err + } + + for _, u := range result.Unsigned { + u.SetFlags(u.Flags() | lv.SigPrimaryZone()) + sig, err := fabric.SignSchnorr(u.SigningId(), secretKey) + if err != nil { + return err + } + if err := result.Message.SetRecords(u.Canonical(), u.PackSig(sig)); err != nil { + return err + } + } + + if err := f.Broadcast(result.Message.ToBytes()); err != nil { + return err + } + // + + return nil +} + +func joinStrings(ss []string) string { + result := "" + for i, s := range ss { + if i > 0 { + result += ", " + } + result += s + } + return result +} + +func main() { + if err := exampleResolve(); err != nil { + log.Fatal(err) + } + + if err := exampleTrustAndVerification(); err != nil { + fmt.Printf("verification example failed (expected): %v\n", err) + } + + if err := exampleUnpackRecords(); err != nil { + log.Fatal(err) + } + + if err := exampleResolveAll(); err != nil { + log.Fatal(err) + } + + if err := examplePackRecords(); err != nil { + log.Fatal(err) + } + + if err := examplePublish(); err != nil { + log.Fatal(err) + } + + if err := exampleResolveById(); err != nil { + log.Fatal(err) + } + + if err := exampleSearchAddr(); err != nil { + log.Fatal(err) + } + + if err := exampleMessageBuilder(); err != nil { + log.Fatal(err) + } + + fmt.Println("Done!") +} diff --git a/fabric/examples/js/index.mjs b/fabric/examples/js/index.mjs new file mode 100644 index 0000000..a8c4da1 --- /dev/null +++ b/fabric/examples/js/index.mjs @@ -0,0 +1,206 @@ +import { Fabric, RecordSet, Record, MessageBuilder } from "@spacesprotocol/fabric-web"; +import { signSchnorr } from "@spacesprotocol/fabric-web/signing"; + +/// Resolve a single handle +async function exampleResolve() { + // + const fabric = new Fabric(); + const resolved = await fabric.resolve("alice@bitcoin"); + if (!resolved) { + console.log("handle not found"); + return; + } + + console.log(`Handle found: ${resolved.zone.handle}`); + // +} + +/// Verification +async function exampleTrustAndVerification() { + const fabric = new Fabric(); + + // + // Before pinning a trust id: resolve uses observed (peer) state + // badge() returns "unverified" + const resolved = await fabric.resolve("alice@bitcoin"); + + fabric.badge(resolved); // "unverified" + + // Pin trust from a QR scan + const qr = "veritas://scan?id=14ef902621df01bdeee0b23fedf67458563a20df600af8979a4748dcd9d1b9f9"; + + // For highest level of trust (scan QR code from Veritas desktop) + await fabric.trustFromQr(qr); + + // Does not require re-resolving, badge now checks + // whether resolved was against a trusted root + fabric.badge(resolved); // "orange" if handle is sovereign (final certificate) + + // Or from a semi-trusted source (e.g. an explorer you trust with qr scanned over HTTPS) + // .badge() will not show "orange" for roots in this trust pool, + // but it will not report it as "unverified". + await fabric.semiTrustFromQr(qr); + + // Check current trust ids + fabric.trusted(); // pinned id from local verification + fabric.semiTrusted(); // pinned id from semi-trusted source + fabric.observed(); // latest from peers + + // Clear trusted state + fabric.clearTrusted(); + // +} + +/// Unpack records from a resolved handle +async function exampleUnpackRecords() { + const fabric = new Fabric(); + const resolved = await fabric.resolve("alice@bitcoin"); + + // + const json = resolved.zone.toJson(); + + for (const record of json.records) { + if (record.type === "txt") { + console.log(`txt ${record.key}=${record.value.join(", ")}`); + } else if (record.type === "addr") { + console.log(`addr ${record.key}=${record.value.join(", ")}`); + } + } + // +} + +/// Resolve multiple handles +async function exampleResolveAll() { + const fabric = new Fabric(); + + // + const batch = await fabric.resolveAll(["alice@bitcoin", "bob@bitcoin"]); + + for (const zone of batch.zones) { + console.log(`${zone.handle}`); + } + // +} + +/// Pack records into a RecordSet +function examplePackRecords() { + // + const records = RecordSet.pack([ + Record.seq(1n), + Record.txt("website", ["https://example.com"]), + Record.addr("btc", ["bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"]), + Record.addr("nostr", [ + "npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6", + "wss://relay.example.com", + ]), + ]); + // +} + +/// Publish signed records +async function examplePublish() { + const fabric = new Fabric(); + const secretKey = new Uint8Array(Buffer.from( + "0000000000000000000000000000000000000000000000000000000000000001", "hex" + )); + + const rs = RecordSet.pack([ + Record.seq(1n), + Record.txt("website", ["https://example.com"]), + Record.addr("btc", ["bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"]), + ]); + + // + const cert = await fabric.export("alice@bitcoin"); + await fabric.publish({ + cert, + records: rs.toBytes(), + sign: (digest) => signSchnorr(digest, secretKey), + primary: true, + }); + // +} + +/// Resolve by numeric ID +async function exampleResolveById() { + const fabric = new Fabric(); + + // + const resolved = await fabric.resolveById("num1qx8dtlzq..."); + if (!resolved) { + console.log("handle not found"); + return; + } + + console.log(`Handle found: ${resolved.zone.handle}`); + // +} + +/// Search by address +async function exampleSearchAddr() { + const fabric = new Fabric(); + + // + const batch = await fabric.searchAddr("btc", "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"); + + for (const zone of batch.zones) { + console.log(`${zone.handle}`); + } + // +} + +/// Advanced: Build and broadcast a message manually +async function exampleMessageBuilder() { + const fabric = new Fabric(); + const secretKey = new Uint8Array(Buffer.from( + "0000000000000000000000000000000000000000000000000000000000000001", "hex" + )); + + const certBytes = await fabric.export("alice@bitcoin"); + const rs = RecordSet.pack([ + Record.seq(1n), + Record.addr("btc", ["bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"]), + ]); + + // + const builder = new MessageBuilder(); + builder.addHandle(certBytes, rs.toBytes()); + + const chainProofReq = builder.chainProofRequest(); + const chainProof = await fabric.prove( + typeof chainProofReq === "string" ? chainProofReq : JSON.stringify(chainProofReq) + ); + + const { message, unsigned } = builder.build(chainProof); + + for (const u of unsigned) { + u.setFlags(u.flags() | 0x01); // SIG_PRIMARY_ZONE + const sig = signSchnorr(u.signingId(), secretKey); + message.setRecords(u.canonical(), u.packSig(sig)); + } + + await fabric.broadcast(message.toBytes()); + // +} + +async function main() { + await exampleResolve(); + + try { + await exampleTrustAndVerification(); + } catch (e) { + // Expected to fail with example QR ID + } + + await exampleUnpackRecords(); + await exampleResolveAll(); + examplePackRecords(); + await examplePublish(); + await exampleResolveById(); + await exampleSearchAddr(); + await exampleMessageBuilder(); + + console.log("Done!"); +} + +main().catch(console.error); diff --git a/fabric/examples/kotlin/Example.kt b/fabric/examples/kotlin/Example.kt new file mode 100644 index 0000000..afa2e3c --- /dev/null +++ b/fabric/examples/kotlin/Example.kt @@ -0,0 +1,206 @@ +import org.spacesprotocol.fabric.Fabric +import org.spacesprotocol.fabric.RecordSet +import org.spacesprotocol.fabric.Record +import org.spacesprotocol.fabric.SignSchnorr +import org.spacesprotocol.fabric.CertificateChain +import org.spacesprotocol.fabric.MessageBuilder +import org.spacesprotocol.fabric.ChainProof +import org.spacesprotocol.fabric.SIG_PRIMARY_ZONE + +/// Resolve a single handle +suspend fun exampleResolve() { + // + val fabric = Fabric() + val resolved = fabric.resolve("alice@bitcoin") + if (resolved == null) { + println("handle not found") + return + } + + println("Handle found: ${resolved.zone.handle}") + // +} + +/// Verification +suspend fun exampleTrustAndVerification() { + val fabric = Fabric() + + // + // Before pinning a trust id: resolve uses observed (peer) state + // badge() returns Unverified + val resolved = fabric.resolve("alice@bitcoin") + ?: throw IllegalStateException("handle exists") + + fabric.badge(resolved) // Unverified + + // Pin trust from a QR scan + val qr = "veritas://scan?id=14ef902621df01bdeee0b23fedf67458563a20df600af8979a4748dcd9d1b9f9" + + // For highest level of trust (scan QR code from Veritas desktop) + fabric.trustFromQr(qr) + + // Does not require re-resolving, badge now checks + // whether resolved was against a trusted root + fabric.badge(resolved) // Orange if handle is sovereign (final certificate) + + // Or from a semi-trusted source (e.g. an explorer you trust with qr scanned over HTTPS) + // .badge() will not show Orange for roots in this trust pool, + // but it will not report it as "Unverified". + fabric.semiTrustFromQr(qr) + + // Check current trust ids + fabric.trusted() // pinned id from local verification + fabric.semiTrusted() // pinned id from semi-trusted source + fabric.observed() // latest from peers + + // Clear trusted state + fabric.clearTrusted() + fabric.clearSemiTrusted() + + // +} + +/// Unpack records from a resolved handle +suspend fun exampleUnpackRecords() { + val fabric = Fabric() + val resolved = fabric.resolve("alice@bitcoin") + ?: throw IllegalStateException("handle exists") + + // + val records = resolved.zone.records.unpack() + + for (record in records) { + when (record) { + is Record.Txt -> println("txt ${record.key}=${record.value.joinToString(", ")}") + is Record.Addr -> println("addr ${record.key}=${record.value.joinToString(", ")}") + else -> {} + } + } + // +} + +/// Resolve multiple handles +suspend fun exampleResolveAll() { + val fabric = Fabric() + + // + val batch = fabric.resolveAll(listOf("alice@bitcoin", "bob@bitcoin")) + + for (zone in batch.zones) { + println("${zone.handle}: ${zone.sovereignty}") + } + // +} + +/// Pack records into a RecordSet +fun examplePackRecords() { + // + val records = RecordSet.pack(listOf( + Record.seq(1), + Record.txt("website", listOf("https://example.com")), + Record.addr("btc", listOf("bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4")), + Record.addr("nostr", listOf( + "npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6", + "wss://relay.example.com", + )), + )) + // +} + +/// Publish signed records +suspend fun examplePublish() { + val fabric = Fabric() + val secretKey = "0000000000000000000000000000000000000000000000000000000000000001" + .chunked(2).map { it.toInt(16).toByte() }.toByteArray() + + val rs = RecordSet.pack(listOf( + Record.seq(1), + Record.txt("website", listOf("https://example.com")), + Record.addr("btc", listOf("bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4")), + )) + + // + val cert = fabric.export("alice@bitcoin") + fabric.publish(cert, rs, secretKey, primary = true) + // +} + +/// Resolve by numeric ID +suspend fun exampleResolveById() { + val fabric = Fabric() + + // + val resolved = fabric.resolveById("num1qx8dtlzq...") + if (resolved == null) { + println("handle not found") + return + } + + println("Handle found: ${resolved.zone.handle}") + // +} + +/// Search by address +suspend fun exampleSearchAddr() { + val fabric = Fabric() + + // + val batch = fabric.searchAddr("btc", "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4") + + for (zone in batch.zones) { + println("${zone.handle}: ${zone.sovereignty}") + } + // +} + +/// Advanced: Build and broadcast a message manually +suspend fun exampleMessageBuilder() { + val fabric = Fabric() + val secretKey = "0000000000000000000000000000000000000000000000000000000000000001" + .chunked(2).map { it.toInt(16).toByte() }.toByteArray() + + val certBytes = fabric.export("alice@bitcoin") + val records = RecordSet.pack(listOf( + Record.seq(1), + Record.addr("btc", listOf("bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4")), + )) + + // + val cert = CertificateChain.fromSlice(certBytes) + val builder = MessageBuilder() + builder.addHandle(cert, records) + + val proofBytes = fabric.prove(builder.chainProofRequest()) + val proof = ChainProof.fromSlice(proofBytes) + + val (msg, unsigned) = builder.build(proof) + + for (u in unsigned) { + u.flags = u.flags or SIG_PRIMARY_ZONE + val sig = SignSchnorr(u.signingId(), secretKey) + msg.setRecords(u.canonical, u.packSig(sig)) + } + + fabric.broadcast(msg.toBytes()) + // +} + +suspend fun main() { + exampleResolve() + + try { + exampleTrustAndVerification() + } catch (e: Exception) { + println("verification example failed (expected): ${e.message}") + } + + exampleUnpackRecords() + exampleResolveAll() + examplePackRecords() + examplePublish() + exampleResolveById() + exampleSearchAddr() + exampleMessageBuilder() + + println("Done!") +} diff --git a/fabric/examples/python/example.py b/fabric/examples/python/example.py new file mode 100644 index 0000000..836b0db --- /dev/null +++ b/fabric/examples/python/example.py @@ -0,0 +1,198 @@ +import asyncio + +from fabric import Fabric, RecordSet, Record, sign_schnorr +from fabric import CertificateChain, MessageBuilder, ChainProof, SIG_PRIMARY_ZONE + + +async def example_resolve(): + """Resolve a single handle""" + # + fabric = Fabric() + resolved = await fabric.resolve("alice@bitcoin") + if resolved is None: + print("handle not found") + return + + print(f"Handle found: {resolved.zone.handle}") + # + + +async def example_trust_and_verification(): + """Verification""" + fabric = Fabric() + + # + # Before pinning a trust id: resolve uses observed (peer) state + # badge() returns Unverified + resolved = await fabric.resolve("alice@bitcoin") + + fabric.badge(resolved) # Unverified + + # Pin trust from a QR scan + qr = "veritas://scan?id=14ef902621df01bdeee0b23fedf67458563a20df600af8979a4748dcd9d1b9f9" + + # For highest level of trust (scan QR code from Veritas desktop) + await fabric.trust_from_qr(qr) + + # Does not require re-resolving, badge now checks + # whether resolved was against a trusted root + fabric.badge(resolved) # Orange if handle is sovereign (final certificate) + + # Or from a semi-trusted source (e.g. an explorer you trust with qr scanned over HTTPS) + # .badge() will not show Orange for roots in this trust pool, + # but it will not report it as "Unverified". + await fabric.semi_trust_from_qr(qr) + + # Check current trust ids + fabric.trusted() # pinned id from local verification + fabric.semi_trusted() # pinned id from semi-trusted source + fabric.observed() # latest from peers + + # Clear trusted state + fabric.clear_trusted() + fabric.clear_semi_trusted() + + # + + +async def example_unpack_records(): + """Unpack records from a resolved handle""" + fabric = Fabric() + resolved = await fabric.resolve("alice@bitcoin") + + # + records = resolved.zone.records.unpack() + + for record in records: + if record.type == "txt": + print(f"txt {record.key}={', '.join(record.value)}") + elif record.type == "addr": + print(f"addr {record.key}={', '.join(record.value)}") + # + + +async def example_resolve_all(): + """Resolve multiple handles""" + fabric = Fabric() + + # + batch = await fabric.resolve_all(["alice@bitcoin", "bob@bitcoin"]) + + for zone in batch.zones: + print(f"{zone.handle}: {zone.sovereignty}") + # + + +def example_pack_records(): + """Pack records into a RecordSet""" + # + records = RecordSet.pack([ + Record.seq(1), + Record.txt("website", ["https://example.com"]), + Record.addr("btc", ["bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"]), + Record.addr("nostr", [ + "npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6", + "wss://relay.example.com", + ]), + ]) + # + + +async def example_publish(): + """Publish signed records""" + fabric = Fabric() + secret_key = bytes.fromhex( + "0000000000000000000000000000000000000000000000000000000000000001" + ) + + rs = RecordSet.pack([ + Record.seq(1), + Record.txt("website", ["https://example.com"]), + Record.addr("btc", ["bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"]), + ]) + + # + cert = await fabric.export("alice@bitcoin") + await fabric.publish(cert, rs, secret_key, primary=True) + # + + +async def example_resolve_by_id(): + """Resolve by numeric ID""" + fabric = Fabric() + + # + resolved = await fabric.resolve_by_id("num1qx8dtlzq...") + if resolved is None: + print("handle not found") + return + + print(f"Handle found: {resolved.zone.handle}") + # + + +async def example_search_addr(): + """Search by address""" + fabric = Fabric() + + # + batch = await fabric.search_addr("btc", "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4") + + for zone in batch.zones: + print(f"{zone.handle}: {zone.sovereignty}") + # + + +async def example_message_builder(): + """Advanced: Build and broadcast a message manually""" + fabric = Fabric() + secret_key = bytes.fromhex( + "0000000000000000000000000000000000000000000000000000000000000001" + ) + + cert_bytes = await fabric.export("alice@bitcoin") + records = RecordSet.pack([ + Record.seq(1), + Record.addr("btc", ["bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"]), + ]) + + # + cert = CertificateChain.from_slice(cert_bytes) + builder = MessageBuilder() + builder.add_handle(cert, records) + + proof_bytes = await fabric.prove(builder.chain_proof_request()) + proof = ChainProof.from_slice(proof_bytes) + + msg, unsigned = builder.build(proof) + + for u in unsigned: + u.flags |= SIG_PRIMARY_ZONE + sig = sign_schnorr(u.signing_id(), secret_key) + msg.set_records(u.canonical, u.pack_sig(sig)) + + await fabric.broadcast(msg.to_bytes()) + # + + +async def main(): + await example_resolve() + + try: + await example_trust_and_verification() + except Exception as e: + print(f"verification example failed (expected): {e}") + + await example_unpack_records() + await example_resolve_all() + example_pack_records() + await example_publish() + await example_resolve_by_id() + await example_search_addr() + await example_message_builder() + + print("Done!") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/fabric/examples/rust/Cargo.lock b/fabric/examples/rust/Cargo.lock new file mode 100644 index 0000000..fe7525c --- /dev/null +++ b/fabric/examples/rust/Cargo.lock @@ -0,0 +1,2833 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "ark-bn254" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d69eab57e8d2663efa5c63135b2af4f396d66424f88954c21104125ab6b3e6bc" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-r1cs-std", + "ark-std", +] + +[[package]] +name = "ark-crypto-primitives" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0c292754729c8a190e50414fd1a37093c786c709899f29c9f7daccecfa855e" +dependencies = [ + "ahash", + "ark-crypto-primitives-macros", + "ark-ec", + "ark-ff", + "ark-relations", + "ark-serialize", + "ark-snark", + "ark-std", + "blake2", + "derivative", + "digest", + "fnv", + "merlin", + "sha2", +] + +[[package]] +name = "ark-crypto-primitives-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7e89fe77d1f0f4fe5b96dfc940923d88d17b6a773808124f21e764dfb063c6a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "ark-ec" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43d68f2d516162846c1238e755a7c4d131b892b70cc70c471a8e3ca3ed818fce" +dependencies = [ + "ahash", + "ark-ff", + "ark-poly", + "ark-serialize", + "ark-std", + "educe", + "fnv", + "hashbrown 0.15.5", + "itertools", + "num-bigint", + "num-integer", + "num-traits", + "zeroize", +] + +[[package]] +name = "ark-ff" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a177aba0ed1e0fbb62aa9f6d0502e9b46dad8c2eab04c14258a1212d2557ea70" +dependencies = [ + "ark-ff-asm", + "ark-ff-macros", + "ark-serialize", + "ark-std", + "arrayvec", + "digest", + "educe", + "itertools", + "num-bigint", + "num-traits", + "paste", + "zeroize", +] + +[[package]] +name = "ark-ff-asm" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[package]] +name = "ark-ff-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09be120733ee33f7693ceaa202ca41accd5653b779563608f1234f78ae07c4b3" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "ark-groth16" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88f1d0f3a534bb54188b8dcc104307db6c56cdae574ddc3212aec0625740fc7e" +dependencies = [ + "ark-crypto-primitives", + "ark-ec", + "ark-ff", + "ark-poly", + "ark-relations", + "ark-serialize", + "ark-std", +] + +[[package]] +name = "ark-poly" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "579305839da207f02b89cd1679e50e67b4331e2f9294a57693e5051b7703fe27" +dependencies = [ + "ahash", + "ark-ff", + "ark-serialize", + "ark-std", + "educe", + "fnv", + "hashbrown 0.15.5", +] + +[[package]] +name = "ark-r1cs-std" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "941551ef1df4c7a401de7068758db6503598e6f01850bdb2cfdb614a1f9dbea1" +dependencies = [ + "ark-ec", + "ark-ff", + "ark-relations", + "ark-std", + "educe", + "num-bigint", + "num-integer", + "num-traits", + "tracing", +] + +[[package]] +name = "ark-relations" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec46ddc93e7af44bcab5230937635b06fb5744464dd6a7e7b083e80ebd274384" +dependencies = [ + "ark-ff", + "ark-std", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "ark-serialize" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f4d068aaf107ebcd7dfb52bc748f8030e0fc930ac8e360146ca54c1203088f7" +dependencies = [ + "ark-serialize-derive", + "ark-std", + "arrayvec", + "digest", + "num-bigint", +] + +[[package]] +name = "ark-serialize-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "ark-snark" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d368e2848c2d4c129ce7679a7d0d2d612b6a274d3ea6a13bad4445d61b381b88" +dependencies = [ + "ark-ff", + "ark-relations", + "ark-serialize", + "ark-std", +] + +[[package]] +name = "ark-std" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "246a225cc6131e9ee4f24619af0f19d67761fff15d7ccc22e42b80846e69449a" +dependencies = [ + "num-traits", + "rand 0.8.5", +] + +[[package]] +name = "arrayvec" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "base58ck" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c8d66485a3a2ea485c1913c4572ce0256067a5377ac8c75c4960e1cda98605f" +dependencies = [ + "bitcoin-internals", + "bitcoin_hashes", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bech32" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32637268377fc7b10a8c6d51de3e7fba1ce5dd371a96e342b34e6078db558e7f" + +[[package]] +name = "bit-vec" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bitcoin" +version = "0.32.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e499f9fc0407f50fe98af744ab44fa67d409f76b6772e1689ec8485eb0c0f66" +dependencies = [ + "base58ck", + "base64 0.21.7", + "bech32", + "bitcoin-internals", + "bitcoin-io", + "bitcoin-units", + "bitcoin_hashes", + "hex-conservative", + "hex_lit", + "secp256k1", + "serde", +] + +[[package]] +name = "bitcoin-internals" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30bdbe14aa07b06e6cfeffc529a1f099e5fbe249524f8125358604df99a4bed2" +dependencies = [ + "serde", +] + +[[package]] +name = "bitcoin-io" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dee39a0ee5b4095224a0cfc6bf4cc1baf0f9624b96b367e53b66d974e51d953" + +[[package]] +name = "bitcoin-units" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5285c8bcaa25876d07f37e3d30c303f2609179716e11d688f51e8f1fe70063e2" +dependencies = [ + "bitcoin-internals", + "serde", +] + +[[package]] +name = "bitcoin_hashes" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26ec84b80c482df901772e931a9a681e26a1b9ee2302edeff23cb30328745c8b" +dependencies = [ + "bitcoin-io", + "hex-conservative", + "serde", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" + +[[package]] +name = "blake2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +dependencies = [ + "digest", +] + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "borsh" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" +dependencies = [ + "borsh-derive", + "bytes", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59" +dependencies = [ + "once_cell", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "borsh_utils" +version = "0.1.0" +source = "git+https://github.com/spacesprotocol/spaces.git?branch=subspaces#8bfdffc02d7a49c07f7bf7da77d63a606a502515" +dependencies = [ + "bitcoin", + "borsh", +] + +[[package]] +name = "bumpalo" +version = "3.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" + +[[package]] +name = "bytemuck" +version = "1.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" +dependencies = [ + "bytemuck_derive", +] + +[[package]] +name = "bytemuck_derive" +version = "1.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" + +[[package]] +name = "cc" +version = "1.2.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7a4d3ec6524d28a329fc53654bbadc9bdd7b0431f5d65f1a56ffb28a1ee5283" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "cobs" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" +dependencies = [ + "thiserror", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics-types" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "libc", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "derivative" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "derive_more" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.117", + "unicode-xid", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "educe" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7bc049e1bd8cdeb31b68bbd586a9464ecf9f3944af3958a7a9d0f8b9799417" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "elf" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4445909572dbd556c457c849c4ca58623d84b27c8fff1e74b0b4227d8b90d17b" + +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "embedded-io" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" + +[[package]] +name = "enum-ordinalize" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a1091a7bb1f8f2c4b28f1fe2cef4980ca2d410a3d727d67ecc3178c9b0800f0" +dependencies = [ + "enum-ordinalize-derive", +] + +[[package]] +name = "enum-ordinalize-derive" +version = "4.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "fabric" +version = "0.1.0" +dependencies = [ + "dashmap", + "hex", + "libveritas", + "rand 0.9.2", + "reqwest", + "secp256k1", + "serde", + "serde_json", + "sha2", + "spaces_nums", + "tokio", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-conservative" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda06d18ac606267c40c04e41b9947729bf8b9efe74bd4e82b61a5f26a510b9f" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "hex-literal" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fe2267d4ed49bc07b63801559be28c718ea06c4738b7a03c94df7386d2cde46" + +[[package]] +name = "hex_lit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" + +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "hyper" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots", +] + +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + +[[package]] +name = "icu_collections" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" +dependencies = [ + "displaydoc", + "potential_utf", + "utf8_iter", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" + +[[package]] +name = "icu_properties" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" + +[[package]] +name = "icu_provider" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "include_bytes_aligned" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ee796ad498c8d9a1d68e477df8f754ed784ef875de1414ebdaf169f70a6a784" + +[[package]] +name = "indexmap" +version = "2.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", +] + +[[package]] +name = "ipnet" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" + +[[package]] +name = "iri-string" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "js-sys" +version = "0.3.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9" +dependencies = [ + "cfg-if", + "futures-util", + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "keccak" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] + +[[package]] +name = "libc" +version = "0.2.184" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48f5d2a454e16a5ea0f4ced81bd44e4cfc7bd3a507b61887c99fd3538b28e4af" + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "libveritas" +version = "0.1.0" +source = "git+https://github.com/spacesprotocol/libveritas.git#a7d86225bac32cf26383cd8b9d2fcff6d8ce7829" +dependencies = [ + "base64 0.22.1", + "borsh", + "hex", + "libveritas_zk", + "risc0-zkvm", + "serde", + "serde_json", + "sip7", + "spacedb", + "spaces_nums", + "spaces_protocol", +] + +[[package]] +name = "libveritas_zk" +version = "0.1.0" +source = "git+https://github.com/spacesprotocol/libveritas.git#a7d86225bac32cf26383cd8b9d2fcff6d8ce7829" +dependencies = [ + "borsh", + "serde", + "spacedb", +] + +[[package]] +name = "litemap" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "merlin" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58c38e2799fc0978b65dfff8023ec7843e2330bb462f19198840b34b6582397d" +dependencies = [ + "byteorder", + "keccak", + "rand_core 0.6.4", + "zeroize", +] + +[[package]] +name = "metal" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ecfd3296f8c56b7c1f6fbac3c71cefa9d78ce009850c45000015f206dc7fa21" +dependencies = [ + "bitflags 2.11.0", + "block", + "core-graphics-types", + "foreign-types", + "log", + "objc", + "paste", +] + +[[package]] +name = "mio" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.61.2", +] + +[[package]] +name = "no_std_strings" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5b0c77c1b780822bc749a33e39aeb2c07584ab93332303babeabb645298a76e" + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_enum" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26" +dependencies = [ + "num_enum_derive", + "rustversion", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "postcard" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24" +dependencies = [ + "cobs", + "embedded-io 0.4.0", + "embedded-io 0.6.1", + "serde", +] + +[[package]] +name = "potential_utf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" +dependencies = [ + "zerovec", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro-crate" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proptest" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" +dependencies = [ + "bitflags 2.11.0", + "num-traits", + "rand 0.9.2", + "rand_chacha 0.9.0", + "rand_xorshift", + "unarray", +] + +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2", + "thiserror", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" +dependencies = [ + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.2", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.60.2", +] + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" + +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rand_xorshift" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" +dependencies = [ + "rand_core 0.9.5", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.11.0", +] + +[[package]] +name = "reqwest" +version = "0.12.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "risc0-binfmt" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1883f0c5d19b865f395209a137dcb29e56dc49951424967b8d0114c129f46e77" +dependencies = [ + "anyhow", + "borsh", + "bytemuck", + "derive_more", + "elf", + "lazy_static", + "postcard", + "rand 0.9.2", + "risc0-zkp", + "risc0-zkvm-platform", + "ruint", + "semver", + "serde", + "tracing", +] + +[[package]] +name = "risc0-circuit-keccak" +version = "4.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f543c60287fece797a5da4209384ab1bfebd9644fcfe591e11b1aa85f1a02f8" +dependencies = [ + "anyhow", + "bytemuck", + "paste", + "risc0-binfmt", + "risc0-circuit-recursion", + "risc0-core", + "risc0-zkp", + "tracing", +] + +[[package]] +name = "risc0-circuit-recursion" +version = "4.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2347e909c6b2a65584b5898f3802eec5b8c1b4b45329edfdd8587b6a04dd3357" +dependencies = [ + "anyhow", + "bytemuck", + "hex", + "metal", + "risc0-core", + "risc0-zkp", + "tracing", +] + +[[package]] +name = "risc0-circuit-rv32im" +version = "4.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61676419814a818fdb5e10066b13c5488b3f54aa9668794bd06c99bc91bff1f2" +dependencies = [ + "anyhow", + "bit-vec", + "bytemuck", + "derive_more", + "paste", + "risc0-binfmt", + "risc0-core", + "risc0-zkp", + "serde", + "tracing", +] + +[[package]] +name = "risc0-core" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b956a976b8ce4713694dcc6c370b522a42ccef4ba45da5b6e57dbf26cdb7b1" +dependencies = [ + "bytemuck", + "rand_core 0.9.5", +] + +[[package]] +name = "risc0-groth16" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc57e76bb87193d154ac5ee6ee352fbd7edabddab36f02a81f40a048e5ca14f9" +dependencies = [ + "anyhow", + "ark-bn254", + "ark-ec", + "ark-ff", + "ark-groth16", + "ark-serialize", + "bytemuck", + "hex", + "num-bigint", + "num-traits", + "risc0-binfmt", + "risc0-zkp", + "serde", +] + +[[package]] +name = "risc0-zkos-v1compat" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bd70cb45b5d37d025f25663b87c6b9dc9df7f413ee2068531a57f50b0eb95db" +dependencies = [ + "include_bytes_aligned", + "no_std_strings", + "risc0-zkvm-platform", +] + +[[package]] +name = "risc0-zkp" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f40d362a6c146ec6dc69208f539b92fd86e47b0dbc2083801423034a38155a2" +dependencies = [ + "anyhow", + "blake2", + "borsh", + "bytemuck", + "cfg-if", + "digest", + "hex", + "hex-literal", + "metal", + "paste", + "rand_core 0.9.5", + "risc0-core", + "risc0-zkvm-platform", + "serde", + "sha2", + "stability", + "tracing", +] + +[[package]] +name = "risc0-zkvm" +version = "3.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22b7eafb5d85be59cbd9da83f662cf47d834f1b836e14f675d1530b12c666867" +dependencies = [ + "anyhow", + "borsh", + "bytemuck", + "derive_more", + "hex", + "risc0-binfmt", + "risc0-circuit-keccak", + "risc0-circuit-recursion", + "risc0-circuit-rv32im", + "risc0-core", + "risc0-groth16", + "risc0-zkos-v1compat", + "risc0-zkp", + "risc0-zkvm-platform", + "rrs-lib", + "semver", + "serde", + "sha2", + "stability", + "tracing", +] + +[[package]] +name = "risc0-zkvm-platform" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4db893788c416287e2e1a87e6b8f5302511a04a45329e699d6a32a16874fd24f" +dependencies = [ + "bytemuck", + "cfg-if", + "getrandom 0.2.17", + "getrandom 0.3.4", + "libm", + "num_enum", + "paste", + "stability", +] + +[[package]] +name = "rrs-lib" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4382d3af3a4ebdae7f64ba6edd9114fff92c89808004c4943b393377a25d001" +dependencies = [ + "downcast-rs", + "paste", +] + +[[package]] +name = "ruint" +version = "1.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c141e807189ad38a07276942c6623032d3753c8859c146104ac2e4d68865945a" +dependencies = [ + "borsh", + "proptest", + "rand 0.8.5", + "rand 0.9.2", + "ruint-macro", + "serde_core", + "valuable", + "zeroize", +] + +[[package]] +name = "ruint-macro" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" + +[[package]] +name = "rust" +version = "0.1.0" +dependencies = [ + "anyhow", + "fabric", + "hex", + "tokio", +] + +[[package]] +name = "rustc-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustls" +version = "0.23.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df33b2b81ac578cabaf06b89b0631153a3f416b0a886e8a7a1707fb51abbd1ef" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "ryu" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "secp256k1" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9465315bc9d4566e1724f0fffcbcc446268cb522e60f9a27bcded6b19c108113" +dependencies = [ + "bitcoin_hashes", + "secp256k1-sys", + "serde", +] + +[[package]] +name = "secp256k1-sys" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4387882333d3aa8cb20530a17c69a3752e97837832f34f6dccc760e715001d9" +dependencies = [ + "cc", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "serde_json" +version = "1.0.149" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "sip7" +version = "0.1.0" +source = "git+https://github.com/spacesprotocol/spaces.git?branch=subspaces#8bfdffc02d7a49c07f7bf7da77d63a606a502515" +dependencies = [ + "base64 0.22.1", + "hex", + "serde", + "spaces_protocol", +] + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "spacedb" +version = "0.0.12" +source = "git+https://github.com/spacesprotocol/spacedb.git#43f23e78e4e5fffb8d89661a4b7f39ab43a5a644" +dependencies = [ + "borsh", + "sha2", +] + +[[package]] +name = "spaces_nums" +version = "0.1.0" +source = "git+https://github.com/spacesprotocol/spaces.git?branch=subspaces#8bfdffc02d7a49c07f7bf7da77d63a606a502515" +dependencies = [ + "bech32", + "bitcoin", + "borsh", + "borsh_utils", + "hex", + "log", + "serde", + "spaces_protocol", +] + +[[package]] +name = "spaces_protocol" +version = "0.0.7" +source = "git+https://github.com/spacesprotocol/spaces.git?branch=subspaces#8bfdffc02d7a49c07f7bf7da77d63a606a502515" +dependencies = [ + "bitcoin", + "borsh", + "borsh_utils", + "serde", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "stability" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d904e7009df136af5297832a3ace3370cd14ff1546a232f4f185036c2736fcac" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tinystr" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bd1c4c0fc4a7ab90fc15ef6daaa3ec3b893f004f915f2392557ed23237820cd" +dependencies = [ + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-macros" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_edit" +version = "0.25.10+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82418ca169e235e6c399a84e395ab6debeb3bc90edc959bf0f48647c6a32d1b" +dependencies = [ + "indexmap", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" +dependencies = [ + "winnow", +] + +[[package]] +name = "tower" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +dependencies = [ + "bitflags 2.11.0", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-subscriber" +version = "0.2.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e0d2eaa99c3c2e41547cfa109e910a68ea03823cccad4a0525dcbc9b01e8c71" +dependencies = [ + "tracing-core", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + +[[package]] +name = "unarray" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasip2" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03623de6905b7206edd0a75f69f747f134b7f0a2323392d664448bf2d3c5d87e" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2" +dependencies = [ + "bumpalo", + "proc-macro2", + "quote", + "syn 2.0.117", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0a" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winnow" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" + +[[package]] +name = "writeable" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" + +[[package]] +name = "yoke" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zerofrom" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zerotrie" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/fabric/examples/rust/Cargo.toml b/fabric/examples/rust/Cargo.toml new file mode 100644 index 0000000..928bef0 --- /dev/null +++ b/fabric/examples/rust/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "rust" +version = "0.1.0" +edition = "2024" + +[[bin]] +name = "example-rust" +path = "src/main.rs" + +[workspace] + + +[dependencies] +fabric = { path = "../../../fabric/rust", features = ["client", "signing"] } +anyhow = "1.0.102" +tokio = "1.38.2" +hex = "0.4.3" diff --git a/fabric/examples/rust/src/main.rs b/fabric/examples/rust/src/main.rs new file mode 100644 index 0000000..3caab8c --- /dev/null +++ b/fabric/examples/rust/src/main.rs @@ -0,0 +1,228 @@ +use fabric::client::{Fabric}; +use fabric::libveritas::builder::MessageBuilder; +use fabric::libveritas::cert::CertificateChain; +use fabric::libveritas::msg::ChainProof; +use fabric::libveritas::sip7::{ParsedRecord, Record, RecordSet, SIG_PRIMARY_ZONE}; +use fabric::signing::sign_schnorr; + +/// Resolve a single handle +async fn example_resolve() -> anyhow::Result<()> { + // + let fabric = Fabric::new(); + let Some(resolved) = fabric.resolve("alice@bitcoin").await? else { + println!("handle not found"); + return Ok(()); + }; + + println!("Handle found: {}", resolved.zone.handle); + // + + Ok(()) +} + +/// Verification +async fn example_trust_and_verification() -> anyhow::Result<()> { + let fabric = Fabric::new(); + + // + // Before pinning a trust id: resolve uses observed (peer) state + // badge() returns Unverified + let resolved = fabric.resolve("alice@bitcoin").await? + .expect("handle exists"); + fabric.badge(&resolved); // Unverified + + // Pin trust from a QR scan + let qr = "veritas://scan?id=14ef902621df01bdeee0b23fedf67458563a20df600af8979a4748dcd9d1b9f9"; + + // For highest level of trust (scan QR code from Veritas desktop) + fabric.trust_from_qr(qr).await?; + + // Does not require re-resolving, badge now checks + // whether resolved was against a trusted root + fabric.badge(&resolved); // Orange if handle is sovereign (final certificate) + + // Or from a semi-trusted source (e.g. an explorer you trust with qr scanned over HTTPS) + // .badge() will not show Orange for roots in this trust pool, + // but it will not report it as "Unverified". + fabric.semi_trust_from_qr(qr).await?; + + // Check current trust ids + fabric.trusted(); // pinned id from local verification + fabric.semi_trusted(); // pinned id from semi-trusted source + fabric.observed(); // latest from peers + + // Clear trusted state + fabric.clear_trusted(); + fabric.clear_semi_trusted(); + + // + + Ok(()) +} + +/// Unpack records from a resolved handle +async fn example_unpack_records() -> anyhow::Result<()> { + let fabric = Fabric::new(); + let resolved = fabric.resolve("alice@bitcoin").await?.expect("handle exists"); + + // + for record in resolved.zone.records.unpack()? { + match record { + ParsedRecord::Txt { key, value } => { + println!("txt {}={}", key, value.to_vec().join(", ")) + } + ParsedRecord::Addr { key, value } => { + println!("addr {}={}", key, value.to_vec().join(", ")) + } + _ => {} + } + } + // + + Ok(()) +} + +/// Resolve multiple handles +async fn example_resolve_all() -> anyhow::Result<()> { + let fabric = Fabric::new(); + + // + let batch = fabric + .resolve_all(&["alice@bitcoin", "bob@bitcoin"]) + .await?; + + for zone in &batch.zones { + println!("{}: {:?}", zone.handle, zone.sovereignty); + } + // + + Ok(()) +} + +/// Pack records into a RecordSet +fn example_pack_records() -> anyhow::Result<()> { + // + let records = RecordSet::pack(vec![ + Record::seq(1), + Record::txt("website", &["https://example.com"]), + Record::addr("btc", &["bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"]), + Record::addr("nostr", &[ + "npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6", + "wss://relay.example.com", + ]), + ])?; + // + + let _ = records; + Ok(()) +} + +/// Publish signed records +async fn example_publish() -> anyhow::Result<()> { + let fabric = Fabric::new(); + let secret_key: [u8; 32] = hex::decode( + "0000000000000000000000000000000000000000000000000000000000000001", + )? + .try_into() + .unwrap(); + + let records = RecordSet::pack(vec![ + Record::seq(1), + Record::txt("website", &["https://example.com"]), + Record::addr("btc", &["bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"]), + ])?; + + // + let cert = fabric.export("alice@bitcoin").await?; + fabric.publish(&cert, records, &secret_key, true).await?; + // + + Ok(()) +} + +/// Resolve by numeric ID +async fn example_resolve_by_id() -> anyhow::Result<()> { + let fabric = Fabric::new(); + + // + let Some(resolved) = fabric.resolve_by_id("num1qx8dtlzq...").await? else { + println!("handle not found"); + return Ok(()); + }; + + println!("Handle found: {}", resolved.zone.handle); + // + + Ok(()) +} + +/// Search by address +async fn example_search_addr() -> anyhow::Result<()> { + let fabric = Fabric::new(); + + // + let batch = fabric + .search_addr("btc", "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4") + .await?; + + for zone in &batch.zones { + println!("{}: {:?}", zone.handle, zone.sovereignty); + } + // + + Ok(()) +} + +/// Advanced: Build and broadcast a message manually +async fn example_message_builder() -> anyhow::Result<()> { + let fabric = Fabric::new(); + let secret_key: [u8; 32] = hex::decode( + "0000000000000000000000000000000000000000000000000000000000000001", + )? + .try_into() + .unwrap(); + + let cert_bytes = fabric.export("alice@bitcoin").await?; + let records = RecordSet::pack(vec![ + Record::seq(1), + Record::addr("btc", &["bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"]), + ])?; + + // + let cert = CertificateChain::from_slice(&cert_bytes)?; + let mut builder = MessageBuilder::new(); + builder.add_handle(cert, records); + + let proof = ChainProof::from_slice( + &fabric.prove(&builder.chain_proof_request()).await?, + )?; + + let (mut msg, unsigned) = builder.build(proof)?; + + for mut u in unsigned { + u.flags |= SIG_PRIMARY_ZONE; + let sig = sign_schnorr(&u.signing_id(), &secret_key)?; + msg.set_records(&u.canonical, u.pack_sig(sig.to_vec())); + } + + fabric.broadcast(&msg.to_bytes()).await?; + // + + Ok(()) +} + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + example_resolve().await?; + let _ = example_trust_and_verification().await; + example_unpack_records().await?; + example_resolve_all().await?; + example_pack_records()?; + example_publish().await?; + example_resolve_by_id().await?; + example_search_addr().await?; + example_message_builder().await?; + + println!("Done!"); + Ok(()) +} \ No newline at end of file diff --git a/fabric/examples/swift/Example.swift b/fabric/examples/swift/Example.swift new file mode 100644 index 0000000..faa32c4 --- /dev/null +++ b/fabric/examples/swift/Example.swift @@ -0,0 +1,213 @@ +import Fabric + +/// Resolve a single handle +func exampleResolve() async throws { + // + let fabric = Fabric() + guard let resolved = try await fabric.resolve("alice@bitcoin") else { + print("handle not found") + return + } + + print("Handle found: \(resolved.zone.handle)") + // +} + +/// Verification +func exampleTrustAndVerification() async throws { + let fabric = Fabric() + + // + // Before pinning a trust id: resolve uses observed (peer) state + // badge() returns Unverified + let resolved = try await fabric.resolve("alice@bitcoin")! + + fabric.badge(resolved) // Unverified + + // Pin trust from a QR scan + let qr = "veritas://scan?id=14ef902621df01bdeee0b23fedf67458563a20df600af8979a4748dcd9d1b9f9" + + // For highest level of trust (scan QR code from Veritas desktop) + try await fabric.trustFromQr(qr) + + // Does not require re-resolving, badge now checks + // whether resolved was against a trusted root + fabric.badge(resolved) // Orange if handle is sovereign (final certificate) + + // Or from a semi-trusted source (e.g. an explorer you trust with qr scanned over HTTPS) + // .badge() will not show Orange for roots in this trust pool, + // but it will not report it as "Unverified". + try await fabric.semiTrustFromQr(qr) + + // Check current trust ids + fabric.trusted() // pinned id from local verification + fabric.semiTrusted() // pinned id from semi-trusted source + fabric.observed() // latest from peers + + // Clear trusted state + fabric.clearTrusted() + fabric.clearSemiTrusted() + + // +} + +/// Unpack records from a resolved handle +func exampleUnpackRecords() async throws { + let fabric = Fabric() + let resolved = try await fabric.resolve("alice@bitcoin")! + + // + let records = try resolved.zone.records.unpack() + + for record in records { + switch record { + case .txt(let key, let value): + print("txt \(key)=\(value.joined(separator: ", "))") + case .addr(let key, let value): + print("addr \(key)=\(value.joined(separator: ", "))") + default: + break + } + } + // +} + +/// Resolve multiple handles +func exampleResolveAll() async throws { + let fabric = Fabric() + + // + let batch = try await fabric.resolveAll(["alice@bitcoin", "bob@bitcoin"]) + + for zone in batch.zones { + print("\(zone.handle): \(zone.sovereignty)") + } + // +} + +/// Pack records into a RecordSet +func examplePackRecords() throws { + // + let records = try RecordSet.pack([ + Record.seq(1), + Record.txt("website", ["https://example.com"]), + Record.addr("btc", ["bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"]), + Record.addr("nostr", [ + "npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6", + "wss://relay.example.com", + ]), + ]) + // + + _ = records +} + +/// Publish signed records +func examplePublish() async throws { + let fabric = Fabric() + let secretKey = Data(hex: + "0000000000000000000000000000000000000000000000000000000000000001" + ) + + let rs = try RecordSet.pack([ + Record.seq(1), + Record.txt("website", ["https://example.com"]), + Record.addr("btc", ["bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"]), + ]) + + // + let cert = try await fabric.export("alice@bitcoin") + try await fabric.publish(cert, rs, secretKey, primary: true) + // +} + +/// Resolve by numeric ID +func exampleResolveById() async throws { + let fabric = Fabric() + + // + guard let resolved = try await fabric.resolveById("num1qx8dtlzq...") else { + print("handle not found") + return + } + + print("Handle found: \(resolved.zone.handle)") + // +} + +/// Search by address +func exampleSearchAddr() async throws { + let fabric = Fabric() + + // + let batch = try await fabric.searchAddr("btc", "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4") + + for zone in batch.zones { + print("\(zone.handle): \(zone.sovereignty)") + } + // +} + +/// Advanced: Build and broadcast a message manually +func exampleMessageBuilder() async throws { + let fabric = Fabric() + let secretKey = Data(hex: + "0000000000000000000000000000000000000000000000000000000000000001" + ) + + let certBytes = try await fabric.export("alice@bitcoin") + let records = try RecordSet.pack([ + Record.seq(1), + Record.addr("btc", ["bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4"]), + ]) + + // + let cert = try CertificateChain.fromSlice(certBytes) + var builder = MessageBuilder() + builder.addHandle(cert, records) + + let proofBytes = try await fabric.prove(builder.chainProofRequest()) + let proof = try ChainProof.fromSlice(proofBytes) + + var (msg, unsigned) = try builder.build(proof) + + for var u in unsigned { + u.flags |= SIG_PRIMARY_ZONE + let sig = try signSchnorr(u.signingId(), secretKey) + msg.setRecords(u.canonical, u.packSig(sig)) + } + + try await fabric.broadcast(msg.toBytes()) + // +} + +@main +struct Example { + static func main() async { + do { + try await exampleResolve() + } catch { + print("resolve failed: \(error)") + } + + do { + try await exampleTrustAndVerification() + } catch { + print("verification example failed (expected): \(error)") + } + + do { + try await exampleUnpackRecords() + try await exampleResolveAll() + try examplePackRecords() + try await examplePublish() + try await exampleResolveById() + try await exampleSearchAddr() + try await exampleMessageBuilder() + } catch { + print("error: \(error)") + } + + print("Done!") + } +} diff --git a/fabric/examples/test-example.sh b/fabric/examples/test-example.sh new file mode 100755 index 0000000..a821c6e --- /dev/null +++ b/fabric/examples/test-example.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +set -eo pipefail +# +# Test an example by replacing placeholder values with real ones. +# +# Usage: +# HANDLE=@buffrr SECRET_KEY=abc... ./test-example.sh rust +# +# Required env vars: +# HANDLE — handle to resolve/publish (e.g. @buffrr) +# SECRET_KEY — 64-char hex secret key for signing +# +# Optional: +# HANDLES — comma-separated batch (default: HANDLE repeated) +# BTC_ADDR — Bitcoin address to use +# NPUB — Nostr npub to use +# NUM_ID — Numeric ID for resolve_by_id +# + +LANG="${1:?Usage: test-example.sh }" + +HANDLE="${HANDLE:?Set HANDLE env var}" +SECRET_KEY="${SECRET_KEY:?Set SECRET_KEY env var}" +HANDLES="${HANDLES:-$HANDLE}" +BTC_ADDR="${BTC_ADDR:-bc1qtest$(date +%s)}" +NPUB="${NPUB:-npub1placeholder}" +NUM_ID="${NUM_ID:-num1placeholder}" + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +TMPDIR=$(mktemp -d) +trap "rm -rf $TMPDIR" EXIT + +echo "==> Copying $LANG example to $TMPDIR" +cp -r "$SCRIPT_DIR/$LANG" "$TMPDIR/$LANG" + +REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" + +echo "==> Replacing placeholders" +find "$TMPDIR/$LANG" -type f \( -name "*.rs" -o -name "*.ts" -o -name "*.js" -o -name "*.go" -o -name "*.py" -o -name "*.kt" -o -name "*.swift" -o -name "*.toml" \) | while read f; do + sed -i.bak \ + -e "s|alice@bitcoin|$HANDLE|g" \ + -e "s|bob@bitcoin|$HANDLES|g" \ + -e "s|@bitcoin|$(echo $HANDLE | grep -o '[@#].*')|g" \ + -e "s|bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4|$BTC_ADDR|g" \ + -e "s|npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6|$NPUB|g" \ + -e "s|num1qx8dtlzq\.\.\.|$NUM_ID|g" \ + -e "s|0000000000000000000000000000000000000000000000000000000000000001|$SECRET_KEY|g" \ + -e "s|path = \"../../../fabric/rust\"|path = \"$REPO_ROOT/fabric/rust\"|g" \ + "$f" + rm -f "$f.bak" +done + +echo "==> Building and running" +case "$LANG" in + rust) + cd "$TMPDIR/$LANG" + cargo run 2>&1 + ;; + *) + echo "Language '$LANG' not yet supported" + exit 1 + ;; +esac \ No newline at end of file diff --git a/fabric/go/fabric.go b/fabric/go/fabric.go index 683c2c1..4fd370e 100644 --- a/fabric/go/fabric.go +++ b/fabric/go/fabric.go @@ -147,10 +147,8 @@ type Fabric struct { mu sync.Mutex } -func New(seeds []string) *Fabric { - if seeds == nil { - seeds = DefaultSeeds - } +func New() *Fabric { + seeds := DefaultSeeds return &Fabric{ client: &http.Client{}, seeds: seeds, @@ -161,6 +159,7 @@ func New(seeds []string) *Fabric { func (f *Fabric) SetDevMode(v bool) { f.devMode = v } func (f *Fabric) SetPreferLatest(v bool) { f.preferLatest = v } +func (f *Fabric) SetSeeds(seeds []string) { f.seeds = seeds } func (f *Fabric) Relays() []string { return f.pool.URLs() } @@ -553,7 +552,7 @@ func (f *Fabric) SearchAddr(name, addr string) (ResolvedBatch, error) { continue } for _, r := range records { - if a, ok := r.(libveritas.RecordAddr); ok { + if a, ok := r.(libveritas.ParsedRecordAddr); ok { if a.Key == name && len(a.Value) > 0 && a.Value[0] == addr { matching = append(matching, z) break diff --git a/fabric/go/go.mod b/fabric/go/go.mod index 68190a7..25a4b87 100644 --- a/fabric/go/go.mod +++ b/fabric/go/go.mod @@ -4,7 +4,7 @@ go 1.22 require ( github.com/btcsuite/btcd/btcec/v2 v2.3.6 - github.com/spacesprotocol/libveritas-go v0.0.0-dev.20260401232107 + github.com/spacesprotocol/libveritas-go v0.0.0-dev.20260407170108 ) require ( diff --git a/fabric/go/go.sum b/fabric/go/go.sum index 1c20193..6c01b1f 100644 --- a/fabric/go/go.sum +++ b/fabric/go/go.sum @@ -8,5 +8,5 @@ github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= -github.com/spacesprotocol/libveritas-go v0.0.0-dev.20260401232107 h1:G6iAm4v0s08uKtVys3h8oDeJ2gMTwjpXcODHq1Mazis= -github.com/spacesprotocol/libveritas-go v0.0.0-dev.20260401232107/go.mod h1:HXnX2FNL43ueJuedsQwX9GF5jRHYZLqXYfFLWz900H8= +github.com/spacesprotocol/libveritas-go v0.0.0-dev.20260407170108 h1:tpFQOIBRJpM0dYYc4VpAh/OayA8ZPvqr1taTuSZdQ98= +github.com/spacesprotocol/libveritas-go v0.0.0-dev.20260407170108/go.mod h1:HXnX2FNL43ueJuedsQwX9GF5jRHYZLqXYfFLWz900H8= diff --git a/fabric/go/libveritas.go b/fabric/go/libveritas.go deleted file mode 100644 index 05b010b..0000000 --- a/fabric/go/libveritas.go +++ /dev/null @@ -1,22 +0,0 @@ -package fabric - -// Re-export libveritas types so consumers can use them without a separate import. - -import libveritas "github.com/spacesprotocol/libveritas-go" - -type Zone = libveritas.Zone -type Message = libveritas.Message -type MessageBuilder = libveritas.MessageBuilder -type Anchors = libveritas.Anchors -type Veritas = libveritas.Veritas -type QueryContext = libveritas.QueryContext -type VerifiedMessage = libveritas.VerifiedMessage -type Lookup = libveritas.Lookup -type RecordSet = libveritas.RecordSet -type Record = libveritas.Record -type DataUpdateEntry = libveritas.DataUpdateEntry -type CommitmentState = libveritas.CommitmentState -type DelegateState = libveritas.DelegateState -type VeritasError = libveritas.VeritasError - -var CreateCertificateChain = libveritas.CreateCertificateChain diff --git a/fabric/js/fabric-react-native/package.json b/fabric/js/fabric-react-native/package.json index 329b71c..01a19b8 100644 --- a/fabric/js/fabric-react-native/package.json +++ b/fabric/js/fabric-react-native/package.json @@ -23,7 +23,7 @@ }, "dependencies": { "@spacesprotocol/fabric-core": "*", - "@spacesprotocol/react-native-libveritas": "0.0.0-dev.20260401232841", + "@spacesprotocol/react-native-libveritas": "0.0.0-dev.20260407170644", "uniffi-bindgen-react-native": "0.29.3-1" }, "devDependencies": { diff --git a/fabric/js/fabric-web/package.json b/fabric/js/fabric-web/package.json index b6a5300..4b40008 100644 --- a/fabric/js/fabric-web/package.json +++ b/fabric/js/fabric-web/package.json @@ -27,7 +27,7 @@ "dependencies": { "@noble/curves": "^1.8.0", "@spacesprotocol/fabric-core": "*", - "@spacesprotocol/libveritas": "^0.0.0-dev.20260401231450" + "@spacesprotocol/libveritas": "^0.0.0-dev.20260407165333" }, "devDependencies": { "@types/node": "^25.5.0", diff --git a/fabric/js/package-lock.json b/fabric/js/package-lock.json index 9579d0b..aba5223 100644 --- a/fabric/js/package-lock.json +++ b/fabric/js/package-lock.json @@ -28,7 +28,7 @@ "license": "MIT", "dependencies": { "@spacesprotocol/fabric-core": "*", - "@spacesprotocol/react-native-libveritas": "0.0.0-dev.20260401232841", + "@spacesprotocol/react-native-libveritas": "0.0.0-dev.20260407170644", "uniffi-bindgen-react-native": "0.29.3-1" }, "devDependencies": { @@ -42,7 +42,7 @@ "dependencies": { "@noble/curves": "^1.8.0", "@spacesprotocol/fabric-core": "*", - "@spacesprotocol/libveritas": "^0.0.0-dev.20260401231450" + "@spacesprotocol/libveritas": "^0.0.0-dev.20260407165333" }, "bin": { "fabric": "dist/cli.js" @@ -972,14 +972,14 @@ "link": true }, "node_modules/@spacesprotocol/libveritas": { - "version": "0.0.0-dev.20260401231450", - "resolved": "https://registry.npmjs.org/@spacesprotocol/libveritas/-/libveritas-0.0.0-dev.20260401231450.tgz", - "integrity": "sha512-XjMSrkUaXOfkLdScIUmaMb0OabFcB9sh6ZITVr2czsYFgphrl7htSlRuzC33NK6fsIGOw/I6BYuY/OHH14ZVNQ==" + "version": "0.0.0-dev.20260407165333", + "resolved": "https://registry.npmjs.org/@spacesprotocol/libveritas/-/libveritas-0.0.0-dev.20260407165333.tgz", + "integrity": "sha512-YTBvFbODHzr5XhpApkDuFXf6eWy+kqhCV+7rYHXDW/YYd25uWqqcAOIRXRPPGxRNgzbviDFqMRNAuhy5Vtc7UQ==" }, "node_modules/@spacesprotocol/react-native-libveritas": { - "version": "0.0.0-dev.20260401232841", - "resolved": "https://registry.npmjs.org/@spacesprotocol/react-native-libveritas/-/react-native-libveritas-0.0.0-dev.20260401232841.tgz", - "integrity": "sha512-YgDrRKwc7vFHvCK/xU3nPHQXR8F3lpS217hqeqGMV6KEWphe1L+ev2OsBdQKucYbAymagSpCpJt1C8Y1YVZcaQ==", + "version": "0.0.0-dev.20260407170644", + "resolved": "https://registry.npmjs.org/@spacesprotocol/react-native-libveritas/-/react-native-libveritas-0.0.0-dev.20260407170644.tgz", + "integrity": "sha512-EZ4ZFmd/ik8DeIqq8gBN0ZInTNDF9QkLUeeHkzEe6C7MGEb7aXW8hegi2n+voyfd8XV6hozXaCaapKyUzCWl6Q==", "license": "MIT", "peerDependencies": { "react": "*", diff --git a/fabric/kotlin/build.gradle.kts b/fabric/kotlin/build.gradle.kts index 9434ae1..dab75f6 100644 --- a/fabric/kotlin/build.gradle.kts +++ b/fabric/kotlin/build.gradle.kts @@ -19,9 +19,9 @@ dependencies { // compileOnly — consumers provide the right variant at runtime: // Android: org.spacesprotocol:libveritas (AAR) // JVM: org.spacesprotocol:libveritas-jvm (JAR) - compileOnly("org.spacesprotocol:libveritas-jvm:0.0.0-dev.20260401232452") + compileOnly("org.spacesprotocol:libveritas-jvm:0.0.0-dev.20260407170200") // CLI needs it at runtime - runtimeOnly("org.spacesprotocol:libveritas-jvm:0.0.0-dev.20260401232452") + runtimeOnly("org.spacesprotocol:libveritas-jvm:0.0.0-dev.20260407170200") implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3") compileOnly("fr.acinq.secp256k1:secp256k1-kmp:0.17.3") diff --git a/fabric/kotlin/src/main/kotlin/org/spacesprotocol/fabric/Fabric.kt b/fabric/kotlin/src/main/kotlin/org/spacesprotocol/fabric/Fabric.kt index cf0448e..325a207 100644 --- a/fabric/kotlin/src/main/kotlin/org/spacesprotocol/fabric/Fabric.kt +++ b/fabric/kotlin/src/main/kotlin/org/spacesprotocol/fabric/Fabric.kt @@ -285,7 +285,7 @@ class Fabric( try { val rs = RecordSet(bytes) rs.unpack().any { r -> - r is Record.Addr && r.key == name && r.value.isNotEmpty() && r.value[0] == addr + r is ParsedRecord.Addr && r.key == name && r.value.isNotEmpty() && r.value[0] == addr } } catch (_: Exception) { false } } ?: false diff --git a/fabric/kotlin/src/main/kotlin/org/spacesprotocol/fabric/Libveritas.kt b/fabric/kotlin/src/main/kotlin/org/spacesprotocol/fabric/Libveritas.kt index 83dde40..a904999 100644 --- a/fabric/kotlin/src/main/kotlin/org/spacesprotocol/fabric/Libveritas.kt +++ b/fabric/kotlin/src/main/kotlin/org/spacesprotocol/fabric/Libveritas.kt @@ -14,6 +14,7 @@ typealias VerifiedMessage = org.spacesprotocol.libveritas.VerifiedMessage typealias Lookup = org.spacesprotocol.libveritas.Lookup typealias RecordSet = org.spacesprotocol.libveritas.RecordSet typealias Record = org.spacesprotocol.libveritas.Record +typealias ParsedRecord = org.spacesprotocol.libveritas.ParsedRecord typealias DataUpdateEntry = org.spacesprotocol.libveritas.DataUpdateEntry typealias CommitmentState = org.spacesprotocol.libveritas.CommitmentState typealias DelegateState = org.spacesprotocol.libveritas.DelegateState diff --git a/fabric/python/pyproject.toml b/fabric/python/pyproject.toml index ebfda41..85274f1 100644 --- a/fabric/python/pyproject.toml +++ b/fabric/python/pyproject.toml @@ -3,7 +3,7 @@ name = "fabric-resolver" version = "0.1.0" description = "Python client for the certrelay fabric network" requires-python = ">=3.10" -dependencies = ["libveritas==0.0.0.dev20260401231357"] +dependencies = ["libveritas==0.0.0.dev20260407165216"] [project.optional-dependencies] signing = ["coincurve"] diff --git a/fabric/rust/src/client.rs b/fabric/rust/src/client.rs index 12f003e..cd04b13 100644 --- a/fabric/rust/src/client.rs +++ b/fabric/rust/src/client.rs @@ -112,8 +112,8 @@ enum TrustKind { Observed, } -/// UI badge state derived from trust + sovereignty. -pub enum VerificationBadge { +/// UI badge status derived from trust + sovereignty. +pub enum Badge { /// Sovereign handle verified against a trusted root. Show orange checkmark. Orange, /// Resolved against an observed root that differs from the trusted set. @@ -123,6 +123,16 @@ pub enum VerificationBadge { None, } +impl fmt::Display for Badge { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Badge::Orange => write!(f, "orange"), + Badge::Unverified => write!(f, "unverified"), + Badge::None => write!(f, "none"), + } + } +} + #[derive(Clone, Serialize, Deserialize)] pub struct ResolvedBatch { pub zones: Vec, @@ -204,21 +214,21 @@ impl Fabric { true } - pub fn badge(&self, resolved: &Resolved) -> VerificationBadge { + pub fn badge(&self, resolved: &Resolved) -> Badge { self.badge_for(resolved.zone.sovereignty, resolved.roots.as_slice()) } - pub fn badge_for(&self, sov: SovereigntyState, roots: &[TrustId]) -> VerificationBadge { + pub fn badge_for(&self, sov: SovereigntyState, roots: &[TrustId]) -> Badge { let is_trusted = self.are_roots_trusted(roots); let is_observed = is_trusted || self.are_roots_observed(roots); let is_semi_trusted = is_trusted || self.are_roots_semi_trusted(roots); if is_trusted && matches!(sov, SovereigntyState::Sovereign) { - VerificationBadge::Orange + Badge::Orange } else if is_observed && !is_trusted && !is_semi_trusted { - VerificationBadge::Unverified + Badge::Unverified } else { - VerificationBadge::None + Badge::None } } @@ -292,6 +302,11 @@ impl Fabric { *self.trusted.lock().unwrap() = None; } + /// Clear the semi trusted state. + pub fn clear_semi_trusted(&self) { + *self.semi_trusted.lock().unwrap() = None; + } + /// Set whether to query multiple relays for freshness hints before resolving. pub fn set_prefer_latest(&self, latest: bool) { self.prefer_latest.store(latest, Ordering::Relaxed); @@ -383,31 +398,26 @@ impl Fabric { /// Resolve a single handle and return its verified Zone. /// Supports dotted names like `hello.alice@bitcoin`. - pub async fn resolve(&self, handle: &str) -> Result { + pub async fn resolve(&self, handle: &str) -> Result> { let rb = self.resolve_all(&[handle]).await?; let zone = rb.zones.into_iter() - .find(|z| z.handle.to_string() == handle) - .ok_or_else(|| { - Error::Decode(std::io::Error::new( - std::io::ErrorKind::NotFound, - format!("{handle} not found"), - )) - })?; - Ok(Resolved { - zone, + .find(|z| z.handle.to_string() == handle); + Ok(zone.map(|z| Resolved { + zone: z, roots: rb.roots, relays: rb.relays, - }) + })) } /// Reverse-resolve by a num id to retrieve its human-readable name. /// /// Queries relays for the reverse mapping, resolves the forward name, /// and verifies the zone's num_id matches. - pub async fn resolve_by_id(&self, num_id: &str) -> Result { + pub async fn resolve_by_id(&self, num_id: &str) -> Result> { self.bootstrap().await?; let relays = self.pool.shuffled_urls_n(4); - let mut last_err = Error::NoPeers; + let mut last_err: Option = None; + let mut any_responded = false; for url in &relays { // 1. Fetch reverse mapping @@ -426,15 +436,18 @@ impl Fabric { _ => continue, }; + any_responded = true; + let Some(entry) = records.iter().find(|r| r.id == num_id) else { continue; }; // 2. Resolve forward let resolved = match self.resolve(&entry.name).await { - Ok(r) => r, + Ok(Some(r)) => r, + Ok(None) => continue, Err(e) => { - last_err = e; + last_err = Some(e); continue; } }; @@ -444,17 +457,22 @@ impl Fabric { .as_ref() .map(|id| id.to_string()); if zone_num_id.as_deref() != Some(num_id) { - last_err = Error::Decode(std::io::Error::new( + last_err = Some(Error::Decode(std::io::Error::new( std::io::ErrorKind::InvalidData, format!("reverse mismatch: expected {num_id}, got {:?}", zone_num_id), - )); + ))); continue; } - return Ok(resolved); + return Ok(Some(resolved)); } - Err(last_err) + // If relays responded but had no mapping, assume not found + if any_responded && last_err.is_none() { + return Ok(None); + } + + Err(last_err.unwrap_or(Error::NoPeers)) } /// Search for handles by address record. @@ -503,10 +521,12 @@ impl Fabric { // 3. Filter to zones that actually have the matching addr record let matching_zones: Vec = batch.zones.into_iter() .filter(|zone| { - zone.records.iter().filter_map(|r| r.ok()).any(|r| { - matches!(&r, libveritas::sip7::Record::Addr { key, value } - if key == name && value.first().map(|v| v.as_str()) == Some(addr)) - }) + zone.records.iter() + .map(|rrs| rrs.iter().any(|r| { + matches!(r, libveritas::sip7::ParsedRecord::Addr { key, value } + if key == name && value.iter().next() == Some(addr)) + })) + .unwrap_or(false) }) .collect(); @@ -1144,6 +1164,15 @@ async fn fetch_latest_trust_id(http: &reqwest::Client, peers: &[String]) -> Resu } }; + if !resp.status().is_success() { + let status = resp.status().as_u16(); + last_err = Some(Error::Relay { + status, + body: format!("HEAD {url}/anchors: {status}"), + }); + continue; + } + let root = resp .headers() .get("x-anchor-root") diff --git a/fabric/swift/Package.swift b/fabric/swift/Package.swift index 3bf83f9..8026cc8 100644 --- a/fabric/swift/Package.swift +++ b/fabric/swift/Package.swift @@ -9,7 +9,7 @@ let package = Package( .executable(name: "fabric", targets: ["FabricCLI"]), ], dependencies: [ - .package(url: "https://github.com/spacesprotocol/libveritas-swift.git", exact: "0.0.0-dev.20260401232716"), + .package(url: "https://github.com/spacesprotocol/libveritas-swift.git", exact: "0.0.0-dev.20260407170713"), .package(url: "https://github.com/21-DOT-DEV/swift-secp256k1.git", exact: "0.17.0"), ], targets: [ diff --git a/fabric/swift/Sources/Fabric/Fabric.swift b/fabric/swift/Sources/Fabric/Fabric.swift index 630936f..93b27aa 100644 --- a/fabric/swift/Sources/Fabric/Fabric.swift +++ b/fabric/swift/Sources/Fabric/Fabric.swift @@ -383,9 +383,8 @@ public final class Fabric: @unchecked Sendable { // Filter to zones that actually contain the matching addr record let matching = batch.zones.filter { z in - guard let bytes = z.records else { return false } do { - let rs = RecordSet(data: bytes) + let rs = RecordSet(data: z.records) let records = try rs.unpack() return records.contains { r in if case .addr(let k, let v) = r, k == name, let first = v.first, first == addr { diff --git a/relay/src/handler.rs b/relay/src/handler.rs index a73fc63..d2f46aa 100644 --- a/relay/src/handler.rs +++ b/relay/src/handler.rs @@ -11,7 +11,7 @@ use std::str::FromStr; use std::sync::Mutex; use std::sync::atomic::{AtomicU64, Ordering}; use libveritas::builder::{DataUpdateRequest, MessageBuilder}; -use libveritas::sip7::{Error, Record, RecordSet, SIG_PRIMARY_ZONE}; +use libveritas::sip7::{Error, ParsedRecord, Record, RecordSet, SIG_PRIMARY_ZONE}; use resolver::{EpochResult, HandleHint, SpaceHint}; use crate::anchor::AnchorSets; use crate::spaced::SpacedClient; @@ -261,14 +261,20 @@ impl Handler { } } // Collect addr records for the index - let mut addrs = Vec::new(); - for r in zone.records.iter().filter_map(|r| r.ok()) { - if let Record::Addr { key, value } = &r { - if let Some(first) = value.first() { - addrs.push((key.clone(), first.clone())); - } - } - } + let addrs: Vec<(String, String)> = zone + .records + .iter() + .map(|rrs| { + rrs.iter() + .filter_map(|r| match r { + ParsedRecord::Addr { key, value } => { + value.iter().next().map(|v| (key.to_string(), v.to_string())) + } + _ => None, + }) + .collect::>() + }) + .unwrap_or_default(); if !addrs.is_empty() { addr_index.insert(handle_str.clone(), (rev_name, addrs)); }