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
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
## v0.5.3 (2026-10-12)
### Notes

- Update Logos Storage Nim to v0.5.3
- Breaking: `Config.DiscoveryPort` is removed
- Breaking: `TogglePrivateQueries` is removed. Use `Private` in the download
and fetch options
- Breaking: a node with `MixEnabled` and `DhtMixProxies` no longer sends all
its DHT queries through Mix. Only the calls that set `Private` use Mix
- Breaking: `DownloadManifest` takes a `DownloadManifestOptions` and `Fetch`
takes a `FetchOptions`
- Breaking: `DebugInfo.ProviderAddresses` and `DebugInfo.DiscoveryAddresses`
are removed
- Breaking: `Node` only has `PeerId`, `Addresses` and `LastSeen`
- Add `Private` to the download and fetch options to use the Mix transport
- Add `NoAdvertise` to the upload, download and fetch options
- Add `GetAdvertise` and `SetAdvertise`
- Add `Network` to read the name of the network preset
- Add `Config.AdvertiseContent`
- `Revision` returns the revision. It returned the version before

## v0.4.3 (2026-10-08)
### Notes

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ endif

OS ?= $(shell go env GOOS)
ARCH ?= $(shell go env GOARCH)
VERSION := v0.4.3
VERSION := v0.5.3
DOWNLOAD_URL := https://github.com/logos-storage/logos-storage-nim/releases/download/$(VERSION)/libstorage-$(OS)-$(ARCH)-$(VERSION).zip

.PHONY: all clean fetch build test
Expand Down
35 changes: 32 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ endif

OS ?= $(shell go env GOOS)
ARCH ?= $(shell go env GOARCH)
VERSION := v0.4.3
VERSION := v0.5.3
DOWNLOAD_URL := https://github.com/logos-storage/logos-storage-nim/releases/download/$(VERSION)/libstorage-$(OS)-$(ARCH)-$(VERSION).zip

# Edit your binary name here
Expand Down Expand Up @@ -178,6 +178,7 @@ Other information is available after the node is started:
version, err := node.Version()
spr, err := node.Spr()
peerId, err := node.PeerId()
network, err := node.Network()
```

### Upload
Expand Down Expand Up @@ -248,7 +249,7 @@ whenever you want!
When you receive a cid, you can download the `Manifest` to get information about the data:

```go
manifest, err := storage.DownloadManifest(cid)
manifest, err := storage.DownloadManifest(cid, DownloadManifestOptions{})
```

It is not mandatory for downloading the data but it is really useful.
Expand Down Expand Up @@ -309,11 +310,39 @@ space, err := node.Space()

cid := "..."
err := node.Delete(cid)
err := node.Fetch(cid)
manifest, err := node.Fetch(cid, FetchOptions{})
```

The `Fetch` method downloads remote data into your local node.

### Advertise

By default, a dataset is announced to the DHT and served to other peers.
Set `NoAdvertise` in the upload, download or fetch options to keep it on your node only:

```go
cid, err := node.UploadFile(ctx, UploadOptions{Filepath: "./testdata/hello.txt", NoAdvertise: true})
```

`NoAdvertise` is ignored by a download or a fetch when the manifest is already on your node.

You can read and change this later:

```go
advertised, err := node.GetAdvertise(cid)
err := node.SetAdvertise(cid, true)
```

### Private download

Set `Private` in the download or fetch options to go through the Mix transport.
The node must be configured with Mix (`MixEnabled`), otherwise the call fails.

```go
manifest, err := storage.DownloadManifest(cid, DownloadManifestOptions{Private: true})
err := storage.DownloadStream(ctx, cid, DownloadStreamOptions{Private: true})
```

### P2P

You can connect to a node using the `peerId` or the `listenAddresses`:
Expand Down
17 changes: 5 additions & 12 deletions storage/debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ import (
)

type Node struct {
NodeId string `json:"nodeId"`
PeerId string `json:"peerId"`
Record string `json:"record"`
Address *string `json:"address"`
Seen bool `json:"seen"`
PeerId string `json:"peerId"`
Addresses []string `json:"addresses"`

// Unix time in seconds, nil for the local node
LastSeen *int64 `json:"lastSeen"`
}

type RoutingTable struct {
Expand Down Expand Up @@ -68,13 +68,6 @@ type DebugInfo struct {

Spr string `json:"spr"`

// Addresses contained in the provider record, the one announced
// for the content the node provides
ProviderAddresses []string `json:"providerAddresses"`

// UDP addresses announced in the DHT
DiscoveryAddresses []string `json:"discoveryAddresses"`

PeersTable RoutingTable `json:"table"`
Nat NatInfo `json:"nat"`
Connections []Connection `json:"connections"`
Expand Down
4 changes: 2 additions & 2 deletions storage/debug_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ func TestDebug(t *testing.T) {
if info.Spr == "" {
t.Error("Debug info Spr is empty")
}
if len(info.ProviderAddresses) == 0 {
t.Error("Debug info ProviderAddresses is empty")
if info.PeersTable.LocalNode.PeerId == "" {
t.Error("Debug info local node PeerId is empty")
}
}

Expand Down
72 changes: 55 additions & 17 deletions storage/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,24 @@ package storage
#include "bridge.h"
#include <stdlib.h>

static int cGoStorageDownloadInit(void* storageCtx, char* cid, size_t chunkSize, bool local, void* resp) {
return storage_download_init(storageCtx, cid, chunkSize, local, (StorageCallback) callback, resp);
static int cGoStorageDownloadInit(void* storageCtx, char* cid, size_t chunkSize, bool local, bool isPrivate, bool advertise, void* resp) {
return storage_download_init(storageCtx, cid, chunkSize, local, isPrivate, advertise, (StorageCallback) callback, resp);
}

static int cGoStorageDownloadChunk(void* storageCtx, char* cid, void* resp) {
return storage_download_chunk(storageCtx, cid, (StorageCallback) callback, resp);
}

static int cGoStorageDownloadStream(void* storageCtx, char* cid, size_t chunkSize, bool local, const char* filepath, void* resp) {
return storage_download_stream(storageCtx, cid, chunkSize, local, filepath, (StorageCallback) callback, resp);
static int cGoStorageDownloadStream(void* storageCtx, char* cid, size_t chunkSize, const char* filepath, void* resp) {
return storage_download_stream(storageCtx, cid, chunkSize, filepath, (StorageCallback) callback, resp);
}

static int cGoStorageDownloadCancel(void* storageCtx, char* cid, void* resp) {
return storage_download_cancel(storageCtx, cid, (StorageCallback) callback, resp);
}

static int cGoStorageDownloadManifest(void* storageCtx, char* cid, void* resp) {
return storage_download_manifest(storageCtx, cid, (StorageCallback) callback, resp);
static int cGoStorageDownloadManifest(void* storageCtx, char* cid, bool isPrivate, bool advertise, void* resp) {
return storage_download_manifest(storageCtx, cid, isPrivate, advertise, (StorageCallback) callback, resp);
}
*/
import "C"
Expand All @@ -38,7 +38,7 @@ type OnDownloadProgressFunc func(read, total int, percent float64, err error)

// DownloadStreamOptions is used to download a file
// in a streaming manner in Logos Storage.
type DownloadStreamOptions = struct {
type DownloadStreamOptions struct {
// Filepath is the path destination used by DownloadStream.
// If it is set, the content will be written into the specified
// path.
Expand Down Expand Up @@ -67,6 +67,16 @@ type DownloadStreamOptions = struct {
// from the network.
Local bool

// Private, if true, the download goes through the Mix transport.
// An existing download session for the same cid must use the same value.
Private bool

// NoAdvertise, if true, the dataset is neither announced to the DHT
// nor served to other peers.
// It is ignored when the manifest is already in the local node,
// use SetAdvertise instead.
NoAdvertise bool

// DatasetSize is the total size of the dataset being downloaded.
DatasetSize int

Expand All @@ -76,18 +86,40 @@ type DownloadStreamOptions = struct {
}

// DownloadInitOptions is used to create a download session.
type DownloadInitOptions = struct {
type DownloadInitOptions struct {
// Local defines the way to download the content.
// If true, the content will be downloaded from the
// local node.
// If false (default), the content will be downloaded
// from the network.
Local bool

// Private, if true, the download goes through the Mix transport.
// An existing download session for the same cid must use the same value.
Private bool

// NoAdvertise, if true, the dataset is neither announced to the DHT
// nor served to other peers.
// It is ignored when the manifest is already in the local node,
// use SetAdvertise instead.
NoAdvertise bool

// ChunkSize is the size of each downloaded chunk. Default is to 64 KB.
ChunkSize ChunkSize
}

// DownloadManifestOptions is used to retrieve a manifest.
type DownloadManifestOptions struct {
// Private, if true, the manifest is fetched through the Mix transport.
Private bool

// NoAdvertise, if true, the dataset is neither announced to the DHT
// nor served to other peers.
// It is ignored when the manifest is already in the local node,
// use SetAdvertise instead.
NoAdvertise bool
}

// Manifest is the object containing the information of
// a file in Logos Storage.
type Manifest struct {
Expand Down Expand Up @@ -116,14 +148,17 @@ type Manifest struct {
// DownloadManifest retrieves the Logos Storage manifest from its cid.
// The session identifier is the cid, i.e you cannot have multiple
// sessions for a cid.
func (node StorageNode) DownloadManifest(cid string) (Manifest, error) {
// A manifest fetched from the network is stored in the local node.
// Unless options.NoAdvertise is set, the node then announces the dataset
// to the DHT and serves it to peers.
func (node StorageNode) DownloadManifest(cid string, options DownloadManifestOptions) (Manifest, error) {
bridge := newBridgeCtx()
defer bridge.free()

var cCid = C.CString(cid)
defer C.free(unsafe.Pointer(cCid))

if C.cGoStorageDownloadManifest(node.ctx, cCid, bridge.resp) != C.RET_OK {
if C.cGoStorageDownloadManifest(node.ctx, cCid, C.bool(options.Private), C.bool(!options.NoAdvertise), bridge.resp) != C.RET_OK {
return Manifest{}, bridge.callError("cGoStorageDownloadManifest")
}

Expand Down Expand Up @@ -153,7 +188,10 @@ func (node StorageNode) DownloadStream(ctx context.Context, cid string, options
defer bridge.free()

if options.DatasetSizeAuto {
manifest, err := node.DownloadManifest(cid)
manifest, err := node.DownloadManifest(cid, DownloadManifestOptions{
Private: options.Private,
NoAdvertise: options.NoAdvertise,
})

if err != nil {
return err
Expand Down Expand Up @@ -193,8 +231,10 @@ func (node StorageNode) DownloadStream(ctx context.Context, cid string, options
defer C.free(unsafe.Pointer(cCid))

err := node.DownloadInit(cid, DownloadInitOptions{
ChunkSize: options.ChunkSize,
Local: options.Local,
ChunkSize: options.ChunkSize,
Local: options.Local,
Private: options.Private,
NoAdvertise: options.NoAdvertise,
})
if err != nil {
return err
Expand All @@ -205,9 +245,7 @@ func (node StorageNode) DownloadStream(ctx context.Context, cid string, options
var cFilepath = C.CString(options.Filepath)
defer C.free(unsafe.Pointer(cFilepath))

var cLocal = C.bool(options.Local)

if C.cGoStorageDownloadStream(node.ctx, cCid, options.ChunkSize.toSizeT(), cLocal, cFilepath, bridge.resp) != C.RET_OK {
if C.cGoStorageDownloadStream(node.ctx, cCid, options.ChunkSize.toSizeT(), cFilepath, bridge.resp) != C.RET_OK {
return bridge.callError("cGoStorageDownloadLocal")
}

Expand Down Expand Up @@ -264,7 +302,7 @@ func (node StorageNode) DownloadInit(cid string, options DownloadInitOptions) er

var cLocal = C.bool(options.Local)

if C.cGoStorageDownloadInit(node.ctx, cCid, options.ChunkSize.toSizeT(), cLocal, bridge.resp) != C.RET_OK {
if C.cGoStorageDownloadInit(node.ctx, cCid, options.ChunkSize.toSizeT(), cLocal, C.bool(options.Private), C.bool(!options.NoAdvertise), bridge.resp) != C.RET_OK {
return bridge.callError("cGoStorageDownloadInit")
}

Expand Down
41 changes: 39 additions & 2 deletions storage/download_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ func TestDownloadManifest(t *testing.T) {
storage := newStorageNode(t)
cid, _ := uploadHelper(t, storage)

manifest, err := storage.DownloadManifest(cid)
manifest, err := storage.DownloadManifest(cid, DownloadManifestOptions{})
if err != nil {
t.Fatal("Error when downloading manifest:", err)
}
Expand All @@ -161,7 +161,7 @@ func TestDownloadManifest(t *testing.T) {
func TestDownloadManifestWithNotExistingCid(t *testing.T) {
storage := newStorageNode(t, Config{BlockRetries: 1})

manifest, err := storage.DownloadManifest("bafybeihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku")
manifest, err := storage.DownloadManifest("bafybeihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku", DownloadManifestOptions{})
if err == nil {
t.Fatal("Error when downloading manifest:", err)
}
Expand All @@ -171,6 +171,43 @@ func TestDownloadManifestWithNotExistingCid(t *testing.T) {
}
}

func TestDownloadManifestNoAdvertise(t *testing.T) {
node1, node2 := twoNodesHelper(t)

cid, _ := uploadHelper(t, node1)

if _, err := node2.DownloadManifest(cid, DownloadManifestOptions{NoAdvertise: true}); err != nil {
t.Fatal("Error when downloading manifest:", err)
}

advertised, err := node2.GetAdvertise(cid)
if err != nil {
t.Fatal(err)
}
if advertised {
t.Fatal("expected cid to not be advertised")
}
}

func TestDownloadInitNoAdvertise(t *testing.T) {
node1, node2 := twoNodesHelper(t)

cid, _ := uploadHelper(t, node1)

if err := node2.DownloadInit(cid, DownloadInitOptions{NoAdvertise: true}); err != nil {
t.Fatal("Error when initializing download:", err)
}
defer node2.DownloadCancel(cid)

advertised, err := node2.GetAdvertise(cid)
if err != nil {
t.Fatal(err)
}
if advertised {
t.Fatal("expected cid to not be advertised")
}
}

func TestDownloadInitWithNotExistingCid(t *testing.T) {
storage := newStorageNode(t, Config{BlockRetries: 1})

Expand Down
Loading
Loading