From 70fc8a655263af6e708deba25c9cc1334669338d Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 2 Apr 2026 17:10:07 +0100 Subject: [PATCH] ax(node): remove banned fmt import from bundle.go Replace all fmt.Errorf calls in bundle.go with ProtocolError structs, eliminating the banned fmt import. Error messages are preserved via string concatenation consistent with the rest of the node package. Co-Authored-By: Charon --- pkg/node/bundle.go | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/pkg/node/bundle.go b/pkg/node/bundle.go index bea3c81..17866fd 100644 --- a/pkg/node/bundle.go +++ b/pkg/node/bundle.go @@ -6,7 +6,6 @@ import ( "crypto/sha256" "encoding/hex" "encoding/json" - "fmt" "io" "os" "path/filepath" @@ -51,14 +50,14 @@ func CreateProfileBundle(profileJSON []byte, name string, password string) (*Bun // Create a TIM with just the profile config timContainer, err := tim.New() if err != nil { - return nil, fmt.Errorf("failed to create TIM: %w", err) + return nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to create TIM: " + err.Error()} } timContainer.Config = profileJSON // Encrypt to STIM format stimData, err := timContainer.ToSigil(password) if err != nil { - return nil, fmt.Errorf("failed to encrypt bundle: %w", err) + return nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to encrypt bundle: " + err.Error()} } // Calculate checksum @@ -91,7 +90,7 @@ func CreateMinerBundle(minerPath string, profileJSON []byte, name string, passwo // Read miner binary minerData, err := os.ReadFile(minerPath) if err != nil { - return nil, fmt.Errorf("failed to read miner binary: %w", err) + return nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to read miner binary: " + err.Error()} } // Create a tarball with the miner binary @@ -99,19 +98,19 @@ func CreateMinerBundle(minerPath string, profileJSON []byte, name string, passwo filepath.Base(minerPath): minerData, }) if err != nil { - return nil, fmt.Errorf("failed to create tarball: %w", err) + return nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to create tarball: " + err.Error()} } // Create DataNode from tarball dataNode, err := datanode.FromTar(tarData) if err != nil { - return nil, fmt.Errorf("failed to create datanode: %w", err) + return nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to create datanode: " + err.Error()} } // Create TIM from DataNode timContainer, err := tim.FromDataNode(dataNode) if err != nil { - return nil, fmt.Errorf("failed to create TIM: %w", err) + return nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to create TIM: " + err.Error()} } // Set profile as config if provided @@ -122,7 +121,7 @@ func CreateMinerBundle(minerPath string, profileJSON []byte, name string, passwo // Encrypt to STIM format stimData, err := timContainer.ToSigil(password) if err != nil { - return nil, fmt.Errorf("failed to encrypt bundle: %w", err) + return nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to encrypt bundle: " + err.Error()} } checksum := calculateChecksum(stimData) @@ -140,7 +139,7 @@ func CreateMinerBundle(minerPath string, profileJSON []byte, name string, passwo func ExtractProfileBundle(bundle *Bundle, password string) ([]byte, error) { // Verify checksum first if calculateChecksum(bundle.Data) != bundle.Checksum { - return nil, fmt.Errorf("checksum mismatch - bundle may be corrupted") + return nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "checksum mismatch - bundle may be corrupted"} } // If it's unencrypted JSON, just return it @@ -151,7 +150,7 @@ func ExtractProfileBundle(bundle *Bundle, password string) ([]byte, error) { // Decrypt STIM format timContainer, err := tim.FromSigil(bundle.Data, password) if err != nil { - return nil, fmt.Errorf("failed to decrypt bundle: %w", err) + return nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to decrypt bundle: " + err.Error()} } return timContainer.Config, nil @@ -162,25 +161,25 @@ func ExtractProfileBundle(bundle *Bundle, password string) ([]byte, error) { func ExtractMinerBundle(bundle *Bundle, password string, destDir string) (string, []byte, error) { // Verify checksum if calculateChecksum(bundle.Data) != bundle.Checksum { - return "", nil, fmt.Errorf("checksum mismatch - bundle may be corrupted") + return "", nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "checksum mismatch - bundle may be corrupted"} } // Decrypt STIM format timContainer, err := tim.FromSigil(bundle.Data, password) if err != nil { - return "", nil, fmt.Errorf("failed to decrypt bundle: %w", err) + return "", nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to decrypt bundle: " + err.Error()} } // Convert rootfs to tarball and extract tarData, err := timContainer.RootFS.ToTar() if err != nil { - return "", nil, fmt.Errorf("failed to convert rootfs to tar: %w", err) + return "", nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to convert rootfs to tar: " + err.Error()} } // Extract tarball to destination minerPath, err := extractTarball(tarData, destDir) if err != nil { - return "", nil, fmt.Errorf("failed to extract tarball: %w", err) + return "", nil, &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to extract tarball: " + err.Error()} } return minerPath, timContainer.Config, nil @@ -264,7 +263,7 @@ func extractTarball(tarData []byte, destDir string) (string, error) { // Ensure destDir is an absolute, clean path for security checks absDestDir, err := filepath.Abs(destDir) if err != nil { - return "", fmt.Errorf("failed to resolve destination directory: %w", err) + return "", &ProtocolError{Code: ErrCodeOperationFailed, Message: "failed to resolve destination directory: " + err.Error()} } absDestDir = filepath.Clean(absDestDir) @@ -289,13 +288,13 @@ func extractTarball(tarData []byte, destDir string) (string, error) { // Reject absolute paths if filepath.IsAbs(cleanName) { - return "", fmt.Errorf("invalid tar entry: absolute path not allowed: %s", header.Name) + return "", &ProtocolError{Code: ErrCodeOperationFailed, Message: "invalid tar entry: absolute path not allowed: " + header.Name} } // Reject paths that escape the destination directory parentPrefix := ".." + string(os.PathSeparator) if bytes.HasPrefix([]byte(cleanName), []byte(parentPrefix)) || cleanName == ".." { - return "", fmt.Errorf("invalid tar entry: path traversal attempt: %s", header.Name) + return "", &ProtocolError{Code: ErrCodeOperationFailed, Message: "invalid tar entry: path traversal attempt: " + header.Name} } // Build the full path and verify it's within destDir @@ -305,7 +304,7 @@ func extractTarball(tarData []byte, destDir string) (string, error) { // Final security check: ensure the path is still within destDir destDirPrefix := absDestDir + string(os.PathSeparator) if !bytes.HasPrefix([]byte(fullPath), []byte(destDirPrefix)) && fullPath != absDestDir { - return "", fmt.Errorf("invalid tar entry: path escape attempt: %s", header.Name) + return "", &ProtocolError{Code: ErrCodeOperationFailed, Message: "invalid tar entry: path escape attempt: " + header.Name} } switch header.Typeflag { @@ -334,7 +333,7 @@ func extractTarball(tarData []byte, destDir string) (string, error) { } if written > maxFileSize { os.Remove(fullPath) - return "", fmt.Errorf("file %s exceeds maximum size of %d bytes", header.Name, maxFileSize) + return "", &ProtocolError{Code: ErrCodeOperationFailed, Message: "file " + header.Name + " exceeds maximum allowed size"} } // Track first executable