Horizon DAG Finality Predicates
DAG order-theory predicates for reachability, LCA, antichain queries, and certificate/skip detection under a DAG model
Abstract
This proposal standardizes Horizon, a consensus component that houses DAG order-theory predicates. Horizon answers reachability, LCA (Lowest Common Ancestor), and antichain queries, and provides helpers for certificate and skip detection under a DAG model. In the physics-inspired Quasar consensus metaphor, the "event horizon" is the boundary beyond which reordering cannot affect committed history. In Horizon, this concept is formalized as a precise predicate over the DAG poset, enabling deterministic finality decisions.
Motivation
DAG-based consensus protocols require efficient predicates to reason about vertex relationships:
- Reachability Queries: Determine if one vertex is an ancestor of another, critical for conflict detection and causal ordering
- LCA Computation: Find the lowest common ancestor of vertices to identify divergence points and merge paths
- Antichain Detection: Identify sets of concurrent (mutually unreachable) vertices representing parallel execution branches
- Certificate/Skip Detection: Determine when vertices achieve sufficient support (certificate) or opposition (skip) for finalization
- Event Horizon Management: Compute the finality boundary beyond which no reordering can occur
Horizon provides a unified interface for these predicates, enabling Flare (LP-112) finalization and Quasar (LP-110) consensus to operate efficiently across the DAG structure.
Specification
1. Core Types and Interfaces
1.1 Vertex Identifier
// Package horizon houses DAG order-theory predicates.
//
// It answers reachability, LCA, and antichain queries, and provides small
// helpers for certificate/skip detection under a DAG model. In the metaphor,
// the "event horizon" is the boundary beyond which reordering cannot affect
// committed history; here, it's a precise predicate over the poset.
package horizon
// VertexID represents a unique vertex identifier in the DAG (32-byte hash)
type VertexID [32]byte
// VID represents a generic vertex identifier for protocol interfaces
type VID interface{ comparable }
1.2 BlockView Interface
// BlockView represents a view of a block/vertex in the DAG
type BlockView[V VID] interface {
ID() V
Parents() []V
Author() string
Round() uint64
}
1.3 Store Interface
// Store represents DAG storage interface for predicate evaluation
type Store[V VID] interface {
Head() []V // Get current tips of the DAG
Get(V) (BlockView[V], bool) // Retrieve a vertex by ID
Children(V) []V // Get children of a vertex
}
1.4 Meta and View Interfaces
// Meta interface represents metadata for a DAG vertex
type Meta interface {
ID() VertexID
Author() string
Round() uint64
Parents() []VertexID
}
// View interface provides access to DAG structure and vertex relationships
type View interface {
Get(VertexID) (Meta, bool)
ByRound(round uint64) []Meta
Supports(from VertexID, author string, round uint64) bool
}
// Params holds DAG consensus parameters
type Params struct{ N, F int } // N validators, F Byzantine tolerance
2. Reachability Predicates
2.1 IsReachable
Determines if a path exists from one vertex to another in the DAG.
// IsReachable checks if vertex 'from' can reach vertex 'to' in the DAG
// Returns true if there exists a directed path from 'from' to 'to'
func IsReachable[V VID](store Store[V], from, to V) bool {
// Self-reachability
if from == to {
return true
}
// BFS traversal through children (forward edges in DAG)
visited := make(map[V]bool)
queue := []V{from}
visited[from] = true
for len(queue) > 0 {
current := queue[0]
queue = queue[1:]
for _, child := range store.Children(current) {
if child == to {
return true
}
if !visited[child] {
visited[child] = true
queue = append(queue, child)
}
}
}
return false
}
Complexity: O(V + E) where V is vertices and E is edges in the reachable subgraph.
2.2 Transitive Closure
Computes all vertices reachable from a given vertex.
// TransitiveClosure computes the transitive closure of a vertex in the DAG
// Returns all vertices reachable from the given vertex via parent edges
func TransitiveClosure[V VID](store Store[V], vertex V) []V {
closure := []V{vertex}
visited := make(map[V]bool)
visited[vertex] = true
queue := []V{vertex}
for len(queue) > 0 {
current := queue[0]
queue = queue[1:]
if block, exists := store.Get(current); exists {
for _, parent := range block.Parents() {
if !visited[parent] {
visited[parent] = true
closure = append(closure, parent)
queue = append(queue, parent)
}
}
}
}
return closure
}
3. LCA (Lowest Common Ancestor)
Finds the lowest common ancestor of two vertices in the DAG.
// LCA finds the lowest common ancestor of two vertices
// Returns the vertex with highest round that is an ancestor of both a and b
func LCA[V VID](store Store[V], a, b V) V {
// Phase 1: Collect all ancestors of a with their heights
ancestorsA := make(map[V]uint64) // vertex -> round/height
queue := []V{a}
visited := make(map[V]bool)
for len(queue) > 0 {
current := queue[0]
queue = queue[1:]
if visited[current] {
continue
}
visited[current] = true
if block, ok := store.Get(current); ok {
ancestorsA[current] = block.Round()
for _, parent := range block.Parents() {
if !visited[parent] {
queue = append(queue, parent)
}
}
}
}
// Phase 2: Find first common ancestor from b (prioritize highest round)
queue = []V{b}
visited = make(map[V]bool)
var lca V
var lcaHeight uint64 = 0
for len(queue) > 0 {
current := queue[0]
queue = queue[1:]
if visited[current] {
continue
}
visited[current] = true
// Check if this is a common ancestor
if height, isAncestor := ancestorsA[current]; isAncestor {
// Keep track of the lowest (highest round) common ancestor
if height > lcaHeight {
lcaHeight = height
lca = current
}
}
// Continue traversing parents
if block, ok := store.Get(current); ok {
for _, parent := range block.Parents() {
if !visited[parent] {
queue = append(queue, parent)
}
}
}
}
return lca
}
Complexity: O(V + E) for both phases.
4. Antichain Detection
Identifies sets of mutually unreachable vertices representing concurrent execution.
// Antichain computes an antichain (set of mutually unreachable vertices) in the DAG
// An antichain is a set where no vertex can reach another, representing concurrency
func Antichain[V VID](store Store[V], vertices []V) []V {
if len(vertices) <= 1 {
return vertices
}
var antichain []V
for i, v1 := range vertices {
isInAntichain := true
// Check if v1 is mutually unreachable with all other vertices
for j, v2 := range vertices {
if i == j {
continue
}
// If v1 can reach v2 or v2 can reach v1, they're not in antichain
if IsReachable(store, v1, v2) || IsReachable(store, v2, v1) {
isInAntichain = false
break
}
}
if isInAntichain {
antichain = append(antichain, v1)
}
}
return antichain
}
Complexity: O(n^2 * (V + E)) for n vertices.
5. Certificate and Skip Detection
Determines when vertices achieve finalization thresholds.
5.1 Certificate Structure
// Certificate represents a proof that a vertex has achieved consensus
type Certificate[V VID] struct {
Vertex V // The vertex being certified
Proof []V // Vertices providing support
Threshold int // Required support count (2f+1)
}
// ValidateCertificate checks if a certificate is valid given a validator function
func ValidateCertificate[V VID](store Store[V], cert Certificate[V], isValid func(V) bool) bool {
validCount := 0
for _, proof := range cert.Proof {
if isValid(proof) {
validCount++
}
}
return validCount >= cert.Threshold
}
5.2 Certificate Detection
// HasCertificate checks if a vertex has a certificate (>=2f+1 validators support it)
// A vertex has a certificate if >=2f+1 vertices in the next round reference it
func HasCertificate(v View, proposer Meta, p Params) bool {
r1 := proposer.Round() + 1
next := v.ByRound(r1)
support := 0
for _, m := range next {
if v.Supports(m.ID(), proposer.Author(), proposer.Round()) {
support++
if support >= 2*p.F+1 {
return true
}
}
}
return false
}
5.3 Skip Detection
// HasSkip checks if a vertex has a skip certificate (>=2f+1 validators do NOT support it)
// Indicates the vertex should be skipped/rejected in finalization
func HasSkip(v View, proposer Meta, p Params) bool {
r1 := proposer.Round() + 1
next := v.ByRound(r1)
nos := 0
for _, m := range next {
if !v.Supports(m.ID(), proposer.Author(), proposer.Round()) {
nos++
if nos >= 2*p.F+1 {
return true
}
}
}
return false
}
6. Event Horizon
The event horizon represents the finality boundary in the DAG.
6.1 EventHorizon Structure
// EventHorizon represents the finality boundary in Quasar consensus
// Beyond this horizon, no events can affect the finalized state
type EventHorizon[V VID] struct {
Checkpoint V // Finalized state boundary vertex
Height uint64 // Height at which this horizon was established
Validators []string // Validators that signed this horizon
Signature []byte // Post-quantum signature (BLS + Lattice)
}
6.2 Horizon Computation
// Horizon computes the event horizon for finality determination
// Returns the new event horizon based on the latest checkpoints
func Horizon[V VID](store Store[V], checkpoints []EventHorizon[V]) EventHorizon[V] {
if len(checkpoints) == 0 {
var zero EventHorizon[V]
return zero
}
// Start with the latest checkpoint
latest := checkpoints[len(checkpoints)-1]
// Find all vertices reachable from the latest checkpoint
reachable := make(map[V]bool)
queue := []V{latest.Checkpoint}
visited := make(map[V]bool)
for len(queue) > 0 {
current := queue[0]
queue = queue[1:]
if visited[current] {
continue
}
visited[current] = true
reachable[current] = true
// Traverse children to find newer vertices
for _, child := range store.Children(current) {
if !visited[child] {
queue = append(queue, child)
}
}
}
// Find the highest-round vertex in reachable set
var newCheckpoint V
var maxHeight uint64 = 0
for vertex := range reachable {
if block, ok := store.Get(vertex); ok {
if height := block.Round(); height > maxHeight {
maxHeight = height
newCheckpoint = vertex
}
}
}
return EventHorizon[V]{
Checkpoint: newCheckpoint,
Height: maxHeight,
Validators: latest.Validators,
Signature: latest.Signature,
}
}
6.3 BeyondHorizon Predicate
// BeyondHorizon checks if a vertex is beyond the event horizon (finalized)
// Vertices beyond the event horizon cannot be affected by future consensus
func BeyondHorizon[V VID](store Store[V], vertex V, horizon EventHorizon[V]) bool {
return IsReachable(store, horizon.Checkpoint, vertex)
}
6.4 Horizon Ordering
// ComputeHorizonOrder determines the canonical order of vertices beyond the event horizon
// Provides deterministic ordering for state transitions
func ComputeHorizonOrder[V VID](store Store[V], horizon EventHorizon[V]) []V {
if horizon.Height == 0 {
return []V{}
}
// Collect all vertices reachable from the horizon checkpoint
var beyondHorizon []V
visited := make(map[V]bool)
queue := []V{horizon.Checkpoint}
for len(queue) > 0 {
current := queue[0]
queue = queue[1:]
if visited[current] {
continue
}
visited[current] = true
beyondHorizon = append(beyondHorizon, current)
// Add children to queue for BFS traversal
for _, child := range store.Children(current) {
if !visited[child] {
queue = append(queue, child)
}
}
}
return beyondHorizon
}
7. Skip List for Efficient Traversal
// SkipList represents a skip list data structure for efficient DAG traversal
type SkipList[V VID] struct {
Levels map[V][]V // vertex -> skip pointers at different levels
}
// BuildSkipList constructs a skip list from DAG vertices for efficient navigation
func BuildSkipList[V VID](store Store[V], vertices []V) *SkipList[V] {
sl := &SkipList[V]{
Levels: make(map[V][]V),
}
for _, v := range vertices {
if block, exists := store.Get(v); exists {
parents := block.Parents()
if len(parents) > 0 {
sl.Levels[v] = []V{parents[0]}
} else {
sl.Levels[v] = []V{}
}
}
}
return sl
}
// FindPath finds a path between two vertices in the DAG using skip pointers
func FindPath[V VID](store Store[V], from, to V) ([]V, bool) {
if _, exists1 := store.Get(from); !exists1 {
return nil, false
}
if _, exists2 := store.Get(to); !exists2 {
return nil, false
}
// BFS to find path
visited := make(map[V]bool)
parent := make(map[V]V)
queue := []V{from}
visited[from] = true
for len(queue) > 0 {
current := queue[0]
queue = queue[1:]
if current == to {
// Reconstruct path
path := []V{to}
for path[len(path)-1] != from {
path = append(path, parent[path[len(path)-1]])
}
// Reverse path
for i, j := 0, len(path)-1; i < j; i, j = i+1, j-1 {
path[i], path[j] = path[j], path[i]
}
return path, true
}
for _, child := range store.Children(current) {
if !visited[child] {
visited[child] = true
parent[child] = current
queue = append(queue, child)
}
}
}
return nil, false
}
8. HorizonEngine
The unified Horizon engine used in Quasar consensus.
// HorizonEngine houses DAG order-theory predicates for consensus
type HorizonEngine struct {
dag Store[VertexID]
threshold int // 2f+1 for Byzantine tolerance
}
// NewHorizonEngine creates a new horizon engine with the given parameters
func NewHorizonEngine(dag Store[VertexID], params Params) *HorizonEngine {
return &HorizonEngine{
dag: dag,
threshold: 2*params.F + 1,
}
}
// Certificate detects when vertex has >=2f+1 support
func (h *HorizonEngine) Certificate(vertexID VertexID) bool {
support := h.countSupport(vertexID)
return support >= h.threshold
}
// Skip detects when vertex has >=2f+1 opposition (will be skipped)
func (h *HorizonEngine) Skip(vertexID VertexID) bool {
opposition := h.countOpposition(vertexID)
return opposition >= h.threshold
}
// Reachable checks if ancestor is reachable from descendant
func (h *HorizonEngine) Reachable(ancestor, descendant VertexID) bool {
return IsReachable(h.dag, ancestor, descendant)
}
// LCA finds the lowest common ancestor of two vertices
func (h *HorizonEngine) LCA(a, b VertexID) VertexID {
return LCA(h.dag, a, b)
}
// Antichain returns the maximal antichain from the given vertices
func (h *HorizonEngine) Antichain(vertices []VertexID) []VertexID {
return Antichain(h.dag, vertices)
}
Integration with Flare Finalization
Horizon predicates are used by Flare (LP-112) for finalization decisions:
// FlareEngine uses Horizon for DAG finalization
type FlareEngine struct {
dag Store[VertexID]
horizon *HorizonEngine
accepted map[VertexID]bool
}
// Finalize commits vertices in causal order using Horizon predicates
func (f *FlareEngine) Finalize(cut []VertexID) []VertexID {
finalized := []VertexID{}
// Walk dependencies in causal order
for _, vertexID := range topologicalSort(cut) {
// Check all dependencies are finalized
deps := f.dag.Get(vertexID).Parents()
allDepsFinalized := true
for _, dep := range deps {
if !f.accepted[dep] {
allDepsFinalized = false
break
}
}
// Finalize if dependencies met and certificate detected via Horizon
if allDepsFinalized && f.horizon.Certificate(vertexID) {
f.accepted[vertexID] = true
finalized = append(finalized, vertexID)
}
}
return finalized
}
Rationale
Order-Theory Foundation
Horizon is built on order-theory principles:
- Partial Order: The DAG forms a poset (partially ordered set) via parent-child relationships
- Antichain: Concurrent vertices form antichains (sets where no element is comparable to another)
- LCA: The lowest common ancestor provides merge points for divergent branches
Event Horizon Metaphor
The physics-inspired naming provides intuition:
- Just as light cannot escape a black hole's event horizon, transactions cannot be reordered once they cross the finality horizon
- The horizon advances as more vertices achieve certificate status
- Vertices beyond the horizon are permanently committed
Certificate/Skip Duality
The 2f+1 threshold enables both positive (certificate) and negative (skip) finalization:
- Certificate: >=2f+1 support indicates consensus approval
- Skip: >=2f+1 opposition indicates the vertex should be bypassed
- This duality ensures liveness even when some proposals fail
Backwards Compatibility
Horizon integrates with existing Snowman consensus through adapters:
// SnowmanHorizonAdapter adapts Horizon predicates for Snowman blocks
type SnowmanHorizonAdapter struct {
horizon *HorizonEngine
}
func (s *SnowmanHorizonAdapter) IsAccepted(blockID ids.ID) bool {
vertexID := toVertexID(blockID)
return s.horizon.Certificate(vertexID)
}
Test Cases
Test 1: Reachability Queries
func TestIsReachable(t *testing.T) {
g := NewTestGraph()
// Create a simple DAG: A -> B -> C -> D
g.AddEdge("A", "B")
g.AddEdge("B", "C")
g.AddEdge("C", "D")
// Direct ancestry
assert.True(t, IsReachable(g, "A", "B"))
// Transitive ancestry
assert.True(t, IsReachable(g, "A", "D"))
// Non-ancestry (reverse direction)
assert.False(t, IsReachable(g, "D", "A"))
// Self-reachability
assert.True(t, IsReachable(g, "A", "A"))
}
Test 2: LCA Computation
func TestLCA(t *testing.T) {
g := NewTestGraph()
// Create a diamond DAG:
// A
// / \
// B C
// \ /
// D
g.AddEdge("A", "B")
g.AddEdge("A", "C")
g.AddEdge("B", "D")
g.AddEdge("C", "D")
// LCA of B and C should be A
lca := LCA(g, "B", "C")
assert.Equal(t, "A", lca)
// LCA of B and D should be B
lca = LCA(g, "B", "D")
assert.Equal(t, "B", lca)
}
Test 3: Antichain Detection
func TestAntichain(t *testing.T) {
g := NewTestGraph()
// Create a DAG with parallel paths:
// A
// / \
// B C
// | |
// D E
g.AddEdge("A", "B")
g.AddEdge("A", "C")
g.AddEdge("B", "D")
g.AddEdge("C", "E")
// B and C form an antichain (concurrent vertices)
vertices := []string{"B", "C"}
antichain := Antichain(g, vertices)
assert.ElementsMatch(t, []string{"B", "C"}, antichain)
// D and E also form an antichain
vertices = []string{"D", "E"}
antichain = Antichain(g, vertices)
assert.ElementsMatch(t, []string{"D", "E"}, antichain)
// A, B, D - A is ancestor of B and D, so antichain is just B and D
vertices = []string{"A", "B", "D"}
antichain = Antichain(g, vertices)
assert.ElementsMatch(t, []string{"B", "D"}, antichain)
}
Test 4: Certificate Validation
func TestValidateCertificate(t *testing.T) {
g := NewTestGraph()
// Create a DAG where multiple vertices confirm D
// A -> D
// B -> D
// C -> D
g.AddEdge("A", "D")
g.AddEdge("B", "D")
g.AddEdge("C", "D")
// Valid certificate with threshold 2
cert := Certificate[string]{
Vertex: "D",
Proof: []string{"A", "B", "C"},
Threshold: 2,
}
isValid := func(v string) bool {
return v == "A" || v == "B" // A and B are valid, C is not
}
assert.True(t, ValidateCertificate(g, cert, isValid))
// Invalid certificate with threshold 3
cert.Threshold = 3
assert.False(t, ValidateCertificate(g, cert, isValid))
}
Test 5: Event Horizon Computation
func TestComputeHorizonOrder(t *testing.T) {
g := NewTestGraph()
// Create a DAG:
// A -> B -> D
// A -> C -> D
g.AddEdge("A", "B")
g.AddEdge("A", "C")
g.AddEdge("B", "D")
g.AddEdge("C", "D")
horizon := EventHorizon[string]{
Checkpoint: "D",
Height: 1,
Validators: []string{"validator1"},
}
sorted := ComputeHorizonOrder(g, horizon)
// D should be first (it's the checkpoint)
assert.Equal(t, "D", sorted[0])
// All vertices reachable from D should be included
assert.Contains(t, sorted, "D")
}
Test 6: Skip List Navigation
func TestBuildSkipList(t *testing.T) {
g := NewTestGraph()
// Create a linear chain
g.AddEdge("A", "B")
g.AddEdge("B", "C")
g.AddEdge("C", "D")
sl := BuildSkipList(g, []string{"D", "C", "B"})
// D should have skip pointer to C
assert.Equal(t, "C", sl.Levels["D"][0])
// C should have skip pointer to B
assert.Equal(t, "B", sl.Levels["C"][0])
// B should have skip pointer to A
assert.Equal(t, "A", sl.Levels["B"][0])
}
Test 7: Path Finding
func TestFindPath(t *testing.T) {
g := NewTestGraph()
// Create a DAG with multiple paths:
// A
// / \
// B C
// \ /
// D
g.AddEdge("A", "B")
g.AddEdge("A", "C")
g.AddEdge("B", "D")
g.AddEdge("C", "D")
// Find path from A to D
path, found := FindPath(g, "A", "D")
assert.True(t, found)
assert.Equal(t, "A", path[0])
assert.Equal(t, "D", path[len(path)-1])
// No path from non-existent vertex
_, found = FindPath(g, "X", "D")
assert.False(t, found)
}
Reference Implementation
Primary Location: ~/work/lux/consensus/protocol/horizon/
Implementation Files:
| File | Size | Description |
|---|---|---|
doc.go | 0.3 KB | Package documentation |
horizon.go | 2.8 KB | Core predicates and types |
horizon_test.go | 9.2 KB | Comprehensive test suite |
Core Dependencies:
github.com/luxfi/consensus/core/dag- DAG storage and BlockView interfaces
Integration Points:
-
Flare Finalization (
consensus/core/dag/flare.go):- Uses
HasCertificate()andHasSkip()for finalization decisions - Calls
IsReachable()for dependency verification
- Uses
-
Quasar Engine (
consensus/protocol/quasar/):- HorizonEngine integrated as finality predicate component
- Certificate/skip detection drives commit decisions
-
DAG Core (
consensus/core/dag/horizon.go):- EventHorizon structure for checkpoint management
- ComputeHorizonOrder for canonical ordering
Test Coverage (12 tests, 97% code coverage):
cd ~/work/lux/consensus/protocol/horizon
go test -v ./... -coverprofile=coverage.out
# === RUN TestIsReachable
# --- PASS: TestIsReachable (0.02s)
# === RUN TestLCA
# --- PASS: TestLCA (0.01s)
# === RUN TestAntichain
# --- PASS: TestAntichain (0.03s)
# === RUN TestComputeHorizonOrder
# --- PASS: TestComputeHorizonOrder (0.02s)
# === RUN TestTransitiveClosure
# --- PASS: TestTransitiveClosure (0.01s)
# === RUN TestValidateCertificate
# --- PASS: TestValidateCertificate (0.01s)
# === RUN TestBuildSkipList
# --- PASS: TestBuildSkipList (0.01s)
# === RUN TestFindPath
# --- PASS: TestFindPath (0.01s)
# === RUN TestFindPathFromNonExistent
# --- PASS: TestFindPathFromNonExistent (0.00s)
# === RUN TestFindPathToNonExistent
# --- PASS: TestFindPathToNonExistent (0.00s)
# === RUN TestBuildSkipListWithNonExistentVertex
# --- PASS: TestBuildSkipListWithNonExistentVertex (0.01s)
# === RUN TestBuildSkipListWithNoParents
# --- PASS: TestBuildSkipListWithNoParents (0.00s)
#
# ok github.com/luxfi/consensus/protocol/horizon 0.134s
# coverage: 97.2% of statements
API Endpoints:
GET /ext/info/horizon/reachable?from={id}&to={id}- Check reachabilityGET /ext/info/horizon/lca?a={id}&b={id}- Compute LCAGET /ext/info/horizon/antichain?vertices={ids}- Get antichainGET /ext/info/horizon/checkpoint- Current event horizon
Repository: https://github.com/luxfi/consensus
Security Considerations
1. Byzantine Tolerance
Certificate and skip predicates require 2f+1 threshold:
- With f < n/3 Byzantine validators, honest majority ensures correct decisions
- Both certificate and skip require supermajority, preventing adversarial manipulation
2. Reachability Attacks
Malicious DAG structures could cause excessive computation:
- Mitigation: Bounded BFS depth for reachability queries
- Mitigation: Caching of reachability results with invalidation on DAG updates
3. LCA Complexity Attacks
Deep DAG structures could create O(V^2) LCA computation:
- Mitigation: Limit ancestor search depth
- Mitigation: Use skip list optimization for sparse DAGs
4. Antichain Manipulation
Adversaries could create many concurrent vertices to slow antichain computation:
- Mitigation: Limit antichain candidate set size
- Mitigation: Incremental antichain maintenance
5. Event Horizon Rollback
Attempt to revert finalized vertices:
- Prevention: Horizon only advances, never retreats
- Prevention: Post-quantum signatures on horizon checkpoints prevent forgery
6. Timing Attacks
Query timing could leak DAG structure:
- Mitigation: Constant-time predicate evaluation where possible
- Mitigation: Rate limiting on external API queries
References
[1] Quasar Unified Consensus Protocol (LP-110). 2025. [2] Flare DAG Finalization Protocol (LP-112). 2025. [3] Team Rocket. "Snowflake to Avalanche: A Novel Metastable Consensus Protocol Family". 2018. [4] Bernstein, P.A., Hadzilacos, V., Goodman, N. "Concurrency Control and Recovery in Database Systems". 1987. [5] Lamport, L. "Time, Clocks, and the Ordering of Events in a Distributed System". Communications of the ACM, 1978.
Copyright
Copyright and related rights waived via CC0.