Skip to content

Commit 9bbcea7

Browse files
committed
Update caching behavior
1 parent 93dd99a commit 9bbcea7

13 files changed

Lines changed: 207 additions & 117 deletions

File tree

Cargo.lock

Lines changed: 63 additions & 64 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

fabric/examples/go/main.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,18 @@ import (
99
lv "github.com/spacesprotocol/libveritas-go"
1010
)
1111

12+
func exampleResolveIntro() error {
13+
// <doc:resolve-intro>
14+
f := fabric.New()
15+
resolved, err := f.Resolve("alice@bitcoin")
16+
// </doc:resolve-intro>
17+
if err != nil {
18+
return err
19+
}
20+
_ = resolved
21+
return nil
22+
}
23+
1224
/// Resolve a single handle
1325
func exampleResolve() error {
1426
// <doc:resolve>

fabric/examples/js/index.mjs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import { Fabric, RecordSet, Record, MessageBuilder } from "@spacesprotocol/fabric-web";
22
import { signSchnorr } from "@spacesprotocol/fabric-web/signing";
33

4+
async function exampleResolveIntro() {
5+
// <doc:resolve-intro>
6+
const fabric = new Fabric();
7+
const resolved = await fabric.resolve("alice@bitcoin");
8+
// </doc:resolve-intro>
9+
}
10+
411
/// Resolve a single handle
512
async function exampleResolve() {
613
// <doc:resolve>
@@ -100,9 +107,6 @@ function examplePackRecords() {
100107
/// Publish signed records
101108
async function examplePublish() {
102109
const fabric = new Fabric();
103-
const secretKey = new Uint8Array(Buffer.from(
104-
"0000000000000000000000000000000000000000000000000000000000000001", "hex"
105-
));
106110

107111
const rs = RecordSet.pack([
108112
Record.seq(1n),
@@ -114,8 +118,8 @@ async function examplePublish() {
114118
const cert = await fabric.export("alice@bitcoin");
115119
await fabric.publish({
116120
cert,
117-
records: rs.toBytes(),
118-
sign: (digest) => signSchnorr(digest, secretKey),
121+
records: rs,
122+
secretKey: "0000000000000000000000000000000000000000000000000000000000000001",
119123
primary: true,
120124
});
121125
// </doc:publish>

fabric/examples/kotlin/Example.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ import org.spacesprotocol.fabric.MessageBuilder
77
import org.spacesprotocol.fabric.ChainProof
88
import org.spacesprotocol.fabric.SIG_PRIMARY_ZONE
99

10+
suspend fun exampleResolveIntro() {
11+
// <doc:resolve-intro>
12+
val fabric = Fabric()
13+
val resolved = fabric.resolve("alice@bitcoin")
14+
// </doc:resolve-intro>
15+
}
16+
1017
/// Resolve a single handle
1118
suspend fun exampleResolve() {
1219
// <doc:resolve>

fabric/examples/python/example.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44
from fabric import CertificateChain, MessageBuilder, ChainProof, SIG_PRIMARY_ZONE
55

66

7+
async def example_resolve_intro():
8+
# <doc:resolve-intro>
9+
fabric = Fabric()
10+
resolved = await fabric.resolve("alice@bitcoin")
11+
# </doc:resolve-intro>
12+
13+
714
async def example_resolve():
815
"""Resolve a single handle"""
916
# <doc:resolve>

fabric/examples/rust/src/main.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ use fabric::libveritas::msg::ChainProof;
55
use fabric::libveritas::sip7::{ParsedRecord, Record, RecordSet, SIG_PRIMARY_ZONE};
66
use fabric::signing::sign_schnorr;
77

8+
async fn example_resolve_intro() -> anyhow::Result<()> {
9+
// <doc:resolve-intro>
10+
let fabric = Fabric::new();
11+
let resolved = fabric.resolve("alice@bitcoin").await?;
12+
// </doc:resolve-intro>
13+
let _ = resolved;
14+
Ok(())
15+
}
16+
17+
818
/// Resolve a single handle
919
async fn example_resolve() -> anyhow::Result<()> {
1020
// <doc:resolve>

fabric/examples/swift/Example.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,12 @@
11
import Fabric
22

3+
func exampleResolveIntro() async throws {
4+
// <doc:resolve-intro>
5+
let fabric = Fabric()
6+
let resolved = try await fabric.resolve("alice@bitcoin")
7+
// </doc:resolve-intro>
8+
}
9+
310
/// Resolve a single handle
411
func exampleResolve() async throws {
512
// <doc:resolve>

fabric/js/fabric-core/src/fabric.ts

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,22 @@ function toHex(bytes: Uint8Array): string {
7070
return Array.from(bytes).map(b => b.toString(16).padStart(2, "0")).join("");
7171
}
7272

73+
function hexToBytes(hex: string): Uint8Array {
74+
const bytes = new Uint8Array(hex.length / 2);
75+
for (let i = 0; i < bytes.length; i++) {
76+
bytes[i] = parseInt(hex.substring(i * 2, i * 2 + 2), 16);
77+
}
78+
return bytes;
79+
}
80+
81+
function parseSecretKey(key: string | Uint8Array): Uint8Array {
82+
if (key instanceof Uint8Array) return key;
83+
if (typeof key === "string" && /^[0-9a-fA-F]{64}$/.test(key)) {
84+
return hexToBytes(key);
85+
}
86+
throw new FabricError("secretKey must be 32-byte Uint8Array or 64-char hex string", "decode");
87+
}
88+
7389
/**
7490
* Certrelay client for JavaScript/TypeScript.
7591
*
@@ -88,7 +104,19 @@ function toHex(bytes: Uint8Array): string {
88104
* const fabric = new Fabric({ provider: reactNativeProvider({ Veritas, VeritasAnchors, VeritasQueryContext }) });
89105
* ```
90106
*/
107+
export type SignSchnorrFn = (digest: Uint8Array, secretKey: Uint8Array) => Uint8Array;
108+
91109
export class Fabric {
110+
private static _signSchnorr: SignSchnorrFn | null = null;
111+
112+
/**
113+
* Register a Schnorr signing function. Called automatically when
114+
* `@spacesprotocol/fabric-web/signing` is imported.
115+
*/
116+
static registerSigner(fn: SignSchnorrFn): void {
117+
Fabric._signSchnorr = fn;
118+
}
119+
92120
private provider: VeritasProvider;
93121
private pool = new RelayPool();
94122
private veritas: VeritasHandle | null = null;
@@ -234,21 +262,35 @@ export class Fabric {
234262
/**
235263
* Build and sign a message ready for broadcasting.
236264
*
265+
* Requires the signing module to be loaded first:
266+
* ```ts
267+
* import "@spacesprotocol/fabric-web/signing";
268+
* ```
269+
*
237270
* @param opts.cert - Certificate bytes (.spacecert)
238-
* @param opts.records - RecordSet bytes (from RecordSet.pack().toBytes())
239-
* @param opts.sign - Signs a 32-byte digest, returns 64-byte Schnorr signature
271+
* @param opts.records - RecordSet or raw bytes
272+
* @param opts.secretKey - 32-byte secret key as Uint8Array or 64-char hex string
240273
* @param opts.primary - Set SIG_PRIMARY_ZONE flag for num id reverse mapping (default: true)
241274
* @returns Signed message bytes ready for broadcast()
242275
*/
243276
async sign(opts: {
244277
cert: Uint8Array;
245-
records: Uint8Array;
246-
sign: (signingId: Uint8Array) => Uint8Array | Promise<Uint8Array>;
278+
records: Uint8Array | { toBytes(): Uint8Array };
279+
secretKey: string | Uint8Array;
247280
primary?: boolean;
248281
}): Promise<Uint8Array> {
282+
if (!Fabric._signSchnorr) {
283+
throw new FabricError(
284+
"signing module not loaded. Import '@spacesprotocol/fabric-web/signing' first.",
285+
"decode",
286+
);
287+
}
249288
await this.bootstrap();
250289

251-
const { cert, records, sign, primary = true } = opts;
290+
const { cert, primary = true } = opts;
291+
const records = opts.records instanceof Uint8Array ? opts.records : opts.records.toBytes();
292+
const key = parseSecretKey(opts.secretKey);
293+
const signFn = Fabric._signSchnorr;
252294

253295
const builder = this.provider.createMessageBuilder();
254296
builder.addHandle(cert, records);
@@ -263,7 +305,7 @@ export class Fabric {
263305
if (primary) {
264306
u.setFlags(u.flags() | 0x01); // SIG_PRIMARY_ZONE
265307
}
266-
const sig = await sign(u.signingId());
308+
const sig = signFn(u.signingId(), key);
267309
const signed = u.packSig(sig);
268310
message.setRecords(u.canonical(), signed);
269311
}
@@ -274,15 +316,20 @@ export class Fabric {
274316
/**
275317
* Build, sign, and broadcast a message.
276318
*
319+
* Requires the signing module to be loaded first:
320+
* ```ts
321+
* import "@spacesprotocol/fabric-web/signing";
322+
* ```
323+
*
277324
* @param opts.cert - Certificate bytes (.spacecert)
278-
* @param opts.records - RecordSet bytes (from RecordSet.pack().toBytes())
279-
* @param opts.sign - Signs a 32-byte digest, returns 64-byte Schnorr signature
325+
* @param opts.records - RecordSet or raw bytes
326+
* @param opts.secretKey - 32-byte secret key as Uint8Array or 64-char hex string
280327
* @param opts.primary - Set SIG_PRIMARY_ZONE flag for num id reverse mapping (default: true)
281328
*/
282329
async publish(opts: {
283330
cert: Uint8Array;
284-
records: Uint8Array;
285-
sign: (signingId: Uint8Array) => Uint8Array | Promise<Uint8Array>;
331+
records: Uint8Array | { toBytes(): Uint8Array };
332+
secretKey: string | Uint8Array;
286333
primary?: boolean;
287334
}): Promise<void> {
288335
const msg = await this.sign(opts);

fabric/js/fabric-core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export type {
66
Resolved,
77
ResolvedBatch,
88
ScanParams,
9+
SignSchnorrFn,
910
} from "./fabric.js";
1011
export { RelayPool } from "./pool.js";
1112
export { compareHints } from "./hints.js";

fabric/js/fabric-web/src/signing.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { schnorr } from "@noble/curves/secp256k1";
2+
import { Fabric as FabricCore } from "@spacesprotocol/fabric-core";
23

34
/**
45
* Sign a 32-byte digest using BIP-340 Schnorr.
@@ -23,4 +24,7 @@ export function verifySchnorr(
2324
pubkey: Uint8Array,
2425
): boolean {
2526
return schnorr.verify(signature, digest, pubkey);
26-
}
27+
}
28+
29+
// Auto-register signer so publish()/sign() work without a callback
30+
FabricCore.registerSigner(signSchnorr);

0 commit comments

Comments
 (0)