From 42e206af5f12f87ae7817b46fc4489a36c228da5 Mon Sep 17 00:00:00 2001 From: Matee ullah Date: Tue, 23 Sep 2025 13:03:27 +0500 Subject: [PATCH 1/2] prepare decode --- p2p/kademlia/network.go | 16 +- pkg/codec/codec_mock.go | 12 +- pkg/codec/decode.go | 257 ++++++++++++++---- pkg/net/grpc/client/client.go | 6 +- pkg/net/grpc/server/server.go | 8 +- .../cascade/adaptors/mocks/lumera_mock.go | 48 ++-- .../cascade/adaptors/mocks/p2p_mock.go | 10 +- .../cascade/adaptors/mocks/rq_mock.go | 31 ++- supernode/services/cascade/adaptors/rq.go | 7 +- .../cascade/mocks/cascade_interfaces_mock.go | 15 +- 10 files changed, 267 insertions(+), 143 deletions(-) diff --git a/p2p/kademlia/network.go b/p2p/kademlia/network.go index a2322ff7..935d1583 100644 --- a/p2p/kademlia/network.go +++ b/p2p/kademlia/network.go @@ -2,7 +2,6 @@ package kademlia import ( "context" - "encoding/hex" "fmt" "io" "net" @@ -951,7 +950,7 @@ func (s *Network) handleGetValuesRequest(ctx context.Context, message *Message, i++ } - values, count, err := s.dht.store.RetrieveBatchValues(ctx, keys, true) + values, count, err := s.dht.store.RetrieveBatchValues(ctx, keys, false) if err != nil { err = errors.Errorf("batch find values: %w", err) s.appendRetrieveEntry(message.Sender.IP, RecentBatchRetrieveEntry{ @@ -976,17 +975,8 @@ func (s *Network) handleGetValuesRequest(ctx context.Context, message *Message, for i, key := range keys { val := KeyValWithClosest{ - Value: values[i], - } - if len(val.Value) == 0 { - decodedKey, err := hex.DecodeString(keys[i]) - if err != nil { - err = errors.Errorf("batch find vals: decode key: %w - key %s", err, keys[i]) - return s.generateResponseMessage(BatchGetValues, message.Sender, ResultFailed, err.Error()) - } - - nodes, _ := s.dht.ht.closestContacts(Alpha, decodedKey, []*Node{message.Sender}) - val.Closest = nodes.Nodes + Value: values[i], + Closest: make([]*Node, 0), // for compatibility, not used - each node now has full view of the whole network } request.Data[key] = val diff --git a/pkg/codec/codec_mock.go b/pkg/codec/codec_mock.go index 9c3cf864..09484cee 100644 --- a/pkg/codec/codec_mock.go +++ b/pkg/codec/codec_mock.go @@ -1,10 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. // Source: codec.go -// -// Generated by this command: -// -// mockgen -destination=codec_mock.go -package=codec -source=codec.go -// // Package codec is a generated GoMock package. package codec @@ -13,14 +8,13 @@ import ( context "context" reflect "reflect" - gomock "go.uber.org/mock/gomock" + gomock "github.com/golang/mock/gomock" ) // MockCodec is a mock of Codec interface. type MockCodec struct { ctrl *gomock.Controller recorder *MockCodecMockRecorder - isgomock struct{} } // MockCodecMockRecorder is the mock recorder for MockCodec. @@ -50,7 +44,7 @@ func (m *MockCodec) Decode(ctx context.Context, req DecodeRequest) (DecodeRespon } // Decode indicates an expected call of Decode. -func (mr *MockCodecMockRecorder) Decode(ctx, req any) *gomock.Call { +func (mr *MockCodecMockRecorder) Decode(ctx, req interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Decode", reflect.TypeOf((*MockCodec)(nil).Decode), ctx, req) } @@ -65,7 +59,7 @@ func (m *MockCodec) Encode(ctx context.Context, req EncodeRequest) (EncodeRespon } // Encode indicates an expected call of Encode. -func (mr *MockCodecMockRecorder) Encode(ctx, req any) *gomock.Call { +func (mr *MockCodecMockRecorder) Encode(ctx, req interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Encode", reflect.TypeOf((*MockCodec)(nil).Encode), ctx, req) } diff --git a/pkg/codec/decode.go b/pkg/codec/decode.go index fe77d752..bd3b0231 100644 --- a/pkg/codec/decode.go +++ b/pkg/codec/decode.go @@ -5,9 +5,13 @@ import ( "encoding/json" "fmt" "os" + "path" "path/filepath" + "strings" + "sync" raptorq "github.com/LumeraProtocol/rq-go" + "github.com/LumeraProtocol/supernode/v2/pkg/errors" "github.com/LumeraProtocol/supernode/v2/pkg/logtrace" ) @@ -18,81 +22,160 @@ type DecodeRequest struct { } type DecodeResponse struct { - Path string + FilePath string DecodeTmpDir string } -func (rq *raptorQ) Decode(ctx context.Context, req DecodeRequest) (DecodeResponse, error) { +// Workspace holds paths & reverse index for prepared decoding. +type Workspace struct { + ActionID string + SymbolsDir string // ...// + BlockDirs []string // index = blockID (or 0 if single block) + symbolToBlock map[string]int + mu sync.RWMutex // protects symbolToBlock reads if you expand it later +} + +// PrepareDecode creates the on-disk workspace for decoding and returns: +// - blockPaths[0] => where to write symbols for block 0 (your single-block case) +// - Write(block, id, data) callback that writes symbol bytes directly to disk +// - Cleanup() to remove the workspace on abort (no-op if you want to keep it) +func (rq *raptorQ) PrepareDecode( + ctx context.Context, + actionID string, + layout Layout, +) (blockPaths []string, Write func(block int, symbolID string, data []byte) (string, error), Cleanup func() error, ws *Workspace, err error) { fields := logtrace.Fields{ - logtrace.FieldMethod: "Decode", + logtrace.FieldMethod: "PrepareDecode", logtrace.FieldModule: "rq", - logtrace.FieldActionID: req.ActionID, + logtrace.FieldActionID: actionID, } - logtrace.Info(ctx, "RaptorQ decode request received", fields) - // Use deterministic processor settings (matching encoder) - processor, err := raptorq.NewRaptorQProcessor(rqSymbolSize, rqRedundancyFactor, rqMaxMemoryMB, rqConcurrency) - if err != nil { + // Create root symbols dir for this action + symbolsDir := filepath.Join(rq.symbolsBaseDir, actionID) + if err := os.MkdirAll(symbolsDir, 0o755); err != nil { fields[logtrace.FieldError] = err.Error() - return DecodeResponse{}, fmt.Errorf("create RaptorQ processor: %w", err) + logtrace.Error(ctx, "mkdir symbols base dir failed", fields) + return nil, nil, nil, nil, fmt.Errorf("mkdir %s: %w", symbolsDir, err) } - defer processor.Free() - symbolsDir := filepath.Join(rq.symbolsBaseDir, req.ActionID) - // Ensure a clean scratch directory (avoid contamination from previous attempts) - if err := os.RemoveAll(symbolsDir); err != nil { - fields[logtrace.FieldError] = err.Error() - return DecodeResponse{}, fmt.Errorf("cleanup decode dir %s: %w", symbolsDir, err) + // Ensure block directories exist; build reverse index symbol -> block + maxBlockID := 0 + for _, b := range layout.Blocks { + if int(b.BlockID) > maxBlockID { + maxBlockID = int(b.BlockID) + } } - if err := os.MkdirAll(symbolsDir, 0o755); err != nil { - fields[logtrace.FieldError] = err.Error() - return DecodeResponse{}, fmt.Errorf("mkdir %s: %w", symbolsDir, err) + blockDirs := make([]string, maxBlockID+1) + s2b := make(map[string]int, 1024) + + for _, b := range layout.Blocks { + dir := filepath.Join(symbolsDir, fmt.Sprintf("block_%d", b.BlockID)) + if err := os.MkdirAll(dir, 0o755); err != nil { + fields[logtrace.FieldError] = err.Error() + logtrace.Error(ctx, "mkdir block dir failed", fields) + return nil, nil, nil, nil, fmt.Errorf("mkdir %s: %w", dir, err) + } + blockDirs[b.BlockID] = dir + for _, sym := range b.Symbols { + s2b[sym] = b.BlockID + } } - // Validate layout before writing any symbols - if len(req.Layout.Blocks) == 0 { - fields[logtrace.FieldError] = "empty layout" - return DecodeResponse{}, fmt.Errorf("invalid layout: no blocks present") + ws = &Workspace{ + ActionID: actionID, + SymbolsDir: symbolsDir, + BlockDirs: blockDirs, + symbolToBlock: s2b, } - for _, blk := range req.Layout.Blocks { - if len(blk.Symbols) == 0 { - fields[logtrace.FieldError] = fmt.Sprintf("block_%d has no symbols", blk.BlockID) - return DecodeResponse{}, fmt.Errorf("invalid layout: block %d has no symbols", blk.BlockID) + + // Helper: atomic write (tmp file + rename) to avoid partials on crash + writeFileAtomic := func(path string, data []byte) error { + tmp := path + ".tmp" + if err := os.WriteFile(tmp, data, 0o644); err != nil { + return err } + return os.Rename(tmp, path) } - // Build symbol->block mapping from layout and ensure block directories exist - symbolToBlock := make(map[string]int) - for _, blk := range req.Layout.Blocks { - blockDir := filepath.Join(symbolsDir, fmt.Sprintf("block_%d", blk.BlockID)) - if err := os.MkdirAll(blockDir, 0o755); err != nil { - fields[logtrace.FieldError] = err.Error() - return DecodeResponse{}, fmt.Errorf("mkdir %s: %w", blockDir, err) + // Write callback; if block < 0, resolve via layout reverse index; default to 0. + Write = func(block int, symbolID string, data []byte) (string, error) { + // Quick cancellation check + select { + case <-ctx.Done(): + return "", ctx.Err() + default: } - for _, sym := range blk.Symbols { - symbolToBlock[sym] = blk.BlockID + + // Resolve block if caller passes default + if block < 0 { + ws.mu.RLock() + bid, ok := ws.symbolToBlock[symbolID] + ws.mu.RUnlock() + if !ok { + // Single-block simplification: default to block 0 if layout maps are absent + if len(ws.BlockDirs) == 0 || ws.BlockDirs[0] == "" { + return "", errors.Errorf("no block directories prepared") + } + bid = 0 + } + block = bid } - } - // Write symbols to their respective block directories - for id, data := range req.Symbols { - blkID, ok := symbolToBlock[id] - if !ok { - fields[logtrace.FieldError] = "symbol not present in layout" - return DecodeResponse{}, fmt.Errorf("symbol %s not present in layout", id) + if block < 0 || block >= len(ws.BlockDirs) || ws.BlockDirs[block] == "" { + return "", errors.Errorf("invalid block index %d", block) } - blockDir := filepath.Join(symbolsDir, fmt.Sprintf("block_%d", blkID)) - symbolPath := filepath.Join(blockDir, id) - if err := os.WriteFile(symbolPath, data, 0o644); err != nil { - fields[logtrace.FieldError] = err.Error() - return DecodeResponse{}, fmt.Errorf("write symbol %s: %w", id, err) + + // sanitize symbolID to a basename (prevents traversal) + clean := path.Clean("/" + symbolID) + base := strings.TrimPrefix(clean, "/") + if base == "" || strings.Contains(base, "/") { + return "", errors.Errorf("invalid symbol id %q", symbolID) + + } + + dest := filepath.Join(ws.BlockDirs[block], base) + if err := writeFileAtomic(dest, data); err != nil { + return "", fmt.Errorf("write symbol %s (block %d): %w", base, block, err) } + return dest, nil + } + + Cleanup = func() error { + // Remove the whole workspace directory (symbols + layout + output if any) + return os.RemoveAll(symbolsDir) + } + + logtrace.Info(ctx, "prepare decode workspace created", logtrace.Fields{ + "symbols_dir": symbolsDir, + "blocks": len(blockDirs), + }) + return blockDirs, Write, Cleanup, ws, nil +} + +// DecodeFromPrepared performs RaptorQ decode using an already-prepared workspace. +// It writes layout.json under the workspace, runs decode, and returns output paths. +func (rq *raptorQ) DecodeFromPrepared( + ctx context.Context, + ws *Workspace, + layout Layout, +) (DecodeResponse, error) { + fields := logtrace.Fields{ + logtrace.FieldMethod: "DecodeFromPrepared", + logtrace.FieldModule: "rq", + logtrace.FieldActionID: ws.ActionID, + } + logtrace.Info(ctx, "RaptorQ decode (prepared) requested", fields) + + processor, err := raptorq.NewRaptorQProcessor(rqSymbolSize, rqRedundancyFactor, rqMaxMemoryMB, rqConcurrency) + if err != nil { + fields[logtrace.FieldError] = err.Error() + return DecodeResponse{}, fmt.Errorf("create RaptorQ processor: %w", err) } - logtrace.Info(ctx, "symbols written to block directories", fields) + defer processor.Free() - // ---------- write layout.json ---------- - layoutPath := filepath.Join(symbolsDir, "layout.json") - layoutBytes, err := json.Marshal(req.Layout) + // Write layout.json (idempotent) + layoutPath := filepath.Join(ws.SymbolsDir, "layout.json") + layoutBytes, err := json.Marshal(layout) if err != nil { fields[logtrace.FieldError] = err.Error() return DecodeResponse{}, fmt.Errorf("marshal layout: %w", err) @@ -101,16 +184,74 @@ func (rq *raptorQ) Decode(ctx context.Context, req DecodeRequest) (DecodeRespons fields[logtrace.FieldError] = err.Error() return DecodeResponse{}, fmt.Errorf("write layout file: %w", err) } - logtrace.Info(ctx, "layout.json written", fields) + logtrace.Info(ctx, "layout.json written (prepared)", fields) - // Decode - outputPath := filepath.Join(symbolsDir, "output") - if err := processor.DecodeSymbols(symbolsDir, outputPath, layoutPath); err != nil { + // Decode to output (idempotent-safe: overwrite on success) + outputPath := filepath.Join(ws.SymbolsDir, "output") + if err := processor.DecodeSymbols(ws.SymbolsDir, outputPath, layoutPath); err != nil { fields[logtrace.FieldError] = err.Error() - _ = os.Remove(outputPath) + _ = os.Remove(outputPath) // best-effort cleanup of partial output return DecodeResponse{}, fmt.Errorf("raptorq decode: %w", err) } - logtrace.Info(ctx, "RaptorQ decoding completed successfully", fields) - return DecodeResponse{Path: outputPath, DecodeTmpDir: symbolsDir}, nil + logtrace.Info(ctx, "RaptorQ decoding completed successfully (prepared)", logtrace.Fields{ + "output_path": outputPath, + }) + return DecodeResponse{FilePath: outputPath, DecodeTmpDir: ws.SymbolsDir}, nil +} + +func (rq *raptorQ) Decode(ctx context.Context, req DecodeRequest) (DecodeResponse, error) { + fields := logtrace.Fields{ + logtrace.FieldMethod: "Decode", + logtrace.FieldModule: "rq", + logtrace.FieldActionID: req.ActionID, + } + logtrace.Info(ctx, "RaptorQ decode request received", fields) + + // 1) Validate layout (the check) + if len(req.Layout.Blocks) == 0 { + fields[logtrace.FieldError] = "empty layout" + return DecodeResponse{}, fmt.Errorf("invalid layout: no blocks present") + } + for _, blk := range req.Layout.Blocks { + if len(blk.Symbols) == 0 { + fields[logtrace.FieldError] = fmt.Sprintf("block_%d has no symbols", blk.BlockID) + return DecodeResponse{}, fmt.Errorf("invalid layout: block %d has no symbols", blk.BlockID) + } + } + + // 2) Prepare workspace (functionality) + _, Write, Cleanup, ws, err := rq.PrepareDecode(ctx, req.ActionID, req.Layout) + if err != nil { + fields[logtrace.FieldError] = err.Error() + return DecodeResponse{}, fmt.Errorf("prepare decode workspace: %w", err) + } + + // Ensure workspace cleanup on failure. On success, caller cleans up via returned path. + success := false + defer func() { + if !success && Cleanup != nil { + _ = Cleanup() + } + }() + + // 3) Persist provided in-memory symbols via Write (functionality) + if len(req.Symbols) > 0 { + for id, data := range req.Symbols { + if _, werr := Write(-1, id, data); werr != nil { + fields[logtrace.FieldError] = werr.Error() + return DecodeResponse{}, werr + } + } + logtrace.Info(ctx, "symbols persisted via Write()", fields) + } + + // 4) Decode using the prepared workspace (functionality) + resp, derr := rq.DecodeFromPrepared(ctx, ws, req.Layout) + if derr != nil { + fields[logtrace.FieldError] = derr.Error() + return DecodeResponse{}, derr + } + success = true + return resp, nil } diff --git a/pkg/net/grpc/client/client.go b/pkg/net/grpc/client/client.go index dc4f45de..907c5b58 100644 --- a/pkg/net/grpc/client/client.go +++ b/pkg/net/grpc/client/client.go @@ -112,9 +112,9 @@ var defaultBackoffConfig = backoff.Config{ func DefaultClientOptions() *ClientOptions { return &ClientOptions{ MaxRecvMsgSize: 100 * MB, - MaxSendMsgSize: 100 * MB, // 100MB - InitialWindowSize: (int32)(1 * MB), // 1MB - controls initial frame size for streams - InitialConnWindowSize: (int32)(1 * MB), // 1MB - controls initial frame size for connection + MaxSendMsgSize: 100 * MB, // 100MB + InitialWindowSize: (int32)(32 * MB), // 32MB - controls initial frame size for streams + InitialConnWindowSize: (int32)(128 * MB), // 128MB - controls initial frame size for connection ConnWaitTime: defaultConnWaitTime, KeepAliveTime: 30 * time.Minute, diff --git a/pkg/net/grpc/server/server.go b/pkg/net/grpc/server/server.go index 10a2452c..64dfe0f2 100644 --- a/pkg/net/grpc/server/server.go +++ b/pkg/net/grpc/server/server.go @@ -94,7 +94,7 @@ func DefaultServerOptions() *ServerOptions { return &ServerOptions{ MaxRecvMsgSize: 100 * MB, MaxSendMsgSize: 100 * MB, - InitialWindowSize: (int32)(1 * MB), + InitialWindowSize: (int32)(32 * MB), InitialConnWindowSize: (int32)(1 * MB), MaxConcurrentStreams: 1000, GracefulShutdownTime: defaultGracefulShutdownTimeout, @@ -102,13 +102,13 @@ func DefaultServerOptions() *ServerOptions { MaxConnectionIdle: 2 * time.Hour, MaxConnectionAge: 2 * time.Hour, MaxConnectionAgeGrace: 1 * time.Hour, - Time: 1 * time.Hour, + Time: 30 * time.Minute, Timeout: 30 * time.Minute, MinTime: 5 * time.Minute, PermitWithoutStream: true, - WriteBufferSize: 32 * KB, - ReadBufferSize: 32 * KB, + WriteBufferSize: 512 * KB, + ReadBufferSize: 512 * KB, } } diff --git a/supernode/services/cascade/adaptors/mocks/lumera_mock.go b/supernode/services/cascade/adaptors/mocks/lumera_mock.go index 15a6c901..29cdd48f 100644 --- a/supernode/services/cascade/adaptors/mocks/lumera_mock.go +++ b/supernode/services/cascade/adaptors/mocks/lumera_mock.go @@ -1,10 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. // Source: lumera.go -// -// Generated by this command: -// -// mockgen -destination=mocks/lumera_mock.go -package=cascadeadaptormocks -source=lumera.go -// // Package cascadeadaptormocks is a generated GoMock package. package cascadeadaptormocks @@ -16,14 +11,13 @@ import ( types "github.com/LumeraProtocol/lumera/x/action/v1/types" types0 "github.com/LumeraProtocol/lumera/x/supernode/v1/types" tx "github.com/cosmos/cosmos-sdk/types/tx" - gomock "go.uber.org/mock/gomock" + gomock "github.com/golang/mock/gomock" ) // MockLumeraClient is a mock of LumeraClient interface. type MockLumeraClient struct { ctrl *gomock.Controller recorder *MockLumeraClientMockRecorder - isgomock struct{} } // MockLumeraClientMockRecorder is the mock recorder for MockLumeraClient. @@ -53,26 +47,11 @@ func (m *MockLumeraClient) FinalizeAction(ctx context.Context, actionID string, } // FinalizeAction indicates an expected call of FinalizeAction. -func (mr *MockLumeraClientMockRecorder) FinalizeAction(ctx, actionID, rqids any) *gomock.Call { +func (mr *MockLumeraClientMockRecorder) FinalizeAction(ctx, actionID, rqids interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FinalizeAction", reflect.TypeOf((*MockLumeraClient)(nil).FinalizeAction), ctx, actionID, rqids) } -// SimulateFinalizeAction mocks base method. -func (m *MockLumeraClient) SimulateFinalizeAction(ctx context.Context, actionID string, rqids []string) (*tx.SimulateResponse, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "SimulateFinalizeAction", ctx, actionID, rqids) - ret0, _ := ret[0].(*tx.SimulateResponse) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// SimulateFinalizeAction indicates an expected call of SimulateFinalizeAction. -func (mr *MockLumeraClientMockRecorder) SimulateFinalizeAction(ctx, actionID, rqids any) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SimulateFinalizeAction", reflect.TypeOf((*MockLumeraClient)(nil).SimulateFinalizeAction), ctx, actionID, rqids) -} - // GetAction mocks base method. func (m *MockLumeraClient) GetAction(ctx context.Context, actionID string) (*types.QueryGetActionResponse, error) { m.ctrl.T.Helper() @@ -83,7 +62,7 @@ func (m *MockLumeraClient) GetAction(ctx context.Context, actionID string) (*typ } // GetAction indicates an expected call of GetAction. -func (mr *MockLumeraClientMockRecorder) GetAction(ctx, actionID any) *gomock.Call { +func (mr *MockLumeraClientMockRecorder) GetAction(ctx, actionID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAction", reflect.TypeOf((*MockLumeraClient)(nil).GetAction), ctx, actionID) } @@ -98,7 +77,7 @@ func (m *MockLumeraClient) GetActionFee(ctx context.Context, dataSize string) (* } // GetActionFee indicates an expected call of GetActionFee. -func (mr *MockLumeraClientMockRecorder) GetActionFee(ctx, dataSize any) *gomock.Call { +func (mr *MockLumeraClientMockRecorder) GetActionFee(ctx, dataSize interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetActionFee", reflect.TypeOf((*MockLumeraClient)(nil).GetActionFee), ctx, dataSize) } @@ -113,11 +92,26 @@ func (m *MockLumeraClient) GetTopSupernodes(ctx context.Context, height uint64) } // GetTopSupernodes indicates an expected call of GetTopSupernodes. -func (mr *MockLumeraClientMockRecorder) GetTopSupernodes(ctx, height any) *gomock.Call { +func (mr *MockLumeraClientMockRecorder) GetTopSupernodes(ctx, height interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTopSupernodes", reflect.TypeOf((*MockLumeraClient)(nil).GetTopSupernodes), ctx, height) } +// SimulateFinalizeAction mocks base method. +func (m *MockLumeraClient) SimulateFinalizeAction(ctx context.Context, actionID string, rqids []string) (*tx.SimulateResponse, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SimulateFinalizeAction", ctx, actionID, rqids) + ret0, _ := ret[0].(*tx.SimulateResponse) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// SimulateFinalizeAction indicates an expected call of SimulateFinalizeAction. +func (mr *MockLumeraClientMockRecorder) SimulateFinalizeAction(ctx, actionID, rqids interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SimulateFinalizeAction", reflect.TypeOf((*MockLumeraClient)(nil).SimulateFinalizeAction), ctx, actionID, rqids) +} + // Verify mocks base method. func (m *MockLumeraClient) Verify(ctx context.Context, creator string, file, sigBytes []byte) error { m.ctrl.T.Helper() @@ -127,7 +121,7 @@ func (m *MockLumeraClient) Verify(ctx context.Context, creator string, file, sig } // Verify indicates an expected call of Verify. -func (mr *MockLumeraClientMockRecorder) Verify(ctx, creator, file, sigBytes any) *gomock.Call { +func (mr *MockLumeraClientMockRecorder) Verify(ctx, creator, file, sigBytes interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Verify", reflect.TypeOf((*MockLumeraClient)(nil).Verify), ctx, creator, file, sigBytes) } diff --git a/supernode/services/cascade/adaptors/mocks/p2p_mock.go b/supernode/services/cascade/adaptors/mocks/p2p_mock.go index 4f62a440..ec99d92a 100644 --- a/supernode/services/cascade/adaptors/mocks/p2p_mock.go +++ b/supernode/services/cascade/adaptors/mocks/p2p_mock.go @@ -1,10 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. // Source: p2p.go -// -// Generated by this command: -// -// mockgen -destination=mocks/p2p_mock.go -package=cascadeadaptormocks -source=p2p.go -// // Package cascadeadaptormocks is a generated GoMock package. package cascadeadaptormocks @@ -15,14 +10,13 @@ import ( logtrace "github.com/LumeraProtocol/supernode/v2/pkg/logtrace" adaptors "github.com/LumeraProtocol/supernode/v2/supernode/services/cascade/adaptors" - gomock "go.uber.org/mock/gomock" + gomock "github.com/golang/mock/gomock" ) // MockP2PService is a mock of P2PService interface. type MockP2PService struct { ctrl *gomock.Controller recorder *MockP2PServiceMockRecorder - isgomock struct{} } // MockP2PServiceMockRecorder is the mock recorder for MockP2PService. @@ -51,7 +45,7 @@ func (m *MockP2PService) StoreArtefacts(ctx context.Context, req adaptors.StoreA } // StoreArtefacts indicates an expected call of StoreArtefacts. -func (mr *MockP2PServiceMockRecorder) StoreArtefacts(ctx, req, f any) *gomock.Call { +func (mr *MockP2PServiceMockRecorder) StoreArtefacts(ctx, req, f interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "StoreArtefacts", reflect.TypeOf((*MockP2PService)(nil).StoreArtefacts), ctx, req, f) } diff --git a/supernode/services/cascade/adaptors/mocks/rq_mock.go b/supernode/services/cascade/adaptors/mocks/rq_mock.go index 4c53c1dd..f45f2eb5 100644 --- a/supernode/services/cascade/adaptors/mocks/rq_mock.go +++ b/supernode/services/cascade/adaptors/mocks/rq_mock.go @@ -1,10 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. // Source: rq.go -// -// Generated by this command: -// -// mockgen -destination=mocks/rq_mock.go -package=cascadeadaptormocks -source=rq.go -// // Package cascadeadaptormocks is a generated GoMock package. package cascadeadaptormocks @@ -13,15 +8,15 @@ import ( context "context" reflect "reflect" + codec "github.com/LumeraProtocol/supernode/v2/pkg/codec" adaptors "github.com/LumeraProtocol/supernode/v2/supernode/services/cascade/adaptors" - gomock "go.uber.org/mock/gomock" + gomock "github.com/golang/mock/gomock" ) // MockCodecService is a mock of CodecService interface. type MockCodecService struct { ctrl *gomock.Controller recorder *MockCodecServiceMockRecorder - isgomock struct{} } // MockCodecServiceMockRecorder is the mock recorder for MockCodecService. @@ -51,7 +46,7 @@ func (m *MockCodecService) Decode(ctx context.Context, req adaptors.DecodeReques } // Decode indicates an expected call of Decode. -func (mr *MockCodecServiceMockRecorder) Decode(ctx, req any) *gomock.Call { +func (mr *MockCodecServiceMockRecorder) Decode(ctx, req interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Decode", reflect.TypeOf((*MockCodecService)(nil).Decode), ctx, req) } @@ -66,7 +61,25 @@ func (m *MockCodecService) EncodeInput(ctx context.Context, taskID, path string, } // EncodeInput indicates an expected call of EncodeInput. -func (mr *MockCodecServiceMockRecorder) EncodeInput(ctx, taskID, path, dataSize any) *gomock.Call { +func (mr *MockCodecServiceMockRecorder) EncodeInput(ctx, taskID, path, dataSize interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EncodeInput", reflect.TypeOf((*MockCodecService)(nil).EncodeInput), ctx, taskID, path, dataSize) } + +// PrepareDecode mocks base method. +func (m *MockCodecService) PrepareDecode(ctx context.Context, actionID string, layout codec.Layout) ([]string, func(int, string, []byte) (string, error), func() error, *codec.Workspace, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PrepareDecode", ctx, actionID, layout) + ret0, _ := ret[0].([]string) + ret1, _ := ret[1].(func(int, string, []byte) (string, error)) + ret2, _ := ret[2].(func() error) + ret3, _ := ret[3].(*codec.Workspace) + ret4, _ := ret[4].(error) + return ret0, ret1, ret2, ret3, ret4 +} + +// PrepareDecode indicates an expected call of PrepareDecode. +func (mr *MockCodecServiceMockRecorder) PrepareDecode(ctx, actionID, layout interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PrepareDecode", reflect.TypeOf((*MockCodecService)(nil).PrepareDecode), ctx, actionID, layout) +} diff --git a/supernode/services/cascade/adaptors/rq.go b/supernode/services/cascade/adaptors/rq.go index 5f4443cf..92e89819 100644 --- a/supernode/services/cascade/adaptors/rq.go +++ b/supernode/services/cascade/adaptors/rq.go @@ -11,6 +11,7 @@ import ( //go:generate mockgen -destination=mocks/rq_mock.go -package=cascadeadaptormocks -source=rq.go type CodecService interface { EncodeInput(ctx context.Context, taskID string, path string, dataSize int) (EncodeResult, error) + PrepareDecode(ctx context.Context, actionID string, layout codec.Layout) (blockPaths []string, Write func(block int, symbolID string, data []byte) (string, error), Cleanup func() error, ws *codec.Workspace, err error) Decode(ctx context.Context, req DecodeRequest) (DecodeResponse, error) } @@ -70,7 +71,11 @@ func (c *codecImpl) Decode(ctx context.Context, req DecodeRequest) (DecodeRespon } return DecodeResponse{ - FilePath: resp.Path, + FilePath: resp.FilePath, DecodeTmpDir: resp.DecodeTmpDir, }, nil } + +func (c *codecImpl) PrepareDecode(ctx context.Context, actionID string, layout codec.Layout) (blockPaths []string, Write func(block int, symbolID string, data []byte) (string, error), Cleanup func() error, ws *codec.Workspace, err error) { + return +} diff --git a/supernode/services/cascade/mocks/cascade_interfaces_mock.go b/supernode/services/cascade/mocks/cascade_interfaces_mock.go index 497497c3..44d3189c 100644 --- a/supernode/services/cascade/mocks/cascade_interfaces_mock.go +++ b/supernode/services/cascade/mocks/cascade_interfaces_mock.go @@ -1,10 +1,5 @@ // Code generated by MockGen. DO NOT EDIT. // Source: interfaces.go -// -// Generated by this command: -// -// mockgen -destination=mocks/cascade_interfaces_mock.go -package=cascademocks -source=interfaces.go -// // Package cascademocks is a generated GoMock package. package cascademocks @@ -14,14 +9,13 @@ import ( reflect "reflect" cascade "github.com/LumeraProtocol/supernode/v2/supernode/services/cascade" - gomock "go.uber.org/mock/gomock" + gomock "github.com/golang/mock/gomock" ) // MockCascadeServiceFactory is a mock of CascadeServiceFactory interface. type MockCascadeServiceFactory struct { ctrl *gomock.Controller recorder *MockCascadeServiceFactoryMockRecorder - isgomock struct{} } // MockCascadeServiceFactoryMockRecorder is the mock recorder for MockCascadeServiceFactory. @@ -59,7 +53,6 @@ func (mr *MockCascadeServiceFactoryMockRecorder) NewCascadeRegistrationTask() *g type MockCascadeTask struct { ctrl *gomock.Controller recorder *MockCascadeTaskMockRecorder - isgomock struct{} } // MockCascadeTaskMockRecorder is the mock recorder for MockCascadeTask. @@ -88,7 +81,7 @@ func (m *MockCascadeTask) CleanupDownload(ctx context.Context, actionID string) } // CleanupDownload indicates an expected call of CleanupDownload. -func (mr *MockCascadeTaskMockRecorder) CleanupDownload(ctx, actionID any) *gomock.Call { +func (mr *MockCascadeTaskMockRecorder) CleanupDownload(ctx, actionID interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CleanupDownload", reflect.TypeOf((*MockCascadeTask)(nil).CleanupDownload), ctx, actionID) } @@ -102,7 +95,7 @@ func (m *MockCascadeTask) Download(ctx context.Context, req *cascade.DownloadReq } // Download indicates an expected call of Download. -func (mr *MockCascadeTaskMockRecorder) Download(ctx, req, send any) *gomock.Call { +func (mr *MockCascadeTaskMockRecorder) Download(ctx, req, send interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Download", reflect.TypeOf((*MockCascadeTask)(nil).Download), ctx, req, send) } @@ -116,7 +109,7 @@ func (m *MockCascadeTask) Register(ctx context.Context, req *cascade.RegisterReq } // Register indicates an expected call of Register. -func (mr *MockCascadeTaskMockRecorder) Register(ctx, req, send any) *gomock.Call { +func (mr *MockCascadeTaskMockRecorder) Register(ctx, req, send interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Register", reflect.TypeOf((*MockCascadeTask)(nil).Register), ctx, req, send) } From 5c01e3c4a2e7b7962086deb0195ce4f98fcc8249 Mon Sep 17 00:00:00 2001 From: Matee Ullah Malik Date: Tue, 23 Sep 2025 16:38:30 +0500 Subject: [PATCH 2/2] Test Fixes --- Makefile | 6 +++--- go.mod | 1 - pkg/net/grpc/client/client_test.go | 4 ++-- pkg/net/grpc/server/server_test.go | 8 ++++---- .../server/cascade/cascade_action_server_test.go | 2 +- supernode/services/cascade/register_test.go | 10 +++++----- supernode/services/cascade/service_test.go | 2 +- tests/system/go.mod | 1 + tests/system/go.sum | 4 ++++ 9 files changed, 21 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index fe5a9852..01272fbf 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ .PHONY: build build-release build-sncli build-sn-manager -.PHONY: install-lumera setup-supernodes system-test-setup +.PHONY: install-lumera setup-supernodes system-test-setup install-deps .PHONY: gen-cascade gen-supernode .PHONY: test-e2e test-unit test-integration test-system @@ -140,9 +140,9 @@ test-e2e: # Run cascade e2e tests only test-cascade: @echo "Running cascade e2e tests..." - @cd tests/system && go test -tags=system_test -v -run TestCascadeE2E . + @cd tests/system && go mod tidy && go test -tags=system_test -v -run TestCascadeE2E . # Run sn-manager e2e tests only test-sn-manager: @echo "Running sn-manager e2e tests..." - @cd tests/system && go test -tags=system_test -v -run '^TestSNManager' . \ No newline at end of file + @cd tests/system && go test -tags=system_test -v -run '^TestSNManager' . diff --git a/go.mod b/go.mod index b7f53ec1..46091df2 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module github.com/LumeraProtocol/supernode/v2 go 1.24.1 replace ( - github.com/LumeraProtocol/supernode/v2/supernode => ./supernode github.com/bytedance/sonic => github.com/bytedance/sonic v1.14.0 github.com/bytedance/sonic/loader => github.com/bytedance/sonic/loader v0.3.0 ) diff --git a/pkg/net/grpc/client/client_test.go b/pkg/net/grpc/client/client_test.go index 12b196fa..0b4a10e1 100644 --- a/pkg/net/grpc/client/client_test.go +++ b/pkg/net/grpc/client/client_test.go @@ -86,8 +86,8 @@ func TestDefaultClientOptions(t *testing.T) { assert.NotNil(t, opts, "ClientOptions should be initialized") assert.Equal(t, 100*MB, opts.MaxRecvMsgSize, "MaxRecvMsgSize should be 100 MB") assert.Equal(t, 100*MB, opts.MaxSendMsgSize, "MaxSendMsgSize should be 100 MB") - assert.Equal(t, int32(1*MB), opts.InitialWindowSize, "InitialWindowSize should be 1 MB") - assert.Equal(t, int32(1*MB), opts.InitialConnWindowSize, "InitialConnWindowSize should be 1 MB") + assert.Equal(t, int32(32*MB), opts.InitialWindowSize, "InitialWindowSize should be 32 MB") + assert.Equal(t, int32(128*MB), opts.InitialConnWindowSize, "InitialConnWindowSize should be 128 MB") assert.Equal(t, defaultConnWaitTime, opts.ConnWaitTime, "ConnWaitTime should be 10 seconds") assert.True(t, opts.EnableRetries, "EnableRetries should be true") assert.Equal(t, maxRetries, opts.MaxRetries, "MaxRetries should be 5") diff --git a/pkg/net/grpc/server/server_test.go b/pkg/net/grpc/server/server_test.go index 4c6067e0..f2308436 100644 --- a/pkg/net/grpc/server/server_test.go +++ b/pkg/net/grpc/server/server_test.go @@ -55,18 +55,18 @@ func TestDefaultServerOptions(t *testing.T) { assert.NotNil(t, opts, "Server options should be initialized") assert.Equal(t, 100*MB, opts.MaxRecvMsgSize, "MaxRecvMsgSize should be 100 MB") assert.Equal(t, 100*MB, opts.MaxSendMsgSize, "MaxSendMsgSize should be 100 MB") - assert.Equal(t, int32(1*MB), opts.InitialWindowSize, "InitialWindowSize should be 1 MB") + assert.Equal(t, int32(32*MB), opts.InitialWindowSize, "InitialWindowSize should be 32 MB") assert.Equal(t, int32(1*MB), opts.InitialConnWindowSize, "InitialConnWindowSize should be 1 MB") assert.Equal(t, uint32(1000), opts.MaxConcurrentStreams, "MaxConcurrentStreams should be 1000") assert.Equal(t, defaultGracefulShutdownTimeout, opts.GracefulShutdownTime, fmt.Sprintf("GracefulShutdownTimeout should be %v", defaultGracefulShutdownTimeout)) assert.Equal(t, uint32(0), opts.NumServerWorkers, "NumServerWorkers should be 0") - assert.Equal(t, 32*KB, opts.WriteBufferSize, "WriteBufferSize should be 32 KB") - assert.Equal(t, 32*KB, opts.ReadBufferSize, "ReadBufferSize should be 32 KB") + assert.Equal(t, 512*KB, opts.WriteBufferSize, "WriteBufferSize should be 512 KB") + assert.Equal(t, 512*KB, opts.ReadBufferSize, "ReadBufferSize should be 512 KB") assert.Equal(t, 2*time.Hour, opts.MaxConnectionIdle, "MaxConnectionIdle should be 2 hours") assert.Equal(t, 2*time.Hour, opts.MaxConnectionAge, "MaxConnectionAge should be 2 hours") assert.Equal(t, 1*time.Hour, opts.MaxConnectionAgeGrace, "MaxConnectionAgeGrace should be 1 hour") - assert.Equal(t, 1*time.Hour, opts.Time, "Time should be 1 hour") + assert.Equal(t, 30*time.Minute, opts.Time, "Time should be 30 minutes") assert.Equal(t, 30*time.Minute, opts.Timeout, "Timeout should be 30 minutes") assert.Equal(t, 5*time.Minute, opts.MinTime, "MinTime should be 5 minutes") assert.True(t, opts.PermitWithoutStream, "PermitWithoutStream should be true") diff --git a/supernode/node/action/server/cascade/cascade_action_server_test.go b/supernode/node/action/server/cascade/cascade_action_server_test.go index eca121d8..ff2738b3 100644 --- a/supernode/node/action/server/cascade/cascade_action_server_test.go +++ b/supernode/node/action/server/cascade/cascade_action_server_test.go @@ -10,7 +10,7 @@ import ( cascademocks "github.com/LumeraProtocol/supernode/v2/supernode/services/cascade/mocks" "github.com/stretchr/testify/assert" - "go.uber.org/mock/gomock" + "github.com/golang/mock/gomock" ) func TestRegister_Success(t *testing.T) { diff --git a/supernode/services/cascade/register_test.go b/supernode/services/cascade/register_test.go index c73b96b7..6f56791a 100644 --- a/supernode/services/cascade/register_test.go +++ b/supernode/services/cascade/register_test.go @@ -21,8 +21,8 @@ import ( "github.com/cosmos/gogoproto/proto" "lukechampine.com/blake3" + "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" - "go.uber.org/mock/gomock" ) func TestCascadeRegistrationTask_Register(t *testing.T) { @@ -104,10 +104,10 @@ func TestCascadeRegistrationTask_Register(t *testing.T) { Metadata: codecpkg.Layout{Blocks: []codecpkg.Block{{BlockID: 1, Hash: "abc"}}}, }, nil) - // 8. Store artefacts (no metrics returned; recorded centrally) - p2p.EXPECT(). - StoreArtefacts(gomock.Any(), gomock.Any(), gomock.Any()). - Return(nil) + // 8. Store artefacts (no metrics returned; recorded centrally) + p2p.EXPECT(). + StoreArtefacts(gomock.Any(), gomock.Any(), gomock.Any()). + Return(nil) }, expectedError: "", expectedEvents: 12, diff --git a/supernode/services/cascade/service_test.go b/supernode/services/cascade/service_test.go index eaa7bf7f..bc2998ad 100644 --- a/supernode/services/cascade/service_test.go +++ b/supernode/services/cascade/service_test.go @@ -8,8 +8,8 @@ import ( "github.com/LumeraProtocol/supernode/v2/supernode/services/cascade" cascadeadaptormocks "github.com/LumeraProtocol/supernode/v2/supernode/services/cascade/adaptors/mocks" "github.com/LumeraProtocol/supernode/v2/supernode/services/common" + "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" - "go.uber.org/mock/gomock" ) func TestNewCascadeService(t *testing.T) { diff --git a/tests/system/go.mod b/tests/system/go.mod index 15b8212d..e6eb3bba 100644 --- a/tests/system/go.mod +++ b/tests/system/go.mod @@ -95,6 +95,7 @@ require ( github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/glog v1.2.4 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/mock v1.6.0 // indirect github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect github.com/google/btree v1.1.3 // indirect github.com/google/flatbuffers v1.12.1 // indirect diff --git a/tests/system/go.sum b/tests/system/go.sum index 9ff0158a..6e9c0112 100644 --- a/tests/system/go.sum +++ b/tests/system/go.sum @@ -803,6 +803,7 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/zeebo/errs v1.4.0 h1:XNdoD/RRMKP7HD0UhJnIzUy74ISdGGxURlYG8HSWSfM= github.com/zeebo/errs v1.4.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4= github.com/zondax/hid v0.9.2 h1:WCJFnEDMiqGF64nlZz28E9qLVZ0KSJ7xpc5DLEyma2U= @@ -888,6 +889,7 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -933,6 +935,7 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1025,6 +1028,7 @@ golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.31.0 h1:0EedkvKDbh+qistFTd0Bcwe/YLh4vHwWEkiI0toFIBU= golang.org/x/tools v0.31.0/go.mod h1:naFTU+Cev749tSJRXJlna0T3WxKvb1kWEx15xA4SdmQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=