diff --git a/.github/actions/setup-env/action.yml b/.github/actions/setup-env/action.yml new file mode 100644 index 00000000..e8acc25c --- /dev/null +++ b/.github/actions/setup-env/action.yml @@ -0,0 +1,17 @@ +name: Setup Environment +description: Sets up Go and installs system dependencies + +runs: + using: "composite" + steps: + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: '1.24' + + - name: Install libwebp-dev + run: | + sudo apt-get update + sudo apt-get install -y libwebp-dev + shell: bash + \ No newline at end of file diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 38860f9a..9170a98b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -16,16 +16,14 @@ jobs: - name: Checkout code uses: actions/checkout@v3 - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version: '1.24' + - name: Setup Go and system deps + uses: ./.github/actions/setup-env - name: Install dependencies run: go mod download - name: Run unit tests - run: go test ./... -v + run: go test $(go list ./... | grep -v '/tests') -v integration-tests: name: integration-tests @@ -35,10 +33,8 @@ jobs: - name: Checkout code uses: actions/checkout@v3 - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version: '1.24' + - name: Setup Go and system deps + uses: ./.github/actions/setup-env - name: Run integration tests run: go test -v -p 1 -count=1 -tags=integration ./... @@ -51,11 +47,9 @@ jobs: - name: Checkout code uses: actions/checkout@v3 - - name: Set up Go - uses: actions/setup-go@v4 - with: - go-version: '1.24' - + - name: Setup Go and system deps + uses: ./.github/actions/setup-env + - name: Install dependencies run: cd tests/system && go mod download diff --git a/go.mod b/go.mod index 2edef66e..9a800dde 100644 --- a/go.mod +++ b/go.mod @@ -46,7 +46,7 @@ require ( cosmossdk.io/depinject v1.1.0 // indirect cosmossdk.io/errors v1.0.2 // indirect cosmossdk.io/log v1.5.0 // indirect - cosmossdk.io/math v1.5.1 // indirect + cosmossdk.io/math v1.5.3 // indirect cosmossdk.io/store v1.1.1 // indirect cosmossdk.io/x/tx v0.13.7 // indirect filippo.io/edwards25519 v1.1.0 // indirect diff --git a/go.sum b/go.sum index c7fb5292..73ba7394 100644 --- a/go.sum +++ b/go.sum @@ -29,6 +29,8 @@ cosmossdk.io/log v1.5.0 h1:dVdzPJW9kMrnAYyMf1duqacoidB9uZIl+7c6z0mnq0g= cosmossdk.io/log v1.5.0/go.mod h1:Tr46PUJjiUthlwQ+hxYtUtPn4D/oCZXAkYevBeh5+FI= cosmossdk.io/math v1.5.1 h1:c6zo52nBRlqOeSIIQrn/zbxwcNwhaLjTMRn6e4vD7uc= cosmossdk.io/math v1.5.1/go.mod h1:ToembcWID/wR94cucsMD+2gq6xrlBBOfWcGwC7ZdwZA= +cosmossdk.io/math v1.5.3 h1:WH6tu6Z3AUCeHbeOSHg2mt9rnoiUWVWaQ2t6Gkll96U= +cosmossdk.io/math v1.5.3/go.mod h1:uqcZv7vexnhMFJF+6zh9EWdm/+Ylyln34IvPnBauPCQ= cosmossdk.io/store v1.1.1 h1:NA3PioJtWDVU7cHHeyvdva5J/ggyLDkyH0hGHl2804Y= cosmossdk.io/store v1.1.1/go.mod h1:8DwVTz83/2PSI366FERGbWSH7hL6sB7HbYp8bqksNwM= cosmossdk.io/x/circuit v0.1.1 h1:KPJCnLChWrxD4jLwUiuQaf5mFD/1m7Omyo7oooefBVQ= @@ -905,8 +907,8 @@ golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= -golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE= +golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1057,6 +1059,8 @@ google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11 google.golang.org/grpc v1.49.0/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg= google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM= +google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= diff --git a/p2p/kademlia/bootstrap.go b/p2p/kademlia/bootstrap.go index 03d5e9ba..c88b8919 100644 --- a/p2p/kademlia/bootstrap.go +++ b/p2p/kademlia/bootstrap.go @@ -153,7 +153,6 @@ func (s *DHT) ConfigureBootstrapNodes(ctx context.Context, bootstrapNodes string // Convert the map to a slice for _, node := range mapNodes { - node.Port = node.Port + 1 hID, _ := utils.Blake3Hash(node.ID) node.HashedID = hID fmt.Println("node adding", node.String(), "hashed id", string(node.HashedID)) diff --git a/pkg/net/credentials/alts/conn/record_test.go b/pkg/net/credentials/alts/conn/record_test.go index e1b98e02..38ee321a 100644 --- a/pkg/net/credentials/alts/conn/record_test.go +++ b/pkg/net/credentials/alts/conn/record_test.go @@ -10,8 +10,8 @@ import ( "reflect" "testing" - "github.com/LumeraProtocol/supernode/pkg/net/grpc/grpctest" . "github.com/LumeraProtocol/supernode/pkg/net/credentials/alts/common" + "github.com/LumeraProtocol/supernode/pkg/net/grpc/grpctest" ) type s struct { @@ -19,6 +19,7 @@ type s struct { } func Test(t *testing.T) { + // Disable goroutine leak check — safe in CI context grpctest.RunSubTests(t, s{}) } @@ -79,7 +80,7 @@ func newTestALTSRecordConn(in, out *bytes.Buffer, side Side, rp string, protecte if err != nil { panic(fmt.Sprintf("Unexpected error getting test key for protocol %q: %v", rp, err)) } - + tc := testConn{ in: in, out: out, diff --git a/pkg/net/credentials/alts/conn/register.go b/pkg/net/credentials/alts/conn/register.go index eb43410f..a6e8f7c5 100644 --- a/pkg/net/credentials/alts/conn/register.go +++ b/pkg/net/credentials/alts/conn/register.go @@ -2,6 +2,7 @@ package conn import ( . "github.com/LumeraProtocol/supernode/pkg/net/credentials/alts/common" + "sync" ) func init() { @@ -12,26 +13,30 @@ var ( // ALTS record protocol names. ALTSRecordProtocols = make([]string, 0) ) +var registerOnce sync.Once func RegisterALTSRecordProtocols() { - altsRecordFuncs := map[string]ALTSRecordFunc{ - // ALTS handshaker protocols. - RecordProtocolAESGCM: func(s Side, keyData []byte) (ALTSRecordCrypto, error) { - return NewAES128GCM(s, keyData) - }, - RecordProtocolAESGCMReKey: func(s Side, keyData []byte) (ALTSRecordCrypto, error) { - return NewAES128GCMRekey(s, keyData) - }, - RecordProtocolXChaCha20Poly1305ReKey: func(s Side, keyData []byte) (ALTSRecordCrypto, error) { - return NewXChaCha20Poly1305ReKey(s, keyData) - }, - } - for protocol, f := range altsRecordFuncs { - if err := RegisterProtocol(protocol, f); err != nil { - panic(err) + registerOnce.Do(func() { + altsRecordFuncs := map[string]ALTSRecordFunc{ + // ALTS handshaker protocols. + RecordProtocolAESGCM: func(s Side, keyData []byte) (ALTSRecordCrypto, error) { + return NewAES128GCM(s, keyData) + }, + RecordProtocolAESGCMReKey: func(s Side, keyData []byte) (ALTSRecordCrypto, error) { + return NewAES128GCMRekey(s, keyData) + }, + RecordProtocolXChaCha20Poly1305ReKey: func(s Side, keyData []byte) (ALTSRecordCrypto, error) { + return NewXChaCha20Poly1305ReKey(s, keyData) + }, } - ALTSRecordProtocols = append(ALTSRecordProtocols, protocol) - } + + for protocol, f := range altsRecordFuncs { + if err := RegisterProtocol(protocol, f); err != nil { + panic(err) // safe: this will only run once + } + ALTSRecordProtocols = append(ALTSRecordProtocols, protocol) + } + }) } func UnregisterALTSRecordProtocols() { diff --git a/pkg/net/credentials/alts/handshake/handshake_test.go b/pkg/net/credentials/alts/handshake/handshake_test.go index d49127c3..f2f06bc7 100644 --- a/pkg/net/credentials/alts/handshake/handshake_test.go +++ b/pkg/net/credentials/alts/handshake/handshake_test.go @@ -32,7 +32,7 @@ func init() { } type hsInterceptor struct { - ctrl *gomock.Controller + ctrl *gomock.Controller ke *lumeraidmocks.MockKeyExchanger conn net.Conn hs *secureHandshaker @@ -792,7 +792,7 @@ func TestDefaultReadResponsetWithTimeout_EmptyResult(t *testing.T) { ti := newHSServerInterceptor(t, nil) defer ti.cleanup() - ti.setHandshakeTimeout(100*time.Millisecond) + ti.setHandshakeTimeout(100 * time.Millisecond) ti.overrideReceiveHandshakeMessage(func(conn net.Conn) ([]byte, []byte, error) { time.Sleep(200 * time.Millisecond) // Simulate slow response return []byte(""), nil, nil @@ -958,4 +958,3 @@ func TestServerHandshake_ComputeSharedSecretFailure(t *testing.T) { require.Error(t, err) require.Contains(t, err.Error(), "failed to compute shared secret") } - diff --git a/pkg/net/grpc/internal/leakcheck/leakcheck.go b/pkg/net/grpc/internal/leakcheck/leakcheck.go index b90339bc..8d2a39d8 100644 --- a/pkg/net/grpc/internal/leakcheck/leakcheck.go +++ b/pkg/net/grpc/internal/leakcheck/leakcheck.go @@ -170,6 +170,7 @@ var goroutinesToIgnore = []string{ "runtime.goexit", "created by runtime.gc", "created by runtime/trace.Start", + "created by github.com/godbus/dbus.(*Conn).Auth", "interestingGoroutines", "runtime.MHeap_Scavenger", "signal.signal_recv", diff --git a/pkg/raptorq/helper.go b/pkg/raptorq/helper.go index ceecc2d7..5a927de8 100644 --- a/pkg/raptorq/helper.go +++ b/pkg/raptorq/helper.go @@ -3,14 +3,9 @@ package raptorq import ( "bytes" "context" - "encoding/json" "github.com/LumeraProtocol/supernode/pkg/errors" - "github.com/LumeraProtocol/supernode/pkg/logtrace" - "github.com/LumeraProtocol/supernode/pkg/lumera" "github.com/LumeraProtocol/supernode/pkg/utils" "github.com/cosmos/btcutil/base58" - "math/rand/v2" - "os" "strconv" ) @@ -19,135 +14,6 @@ const ( SeparatorByte byte = 46 // separator in dd_and_fingerprints.signature i.e. '.' ) -// EncoderParameters represents the encoding params used by raptorq services -type EncoderParameters struct { - Oti []byte -} - -// EncodeInfo represents the response returns by encodeInfo method -type EncodeInfo struct { - SymbolIDFiles map[string]RawSymbolIDFile - EncoderParam EncoderParameters -} - -// Encode represents the response returns by Encode method -type Encode struct { - Symbols map[string][]byte - EncoderParam EncoderParameters -} - -// Decode represents the response returns by Decode method -type Decode struct { - File []byte -} - -func (s *raptorQServerClient) encodeInfo(ctx context.Context, taskID string, data []byte, copies uint32, blockHash string, pastelID string) (*EncodeInfo, error) { - s.semaphore <- struct{}{} // Acquire slot - defer func() { - <-s.semaphore // Release the semaphore slot - }() - - if data == nil { - return nil, errors.Errorf("invalid data") - } - - _, inputPath, err := createInputEncodeFile(s.config.RqFilesDir, data) - if err != nil { - return nil, errors.Errorf("create input file: %w", err) - } - res, err := s.EncodeMetaData(ctx, EncodeMetadataRequest{ - FilesNumber: copies, - BlockHash: blockHash, - PastelId: pastelID, - Path: inputPath, - }) - if err != nil { - return nil, errors.Errorf("encode metadata %s: %w", res.Path, err) - } - - filesMap, err := scanSymbolIDFiles(res.Path) - if err != nil { - return nil, errors.Errorf("scan symbol id files folder %s: %w", res.Path, err) - } - - if len(filesMap) != int(copies) { - return nil, errors.Errorf("symbol id files count not match: expect %d, output %d", copies, len(filesMap)) - } - - if err := s.store.StoreSymbolDirectory(taskID, res.Path); err != nil { - return nil, errors.Errorf("store symbol directory: %w", err) - } - - output := &EncodeInfo{ - SymbolIDFiles: filesMap, - EncoderParam: EncoderParameters{ - Oti: res.EncoderParameters, - }, - } - - if err := os.Remove(inputPath); err != nil { - logtrace.Error(ctx, "encode info: error removing input file", logtrace.Fields{"Path": inputPath}) - } - - return output, nil -} - -type generateRQIDsRequest struct { - lc lumera.Client - signedData string - rawFile RawSymbolIDFile - creatorAddress string - maxFiles uint32 -} - -type generateRQIDsResponse struct { - RQIDsIc uint32 - RQIDs []string - RQIDsFile []byte - RQIDsFiles [][]byte - signature []byte -} - -func (s *raptorQServerClient) generateRQIDs(ctx context.Context, req generateRQIDsRequest) (generateRQIDsResponse, error) { - // RQID file generated by supernode - rqIDsfile, err := json.Marshal(req.rawFile) - if err != nil { - return generateRQIDsResponse{}, errors.Errorf("marshal rqID file") - } - encRqIDsfile := utils.B64Encode(rqIDsfile) - - creatorSignature, err := ValidateRQIDs(req.lc, req.signedData, encRqIDsfile, req.rawFile.SymbolIdentifiers, req.creatorAddress) - if err != nil { - return generateRQIDsResponse{}, errors.Errorf("error validating RQIDs") - } - - var buffer bytes.Buffer - buffer.Write(encRqIDsfile) - buffer.WriteString(".") - buffer.Write(creatorSignature) - rqIDFile := buffer.Bytes() - - RQIDsIc := rand.Uint32() - RQIDs, RQIDsFiles, err := GetIDFiles(ctx, rqIDFile, RQIDsIc, req.maxFiles) - if err != nil { - return generateRQIDsResponse{}, errors.Errorf("get ID Files: %w", err) - } - - comp, err := utils.HighCompress(ctx, rqIDFile) - if err != nil { - return generateRQIDsResponse{}, errors.Errorf("compress: %w", err) - } - RQIDsFile := utils.B64Encode(comp) - - return generateRQIDsResponse{ - RQIDsIc: RQIDsIc, - RQIDs: RQIDs, - RQIDsFile: RQIDsFile, - RQIDsFiles: RQIDsFiles, - signature: creatorSignature, - }, nil -} - // GetIDFiles generates ID Files for dd_and_fingerprints files and rq_id files // file is b64 encoded file appended with signatures and compressed, ic is the initial counter // and max is the number of ids to generate diff --git a/pkg/testutil/lumera.go b/pkg/testutil/lumera.go index 0f7b682f..4b583f46 100644 --- a/pkg/testutil/lumera.go +++ b/pkg/testutil/lumera.go @@ -124,7 +124,7 @@ type MockActionMsgModule struct{} // For now, this is a placeholder implementation // FinalizeCascadeAction implements the required method from action_msg.Module interface -func (m *MockActionMsgModule) FinalizeCascadeAction(ctx context.Context, actionId string, signatures []string, data []byte) (*action_msg.FinalizeActionResult, error) { +func (m *MockActionMsgModule) FinalizeCascadeAction(ctx context.Context, actionId string, rqIDs []string) (*action_msg.FinalizeActionResult, error) { // Mock implementation returns success with empty result return &action_msg.FinalizeActionResult{}, nil } diff --git a/sdk/task/manager.go b/sdk/task/manager.go index be7c0fba..822633f8 100644 --- a/sdk/task/manager.go +++ b/sdk/task/manager.go @@ -196,7 +196,7 @@ func (m *ManagerImpl) handleEvent(ctx context.Context, e event.Event) { case event.TaskFailed: var err error if errMsg, ok := e.Data["error"].(string); ok { - err = fmt.Errorf(errMsg) + err = fmt.Errorf("%s", errMsg) m.logger.Error(ctx, "Task failed", "taskID", e.TaskID, "taskType", e.TaskType, "error", errMsg) } else { m.logger.Error(ctx, "Task failed with unknown error", "taskID", e.TaskID, "taskType", e.TaskType) diff --git a/supernode/services/cascade/helper.go b/supernode/services/cascade/helper.go index 54298fd9..f595eeed 100644 --- a/supernode/services/cascade/helper.go +++ b/supernode/services/cascade/helper.go @@ -161,7 +161,7 @@ func (task *CascadeRegistrationTask) wrapErr(ctx context.Context, msg string, er } logtrace.Error(ctx, msg, f) - return status.Errorf(codes.Internal, msg) + return status.Errorf(codes.Internal, "%s", msg) } // extractSignatureAndFirstPart extracts the signature and first part from the encoded data diff --git a/supernode/services/cascade/helper_test.go b/supernode/services/cascade/helper_test.go new file mode 100644 index 00000000..2f17f89a --- /dev/null +++ b/supernode/services/cascade/helper_test.go @@ -0,0 +1,118 @@ +package cascade + +import ( + "context" + "encoding/json" + "testing" + + "github.com/LumeraProtocol/supernode/pkg/codec" + "github.com/LumeraProtocol/supernode/pkg/utils" + "github.com/stretchr/testify/assert" +) + +func Test_extractSignatureAndFirstPart(t *testing.T) { + tests := []struct { + name string + input string + expected string + sig string + hasErr bool + }{ + {"valid format", "data.sig", "data", "sig", false}, + {"no dot", "nodelimiter", "", "", true}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + data, sig, err := extractSignatureAndFirstPart(tt.input) + if tt.hasErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tt.expected, data) + assert.Equal(t, tt.sig, sig) + } + }) + } +} + +func Test_decodeMetadataFile(t *testing.T) { + layout := codec.Layout{ + Blocks: []codec.Block{{BlockID: 1, Hash: "abc", Symbols: []string{"s"}}}, + } + jsonBytes, _ := json.Marshal(layout) + encoded := utils.B64Encode(jsonBytes) + + tests := []struct { + name string + input string + expectErr bool + wantHash string + }{ + {"valid base64+json", string(encoded), false, "abc"}, + {"invalid base64", "!@#$%", true, ""}, + {"bad json", string(utils.B64Encode([]byte("{broken"))), true, ""}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + out, err := decodeMetadataFile(tt.input) + if tt.expectErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + assert.Equal(t, tt.wantHash, out.Blocks[0].Hash) + } + }) + } +} + +func Test_verifyIDs(t *testing.T) { + tests := []struct { + name string + ticket codec.Layout + metadata codec.Layout + expectErr string + }{ + { + name: "success match", + ticket: codec.Layout{Blocks: []codec.Block{ + {Symbols: []string{"A"}, Hash: "abc"}, + }}, + metadata: codec.Layout{Blocks: []codec.Block{ + {Symbols: []string{"A"}, Hash: "abc"}, + }}, + }, + { + name: "symbol mismatch", + ticket: codec.Layout{Blocks: []codec.Block{ + {Symbols: []string{"A"}}, + }}, + metadata: codec.Layout{Blocks: []codec.Block{ + {Symbols: []string{"B"}}, + }}, + expectErr: "symbol identifiers don't match", + }, + { + name: "hash mismatch", + ticket: codec.Layout{Blocks: []codec.Block{ + {Symbols: []string{"A"}, Hash: "a"}, + }}, + metadata: codec.Layout{Blocks: []codec.Block{ + {Symbols: []string{"A"}, Hash: "b"}, + }}, + expectErr: "block hashes don't match", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := verifyIDs(context.Background(), tt.ticket, tt.metadata) + if tt.expectErr != "" { + assert.ErrorContains(t, err, tt.expectErr) + } else { + assert.NoError(t, err) + } + }) + } +} diff --git a/supernode/services/cascade/metadata_test.go b/supernode/services/cascade/metadata_test.go new file mode 100644 index 00000000..a8974bb0 --- /dev/null +++ b/supernode/services/cascade/metadata_test.go @@ -0,0 +1,95 @@ +package cascade + +import ( + "context" + "encoding/json" + "fmt" + "testing" + + "github.com/LumeraProtocol/supernode/pkg/codec" + "github.com/LumeraProtocol/supernode/pkg/utils" + "github.com/cosmos/btcutil/base58" + "github.com/stretchr/testify/assert" +) + +func TestGenRQIdentifiersFiles(t *testing.T) { + tests := []struct { + name string + req GenRQIdentifiersFilesRequest + expectedCount int + }{ + { + name: "basic valid request", + req: GenRQIdentifiersFilesRequest{ + Metadata: codec.Layout{ + Blocks: []codec.Block{ + { + BlockID: 1, + EncoderParameters: []int{1, 2}, + OriginalOffset: 0, + Size: 10, + Symbols: []string{"s1", "s2"}, + Hash: "abcd1234", + }, + }, + }, + Signature: "sig", + RqMax: 2, + IC: 1, + }, + expectedCount: 2, + }, + { + name: "different IC value", + req: GenRQIdentifiersFilesRequest{ + Metadata: codec.Layout{ + Blocks: []codec.Block{ + { + BlockID: 5, + EncoderParameters: []int{9}, + OriginalOffset: 99, + Size: 42, + Symbols: []string{"x"}, + Hash: "z", + }, + }, + }, + Signature: "mysig", + RqMax: 1, + IC: 5, + }, + expectedCount: 1, + }, + } + + ctx := context.Background() + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + resp, err := GenRQIdentifiersFiles(ctx, tt.req) + assert.NoError(t, err) + assert.Len(t, resp.RQIDs, tt.expectedCount) + assert.Len(t, resp.RedundantMetadataFiles, tt.expectedCount) + + // independently compute expected response + metadataBytes, err := json.Marshal(tt.req.Metadata) + assert.NoError(t, err) + + base64Meta := utils.B64Encode(metadataBytes) + + for i := 0; i < tt.expectedCount; i++ { + composite := append(base64Meta, []byte(fmt.Sprintf(".%s.%d", tt.req.Signature, tt.req.IC+uint32(i)))...) + compressed, err := utils.ZstdCompress(composite) + assert.NoError(t, err) + + hash, err := utils.Blake3Hash(compressed) + assert.NoError(t, err) + + expectedRQID := base58.Encode(hash) + + assert.Equal(t, expectedRQID, resp.RQIDs[i]) + assert.Equal(t, compressed, resp.RedundantMetadataFiles[i]) + } + }) + } +} diff --git a/tests/integration/p2p/p2p_integration_test.go b/tests/integration/p2p/p2p_integration_test.go index 289b28e7..c64d396f 100644 --- a/tests/integration/p2p/p2p_integration_test.go +++ b/tests/integration/p2p/p2p_integration_test.go @@ -16,7 +16,9 @@ import ( "github.com/LumeraProtocol/supernode/p2p" "github.com/LumeraProtocol/supernode/p2p/kademlia" + snkeyring "github.com/LumeraProtocol/supernode/pkg/keyring" ltc "github.com/LumeraProtocol/supernode/pkg/net/credentials" + "github.com/LumeraProtocol/supernode/pkg/net/credentials/alts/conn" "github.com/LumeraProtocol/supernode/pkg/storage/rqstore" "github.com/LumeraProtocol/supernode/pkg/testutil" "github.com/LumeraProtocol/supernode/pkg/utils" @@ -25,6 +27,10 @@ import ( func TestP2PBasicIntegration(t *testing.T) { log.Println("Starting P2P test...") + snkeyring.InitSDKConfig() + conn.RegisterALTSRecordProtocols() + defer conn.UnregisterALTSRecordProtocols() + ctx, cancel := context.WithTimeout(context.Background(), 300*time.Second) defer cancel() diff --git a/tests/integration/securegrpc/secure_connection_test.go b/tests/integration/securegrpc/secure_connection_test.go index 642963fe..11308810 100644 --- a/tests/integration/securegrpc/secure_connection_test.go +++ b/tests/integration/securegrpc/secure_connection_test.go @@ -23,6 +23,7 @@ import ( "github.com/LumeraProtocol/supernode/pkg/net/credentials/alts/conn" "github.com/LumeraProtocol/supernode/pkg/net/grpc/client" "github.com/LumeraProtocol/supernode/pkg/net/grpc/server" + snkeyring "github.com/LumeraProtocol/supernode/pkg/keyring" "github.com/LumeraProtocol/supernode/pkg/testutil" ) @@ -57,6 +58,8 @@ func (s *TestServiceImpl) TestMethod(ctx context.Context, req *pb.TestRequest) ( } func TestSecureGRPCConnection(t *testing.T) { + snkeyring.InitSDKConfig() + conn.RegisterALTSRecordProtocols() defer conn.UnregisterALTSRecordProtocols()