sumdb

package module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 28, 2025 License: MIT Imports: 16 Imported by: 0

README

sumdb

A custom implementation of the Go sumdb server.

CI Go Reference Go Report Card Coverage

This package implements the standard sumdb protocol via golang.org/x/mod/sumdb. When a client requests a module checksum, the server checks the local Store first. If no record exists, it fetches the module from the upstream proxy (default: proxy.golang.org), computes the h1 hashes, stores the record with its Merkle tree hashes, and returns the result.

Usage

go get github.com/pseudomuto/sumdb

Implement the Store interface to provide persistence:

  • RecordID / Records / AddRecord - module record storage
  • ReadHashes / WriteHashes - Merkle tree hash storage
  • TreeSize / SetTreeSize - tree state management

See godoc for the full interface and examples/db/ for a complete SQLite implementation.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrNotFound = errors.New("record not found")

ErrNotFound is returned when a requested record does not exist in the store.

Functions

func GenerateKeys

func GenerateKeys(name string) (string, string, error)

GenerateKeys creates a new keypair and returns the encoded signer key, and verifier key.

The name identifies the key (e.g., "sum.golang.org").

The signer key is secret and must be stored securely. The verifier key can be shared publicly for clients to verify signatures.

Types

type Option

type Option func(*SumDB)

Option configures a SumDB instance.

func WithHTTPClient

func WithHTTPClient(c *http.Client) Option

WithHTTPClient sets the client used to communicate with the proxy.

func WithStore

func WithStore(s Store) Option

WithStore sets the Store for handling persistence of the tree.

func WithUpstream

func WithUpstream(u *url.URL) Option

WithUpstream sets the upstream proxy to query when no records are found.

type Record

type Record struct {
	ID      int64
	Path    string
	Version string
	Data    []byte
}

Record represents a module checksum entry in the sumdb.

type Store

type Store interface {
	// RecordID returns the ID of the record for the given module path and version.
	// Returns ErrNotFound if no record exists.
	RecordID(ctx context.Context, path, version string) (int64, error)

	// Records returns records with IDs in the interval [id, id+n).
	// The returned slice may have fewer than n records if the range extends
	// beyond the current tree size.
	Records(ctx context.Context, id, n int64) ([]*Record, error)

	// AddRecord adds a new entry for the specified module.
	// The record's ID field is ignored; the store assigns the next sequential ID.
	// Returns the assigned ID.
	AddRecord(ctx context.Context, r *Record) (int64, error)

	// ReadHashes returns the hashes at the given storage indexes.
	// Indexes are computed using tlog.StoredHashIndex(level, n).
	// The returned slice must have the same length as indexes.
	ReadHashes(ctx context.Context, indexes []int64) ([]tlog.Hash, error)

	// WriteHashes stores hashes at the given storage indexes.
	// indexes and hashes must have the same length.
	WriteHashes(ctx context.Context, indexes []int64, hashes []tlog.Hash) error

	// TreeSize returns the current number of records in the tree.
	TreeSize(ctx context.Context) (int64, error)

	// SetTreeSize updates the tree size.
	// This should be called after successfully adding a record and its hashes.
	SetTreeSize(ctx context.Context, size int64) error
}

Store defines the persistence interface for sumdb data. Implementations must be safe for concurrent use.

type SumDB

type SumDB struct {
	// contains filtered or unexported fields
}

SumDB is a checksum database server that implements the Go sumdb protocol.

It implements the ServerOpts interface defined in https://pkg.go.dev/golang.org/x/mod@v0.31.0/sumdb#ServerOps.

func New

func New(name string, skey string, opts ...Option) (*SumDB, error)

New creates a new SumDB instance with the given server name and signing key. The name identifies this sumdb (e.g., "sum.example.com"). The skey must be in note signer format: "PRIVATE+KEY+<name>+<hash>+<keydata>".

NB: You can use GenerateKeys to create a valid signing key.

func (*SumDB) Handler

func (s *SumDB) Handler() http.Handler

Handler returns an HTTP handler for serving the sumdb over HTTP.

func (*SumDB) Lookup

func (s *SumDB) Lookup(ctx context.Context, mod module.Version) (int64, error)

Lookup finds or creates a record for the given module version. If the record doesn't exist, it fetches the module from the upstream proxy, computes the checksums, and stores the new record with its tree hashes. Concurrent lookups for the same module are deduplicated via singleflight.

func (*SumDB) ReadRecords

func (s *SumDB) ReadRecords(ctx context.Context, id, n int64) ([][]byte, error)

ReadRecords returns the raw data for records with IDs in [id, id+n).

func (*SumDB) ReadTileData

func (s *SumDB) ReadTileData(ctx context.Context, t tlog.Tile) ([]byte, error)

ReadTileData returns the raw record data for a data tile. Data tiles (L=-1) contain concatenated record data rather than hashes.

func (*SumDB) Signed

func (s *SumDB) Signed(ctx context.Context) ([]byte, error)

Signed returns the signed tree head for the current tree state.

Directories

Path Synopsis
examples
db command
Command db demonstrates using sumdb with SQLite storage.
Command db demonstrates using sumdb with SQLite storage.
internal
signer
Package signer provides Ed25519 signing and verification for sumdb tree heads.
Package signer provides Ed25519 signing and verification for sumdb tree heads.
tree
Package tree provides Merkle tree operations for sumdb using tlog.
Package tree provides Merkle tree operations for sumdb using tlog.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL