github.com/MetalBlockchain/metalgo@v1.11.9/x/sync/g_db/db_server.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package gdb 5 6 import ( 7 "context" 8 "errors" 9 10 "google.golang.org/protobuf/types/known/emptypb" 11 12 "github.com/MetalBlockchain/metalgo/ids" 13 "github.com/MetalBlockchain/metalgo/utils/maybe" 14 "github.com/MetalBlockchain/metalgo/x/merkledb" 15 "github.com/MetalBlockchain/metalgo/x/sync" 16 17 pb "github.com/MetalBlockchain/metalgo/proto/pb/sync" 18 ) 19 20 var _ pb.DBServer = (*DBServer)(nil) 21 22 func NewDBServer(db sync.DB) *DBServer { 23 return &DBServer{ 24 db: db, 25 } 26 } 27 28 type DBServer struct { 29 pb.UnsafeDBServer 30 31 db sync.DB 32 } 33 34 func (s *DBServer) GetMerkleRoot( 35 ctx context.Context, 36 _ *emptypb.Empty, 37 ) (*pb.GetMerkleRootResponse, error) { 38 root, err := s.db.GetMerkleRoot(ctx) 39 if err != nil { 40 return nil, err 41 } 42 return &pb.GetMerkleRootResponse{ 43 RootHash: root[:], 44 }, nil 45 } 46 47 func (s *DBServer) GetChangeProof( 48 ctx context.Context, 49 req *pb.GetChangeProofRequest, 50 ) (*pb.GetChangeProofResponse, error) { 51 startRootID, err := ids.ToID(req.StartRootHash) 52 if err != nil { 53 return nil, err 54 } 55 endRootID, err := ids.ToID(req.EndRootHash) 56 if err != nil { 57 return nil, err 58 } 59 start := maybe.Nothing[[]byte]() 60 if req.StartKey != nil && !req.StartKey.IsNothing { 61 start = maybe.Some(req.StartKey.Value) 62 } 63 end := maybe.Nothing[[]byte]() 64 if req.EndKey != nil && !req.EndKey.IsNothing { 65 end = maybe.Some(req.EndKey.Value) 66 } 67 68 changeProof, err := s.db.GetChangeProof( 69 ctx, 70 startRootID, 71 endRootID, 72 start, 73 end, 74 int(req.KeyLimit), 75 ) 76 if err != nil { 77 if !errors.Is(err, merkledb.ErrInsufficientHistory) { 78 return nil, err 79 } 80 return &pb.GetChangeProofResponse{ 81 Response: &pb.GetChangeProofResponse_RootNotPresent{ 82 RootNotPresent: true, 83 }, 84 }, nil 85 } 86 87 return &pb.GetChangeProofResponse{ 88 Response: &pb.GetChangeProofResponse_ChangeProof{ 89 ChangeProof: changeProof.ToProto(), 90 }, 91 }, nil 92 } 93 94 func (s *DBServer) VerifyChangeProof( 95 ctx context.Context, 96 req *pb.VerifyChangeProofRequest, 97 ) (*pb.VerifyChangeProofResponse, error) { 98 var proof merkledb.ChangeProof 99 if err := proof.UnmarshalProto(req.Proof); err != nil { 100 return nil, err 101 } 102 103 rootID, err := ids.ToID(req.ExpectedRootHash) 104 if err != nil { 105 return nil, err 106 } 107 startKey := maybe.Nothing[[]byte]() 108 if req.StartKey != nil && !req.StartKey.IsNothing { 109 startKey = maybe.Some(req.StartKey.Value) 110 } 111 endKey := maybe.Nothing[[]byte]() 112 if req.EndKey != nil && !req.EndKey.IsNothing { 113 endKey = maybe.Some(req.EndKey.Value) 114 } 115 116 // TODO there's probably a better way to do this. 117 var errString string 118 if err := s.db.VerifyChangeProof(ctx, &proof, startKey, endKey, rootID); err != nil { 119 errString = err.Error() 120 } 121 return &pb.VerifyChangeProofResponse{ 122 Error: errString, 123 }, nil 124 } 125 126 func (s *DBServer) CommitChangeProof( 127 ctx context.Context, 128 req *pb.CommitChangeProofRequest, 129 ) (*emptypb.Empty, error) { 130 var proof merkledb.ChangeProof 131 if err := proof.UnmarshalProto(req.Proof); err != nil { 132 return nil, err 133 } 134 135 err := s.db.CommitChangeProof(ctx, &proof) 136 return &emptypb.Empty{}, err 137 } 138 139 func (s *DBServer) GetProof( 140 ctx context.Context, 141 req *pb.GetProofRequest, 142 ) (*pb.GetProofResponse, error) { 143 proof, err := s.db.GetProof(ctx, req.Key) 144 if err != nil { 145 return nil, err 146 } 147 148 return &pb.GetProofResponse{ 149 Proof: proof.ToProto(), 150 }, nil 151 } 152 153 func (s *DBServer) GetRangeProof( 154 ctx context.Context, 155 req *pb.GetRangeProofRequest, 156 ) (*pb.GetRangeProofResponse, error) { 157 rootID, err := ids.ToID(req.RootHash) 158 if err != nil { 159 return nil, err 160 } 161 start := maybe.Nothing[[]byte]() 162 if req.StartKey != nil && !req.StartKey.IsNothing { 163 start = maybe.Some(req.StartKey.Value) 164 } 165 end := maybe.Nothing[[]byte]() 166 if req.EndKey != nil && !req.EndKey.IsNothing { 167 end = maybe.Some(req.EndKey.Value) 168 } 169 proof, err := s.db.GetRangeProofAtRoot(ctx, rootID, start, end, int(req.KeyLimit)) 170 if err != nil { 171 return nil, err 172 } 173 174 protoProof := &pb.GetRangeProofResponse{ 175 Proof: &pb.RangeProof{ 176 StartProof: make([]*pb.ProofNode, len(proof.StartProof)), 177 EndProof: make([]*pb.ProofNode, len(proof.EndProof)), 178 KeyValues: make([]*pb.KeyValue, len(proof.KeyValues)), 179 }, 180 } 181 for i, node := range proof.StartProof { 182 protoProof.Proof.StartProof[i] = node.ToProto() 183 } 184 for i, node := range proof.EndProof { 185 protoProof.Proof.EndProof[i] = node.ToProto() 186 } 187 for i, kv := range proof.KeyValues { 188 protoProof.Proof.KeyValues[i] = &pb.KeyValue{ 189 Key: kv.Key, 190 Value: kv.Value, 191 } 192 } 193 194 return protoProof, nil 195 } 196 197 func (s *DBServer) CommitRangeProof( 198 ctx context.Context, 199 req *pb.CommitRangeProofRequest, 200 ) (*emptypb.Empty, error) { 201 var proof merkledb.RangeProof 202 if err := proof.UnmarshalProto(req.RangeProof); err != nil { 203 return nil, err 204 } 205 206 start := maybe.Nothing[[]byte]() 207 if req.StartKey != nil && !req.StartKey.IsNothing { 208 start = maybe.Some(req.StartKey.Value) 209 } 210 211 end := maybe.Nothing[[]byte]() 212 if req.EndKey != nil && !req.EndKey.IsNothing { 213 end = maybe.Some(req.EndKey.Value) 214 } 215 216 err := s.db.CommitRangeProof(ctx, start, end, &proof) 217 return &emptypb.Empty{}, err 218 } 219 220 func (s *DBServer) Clear(context.Context, *emptypb.Empty) (*emptypb.Empty, error) { 221 return &emptypb.Empty{}, s.db.Clear() 222 }