// Package neofs provides a NeoFS storage adapter for Tutus. // // NeoFS is a decentralized storage network that can be deployed as either // a public network or a private sovereign network for government use. // // For sovereign deployments, governments should run their own NeoFS // infrastructure within national borders to ensure data residency compliance. package neofs import ( "bytes" "context" "fmt" "io" "time" "github.com/nspcc-dev/neofs-sdk-go/pool" "github.com/tutus-one/tutus-chain/pkg/storage" ) const providerName = "neofs" // Adapter implements the storage.Provider interface for NeoFS. type Adapter struct { pool *pool.Pool container string timeout time.Duration } // Config holds NeoFS adapter configuration. type Config struct { // Pool is an initialized NeoFS connection pool Pool *pool.Pool // Container is the NeoFS container ID string Container string // Timeout for NeoFS operations Timeout time.Duration } // New creates a new NeoFS storage adapter. func New(cfg Config) *Adapter { timeout := cfg.Timeout if timeout == 0 { timeout = 30 * time.Second } return &Adapter{ pool: cfg.Pool, container: cfg.Container, timeout: timeout, } } // Name returns the provider identifier. func (a *Adapter) Name() string { return providerName } // Put stores data in NeoFS and returns the object ID. func (a *Adapter) Put(ctx context.Context, data io.Reader, opts storage.PutOptions) (storage.ObjectID, error) { ctx, cancel := context.WithTimeout(ctx, a.timeout) defer cancel() // Read all data content, err := io.ReadAll(data) if err != nil { return storage.ObjectID{}, fmt.Errorf("neofs: read data: %w", err) } // TODO: Implement NeoFS object upload using pool // This requires proper NeoFS SDK integration with: // - Container ID parsing // - Object creation with attributes // - Signing with user credentials // - Upload via pool.ObjectPutInit() _ = content // Use content when implementing return storage.ObjectID{}, fmt.Errorf("neofs: Put not yet implemented - use existing neofs helpers") } // Get retrieves an object from NeoFS. func (a *Adapter) Get(ctx context.Context, id storage.ObjectID) (io.ReadCloser, error) { ctx, cancel := context.WithTimeout(ctx, a.timeout) defer cancel() // TODO: Implement NeoFS object download // This requires: // - Object ID parsing // - Download via pool.ObjectGetInit() // - Payload reading _ = ctx // Use ctx when implementing return nil, fmt.Errorf("neofs: Get not yet implemented - use existing neofs helpers") } // Delete removes an object from NeoFS. func (a *Adapter) Delete(ctx context.Context, id storage.ObjectID) error { ctx, cancel := context.WithTimeout(ctx, a.timeout) defer cancel() // TODO: Implement NeoFS object deletion _ = ctx return fmt.Errorf("neofs: Delete not yet implemented") } // Exists checks if an object exists in NeoFS. func (a *Adapter) Exists(ctx context.Context, id storage.ObjectID) (bool, error) { ctx, cancel := context.WithTimeout(ctx, a.timeout) defer cancel() // TODO: Implement via ObjectHead _ = ctx return false, fmt.Errorf("neofs: Exists not yet implemented") } // List returns objects matching the given prefix. func (a *Adapter) List(ctx context.Context, prefix string, opts storage.ListOptions) ([]storage.ObjectInfo, error) { ctx, cancel := context.WithTimeout(ctx, a.timeout) defer cancel() // TODO: Implement via ObjectSearch _ = ctx _ = prefix return nil, fmt.Errorf("neofs: List not yet implemented") } // Head retrieves object metadata. func (a *Adapter) Head(ctx context.Context, id storage.ObjectID) (storage.ObjectInfo, error) { ctx, cancel := context.WithTimeout(ctx, a.timeout) defer cancel() // TODO: Implement via ObjectHead _ = ctx return storage.ObjectInfo{}, fmt.Errorf("neofs: Head not yet implemented") } // Close releases NeoFS pool resources. func (a *Adapter) Close() error { if a.pool != nil { a.pool.Close() } return nil } // WrapExistingReader wraps data from the existing NeoFS helpers into the storage interface. // This is a bridge to use existing pkg/services/helpers/neofs code with the new interface. func WrapExistingReader(data []byte) io.ReadCloser { return io.NopCloser(bytes.NewReader(data)) }