Files
fhe/pkg/encrypted/anchor.go
T
Hanzo AI 8b8447a0a4 feat(encrypted): FHE CRDT primitives + RFC 3526 safe prime
LWW-Register, ORSet, GCounter merge under TFHE encryption.
EncryptedDocument with structural StateRoot (deterministic across
replicas despite ciphertext non-determinism). AnchorClient interface
for CRDTAnchor.sol checkpoint wiring.

Safe prime swap: 256-bit composite → 2048-bit RFC 3526 Group 14.
Feldman VSS generator now element of order q (was full group).
Reshare uses additive sub-sharing (no secret materialization).

19 encrypted + 10 threshold tests pass. Red-reviewed: 16 findings,
13 fixed, 5 scientist findings addressed.
2026-04-13 01:03:34 -07:00

57 lines
2.2 KiB
Go

// Copyright (C) 2025-2026, Lux Industries Inc. All rights reserved.
// SPDX-License-Identifier: BSD-3-Clause
package encrypted
import (
"context"
"crypto/sha256"
"fmt"
)
// AnchorClient is the minimal surface required to checkpoint a Document's
// StateRoot onto a blockchain via CRDTAnchor.sol. This package intentionally
// does not depend on go-ethereum or any specific RPC library — callers pass
// in their own client that adapts viem / ethers / ethclient / etc.
//
// Implementations must:
// - send a transaction calling CRDTAnchor.checkpoint(docID, root, opCount)
// - return nil only on confirmed inclusion (or the RPC's equivalent)
// - surface RPC errors without retrying (retry/backoff is caller's concern)
type AnchorClient interface {
Checkpoint(ctx context.Context, docID [32]byte, root [32]byte, opCount uint64) error
}
// Anchor submits the document's current StateRoot to the configured
// AnchorClient. The docID is derived deterministically from the document's
// string ID via SHA-256 so every replica produces the same on-chain key.
//
// Typical caller: a cron job on the leader replica, or a client-side hook
// triggered after every N writes. Do NOT call this on every Set — on-chain
// gas dominates; batch via opCount delta thresholds instead.
//
// Returns the (docID, root, opCount) that was submitted so the caller can
// log / record the checkpoint for reconciliation.
func (d *Document) Anchor(ctx context.Context, client AnchorClient) ([32]byte, [32]byte, uint64, error) {
if client == nil {
return [32]byte{}, [32]byte{}, 0, fmt.Errorf("encrypted/anchor: nil client")
}
root, err := d.StateRoot()
if err != nil {
return [32]byte{}, [32]byte{}, 0, fmt.Errorf("encrypted/anchor: state root: %w", err)
}
docID := DocIDHash(d.ID())
opCount := d.OpCount()
if err := client.Checkpoint(ctx, docID, root, opCount); err != nil {
return docID, root, opCount, fmt.Errorf("encrypted/anchor: checkpoint: %w", err)
}
return docID, root, opCount, nil
}
// DocIDHash returns the canonical on-chain identifier for a document ID
// string. Exposed so callers can look up existing checkpoints via
// CRDTAnchor.latest(owner, DocIDHash(id)).
func DocIDHash(id string) [32]byte {
return sha256.Sum256([]byte(id))
}