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
44 changes: 44 additions & 0 deletions sdk/task/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,20 @@ package task
import (
"context"
"encoding/base64"
"errors"
"fmt"
"os"
"path/filepath"
"strings"

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

const maxFileSize = 1 * 1024 * 1024 * 1024 // 1GB limit

var ErrNoPeersConnected = errors.New("no P2P peers connected on available supernodes")

// ValidateFileSize checks if a file size is within the allowed 1GB limit
func ValidateFileSize(filePath string) error {
fileInfo, err := os.Stat(filePath)
Expand Down Expand Up @@ -100,6 +104,46 @@ func (m *ManagerImpl) validateSignature(ctx context.Context, action lumera.Actio
return nil
}

// checkSupernodesPeerConnectivity verifies that at least one supernode has P2P peers connected
func (m *ManagerImpl) checkSupernodesPeerConnectivity(ctx context.Context, blockHeight int64) error {
// Fetch supernodes for the action's block height
supernodes, err := m.lumeraClient.GetSupernodes(ctx, blockHeight)
if err != nil {
return fmt.Errorf("failed to get supernodes: %w", err)
}

if len(supernodes) == 0 {
return fmt.Errorf("no supernodes available for block height %d", blockHeight)
}

// Check each supernode for peer connectivity
factoryCfg := net.FactoryConfig{
LocalCosmosAddress: m.config.Account.LocalCosmosAddress,
PeerType: m.config.Account.PeerType,
}
clientFactory := net.NewClientFactory(ctx, m.logger, m.keyring, m.lumeraClient, factoryCfg)

for _, sn := range supernodes {
client, err := clientFactory.CreateClient(ctx, sn)
if err != nil {
continue // Skip this supernode if we can't connect
}

status, err := client.GetSupernodeStatus(ctx)
client.Close(ctx)
if err != nil {
continue // Skip this supernode if we can't get status
}

// Check if this supernode has peers
if status.Network.PeersCount > 1 {
return nil // Found at least one supernode with peers
}
}

return ErrNoPeersConnected
}

func (m *ManagerImpl) validateDownloadAction(ctx context.Context, actionID string) (lumera.Action, error) {
action, err := m.lumeraClient.GetAction(ctx, actionID)
if err != nil {
Expand Down
12 changes: 12 additions & 0 deletions sdk/task/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@ func (m *ManagerImpl) CreateCascadeTask(ctx context.Context, filePath string, ac
return "", err
}

// Check peer connectivity before creating task
if err := m.checkSupernodesPeerConnectivity(taskCtx, action.Height); err != nil {
cancel() // Clean up if peer check fails
return "", err
}

taskID := uuid.New().String()[:8]

m.logger.Debug(taskCtx, "Generated task ID", "taskID", taskID)
Expand Down Expand Up @@ -275,6 +281,12 @@ func (m *ManagerImpl) CreateDownloadTask(ctx context.Context, actionID string, o
return "", fmt.Errorf("no filename found in cascade metadata")
}

// Check peer connectivity before creating task
if err := m.checkSupernodesPeerConnectivity(taskCtx, action.Height); err != nil {
cancel() // Clean up if peer check fails
return "", err
}

// Ensure the output path includes the correct filename
finalOutputPath := path.Join(outputDir, action.ID, metadata.FileName)

Expand Down