oplog

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Oct 29, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package oplog implements OrbitDB's operation log: an append-only, signed Merkle-CRDT of entries.

It is a port of src/oplog in @orbitdb/core 4. Entries are byte-compatible with the JavaScript implementation, and the algorithms that decide entry contents (heads, references, traversal order, conflict resolution) follow it exactly, so a Go and a JavaScript peer appending the same operations produce the same hashes.

Index

Constants

View Source
const EntryVersion = 2

EntryVersion is the version tag of the entry format ("v" field).

Variables

This section is empty.

Functions

func CompareClocks

func CompareClocks(a, b Clock) int

CompareClocks orders clocks by time and, for concurrent clocks with different ids, by id. The result is negative when a is less than b and positive when it is greater; it is zero only when a and b are the same clock.

func EncodeEntry

func EncodeEntry(ctx context.Context, entry *Entry, enc Encryption) (hash string, data []byte, err error)

EncodeEntry returns the hash and bytes of the block entry is stored as.

func IsEntry

func IsEntry(entry *Entry) bool

IsEntry reports whether entry has the fields every entry must have.

func IsEqual

func IsEqual(a, b *Entry) bool

IsEqual reports whether a and b are the same stored entry.

func LastWriteWins

func LastWriteWins(a, b *Entry) int

LastWriteWins orders entries by clock time, then by clock id. Entries with identical clocks compare equal and keep their relative order.

func SortByClockID

func SortByClockID(a, b *Entry, resolveConflict SortFn) int

SortByClockID orders entries by clock id and calls resolveConflict for entries with the same clock id.

func SortByClocks

func SortByClocks(a, b *Entry, resolveConflict SortFn) int

SortByClocks orders entries by clock and calls resolveConflict for entries with identical clocks.

func VerifyEntry

func VerifyEntry(entry *Entry) (bool, error)

VerifyEntry reports whether the entry's signature was made by the key in entry.Key. It does not check that the key belongs to entry.Identity; an access controller does that.

Types

type AccessController

type AccessController interface {
	CanAppend(ctx context.Context, entry *Entry) (bool, error)
}

AccessController decides who may write to a log. It is consulted for every appended entry and for every entry joined from a peer, after the entry's signature has been checked.

func AllowAll

func AllowAll() AccessController

AllowAll returns an AccessController that accepts every entry.

type AppendOptions

type AppendOptions struct {
	// ReferencesCount is how many entries beyond the heads the new entry
	// refers to, so readers can skip ahead when traversing.
	ReferencesCount int
}

AppendOptions configures Log.Append.

type Clock

type Clock struct {
	ID   string
	Time int64
}

Clock is a Lamport clock. ID is the public key of the writer that produced the entry, Time its logical time.

func NewClock

func NewClock(id string, time int64) Clock

NewClock returns a clock with the given id and time.

func TickClock

func TickClock(c Clock) Clock

TickClock returns c advanced by one.

type Encrypter

type Encrypter interface {
	Encrypt(ctx context.Context, plaintext []byte) ([]byte, error)
	Decrypt(ctx context.Context, ciphertext []byte) ([]byte, error)
}

Encrypter encrypts and decrypts bytes. An implementation is given to a log through Encryption.

type Encryption

type Encryption struct {
	// Replication encrypts whole entry blocks, so storage and the network
	// only see ciphertext. The stored block is the dag-cbor byte string of
	// the ciphertext.
	Replication Encrypter
	// Data encrypts entry payloads. The payload is encoded as dag-cbor,
	// encrypted, and the ciphertext is what gets signed and stored.
	Data Encrypter
}

Encryption configures the optional encryption hooks of @orbitdb/core 4. Both are off when nil.

type Entry

type Entry struct {
	// ID is the id of the log the entry belongs to.
	ID string
	// Payload is any value dag-cbor can encode; see package block for the
	// Go types it maps to.
	Payload any
	// Next holds the hashes of the log heads the entry was appended on.
	Next []string
	// Refs holds hashes of older entries, to speed up traversal.
	Refs  []string
	Clock Clock
	V     int64
	// Key is the public key of the writer's identity.
	Key string
	// Identity is the hash of the writer's identity block.
	Identity string
	// Sig is the writer's signature of the entry.
	Sig string
	// Hash is the base58btc CID of the stored entry block. It is set once
	// the entry has been stored or decoded.
	Hash string
	// contains filtered or unexported fields
}

Entry is a signed, content-addressed log entry.

Its dag-cbor encoding is byte-compatible with @orbitdb/core 4: the map {id, payload, next, refs, clock: {id, time}, v, key, identity, sig}, where sig signs the encoding of the first six fields.

func CreateEntry

func CreateEntry(ctx context.Context, identity *identitytypes.Identity, logID string, payload any, opts EntryOptions) (*Entry, error)

CreateEntry creates and signs an entry for log logID. The entry is not stored; its Hash is empty until it is.

func DecodeEntry

func DecodeEntry(ctx context.Context, data []byte, enc Encryption) (*Entry, error)

DecodeEntry parses an entry block, decrypting it if enc says so. The returned entry's Hash is the CID of data.

func FindHeads

func FindHeads(entries []*Entry) []*Entry

FindHeads returns the entries no other entry in entries points to with its Next field, in their given order.

type EntryOptions

type EntryOptions struct {
	// Clock of the entry. Defaults to time 0 on the identity's public key.
	Clock *Clock
	Next  []string
	Refs  []string
	// EncryptPayload, if set, encrypts the payload (see Encryption.Data).
	EncryptPayload Encrypter
}

EntryOptions configures CreateEntry.

type IteratorOptions

type IteratorOptions struct {
	// Amount limits the number of entries. Zero or negative means all.
	Amount int
	// GT and GTE end the iteration at an entry, excluding or including it.
	GT, GTE string
	// LT and LTE start the iteration at an entry, excluding or including
	// it.
	LT, LTE string
}

IteratorOptions selects a range of entries for Log.Iterator. Ranges are given by entry hash and follow the traversal order (newest first).

type Log

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

Log is an append-only log of signed entries.

func NewLog

func NewLog(ctx context.Context, identity *identitytypes.Identity, opts Options) (*Log, error)

NewLog creates a log that appends as identity.

func (*Log) AccessController

func (l *Log) AccessController() AccessController

AccessController returns the log's access controller.

func (*Log) Append

func (l *Log) Append(ctx context.Context, payload any, opts AppendOptions) (*Entry, error)

Append signs payload into a new entry on top of the current heads and makes it the only head.

func (*Log) Clear

func (l *Log) Clear(ctx context.Context) error

Clear removes every entry, head and index record.

func (*Log) Clock

func (l *Log) Clock(ctx context.Context) (Clock, error)

Clock returns the log's clock: the writer's public key at the latest time among the heads.

func (*Log) Close

func (l *Log) Close() error

Close waits for a pending Append or JoinEntry and closes the storages.

func (*Log) Encryption

func (l *Log) Encryption() Encryption

Encryption returns the log's encryption settings.

func (*Log) Get

func (l *Log) Get(ctx context.Context, hash string) (*Entry, error)

Get returns the entry with the given hash. It returns an error wrapping storage.ErrNotFound if the entry is not stored.

func (*Log) Has

func (l *Log) Has(ctx context.Context, hash string) (bool, error)

Has reports whether the entry with the given hash is part of the log.

func (*Log) Heads

func (l *Log) Heads(ctx context.Context) ([]*Entry, error)

Heads returns the current heads, latest first.

func (*Log) ID

func (l *Log) ID() string

ID returns the log id.

func (*Log) Identity

func (l *Log) Identity() *identitytypes.Identity

Identity returns the identity the log appends as.

func (*Log) Iterator

func (l *Log) Iterator(ctx context.Context, opts IteratorOptions) iter.Seq2[*Entry, error]

Iterator yields the entries selected by opts, latest first.

func (*Log) Join

func (l *Log) Join(ctx context.Context, other *Log) error

Join merges other into this log: other's entry blocks are copied into this log's entry storage and each of its heads is joined.

func (*Log) JoinEntry

func (l *Log) JoinEntry(ctx context.Context, entry *Entry) (bool, error)

JoinEntry adds an entry received from a peer, together with every ancestor the log does not have yet. Each new entry must belong to the log, pass the access controller and carry a valid signature. Ancestors are read from the entry storage, which fetches them from peers when it is backed by IPFS. It reports whether the log changed.

func (*Log) Storage

func (l *Log) Storage() storage.Storage

Storage returns the storage holding the log's entry blocks.

func (*Log) Traverse

func (l *Log) Traverse(ctx context.Context, roots []*Entry, shouldStop func(*Entry) (bool, error)) iter.Seq2[*Entry, error]

Traverse walks the log from roots (the current heads when nil), yielding each reachable entry once, latest first according to the sort function. If shouldStop is set it is called after each yielded entry and ends the walk when it returns true. Entries missing from storage are skipped.

func (*Log) Values

func (l *Log) Values(ctx context.Context) ([]*Entry, error)

Values returns every entry in the log, oldest first.

type Options

type Options struct {
	// LogID identifies the log; entries of other logs cannot be joined.
	// Defaults to the current Unix time in milliseconds.
	LogID string
	// LogHeads, if set, replaces the persisted heads.
	LogHeads []*Entry
	// AccessController decides who may write. Defaults to AllowAll.
	AccessController AccessController
	// EntryStorage holds entry blocks, IndexStorage records which entries
	// are part of the log and HeadsStorage the current heads. Each
	// defaults to a MemoryStorage.
	EntryStorage storage.Storage
	HeadsStorage storage.Storage
	IndexStorage storage.Storage
	// SortFn orders concurrent entries. Defaults to LastWriteWins.
	SortFn SortFn
	// Encryption turns on entry and/or payload encryption.
	Encryption Encryption
}

Options configures NewLog.

type SortFn

type SortFn func(a, b *Entry) int

SortFn orders two entries, returning a negative number when a sorts before b (is older) and a positive number when it sorts after. Log uses it to order heads and traversal; the default is LastWriteWins.

Jump to

Keyboard shortcuts

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