Libveritas
Stateless verification for Bitcoin handles using the Spaces protocol.
Similar to BIP-353, but replaces centralized ICANN signing keys with a permissionless trust anchor.
Installation
Rust
JavaScript / Node.js
Swift (iOS / macOS)
Add to your Package.swift:
dependencies: [
.package(url: "https://github.com/spacesprotocol/libveritas-swift.git", from: "0.1.0")
]
Kotlin / Android
// build.gradle.kts
dependencies {
implementation("org.spacesprotocol:libveritas:0.1.0")
}
React Native
Python
Go
Usage
Rust
use Veritas;
use ;
let anchors_json = read?;
let veritas = new
.with_anchors?;
let msg_bytes = read?;
let msg = from_slice?;
let ctx = new;
let result = veritas.verify_message?;
for zone in &result.zones
JavaScript
import from "fs";
import from "@spacesprotocol/libveritas";
const anchors = JSON.;
const msg = ;
const veritas = ;
const ctx = ;
const result = veritas.;
Swift
import Libveritas
let anchorsJson = try String(contentsOfFile: "trust_anchors.json", encoding: .utf8)
let msgBytes = try Data(contentsOf: URL(fileURLWithPath: "message.bin"))
let anchors = try Anchors.fromJson(json: anchorsJson)
let veritas = try Veritas(anchors: anchors)
let msg = try Message(bytes: Array(msgBytes))
let ctx = QueryContext()
let result = try veritas.verifyMessage(ctx: ctx, msg: msg)
for zone in result.zones() {
print("\(zone.handle()) -> \(zone.sovereignty())")
switch zone.commitment() {
case .exists(_, _, _, let blockHeight, _):
print(" commitment at block \(blockHeight)")
case .empty:
print(" no commitment")
case .unknown:
print(" commitment unknown")
}
}
Kotlin
import uniffi.libveritas_uniffi.*
val anchorsJson = File("trust_anchors.json").readText()
val msgBytes = File("message.bin").readBytes()
val anchors = Anchors.fromJson(anchorsJson)
val veritas = Veritas(anchors)
val msg = Message(msgBytes.toList())
val ctx = QueryContext()
val result = veritas.verifyMessage(ctx, msg)
for (zone in result.zones()) {
println("${zone.handle()} -> ${zone.sovereignty()}")
when (val c = zone.commitment()) {
is CommitmentState.Exists ->
println(" commitment at block ${c.blockHeight}")
is CommitmentState.Empty ->
println(" no commitment")
is CommitmentState.Unknown ->
println(" commitment unknown")
}
}
React Native
import {
Veritas,
Anchors,
QueryContext,
Message,
} from '@spacesprotocol/react-native-libveritas';
const anchors = Anchors.fromJson(anchorsJsonString);
const veritas = new Veritas(anchors);
const ctx = new QueryContext();
const msg = new Message(messageBytes);
const result = veritas.verifyMessage(ctx, msg);
for (const zone of result.zones()) {
console.log(`${zone.handle()} -> ${zone.sovereignty()}`);
}
Python
=
=
=
=
=
Go
import veritas "github.com/spacesprotocol/libveritas-go"
anchors, _ := veritas.AnchorsFromJson(anchorsJsonString)
v, _ := veritas.NewVeritas(anchors)
msg, _ := veritas.NewMessage(messageBytes)
ctx := veritas.NewQueryContext()
result, _ := v.VerifyMessage(ctx, msg)
for _, zone := range result.Zones()
Query Context
By default, all handles in a message are verified. Use QueryContext to verify specific handles or provide previously-known zones for incremental verification:
const ctx = ;
// Only verify specific handles
ctx.;
// Provide a previously stored zone for context
ctx.;
const result = veritas.;
Zone Comparison
When you have multiple zone snapshots for the same handle, use is_better_than to determine which is more recent:
const better = newerZone.; // true
Zones can be serialized for storage with toBytes() and later restored with decodeZone().
Guest ELF binaries
The compiled guest program ELF binaries are available behind the elf feature flag for provers:
[]
= { = "0.1", = ["elf"] }
use ;
The image IDs (FOLD_ID, STEP_ID) are always available without the feature flag.
Development
Updating guest programs
When modifying the ZK guest programs in methods/guest/src/bin/, the baked ELF binaries and
image IDs must be updated. Run:
This will:
- Build the guest programs reproducibly using Docker (
cargo risczero build) - Copy the compiled ELF binaries to
veritas/elfs/ - Compute the image IDs and update
veritas/src/constants.rs
Requirements: RISC Zero toolchain (cargo-risczero, r0vm) and Docker.