Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ require (
cosmossdk.io/math v1.5.3
github.com/AlecAivazis/survey/v2 v2.3.7
github.com/DataDog/zstd v1.5.7
github.com/LumeraProtocol/lumera v1.11.0-rc
github.com/LumeraProtocol/lumera v1.11.2-0.20260331140230-4aeb5d0d7a89
github.com/LumeraProtocol/rq-go v0.2.1
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
github.com/cenkalti/backoff/v4 v4.3.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.50
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.50.0 h1:ig/FpDD2JofP/NExKQUbn7uOSZzJAQqogfqluZK4ed4=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.50.0/go.mod h1:otE2jQekW/PqXk1Awf5lmfokJx4uwuqcj1ab5SpGeW0=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/LumeraProtocol/lumera v1.11.0-rc h1:ISJLUhjihuOterLMHpgGWpMZmybR1vmQLNgmSHkc1WA=
github.com/LumeraProtocol/lumera v1.11.0-rc/go.mod h1:p2sZZG3bLzSBdaW883qjuU3DXXY4NJzTTwLywr8uI0w=
github.com/LumeraProtocol/lumera v1.11.2-0.20260331140230-4aeb5d0d7a89 h1:wDZnZ5wi4l0qyMufE3bOQImu1BF/igMAsxr6aMWRmp4=
github.com/LumeraProtocol/lumera v1.11.2-0.20260331140230-4aeb5d0d7a89/go.mod h1:p2sZZG3bLzSBdaW883qjuU3DXXY4NJzTTwLywr8uI0w=
github.com/LumeraProtocol/rq-go v0.2.1 h1:8B3UzRChLsGMmvZ+UVbJsJj6JZzL9P9iYxbdUwGsQI4=
github.com/LumeraProtocol/rq-go v0.2.1/go.mod h1:APnKCZRh1Es2Vtrd2w4kCLgAyaL5Bqrkz/BURoRJ+O8=
github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4=
Expand Down
27 changes: 21 additions & 6 deletions sdk/adapters/lumera/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,17 @@ type SuperNodeInfo struct {
CurrentState string `json:"current_state"`
}

// CascadeClientFailureDetails is the structured payload for audit cascade-client-failure evidence.
type CascadeClientFailureDetails struct {
Operation string
Iteration string
SupernodeEndpoint string
SupernodeAccount string
TaskID string
Error string
ActionID string
}

// ConfigParams holds configuration parameters from global config
type ConfigParams struct {
GRPCAddr string
Expand Down Expand Up @@ -389,7 +400,7 @@ func (a *Adapter) SubmitCascadeClientFailureEvidence(
subjectAddress string,
actionID string,
targetSupernodeAccounts []string,
details map[string]string,
details CascadeClientFailureDetails,
) error {
if a.client == nil {
return fmt.Errorf("lumera client is nil")
Expand All @@ -398,14 +409,18 @@ func (a *Adapter) SubmitCascadeClientFailureEvidence(
if subjectAddress == "" {
return fmt.Errorf("subject address cannot be empty")
}
if details == nil {
details = map[string]string{}
}

meta := audittypes.CascadeClientFailureEvidenceMetadata{
ReporterComponent: audittypes.CascadeClientFailureReporterComponent_CASCADE_CLIENT_FAILURE_REPORTER_COMPONENT_SDK_GO,
TargetSupernodeAccounts: append([]string(nil), targetSupernodeAccounts...),
Details: details,
Details: &audittypes.CascadeClientFailureDetails{
Operation: details.Operation,
Iteration: details.Iteration,
SupernodeEndpoint: details.SupernodeEndpoint,
SupernodeAccount: details.SupernodeAccount,
TaskId: details.TaskID,
Error: details.Error,
ActionId: details.ActionID,
},
}
bz, err := json.Marshal(meta)
if err != nil {
Expand Down
12 changes: 6 additions & 6 deletions sdk/task/cascade.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,12 @@ func (t *CascadeTask) registerWithSupernodes(ctx context.Context, supernodes lum
event.KeyIteration: iteration,
event.KeyError: err.Error(),
})
t.submitCascadeClientFailureEvidence(ctx, sn.CosmosAddress, []string{sn.CosmosAddress}, map[string]string{
"operation": "register",
"iteration": fmt.Sprintf("%d", iteration),
"supernode_endpoint": sn.GrpcEndpoint,
"supernode_account": sn.CosmosAddress,
"error": err.Error(),
t.submitCascadeClientFailureEvidence(ctx, sn.CosmosAddress, []string{sn.CosmosAddress}, lumera.CascadeClientFailureDetails{
Operation: "register",
Iteration: fmt.Sprintf("%d", iteration),
SupernodeEndpoint: sn.GrpcEndpoint,
SupernodeAccount: sn.CosmosAddress,
Error: err.Error(),
})
lastErr = err
continue
Expand Down
12 changes: 6 additions & 6 deletions sdk/task/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,12 @@ func (t *CascadeDownloadTask) downloadFromSupernodes(ctx context.Context, supern
event.KeyIteration: iteration,
event.KeyError: err.Error(),
})
t.submitCascadeClientFailureEvidence(ctx, sn.CosmosAddress, []string{sn.CosmosAddress}, map[string]string{
"operation": "download",
"iteration": fmt.Sprintf("%d", iteration),
"supernode_endpoint": sn.GrpcEndpoint,
"supernode_account": sn.CosmosAddress,
"error": err.Error(),
t.submitCascadeClientFailureEvidence(ctx, sn.CosmosAddress, []string{sn.CosmosAddress}, lumera.CascadeClientFailureDetails{
Operation: "download",
Iteration: fmt.Sprintf("%d", iteration),
SupernodeEndpoint: sn.GrpcEndpoint,
SupernodeAccount: sn.CosmosAddress,
Error: err.Error(),
})
lastErr = err
continue
Expand Down
24 changes: 10 additions & 14 deletions sdk/task/evidence.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"context"
"strings"
"time"

"github.com/LumeraProtocol/supernode/v2/sdk/adapters/lumera"
)

// Optional interface so existing test doubles that only implement the base
Expand All @@ -14,7 +16,7 @@ type cascadeClientFailureEvidenceSubmitter interface {
subjectAddress string,
actionID string,
targetSupernodeAccounts []string,
details map[string]string,
details lumera.CascadeClientFailureDetails,
) error
}

Expand All @@ -24,7 +26,7 @@ func (t *BaseTask) submitCascadeClientFailureEvidence(
ctx context.Context,
subjectAddress string,
targetSupernodeAccounts []string,
details map[string]string,
details lumera.CascadeClientFailureDetails,
) {
subjectAddress = strings.TrimSpace(subjectAddress)
if subjectAddress == "" {
Expand All @@ -37,24 +39,18 @@ func (t *BaseTask) submitCascadeClientFailureEvidence(
return
}

if details == nil {
details = map[string]string{}
}
if _, exists := details["task_id"]; !exists {
details["task_id"] = t.TaskID
if details.TaskID == "" {
details.TaskID = t.TaskID
}
if _, exists := details["action_id"]; !exists {
details["action_id"] = t.ActionID
if details.ActionID == "" {
details.ActionID = t.ActionID
}

targetsCopy := append([]string(nil), targetSupernodeAccounts...)
detailsCopy := make(map[string]string, len(details))
for k, v := range details {
detailsCopy[k] = v
}
detailsCopy := details

// Evidence submission should not block retry loops.
go func(parent context.Context, subject string, actionID string, targets []string, metadata map[string]string) {
go func(parent context.Context, subject string, actionID string, targets []string, metadata lumera.CascadeClientFailureDetails) {
submitCtx, cancel := context.WithTimeout(context.WithoutCancel(parent), cascadeEvidenceSubmitTimeout)
defer cancel()

Expand Down
38 changes: 29 additions & 9 deletions supernode/storage_challenge/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -595,15 +595,15 @@ func (s *Service) maybeSubmitEvidence(ctx context.Context, params audittypes.Par
return nil
}

meta := audittypes.StorageChallengeFailureEvidenceMetadata{
EpochId: epochID,
ChallengerSupernodeAccount: s.identity,
ChallengedSupernodeAccount: recipient,
ChallengeId: challengeID,
FileKey: fileKey,
FailureType: failureType,
TranscriptHash: transcriptHashHex,
}
meta := buildStorageChallengeFailureEvidenceMetadata(
epochID,
s.identity,
recipient,
challengeID,
fileKey,
failureType,
transcriptHashHex,
)
bz, err := json.Marshal(meta)
if err != nil {
return err
Expand All @@ -628,6 +628,26 @@ func (s *Service) maybeSubmitEvidence(ctx context.Context, params audittypes.Par
return nil
}

func buildStorageChallengeFailureEvidenceMetadata(
epochID uint64,
challengerSupernodeAccount string,
challengedSupernodeAccount string,
challengeID string,
fileKey string,
failureType string,
transcriptHashHex string,
) audittypes.StorageChallengeFailureEvidenceMetadata {
return audittypes.StorageChallengeFailureEvidenceMetadata{
EpochId: epochID,
ChallengerSupernodeAccount: challengerSupernodeAccount,
ChallengedSupernodeAccount: challengedSupernodeAccount,
ChallengeId: challengeID,
FileKey: fileKey,
FailureType: failureType,
TranscriptHash: transcriptHashHex,
}
}

func deriveChallengeID(seed []byte, epochID uint64, fileKey, challenger, recipient string) string {
msg := []byte("sc:challenge:" + hex.EncodeToString(seed) + ":" + strconv.FormatUint(epochID, 10) + ":" + fileKey + ":" + challenger + ":" + recipient)
sum := blake3.Sum256(msg)
Expand Down
39 changes: 39 additions & 0 deletions supernode/storage_challenge/service_metadata_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package storage_challenge

import (
"encoding/json"
"testing"

audittypes "github.com/LumeraProtocol/lumera/x/audit/v1/types"
"github.com/stretchr/testify/require"
)

func TestBuildStorageChallengeFailureEvidenceMetadata_NoMapPayload(t *testing.T) {
meta := buildStorageChallengeFailureEvidenceMetadata(
42,
"lumera1challengerxxxxxxxxxxxxxxxxxxxx",
"lumera1recipientxxxxxxxxxxxxxxxxxxxxx",
"challenge-id-123",
"file-key-abc",
"INVALID_PROOF",
"deadbeef",
)

require.Equal(t, uint64(42), meta.EpochId)
require.Equal(t, "challenge-id-123", meta.ChallengeId)
require.Equal(t, "file-key-abc", meta.FileKey)
require.Equal(t, "INVALID_PROOF", meta.FailureType)
require.Equal(t, "deadbeef", meta.TranscriptHash)

bz, err := json.Marshal(meta)
require.NoError(t, err)

var got map[string]any
require.NoError(t, json.Unmarshal(bz, &got))
require.NotContains(t, got, "details")
require.NotContains(t, got, "metadata")

var roundtrip audittypes.StorageChallengeFailureEvidenceMetadata
require.NoError(t, json.Unmarshal(bz, &roundtrip))
require.Equal(t, meta, roundtrip)
}
Loading