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 }