mirror of
https://github.com/luxfi/consensus.git
synced 2026-09-24 00:26:58 +00:00
- Add state.SerializerConfig and state.NewSerializer for vertex serialization - Add state.Manager interface extending State with DAG operations - Add bootstrap.Config with all required interfaces (Blocker, Halter, LinearizableVM) - Add bootstrap.Bootstrapper implementing BootstrapableEngine - Add bootstrap/queue.Queue for job processing - Add getter.Handler and getter.Getter interfaces This enables the DAG consensus engine to be properly wired up in the node.
212 lines
4.6 KiB
Go
212 lines
4.6 KiB
Go
package state
|
|
|
|
import (
|
|
"context"
|
|
"sync"
|
|
|
|
"github.com/luxfi/database"
|
|
"github.com/luxfi/ids"
|
|
"github.com/luxfi/log"
|
|
)
|
|
|
|
// State represents DAG state
|
|
type State interface {
|
|
// GetVertex gets a vertex
|
|
GetVertex(ids.ID) (Vertex, error)
|
|
|
|
// AddVertex adds a vertex
|
|
AddVertex(Vertex) error
|
|
|
|
// VertexIssued checks if vertex issued
|
|
VertexIssued(Vertex) bool
|
|
|
|
// IsProcessing checks if processing
|
|
IsProcessing(ids.ID) bool
|
|
}
|
|
|
|
// Vertex represents a DAG vertex
|
|
type Vertex interface {
|
|
ID() ids.ID
|
|
ParentIDs() []ids.ID
|
|
Height() uint64
|
|
Bytes() []byte
|
|
}
|
|
|
|
// DAGVM is the interface for a DAG-based virtual machine
|
|
type DAGVM interface {
|
|
// ParseVtx parses a vertex from bytes
|
|
ParseVtx(ctx context.Context, bytes []byte) (Vertex, error)
|
|
}
|
|
|
|
// Manager extends State with vertex management capabilities
|
|
type Manager interface {
|
|
State
|
|
|
|
// ParseVtx parses a vertex from bytes
|
|
ParseVtx(ctx context.Context, bytes []byte) (Vertex, error)
|
|
|
|
// GetVtx returns a vertex by ID
|
|
GetVtx(ctx context.Context, vtxID ids.ID) (Vertex, error)
|
|
|
|
// Edge returns the current edge of the DAG
|
|
Edge(ctx context.Context) []ids.ID
|
|
|
|
// StopVertexAccepted marks a vertex as no longer accepted
|
|
StopVertexAccepted()
|
|
}
|
|
|
|
// SerializerConfig configures the vertex serializer
|
|
type SerializerConfig struct {
|
|
ChainID ids.ID
|
|
VM DAGVM
|
|
DB database.Database
|
|
Log log.Logger
|
|
}
|
|
|
|
// serializer implements Manager for vertex serialization
|
|
type serializer struct {
|
|
mu sync.RWMutex
|
|
chainID ids.ID
|
|
vm DAGVM
|
|
db database.Database
|
|
log log.Logger
|
|
vertices map[ids.ID]Vertex
|
|
processing map[ids.ID]bool
|
|
edge []ids.ID
|
|
}
|
|
|
|
// NewSerializer creates a new vertex serializer/manager
|
|
func NewSerializer(config SerializerConfig) Manager {
|
|
return &serializer{
|
|
chainID: config.ChainID,
|
|
vm: config.VM,
|
|
db: config.DB,
|
|
log: config.Log,
|
|
vertices: make(map[ids.ID]Vertex),
|
|
processing: make(map[ids.ID]bool),
|
|
edge: make([]ids.ID, 0),
|
|
}
|
|
}
|
|
|
|
// GetVertex gets a vertex by ID
|
|
func (s *serializer) GetVertex(id ids.ID) (Vertex, error) {
|
|
s.mu.RLock()
|
|
defer s.mu.RUnlock()
|
|
vertex, exists := s.vertices[id]
|
|
if !exists {
|
|
return nil, ErrVertexNotFound
|
|
}
|
|
return vertex, nil
|
|
}
|
|
|
|
// AddVertex adds a vertex to the state
|
|
func (s *serializer) AddVertex(vertex Vertex) error {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
s.vertices[vertex.ID()] = vertex
|
|
return nil
|
|
}
|
|
|
|
// VertexIssued checks if a vertex has been issued
|
|
func (s *serializer) VertexIssued(vertex Vertex) bool {
|
|
s.mu.RLock()
|
|
defer s.mu.RUnlock()
|
|
_, exists := s.vertices[vertex.ID()]
|
|
return exists
|
|
}
|
|
|
|
// IsProcessing checks if a vertex is being processed
|
|
func (s *serializer) IsProcessing(id ids.ID) bool {
|
|
s.mu.RLock()
|
|
defer s.mu.RUnlock()
|
|
return s.processing[id]
|
|
}
|
|
|
|
// ParseVtx parses a vertex from bytes
|
|
func (s *serializer) ParseVtx(ctx context.Context, bytes []byte) (Vertex, error) {
|
|
return s.vm.ParseVtx(ctx, bytes)
|
|
}
|
|
|
|
// GetVtx returns a vertex by ID, fetching from VM if necessary
|
|
func (s *serializer) GetVtx(ctx context.Context, vtxID ids.ID) (Vertex, error) {
|
|
s.mu.RLock()
|
|
vtx, exists := s.vertices[vtxID]
|
|
s.mu.RUnlock()
|
|
if exists {
|
|
return vtx, nil
|
|
}
|
|
|
|
// Try to fetch from database
|
|
bytes, err := s.db.Get(vtxID[:])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return s.ParseVtx(ctx, bytes)
|
|
}
|
|
|
|
// Edge returns the current edge of the DAG
|
|
func (s *serializer) Edge(ctx context.Context) []ids.ID {
|
|
s.mu.RLock()
|
|
defer s.mu.RUnlock()
|
|
edge := make([]ids.ID, len(s.edge))
|
|
copy(edge, s.edge)
|
|
return edge
|
|
}
|
|
|
|
// StopVertexAccepted marks vertices as no longer being accepted
|
|
func (s *serializer) StopVertexAccepted() {
|
|
s.mu.Lock()
|
|
defer s.mu.Unlock()
|
|
s.processing = make(map[ids.ID]bool)
|
|
}
|
|
|
|
// state implementation
|
|
type state struct {
|
|
vertices map[ids.ID]Vertex
|
|
processing map[ids.ID]bool
|
|
}
|
|
|
|
// New creates a new state
|
|
func New() State {
|
|
return &state{
|
|
vertices: make(map[ids.ID]Vertex),
|
|
processing: make(map[ids.ID]bool),
|
|
}
|
|
}
|
|
|
|
// GetVertex gets a vertex
|
|
func (s *state) GetVertex(id ids.ID) (Vertex, error) {
|
|
vertex, exists := s.vertices[id]
|
|
if !exists {
|
|
return nil, ErrVertexNotFound
|
|
}
|
|
return vertex, nil
|
|
}
|
|
|
|
// AddVertex adds a vertex
|
|
func (s *state) AddVertex(vertex Vertex) error {
|
|
s.vertices[vertex.ID()] = vertex
|
|
return nil
|
|
}
|
|
|
|
// VertexIssued checks if vertex issued
|
|
func (s *state) VertexIssued(vertex Vertex) bool {
|
|
_, exists := s.vertices[vertex.ID()]
|
|
return exists
|
|
}
|
|
|
|
// IsProcessing checks if processing
|
|
func (s *state) IsProcessing(id ids.ID) bool {
|
|
return s.processing[id]
|
|
}
|
|
|
|
// ErrVertexNotFound is returned when vertex not found
|
|
var ErrVertexNotFound = &vertexNotFoundError{}
|
|
|
|
type vertexNotFoundError struct{}
|
|
|
|
func (e *vertexNotFoundError) Error() string {
|
|
return "vertex not found"
|
|
}
|