github.com/MetalBlockchain/metalgo@v1.11.9/snow/engine/avalanche/state/serializer.go (about)

     1  // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
     2  // See the file LICENSE for licensing terms.
     3  
     4  // Package state manages the meta-data required by consensus for an avalanche
     5  // dag.
     6  package state
     7  
     8  import (
     9  	"context"
    10  	"errors"
    11  	"time"
    12  
    13  	"github.com/MetalBlockchain/metalgo/cache"
    14  	"github.com/MetalBlockchain/metalgo/database"
    15  	"github.com/MetalBlockchain/metalgo/database/versiondb"
    16  	"github.com/MetalBlockchain/metalgo/ids"
    17  	"github.com/MetalBlockchain/metalgo/snow/choices"
    18  	"github.com/MetalBlockchain/metalgo/snow/consensus/avalanche"
    19  	"github.com/MetalBlockchain/metalgo/snow/engine/avalanche/vertex"
    20  	"github.com/MetalBlockchain/metalgo/utils/logging"
    21  	"github.com/MetalBlockchain/metalgo/utils/math"
    22  	"github.com/MetalBlockchain/metalgo/utils/set"
    23  )
    24  
    25  const (
    26  	dbCacheSize = 10000
    27  	idCacheSize = 1000
    28  )
    29  
    30  var (
    31  	errUnknownVertex = errors.New("unknown vertex")
    32  	errWrongChainID  = errors.New("wrong ChainID in vertex")
    33  )
    34  
    35  var _ vertex.Manager = (*Serializer)(nil)
    36  
    37  // Serializer manages the state of multiple vertices
    38  type Serializer struct {
    39  	SerializerConfig
    40  	versionDB *versiondb.Database
    41  	state     *prefixedState
    42  	edge      set.Set[ids.ID]
    43  }
    44  
    45  type SerializerConfig struct {
    46  	ChainID     ids.ID
    47  	VM          vertex.DAGVM
    48  	DB          database.Database
    49  	Log         logging.Logger
    50  	CortinaTime time.Time
    51  }
    52  
    53  func NewSerializer(config SerializerConfig) vertex.Manager {
    54  	versionDB := versiondb.New(config.DB)
    55  	dbCache := &cache.LRU[ids.ID, any]{Size: dbCacheSize}
    56  	s := Serializer{
    57  		SerializerConfig: config,
    58  		versionDB:        versionDB,
    59  	}
    60  
    61  	rawState := &state{
    62  		serializer: &s,
    63  		log:        config.Log,
    64  		dbCache:    dbCache,
    65  		db:         versionDB,
    66  	}
    67  
    68  	s.state = newPrefixedState(rawState, idCacheSize)
    69  	s.edge.Add(s.state.Edge()...)
    70  
    71  	return &s
    72  }
    73  
    74  func (s *Serializer) ParseVtx(ctx context.Context, b []byte) (avalanche.Vertex, error) {
    75  	return newUniqueVertex(ctx, s, b)
    76  }
    77  
    78  func (s *Serializer) BuildStopVtx(
    79  	ctx context.Context,
    80  	parentIDs []ids.ID,
    81  ) (avalanche.Vertex, error) {
    82  	height := uint64(0)
    83  	for _, parentID := range parentIDs {
    84  		parent, err := s.getUniqueVertex(parentID)
    85  		if err != nil {
    86  			return nil, err
    87  		}
    88  		parentHeight := parent.v.vtx.Height()
    89  		childHeight, err := math.Add64(parentHeight, 1)
    90  		if err != nil {
    91  			return nil, err
    92  		}
    93  		height = max(height, childHeight)
    94  	}
    95  
    96  	vtx, err := vertex.BuildStopVertex(
    97  		s.ChainID,
    98  		height,
    99  		parentIDs,
   100  	)
   101  	if err != nil {
   102  		return nil, err
   103  	}
   104  
   105  	uVtx := &uniqueVertex{
   106  		serializer: s,
   107  		id:         vtx.ID(),
   108  	}
   109  	// setVertex handles the case where this vertex already exists even
   110  	// though we just made it
   111  	return uVtx, uVtx.setVertex(ctx, vtx)
   112  }
   113  
   114  func (s *Serializer) GetVtx(_ context.Context, vtxID ids.ID) (avalanche.Vertex, error) {
   115  	return s.getUniqueVertex(vtxID)
   116  }
   117  
   118  func (s *Serializer) Edge(context.Context) []ids.ID {
   119  	return s.edge.List()
   120  }
   121  
   122  func (s *Serializer) parseVertex(b []byte) (vertex.StatelessVertex, error) {
   123  	vtx, err := vertex.Parse(b)
   124  	if err != nil {
   125  		return nil, err
   126  	}
   127  	if vtx.ChainID() != s.ChainID {
   128  		return nil, errWrongChainID
   129  	}
   130  	return vtx, nil
   131  }
   132  
   133  func (s *Serializer) getUniqueVertex(vtxID ids.ID) (*uniqueVertex, error) {
   134  	vtx := &uniqueVertex{
   135  		serializer: s,
   136  		id:         vtxID,
   137  	}
   138  	if vtx.Status() == choices.Unknown {
   139  		return nil, errUnknownVertex
   140  	}
   141  	return vtx, nil
   142  }
   143  
   144  func (s *Serializer) StopVertexAccepted(ctx context.Context) (bool, error) {
   145  	edge := s.Edge(ctx)
   146  	if len(edge) != 1 {
   147  		return false, nil
   148  	}
   149  
   150  	vtx, err := s.getUniqueVertex(edge[0])
   151  	if err != nil {
   152  		return false, err
   153  	}
   154  
   155  	return vtx.v.vtx.StopVertex(), nil
   156  }