From ffbbcf557b44095b31a5005c804829e30f66dd09 Mon Sep 17 00:00:00 2001 From: gmega Date: Tue, 3 Feb 2026 16:42:23 -0300 Subject: [PATCH 1/8] feat: add initial welcome page + libstorage tutorial covering v0.1 use cases --- docs/storage/README.md | 15 ++ docs/storage/libstorage-tutorial.md | 238 ++++++++++++++++++++++++++++ 2 files changed, 253 insertions(+) create mode 100644 docs/storage/libstorage-tutorial.md diff --git a/docs/storage/README.md b/docs/storage/README.md index e69de29..ca027ea 100644 --- a/docs/storage/README.md +++ b/docs/storage/README.md @@ -0,0 +1,15 @@ +# Welcome to Logos Storage + +Logos Storage aims at being a resilient, decentralized and censorship-resistance storage layer for +the Logos stack. At present, Logos Storage provides a basic filesharing layer, not unlike IPFS or +Bittorrent, which allows users to publish and share files with one another. + +Moving forward, Logos Storage will enable full provider and downloader anonymity, as well as +anonymous persistence. Check out [our roadmap](https://roadmap.logos.co/storage/roadmap/) for more details. + +## Using Logos Storage + +Logos Storage can currently be used in two main ways: + +1. via the [Logos Storage UI App](https://github.com/logos-co/logos-storage-ui), which runs as a [Logos Module](https://github.com/logos-co/logos-storage-module). You can use the Logos Storage UI App to upload and download files over the Logos Storage network. +2. Programmatically, using [libstorage](https://github.com/logos-co/logos-storage-nim). See our [simplified libstorage tutorial](./libstorage-tutorial.md) to get a feeling for what can be done. diff --git a/docs/storage/libstorage-tutorial.md b/docs/storage/libstorage-tutorial.md new file mode 100644 index 0000000..b43b157 --- /dev/null +++ b/docs/storage/libstorage-tutorial.md @@ -0,0 +1,238 @@ +# Getting Started with libstorage + +In this tutorial, we will build a simple [libstorage-based](https://github.com/logos-storage/logos-storage-nim) C application which allows sharing files over the Logos Storage network. Since libstorage is a low-level API and its main use case are library and not application developers, however, we will use a higher-level C wrapper developed for this tutorial which we refer to as [easylibstorage](https://github.com/logos-storage/easylibstorage). + +This is, in fact, the way libstorage is supposed to be used: as the building block for higher-level libraries or language bindings. Officially, we currently provide [Go bindings](https://github.com/logos-storage/logos-storage-go-bindings) and [Rust bindings](https://github.com/logos-storage/logos-storage-rust-bindings). + +# Building +To build easylibstorage, you'll need: + +- git +- CMake 3.14+ +- a C11 compiler +- libstorage (https://github.com/logos-storage/logos-storage-nim). To make this tutorial simpler, we suggest using the script bundled with easylibstorage (Step 2 below) to download prebuilt binaries instead of trying to build it from scratch. + +**Step 1.** Clone the [easylibstorage repository](https://github.com/logos-storage/easylibstorage): + +```bash +git clone https://github.com/logos-storage/easylibstorage.git +cd easylibstorage +``` + +**Step 2.** Download prebuilt binaries for libstorage: + +```bash +./scripts/fetch-libstorage.sh +``` + +Ensure that the script completed successfully. + +**Step 3.** Build easylibstorage: + +```bash +cmake -B build -S . -DLOGOS_STORAGE_NIM_ROOT=./libstorage +cmake --build build +``` + +# The Application + +Now that we have a working build for easylibstorage, we can focus on the application. Our application will be composed of two simple CLI apps - a file uploader and a file downloader. Once we are done, you will be able to use the application as follows: + +```bash +./uploader ./myfile +./downloader ./myfile-copy +``` + +The meaning of `` and `` will be explained as we go. + +First, create a `tutorial` folder under `easylibstorage`: + +```bash +cd easylibstorage # or wherever it was that you cloned your repo +mkdir tutorial +``` + +### Uploader + +The code for the uploader is shown in Listing 1. It first defines some configuration options for the storage node (lines 25-29), including the discovery listen port (UDP 9090), and the directory where the node will store its data (`./uploader-data`). It sets `nat` to `none` as we will be running a local node, and the bootstrap node to `NULL` as we will be creating a network from scratch. + +```c +01| /* uploader.c: makes a local file available to the Logos +02| Storage network. */ +03| +04| #include +05| #include +06| #include "easystorage.h" +07| +08| void panic(const char *msg) { +09| fprintf(stderr, "Panic: %s\n", msg); +10| exit(1); +11| } +12| +13| void progress(int total, int complete, int status) { +14| printf("\r %d / %d bytes", complete, total); +15| fflush(stdout); +16| } +17| +18| int main(int argc, char *argv[]) { +19| if (argc < 2) { +20| printf("Usage: %s \n", argv[0]); +21| exit(1); +22| } +23| +24| node_config cfg = { +25| .disc_port = 9090, +26| .data_dir = "./uploader-data", +27| .log_level = "INFO", +28| .bootstrap_node = NULL, +29| .nat = "none", +30| }; +31| +32| char *filepath = argv[1]; +33| +34| STORAGE_NODE node = e_storage_new(cfg); +34| if (node == NULL) panic("Failed to create storage node"); +35| if (e_storage_start(node) != RET_OK) panic("Failed to start storage node"); +36| +37| char *cid = e_storage_upload(node, filepath, progress); +38| if (cid == NULL) panic("Upload failed"); +39| char *spr = e_storage_spr(node); +40| if (spr == NULL) panic("Failed to get node's signed peer record"); +41| +42| printf("Run: downloader %s %s ./output-file\n", spr, cid); +45| +46| printf("\nPress Enter to exit\n"); +47| getchar(); +48| +49| printf("Deleting file (this could take a while)..."); +50| fflush(stdout); +51| if (e_storage_delete(node, cid) != RET_OK) panic("Failed to delete file"); +52| printf("Done\n"); +53| +54| free(cid); +55| free(spr); +56| e_storage_stop(node); +57| e_storage_destroy(node); +58| +59| return 0; +60| } +``` +**Listing 1.** Uploader. + +It then starts the node (line 37), and uploads the file into the local node (line 37). From that moment on, the file becomes available over the network. The program then gathers some critical pieces of information we will need later: + +* the node's [Signed Peer Record](https://github.com/libp2p/specs/blob/master/RFC/0002-signed-envelopes.md). This a string encoding our node's public key, its network ID, and its connection addresses. It can be used to find the node in the network. +* the Content ID ([CID](https://github.com/multiformats/cid)). This is a string that uniquely identifies the file we have just uploaded within the network. + +Those get printed to stdout (line 42), and the program them pauses until the user presses Enter (line 46). After that, the program deletes the file from the local node (line 49), and finally stops and destroys the node (lines 54-57). + +You should place the listing above in an `uploader.c` file in the `easylibstorage/tutorial` folder you created before. + +### Downloader + +```c +01| /* downloader.c: Download files from a Logos Storage node into the local disk. +02| */ +03| #include +04| #include +05| #include "easystorage.h" +06| +07| void panic(const char *msg) { +08| fprintf(stderr, "Panic: %s\n", msg); +09| exit(1); +10| } +11| +12| void progress(int total, int complete, int status) { +13| printf("\r %d / %d bytes", complete, total); +14| fflush(stdout); +15| } +16| +17| int main(int argc, char *argv[]) { +18| if (argc < 4) { +19| printf("Usage: %s BOOTSTRAP_SPR CID \n", argv[0]); +20| exit(1); +21| } +22| +23| char *spr = argv[1]; +24| char *cid = argv[2]; +25| char *filepath = argv[3]; +26| +27| node_config cfg = { +28| .api_port = 8081, +29| .disc_port = 9091, +30| .data_dir = "./downloader-data", +31| .log_level = "INFO", +32| .bootstrap_node = spr, +33| .nat = "none", +34| }; +35| +36| STORAGE_NODE node = e_storage_new(cfg); +37| if (e_storage_start(node) != RET_OK) panic("Failed to start storage node"); +38| if (e_storage_download(node, cid, filepath, progress) != RET_OK) +39| panic("Failed to download file"); +40| e_storage_stop(node); +41| e_storage_destroy(node); +42| } +``` +**Listing 2.** Downloader. + +### Build + +To build the downloader, you will need to modify the `CMakeLists.txt` file in the `easylibstorage` folder so that it builds our new files. You can append the following to the end of the file: + +```cmake +# ---- Tutorial uploader/downloader +add_executable(uploader tutorial/uploader.c) +add_executable(downloader tutorial/downloader.c) + +target_link_libraries(uploader PRIVATE easystorage) +target_link_libraries(downloader PRIVATE easystorage) +target_link_libraries(uploader PRIVATE ${LIBSTORAGE_PATH}) +target_link_libraries(downloader PRIVATE ${LIBSTORAGE_PATH}) +``` + +This will make sure that cmake will include the right files and libraries as it tries to build our files. Now run cmake as before: + +```bash +cmake -B build -S . -DLOGOS_STORAGE_NIM_ROOT=./libstorage +cmake --build build +``` + +And you should end up with two executables under `./build`: `uploader` and `downloader`. + +### Run + +**Upload.** To upload a file, do: + +```bash +./build/uploader ./myfile +``` + +and replace `myfile` with a file you would like to upload. This will print something like: + +```bash +> ./build/uploader ./myfile +... + +Run: downloader spr:CiUIAhIhAkHse4QPQIFlu0xeE9ebpASP946ZRgvUpQEcCsGEc73MEgIDARpJCicAJQgCEiECQex7hA9AgWW7TF4T15ukBI_3jplGC9SlARwKwYRzvcwQkp6IzAYaCwoJBH8AAAGRAiOCGgsKCQTAqFj-kQIjgipGMEQCICMJdw19UmnubC5zeaV2TwSzMRr_sc1U057YwnvFhOkGAiB7020QxcZJ1kL_xrDLpzEnHEgkTVogydnsuR0oevFFbg zDvZRwzm4ABJVP5E6ujcsvZmJjaH76bhaJivirnMhrrhisYbxdGy ./output-file + +Press Enter to exit +``` + +This will start up the node and upload a file to it. The node will then be left running until you press Enter in the terminal. Leave it running and open a new terminal. + +You can now copy the line after `Run: downloader` and paste it into the new terminal to download the file: + +```bash +./build/downloader spr:CiUIAhIhAkHse4QPQIFlu0xeE9ebpASP946ZRgvUpQEcCsGEc73MEgIDARpJCicAJQgCEiECQex7hA9AgWW7TF4T15ukBI_3jplGC9SlARwKwYRzvcwQkp6IzAYaCwoJBH8AAAGRAiOCGgsKCQTAqFj-kQIjgipGMEQCICMJdw19UmnubC5zeaV2TwSzMRr_sc1U057YwnvFhOkGAiB7020QxcZJ1kL_xrDLpzEnHEgkTVogydnsuR0oevFFbg zDvZRwzm4ABJVP5E6ujcsvZmJjaH76bhaJivirnMhrrhisYbxdGy ./output-file +``` + +The command should eventually finish, and you should end up with a file named `./output-file`. You can now test that the two files are indeed the same. The command: + +```bash +cmp ./myfile ./output-file +``` + +should return nothing. + +And there you have it! You have just uploaded and downloaded a file over the Logos Storage network using libstorage. \ No newline at end of file From 15d3c495fad6bfa9e3628adc5541be31570a7097 Mon Sep 17 00:00:00 2001 From: gmega Date: Fri, 6 Feb 2026 09:50:35 -0300 Subject: [PATCH 2/8] some rewording/clarifications --- docs/storage/README.md | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/docs/storage/README.md b/docs/storage/README.md index ca027ea..6ac1653 100644 --- a/docs/storage/README.md +++ b/docs/storage/README.md @@ -9,7 +9,22 @@ anonymous persistence. Check out [our roadmap](https://roadmap.logos.co/storage/ ## Using Logos Storage -Logos Storage can currently be used in two main ways: +Logos Storage can currently be used in the following ways: -1. via the [Logos Storage UI App](https://github.com/logos-co/logos-storage-ui), which runs as a [Logos Module](https://github.com/logos-co/logos-storage-module). You can use the Logos Storage UI App to upload and download files over the Logos Storage network. -2. Programmatically, using [libstorage](https://github.com/logos-co/logos-storage-nim). See our [simplified libstorage tutorial](./libstorage-tutorial.md) to get a feeling for what can be done. +**Logos Storage UI App.** + +* The [Logos Storage UI App](https://github.com/logos-co/logos-storage-ui) is a desktop application which allows one to upload and download files over the Logos Storage network. This is the easiest, simplest way to try out Logos Storage. + +**Programmatically.** + +* **Logos Module API.** The [Logos Storage Module](https://github.com/logos-co/logos-storage-module) is a high-level C++ API which can be used to build applications on top of Logos Storage. It underpins the Logos UI App. + +* **libstorage.** [libstorage](https://github.com/logos-co/logos-storage-nim) is a lower-level C API that goes under the Logos Module API. If you need to construct bindings for a language other than C++, this is what you would use. We have [Go](https://github.com/logos-storage/logos-storage-go), [Rust](https://github.com/nipsysdev/storage-rust-bindings), and higher-level, simple [C](https://github.com/logos-storage/easylibstorage) bindings available. + +## Tutorials + +* [The simplified libstorage tutorial](./libstorage-tutorial.md) shows how to build an app on top of libstorage using the simple C bindings. + +## API Documentation + +* [libstorage API reference](https://github.com/logos-storage/logos-storage-nim/blob/master/library/README.md). From ce403a916ea0599beaf644698289126e7b3b43a4 Mon Sep 17 00:00:00 2001 From: gmega Date: Sat, 28 Feb 2026 11:11:10 -0300 Subject: [PATCH 3/8] complete links to module API tutorial and app skeleton; fix some mistakes --- docs/storage/README.md | 2 + docs/storage/libstorage-tutorial.md | 120 ++++++---------------------- 2 files changed, 28 insertions(+), 94 deletions(-) diff --git a/docs/storage/README.md b/docs/storage/README.md index 6ac1653..008e4d2 100644 --- a/docs/storage/README.md +++ b/docs/storage/README.md @@ -23,6 +23,8 @@ Logos Storage can currently be used in the following ways: ## Tutorials +* [The Logos Module API tutorial](https://github.com/logos-co/logos-storage-module?tab=readme-ov-file#api) shows how to build an app on top of the Logos Module API. It can be coupled with the [Logos Storage App Skeleton](https://github.com/logos-storage/logos-storage-app-skeleton) to build a simple, cli-based app. + * [The simplified libstorage tutorial](./libstorage-tutorial.md) shows how to build an app on top of libstorage using the simple C bindings. ## API Documentation diff --git a/docs/storage/libstorage-tutorial.md b/docs/storage/libstorage-tutorial.md index b43b157..1a7f916 100644 --- a/docs/storage/libstorage-tutorial.md +++ b/docs/storage/libstorage-tutorial.md @@ -1,6 +1,6 @@ # Getting Started with libstorage -In this tutorial, we will build a simple [libstorage-based](https://github.com/logos-storage/logos-storage-nim) C application which allows sharing files over the Logos Storage network. Since libstorage is a low-level API and its main use case are library and not application developers, however, we will use a higher-level C wrapper developed for this tutorial which we refer to as [easylibstorage](https://github.com/logos-storage/easylibstorage). +In this tutorial, we will build a simple [libstorage-based](https://github.com/logos-storage/logos-storage-nim) C application which allows sharing files over the Logos Storage network. Since libstorage is a low-level API and its main use case is library and not application developers, however, we will use a higher-level C wrapper developed for this tutorial which we refer to as [easylibstorage](https://github.com/logos-storage/easylibstorage). This is, in fact, the way libstorage is supposed to be used: as the building block for higher-level libraries or language bindings. Officially, we currently provide [Go bindings](https://github.com/logos-storage/logos-storage-go-bindings) and [Rust bindings](https://github.com/logos-storage/logos-storage-rust-bindings). @@ -91,41 +91,34 @@ The code for the uploader is shown in Listing 1. It first defines some configura 32| char *filepath = argv[1]; 33| 34| STORAGE_NODE node = e_storage_new(cfg); -34| if (node == NULL) panic("Failed to create storage node"); -35| if (e_storage_start(node) != RET_OK) panic("Failed to start storage node"); -36| -37| char *cid = e_storage_upload(node, filepath, progress); -38| if (cid == NULL) panic("Upload failed"); -39| char *spr = e_storage_spr(node); -40| if (spr == NULL) panic("Failed to get node's signed peer record"); -41| -42| printf("Run: downloader %s %s ./output-file\n", spr, cid); -45| -46| printf("\nPress Enter to exit\n"); -47| getchar(); -48| -49| printf("Deleting file (this could take a while)..."); -50| fflush(stdout); -51| if (e_storage_delete(node, cid) != RET_OK) panic("Failed to delete file"); -52| printf("Done\n"); -53| -54| free(cid); -55| free(spr); -56| e_storage_stop(node); -57| e_storage_destroy(node); -58| -59| return 0; -60| } +35| if (node == NULL) panic("Failed to create storage node"); +36| if (e_storage_start(node) != RET_OK) panic("Failed to start storage node"); +37| +38| char *cid = e_storage_upload(node, filepath, progress); +39| if (cid == NULL) panic("Upload failed"); +40| char *spr = e_storage_spr(node); +41| if (spr == NULL) panic("Failed to get node's signed peer record"); +42| +43| printf("Run: downloader %s %s ./output-file\n", spr, cid); +44| free(cid); +45| free(spr); +46| +47| printf("\nPress Enter to exit\n"); +48| getchar(); +49| +50| e_storage_stop(node); +51| e_storage_destroy(node); +52| +53| return 0; +54| } ``` **Listing 1.** Uploader. -It then starts the node (line 37), and uploads the file into the local node (line 37). From that moment on, the file becomes available over the network. The program then gathers some critical pieces of information we will need later: +It then starts the node (line 36), and uploads the file into the local node (line 38). From that moment on, the file becomes available over the network. The program then gathers some critical pieces of information we will need later: * the node's [Signed Peer Record](https://github.com/libp2p/specs/blob/master/RFC/0002-signed-envelopes.md). This a string encoding our node's public key, its network ID, and its connection addresses. It can be used to find the node in the network. * the Content ID ([CID](https://github.com/multiformats/cid)). This is a string that uniquely identifies the file we have just uploaded within the network. -Those get printed to stdout (line 42), and the program them pauses until the user presses Enter (line 46). After that, the program deletes the file from the local node (line 49), and finally stops and destroys the node (lines 54-57). - You should place the listing above in an `uploader.c` file in the `easylibstorage/tutorial` folder you created before. ### Downloader @@ -167,72 +160,11 @@ You should place the listing above in an `uploader.c` file in the `easylibstorag 34| }; 35| 36| STORAGE_NODE node = e_storage_new(cfg); -37| if (e_storage_start(node) != RET_OK) panic("Failed to start storage node"); -38| if (e_storage_download(node, cid, filepath, progress) != RET_OK) -39| panic("Failed to download file"); +37| if (node == NULL) panic("Failed to create storage node"); +38| if (e_storage_start(node) != RET_OK) panic("Failed to start storage node"); +39| if (e_storage_download(node, cid, filepath, progress) != RET_OK) panic("Failed to download file"); 40| e_storage_stop(node); 41| e_storage_destroy(node); 42| } ``` -**Listing 2.** Downloader. - -### Build - -To build the downloader, you will need to modify the `CMakeLists.txt` file in the `easylibstorage` folder so that it builds our new files. You can append the following to the end of the file: - -```cmake -# ---- Tutorial uploader/downloader -add_executable(uploader tutorial/uploader.c) -add_executable(downloader tutorial/downloader.c) - -target_link_libraries(uploader PRIVATE easystorage) -target_link_libraries(downloader PRIVATE easystorage) -target_link_libraries(uploader PRIVATE ${LIBSTORAGE_PATH}) -target_link_libraries(downloader PRIVATE ${LIBSTORAGE_PATH}) -``` - -This will make sure that cmake will include the right files and libraries as it tries to build our files. Now run cmake as before: - -```bash -cmake -B build -S . -DLOGOS_STORAGE_NIM_ROOT=./libstorage -cmake --build build -``` - -And you should end up with two executables under `./build`: `uploader` and `downloader`. - -### Run - -**Upload.** To upload a file, do: - -```bash -./build/uploader ./myfile -``` - -and replace `myfile` with a file you would like to upload. This will print something like: - -```bash -> ./build/uploader ./myfile -... - -Run: downloader spr:CiUIAhIhAkHse4QPQIFlu0xeE9ebpASP946ZRgvUpQEcCsGEc73MEgIDARpJCicAJQgCEiECQex7hA9AgWW7TF4T15ukBI_3jplGC9SlARwKwYRzvcwQkp6IzAYaCwoJBH8AAAGRAiOCGgsKCQTAqFj-kQIjgipGMEQCICMJdw19UmnubC5zeaV2TwSzMRr_sc1U057YwnvFhOkGAiB7020QxcZJ1kL_xrDLpzEnHEgkTVogydnsuR0oevFFbg zDvZRwzm4ABJVP5E6ujcsvZmJjaH76bhaJivirnMhrrhisYbxdGy ./output-file - -Press Enter to exit -``` - -This will start up the node and upload a file to it. The node will then be left running until you press Enter in the terminal. Leave it running and open a new terminal. - -You can now copy the line after `Run: downloader` and paste it into the new terminal to download the file: - -```bash -./build/downloader spr:CiUIAhIhAkHse4QPQIFlu0xeE9ebpASP946ZRgvUpQEcCsGEc73MEgIDARpJCicAJQgCEiECQex7hA9AgWW7TF4T15ukBI_3jplGC9SlARwKwYRzvcwQkp6IzAYaCwoJBH8AAAGRAiOCGgsKCQTAqFj-kQIjgipGMEQCICMJdw19UmnubC5zeaV2TwSzMRr_sc1U057YwnvFhOkGAiB7020QxcZJ1kL_xrDLpzEnHEgkTVogydnsuR0oevFFbg zDvZRwzm4ABJVP5E6ujcsvZmJjaH76bhaJivirnMhrrhisYbxdGy ./output-file -``` - -The command should eventually finish, and you should end up with a file named `./output-file`. You can now test that the two files are indeed the same. The command: - -```bash -cmp ./myfile ./output-file -``` - -should return nothing. - -And there you have it! You have just uploaded and downloaded a file over the Logos Storage network using libstorage. \ No newline at end of file +**Listing 2.** Downloader. \ No newline at end of file From 53d98ca11a548d17b611929c4a32006c1174a4f0 Mon Sep 17 00:00:00 2001 From: gmega Date: Thu, 23 Apr 2026 17:48:00 -0300 Subject: [PATCH 4/8] update storage doc index --- docs/storage/README.md | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/docs/storage/README.md b/docs/storage/README.md index 008e4d2..7f73851 100644 --- a/docs/storage/README.md +++ b/docs/storage/README.md @@ -17,16 +17,6 @@ Logos Storage can currently be used in the following ways: **Programmatically.** -* **Logos Module API.** The [Logos Storage Module](https://github.com/logos-co/logos-storage-module) is a high-level C++ API which can be used to build applications on top of Logos Storage. It underpins the Logos UI App. +* **Logos Module API.** The [Logos Storage Module](https://github.com/logos-co/logos-storage-module) - a high-level C++ API - is the recommended way of using Logos Storage in your app. Make sure to check: [[API Tutorial](https://logos-co.github.io/logos-storage-module/api_tutorial.html) | [API reference](https://logos-co.github.io/logos-storage-module/api_reference.html)] -* **libstorage.** [libstorage](https://github.com/logos-co/logos-storage-nim) is a lower-level C API that goes under the Logos Module API. If you need to construct bindings for a language other than C++, this is what you would use. We have [Go](https://github.com/logos-storage/logos-storage-go), [Rust](https://github.com/nipsysdev/storage-rust-bindings), and higher-level, simple [C](https://github.com/logos-storage/easylibstorage) bindings available. - -## Tutorials - -* [The Logos Module API tutorial](https://github.com/logos-co/logos-storage-module?tab=readme-ov-file#api) shows how to build an app on top of the Logos Module API. It can be coupled with the [Logos Storage App Skeleton](https://github.com/logos-storage/logos-storage-app-skeleton) to build a simple, cli-based app. - -* [The simplified libstorage tutorial](./libstorage-tutorial.md) shows how to build an app on top of libstorage using the simple C bindings. - -## API Documentation - -* [libstorage API reference](https://github.com/logos-storage/logos-storage-nim/blob/master/library/README.md). +* **libstorage.** [libstorage](https://github.com/logos-co/logos-storage-nim) is a lower-level C API that goes under the Logos Module API. If you need to construct bindings for a language other than C++, this is what you would use. We have [Go](https://github.com/logos-storage/logos-storage-go), [Rust](https://github.com/nipsysdev/storage-rust-bindings), and higher-level, simple [C](https://github.com/logos-storage/easylibstorage) bindings available. [[API tutorial](./libstorage-tutorial.md) | [API reference](https://github.com/logos-storage/logos-storage-nim/blob/master/library/README.md)] From 83bfabe9fb630bbaa1e5de1300becbea6df804c4 Mon Sep 17 00:00:00 2001 From: kashepavadan Date: Mon, 4 May 2026 14:47:06 -0400 Subject: [PATCH 5/8] applied formatting to libstorage tutorial --- docs/storage/libstorage-tutorial.md | 408 ++++++++++++++++------------ 1 file changed, 238 insertions(+), 170 deletions(-) diff --git a/docs/storage/libstorage-tutorial.md b/docs/storage/libstorage-tutorial.md index 1a7f916..aef6ac3 100644 --- a/docs/storage/libstorage-tutorial.md +++ b/docs/storage/libstorage-tutorial.md @@ -1,170 +1,238 @@ -# Getting Started with libstorage - -In this tutorial, we will build a simple [libstorage-based](https://github.com/logos-storage/logos-storage-nim) C application which allows sharing files over the Logos Storage network. Since libstorage is a low-level API and its main use case is library and not application developers, however, we will use a higher-level C wrapper developed for this tutorial which we refer to as [easylibstorage](https://github.com/logos-storage/easylibstorage). - -This is, in fact, the way libstorage is supposed to be used: as the building block for higher-level libraries or language bindings. Officially, we currently provide [Go bindings](https://github.com/logos-storage/logos-storage-go-bindings) and [Rust bindings](https://github.com/logos-storage/logos-storage-rust-bindings). - -# Building -To build easylibstorage, you'll need: - -- git -- CMake 3.14+ -- a C11 compiler -- libstorage (https://github.com/logos-storage/logos-storage-nim). To make this tutorial simpler, we suggest using the script bundled with easylibstorage (Step 2 below) to download prebuilt binaries instead of trying to build it from scratch. - -**Step 1.** Clone the [easylibstorage repository](https://github.com/logos-storage/easylibstorage): - -```bash -git clone https://github.com/logos-storage/easylibstorage.git -cd easylibstorage -``` - -**Step 2.** Download prebuilt binaries for libstorage: - -```bash -./scripts/fetch-libstorage.sh -``` - -Ensure that the script completed successfully. - -**Step 3.** Build easylibstorage: - -```bash -cmake -B build -S . -DLOGOS_STORAGE_NIM_ROOT=./libstorage -cmake --build build -``` - -# The Application - -Now that we have a working build for easylibstorage, we can focus on the application. Our application will be composed of two simple CLI apps - a file uploader and a file downloader. Once we are done, you will be able to use the application as follows: - -```bash -./uploader ./myfile -./downloader ./myfile-copy -``` - -The meaning of `` and `` will be explained as we go. - -First, create a `tutorial` folder under `easylibstorage`: - -```bash -cd easylibstorage # or wherever it was that you cloned your repo -mkdir tutorial -``` - -### Uploader - -The code for the uploader is shown in Listing 1. It first defines some configuration options for the storage node (lines 25-29), including the discovery listen port (UDP 9090), and the directory where the node will store its data (`./uploader-data`). It sets `nat` to `none` as we will be running a local node, and the bootstrap node to `NULL` as we will be creating a network from scratch. - -```c -01| /* uploader.c: makes a local file available to the Logos -02| Storage network. */ -03| -04| #include -05| #include -06| #include "easystorage.h" -07| -08| void panic(const char *msg) { -09| fprintf(stderr, "Panic: %s\n", msg); -10| exit(1); -11| } -12| -13| void progress(int total, int complete, int status) { -14| printf("\r %d / %d bytes", complete, total); -15| fflush(stdout); -16| } -17| -18| int main(int argc, char *argv[]) { -19| if (argc < 2) { -20| printf("Usage: %s \n", argv[0]); -21| exit(1); -22| } -23| -24| node_config cfg = { -25| .disc_port = 9090, -26| .data_dir = "./uploader-data", -27| .log_level = "INFO", -28| .bootstrap_node = NULL, -29| .nat = "none", -30| }; -31| -32| char *filepath = argv[1]; -33| -34| STORAGE_NODE node = e_storage_new(cfg); -35| if (node == NULL) panic("Failed to create storage node"); -36| if (e_storage_start(node) != RET_OK) panic("Failed to start storage node"); -37| -38| char *cid = e_storage_upload(node, filepath, progress); -39| if (cid == NULL) panic("Upload failed"); -40| char *spr = e_storage_spr(node); -41| if (spr == NULL) panic("Failed to get node's signed peer record"); -42| -43| printf("Run: downloader %s %s ./output-file\n", spr, cid); -44| free(cid); -45| free(spr); -46| -47| printf("\nPress Enter to exit\n"); -48| getchar(); -49| -50| e_storage_stop(node); -51| e_storage_destroy(node); -52| -53| return 0; -54| } -``` -**Listing 1.** Uploader. - -It then starts the node (line 36), and uploads the file into the local node (line 38). From that moment on, the file becomes available over the network. The program then gathers some critical pieces of information we will need later: - -* the node's [Signed Peer Record](https://github.com/libp2p/specs/blob/master/RFC/0002-signed-envelopes.md). This a string encoding our node's public key, its network ID, and its connection addresses. It can be used to find the node in the network. -* the Content ID ([CID](https://github.com/multiformats/cid)). This is a string that uniquely identifies the file we have just uploaded within the network. - -You should place the listing above in an `uploader.c` file in the `easylibstorage/tutorial` folder you created before. - -### Downloader - -```c -01| /* downloader.c: Download files from a Logos Storage node into the local disk. -02| */ -03| #include -04| #include -05| #include "easystorage.h" -06| -07| void panic(const char *msg) { -08| fprintf(stderr, "Panic: %s\n", msg); -09| exit(1); -10| } -11| -12| void progress(int total, int complete, int status) { -13| printf("\r %d / %d bytes", complete, total); -14| fflush(stdout); -15| } -16| -17| int main(int argc, char *argv[]) { -18| if (argc < 4) { -19| printf("Usage: %s BOOTSTRAP_SPR CID \n", argv[0]); -20| exit(1); -21| } -22| -23| char *spr = argv[1]; -24| char *cid = argv[2]; -25| char *filepath = argv[3]; -26| -27| node_config cfg = { -28| .api_port = 8081, -29| .disc_port = 9091, -30| .data_dir = "./downloader-data", -31| .log_level = "INFO", -32| .bootstrap_node = spr, -33| .nat = "none", -34| }; -35| -36| STORAGE_NODE node = e_storage_new(cfg); -37| if (node == NULL) panic("Failed to create storage node"); -38| if (e_storage_start(node) != RET_OK) panic("Failed to start storage node"); -39| if (e_storage_download(node, cid, filepath, progress) != RET_OK) panic("Failed to download file"); -40| e_storage_stop(node); -41| e_storage_destroy(node); -42| } -``` -**Listing 2.** Downloader. \ No newline at end of file +--- +title: Share files over the Logos Storage network using libstorage +doc_type: procedure +product: storage +topics: [libstorage, file-sharing, c, easylibstorage] +steps_layout: sectioned +authors: +owner: logos +doc_version: 1 +slug: libstorage-share-files +--- + +# Share files over the Logos Storage network using libstorage + +#### Get started building a file uploader and downloader with the easylibstorage C wrapper. + +This tutorial shows you how to use libstorage — a low-level C API — to upload and download files over the Logos Storage network. Because libstorage is designed as a building block for higher-level libraries, this tutorial uses [easylibstorage](https://github.com/logos-storage/easylibstorage), a higher-level C wrapper developed to simplify the API. + +By the end of this tutorial, you will have two CLI applications: one that uploads a local file to the network and one that downloads it by content ID. + +**Before you start**, ensure the following tools are installed: + +- `git` +- CMake 3.14 or later +- A C11-compatible compiler + +## What to expect + +- You will be able to share any local file over the Logos Storage network from a self-hosted node. +- You will be able to retrieve a shared file from any machine using its SPR and CID strings. +- You will be able to verify file integrity after a network round-trip. + +## Step 1: Clone and build easylibstorage locally + +Clone the easylibstorage repository and fetch prebuilt libstorage binaries using the bundled script. + +> **Note** +> +> Use the bundled fetch script rather than building libstorage from source — it is the simplest way to get working binaries for this tutorial. + +1. Clone the repository and enter the project directory: + + ```bash + git clone https://github.com/logos-storage/easylibstorage.git + cd easylibstorage + ``` + +1. Download the prebuilt libstorage binaries: + + ```bash + ./scripts/fetch-libstorage.sh + ``` + + Confirm the script completes without errors before continuing. + +1. Build easylibstorage: + + ```bash + cmake -B build -S . -DLOGOS_STORAGE_NIM_ROOT=./libstorage + cmake --build build + ``` + +## Step 2: Create the tutorial directory and source files + +Create a `tutorial` folder inside the cloned repository and add the uploader and downloader source files. + +1. Create the tutorial directory: + + ```bash + mkdir tutorial + ``` + +1. Create `tutorial/uploader.c` with the following content: + + ```c + /* uploader.c: makes a local file available to the Logos Storage network. */ + + #include + #include + #include "easystorage.h" + + void panic(const char *msg) { + fprintf(stderr, "Panic: %s\n", msg); + exit(1); + } + + void progress(int total, int complete, int status) { + printf("\r %d / %d bytes", complete, total); + fflush(stdout); + } + + int main(int argc, char *argv[]) { + if (argc < 2) { + printf("Usage: %s \n", argv[0]); + exit(1); + } + + node_config cfg = { + .disc_port = 9090, + .data_dir = "./uploader-data", + .log_level = "INFO", + .bootstrap_node = NULL, + .nat = "none", + }; + + char *filepath = argv[1]; + + STORAGE_NODE node = e_storage_new(cfg); + if (node == NULL) panic("Failed to create storage node"); + if (e_storage_start(node) != RET_OK) panic("Failed to start storage node"); + + char *cid = e_storage_upload(node, filepath, progress); + if (cid == NULL) panic("Upload failed"); + char *spr = e_storage_spr(node); + if (spr == NULL) panic("Failed to get node's signed peer record"); + + printf("Run: downloader %s %s ./output-file\n", spr, cid); + free(cid); + free(spr); + + printf("\nPress Enter to exit\n"); + getchar(); + + e_storage_stop(node); + e_storage_destroy(node); + + return 0; + } + ``` + + The configuration sets the discovery port to UDP 9090, stores node data in `./uploader-data`, and sets `nat` to `none` for local-only operation. + + After upload, it prints two values you will need for the download step: + - The node's **Signed Peer Record (SPR)** — encodes the node's public key, network ID, and connection addresses. + - The **Content ID (CID)** — uniquely identifies the uploaded file on the network. + +1. Create `tutorial/downloader.c` with the following content: + + ```c + /* downloader.c: Download files from a Logos Storage node into the local disk. */ + + #include + #include + #include "easystorage.h" + + void panic(const char *msg) { + fprintf(stderr, "Panic: %s\n", msg); + exit(1); + } + + void progress(int total, int complete, int status) { + printf("\r %d / %d bytes", complete, total); + fflush(stdout); + } + + int main(int argc, char *argv[]) { + if (argc < 4) { + printf("Usage: %s BOOTSTRAP_SPR CID \n", argv[0]); + exit(1); + } + + char *spr = argv[1]; + char *cid = argv[2]; + char *filepath = argv[3]; + + node_config cfg = { + .api_port = 8081, + .disc_port = 9091, + .data_dir = "./downloader-data", + .log_level = "INFO", + .bootstrap_node = spr, + .nat = "none", + }; + + STORAGE_NODE node = e_storage_new(cfg); + if (node == NULL) panic("Failed to create storage node"); + if (e_storage_start(node) != RET_OK) panic("Failed to start storage node"); + if (e_storage_download(node, cid, filepath, progress) != RET_OK) panic("Failed to download file"); + e_storage_stop(node); + e_storage_destroy(node); + } + ``` + +## Step 3: Update the build configuration and compile + +Add the uploader and downloader targets to `CMakeLists.txt` and rebuild. + +1. Append the following to the end of `CMakeLists.txt` in the `easylibstorage` root: + + ```cmake + # Tutorial uploader/downloader + add_executable(uploader tutorial/uploader.c) + add_executable(downloader tutorial/downloader.c) + + target_link_libraries(uploader PRIVATE easystorage) + target_link_libraries(downloader PRIVATE easystorage) + target_link_libraries(uploader PRIVATE ${LIBSTORAGE_PATH}) + target_link_libraries(downloader PRIVATE ${LIBSTORAGE_PATH}) + ``` + +1. Rebuild the project: + + ```bash + cmake -B build -S . -DLOGOS_STORAGE_NIM_ROOT=./libstorage + cmake --build build + ``` + + After the build completes, the `uploader` and `downloader` executables appear under `./build/`. + +## Step 4: Upload and download a file with Logos Storage + +Run the uploader and then use its output to download the file in a second terminal. + +1. Upload a local file: + + ```bash + ./build/uploader ./myfile + ``` + + The program outputs a `Run:` line containing the SPR and CID strings, then waits for input. Leave this terminal open. + +1. Open a second terminal and paste the `Run:` command from the uploader output. It will look similar to: + + ```bash + ./build/downloader spr: ./output-file + ``` + + Wait for the command to finish. The file is saved to `./output-file`. + +1. Verify the downloaded file is identical to the original: + + ```bash + cmp ./myfile ./output-file + ``` + + No output means the files match. + +1. Return to the first terminal and press **Enter** to shut down the uploader node. From 549e4019cf46d1602782a227f72bb07ecbd7b8d8 Mon Sep 17 00:00:00 2001 From: Daniel Kashepava Date: Mon, 11 May 2026 09:30:10 -0400 Subject: [PATCH 6/8] Apply suggestion from @weboko README Co-authored-by: Sasha <118575614+weboko@users.noreply.github.com> --- docs/storage/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/storage/README.md b/docs/storage/README.md index 7f73851..5cd4cf4 100644 --- a/docs/storage/README.md +++ b/docs/storage/README.md @@ -19,4 +19,4 @@ Logos Storage can currently be used in the following ways: * **Logos Module API.** The [Logos Storage Module](https://github.com/logos-co/logos-storage-module) - a high-level C++ API - is the recommended way of using Logos Storage in your app. Make sure to check: [[API Tutorial](https://logos-co.github.io/logos-storage-module/api_tutorial.html) | [API reference](https://logos-co.github.io/logos-storage-module/api_reference.html)] -* **libstorage.** [libstorage](https://github.com/logos-co/logos-storage-nim) is a lower-level C API that goes under the Logos Module API. If you need to construct bindings for a language other than C++, this is what you would use. We have [Go](https://github.com/logos-storage/logos-storage-go), [Rust](https://github.com/nipsysdev/storage-rust-bindings), and higher-level, simple [C](https://github.com/logos-storage/easylibstorage) bindings available. [[API tutorial](./libstorage-tutorial.md) | [API reference](https://github.com/logos-storage/logos-storage-nim/blob/master/library/README.md)] +* **libstorage.** [libstorage](https://github.com/logos-storage/logos-storage-nim) is a lower-level C API that goes under the Logos Module API. If you need to construct bindings for a language other than C++, this is what you would use. We have [Go](https://github.com/logos-storage/logos-storage-go), [Rust](https://github.com/nipsysdev/storage-rust-bindings), and higher-level, simple [C](https://github.com/logos-storage/easylibstorage) bindings available. [[API tutorial](./libstorage-tutorial.md) | [API reference](https://github.com/logos-storage/logos-storage-nim/blob/master/library/README.md)] From a3915b4e899fc29a122c2fe6894f8993cd0fc209 Mon Sep 17 00:00:00 2001 From: kashepavadan Date: Tue, 19 May 2026 15:12:20 -0400 Subject: [PATCH 7/8] changed docs to module --- docs/storage/libstorage-tutorial.md | 320 +++++++++++++--------------- 1 file changed, 146 insertions(+), 174 deletions(-) diff --git a/docs/storage/libstorage-tutorial.md b/docs/storage/libstorage-tutorial.md index aef6ac3..683173b 100644 --- a/docs/storage/libstorage-tutorial.md +++ b/docs/storage/libstorage-tutorial.md @@ -1,238 +1,210 @@ --- -title: Share files over the Logos Storage network using libstorage +title: Build a CLI app with Logos Storage doc_type: procedure product: storage -topics: [libstorage, file-sharing, c, easylibstorage] +topics: [] steps_layout: sectioned authors: owner: logos doc_version: 1 -slug: libstorage-share-files +slug: libstorage-tutorial --- -# Share files over the Logos Storage network using libstorage +# Build a CLI app with Logos Storage -#### Get started building a file uploader and downloader with the easylibstorage C wrapper. +#### Get started building a CLI application that transfers files over the Logos Storage network. -This tutorial shows you how to use libstorage — a low-level C API — to upload and download files over the Logos Storage network. Because libstorage is designed as a building block for higher-level libraries, this tutorial uses [easylibstorage](https://github.com/logos-storage/easylibstorage), a higher-level C wrapper developed to simplify the API. +This tutorial walks you through building a simple CLI application that uploads and downloads files over the Logos Storage network using the [Logos Storage Module API](https://logos-co.github.io/logos-storage-module/api_reference.html). It is intended for developers who are setting up a new application using the skeleton project and working through the module lifecycle for the first time. -By the end of this tutorial, you will have two CLI applications: one that uploads a local file to the network and one that downloads it by content ID. +The tutorial uses the [Logos Storage App Skeleton](https://github.com/logos-storage/logos-storage-app-skeleton), which provides a ready-made entry point at `app_main` that uses the `LogosModules` object to access the API. The skeleton also provides a set of Qt-compatible synchronization utilities. -**Before you start**, ensure the following tools are installed: +**Before you start**, make sure you have the following: -- `git` -- CMake 3.14 or later -- A C11-compatible compiler +- Nix package manager +- Git ## What to expect -- You will be able to share any local file over the Logos Storage network from a self-hosted node. -- You will be able to retrieve a shared file from any machine using its SPR and CID strings. -- You will be able to verify file integrity after a network round-trip. +- You can initialize, start, and cleanly shut down the storage module within your application. +- You can upload a file to the network and receive a Content Identifier (CID) that uniquely identifies it. +- You can download a file from the network using a CID and a Signed Peer Record (SPR). -## Step 1: Clone and build easylibstorage locally +## Step 1: Build the skeleton app -Clone the easylibstorage repository and fetch prebuilt libstorage binaries using the bundled script. +Clone the skeleton repository and compile the binary so you have a working entry point before adding any storage logic. -> **Note** -> -> Use the bundled fetch script rather than building libstorage from source — it is the simplest way to get working binaries for this tutorial. - -1. Clone the repository and enter the project directory: +1. Clone the skeleton repository: ```bash - git clone https://github.com/logos-storage/easylibstorage.git - cd easylibstorage + git clone https://github.com/logos-storage/logos-storage-app-skeleton.git + cd logos-storage-app-skeleton ``` -1. Download the prebuilt libstorage binaries: +1. Build with Nix: ```bash - ./scripts/fetch-libstorage.sh + nix build ``` - Confirm the script completes without errors before continuing. - -1. Build easylibstorage: +1. Confirm the compiled binary is available at `./result/bin/storage-app`. - ```bash - cmake -B build -S . -DLOGOS_STORAGE_NIM_ROOT=./libstorage - cmake --build build - ``` +## Step 2: Initialize the module -## Step 2: Create the tutorial directory and source files +Call `init()` with your configuration once at startup, passing a JSON configuration string. See the [API Reference]((https://logos-co.github.io/logos-storage-module/api_reference.html)) for all available options. -Create a `tutorial` folder inside the cloned repository and add the uploader and downloader source files. - -1. Create the tutorial directory: - - ```bash - mkdir tutorial + ```cpp + const QString jsonConfig = "{}"; + bool result = m_logos->storage_module.init(jsonConfig); ``` -1. Create `tutorial/uploader.c` with the following content: - - ```c - /* uploader.c: makes a local file available to the Logos Storage network. */ - - #include - #include - #include "easystorage.h" +> **Caution** +> +> Do not call `init()` more than once per instance unless you call `destroy()` first. - void panic(const char *msg) { - fprintf(stderr, "Panic: %s\n", msg); - exit(1); - } +## Step 3: Start the node - void progress(int total, int complete, int status) { - printf("\r %d / %d bytes", complete, total); - fflush(stdout); - } +Subscribe to the `storageStart` event and call `start()` afterward, to be able to detect failures. - int main(int argc, char *argv[]) { - if (argc < 2) { - printf("Usage: %s \n", argv[0]); - exit(1); + ```cpp + m_logos->storage_module.on("storageStart", [this](const QVariantList& data) { + bool success = data[0].toBool(); + if (!success) { + QString error = data[1].toString(); + // Handle error } + }); - node_config cfg = { - .disc_port = 9090, - .data_dir = "./uploader-data", - .log_level = "INFO", - .bootstrap_node = NULL, - .nat = "none", - }; - - char *filepath = argv[1]; - - STORAGE_NODE node = e_storage_new(cfg); - if (node == NULL) panic("Failed to create storage node"); - if (e_storage_start(node) != RET_OK) panic("Failed to start storage node"); - - char *cid = e_storage_upload(node, filepath, progress); - if (cid == NULL) panic("Upload failed"); - char *spr = e_storage_spr(node); - if (spr == NULL) panic("Failed to get node's signed peer record"); - - printf("Run: downloader %s %s ./output-file\n", spr, cid); - free(cid); - free(spr); - - printf("\nPress Enter to exit\n"); - getchar(); - - e_storage_stop(node); - e_storage_destroy(node); - - return 0; - } + bool result = m_logos->storage_module.start(); ``` - The configuration sets the discovery port to UDP 9090, stores node data in `./uploader-data`, and sets `nat` to `none` for local-only operation. +## Step 4: Upload a file - After upload, it prints two values you will need for the download step: - - The node's **Signed Peer Record (SPR)** — encodes the node's public key, network ID, and connection addresses. - - The **Content ID (CID)** — uniquely identifies the uploaded file on the network. +The Storage Module allows for two upload approaches. Choose `uploadUrl` for straightforward cases. Use the streaming API when you need fine-grained control over how data is sent. -1. Create `tutorial/downloader.c` with the following content: +### Upload with `uploadUrl` - ```c - /* downloader.c: Download files from a Logos Storage node into the local disk. */ +The simplest way to upload files is to subscribe to the upload events, then call `uploadUrl()` with the path to your file. The network returns a Content Identifier (CID) on success. - #include - #include - #include "easystorage.h" +1. Subscribe to the `storageUploadDone` and `storageUploadProgress` events: - void panic(const char *msg) { - fprintf(stderr, "Panic: %s\n", msg); - exit(1); - } + ```cpp + //m_logos is the LogosModules object, used for API calls + m_logos->storage_module.on("storageUploadDone", [this](const QVariantList& data) { + bool success = data[0].toBool(); + QString sessionId = data[1].toString(); + QString cidOrError = data[2].toString(); - void progress(int total, int complete, int status) { - printf("\r %d / %d bytes", complete, total); - fflush(stdout); - } - - int main(int argc, char *argv[]) { - if (argc < 4) { - printf("Usage: %s BOOTSTRAP_SPR CID \n", argv[0]); - exit(1); + if (success) { + qDebug() << "Upload complete. CID:" << cidOrError; + } else { + qDebug() << "Upload failed:" << cidOrError; } - - char *spr = argv[1]; - char *cid = argv[2]; - char *filepath = argv[3]; - - node_config cfg = { - .api_port = 8081, - .disc_port = 9091, - .data_dir = "./downloader-data", - .log_level = "INFO", - .bootstrap_node = spr, - .nat = "none", - }; - - STORAGE_NODE node = e_storage_new(cfg); - if (node == NULL) panic("Failed to create storage node"); - if (e_storage_start(node) != RET_OK) panic("Failed to start storage node"); - if (e_storage_download(node, cid, filepath, progress) != RET_OK) panic("Failed to download file"); - e_storage_stop(node); - e_storage_destroy(node); - } + }); + + m_logos->storage_module.on("storageUploadProgress", [this](const QVariantList& data) { + bool success = data[0].toBool(); + QString sessionId = data[1].toString(); + int bytes = data[2].toInt(); + qDebug() << "Uploaded" << bytes << "bytes"; + }); ``` -## Step 3: Update the build configuration and compile - -Add the uploader and downloader targets to `CMakeLists.txt` and rebuild. - -1. Append the following to the end of `CMakeLists.txt` in the `easylibstorage` root: - - ```cmake - # Tutorial uploader/downloader - add_executable(uploader tutorial/uploader.c) - add_executable(downloader tutorial/downloader.c) +1. Call `uploadUrl()` with the local file path: - target_link_libraries(uploader PRIVATE easystorage) - target_link_libraries(downloader PRIVATE easystorage) - target_link_libraries(uploader PRIVATE ${LIBSTORAGE_PATH}) - target_link_libraries(downloader PRIVATE ${LIBSTORAGE_PATH}) + ```cpp + QUrl fileUrl = QUrl::fromLocalFile("/path/to/myfile"); + LogosResult result = m_logos->storage_module.uploadUrl(fileUrl); ``` -1. Rebuild the project: - - ```bash - cmake -B build -S . -DLOGOS_STORAGE_NIM_ROOT=./libstorage - cmake --build build +### Upload with the streaming API + +Use the streaming upload API for chunk-level control. + +1. Initialize the session: + ```cpp + LogosResult result = m_logos->storage_module.uploadInit(filename); + QString sessionId = result.getValue(); + ``` + +1. . Upload chunks: + ```cpp + QFile file(filepath); + file.open(QIODevice::ReadOnly); + int chunkSize = 1024 * 64; + while (!file.atEnd()) { + QByteArray chunk = file.read(chunkSize); + result = m_logos->storage_module.uploadChunk(sessionId, chunk); + if (!result.success) { + // Handle error + break; + } + } + ``` + +1. Finalize + ```cpp + result = m_logos->storage_module.uploadFinalize(sessionId); + if (result.success) { + QString cid = result.getValue(); + qDebug() << "CID:" << cid; + } + ``` + +## Step 5: Download a file + +To download content, you need the CID returned during upload and the Signed Peer Record (SPR) of a node that holds the content. + +1. Subscribe to the `storageDownloadDone` and `storageDownloadProgress` events: + + ```cpp + //m_logos is the LogosModules object, used for API calls + m_logos->storage_module.on("storageDownloadDone", [this](const QVariantList& data) { + bool success = data[0].toBool(); + QString message = data[1].toString(); + if (success) { + qDebug() << "Download complete"; + } else { + qDebug() << "Download failed:" << message; + } + }); + + m_logos->storage_module.on("storageDownloadProgress", [this](const QVariantList& data) { + bool success = data[0].toBool(); + QString sessionId = data[1].toString(); + int size = data[2].toInt(); + qDebug() << "Downloaded" << size << "bytes"; + }); ``` - After the build completes, the `uploader` and `downloader` executables appear under `./build/`. - -## Step 4: Upload and download a file with Logos Storage +1. Call `downloadToUrl()` with the CID and the local destination path: -Run the uploader and then use its output to download the file in a second terminal. - -1. Upload a local file: - - ```bash - ./build/uploader ./myfile + ```cpp + QUrl destination = QUrl::fromLocalFile("/path/to/output"); + LogosResult result = m_logos->storage_module.downloadToUrl(cid, destination /*, local = false*/); ``` - The program outputs a `Run:` line containing the SPR and CID strings, then waits for input. Leave this terminal open. + - Set the `local` (third) parameter of `downloadToUrl` to `true` to retrieve only locally-cached data. + - Leave `local` as `false` (default) to fetch from the network. -1. Open a second terminal and paste the `Run:` command from the uploader output. It will look similar to: +## Step 6: Stop and clean up - ```bash - ./build/downloader spr: ./output-file - ``` +Always stop the node before destroying resources to avoid leaving sessions open. To do so, call `stop()` and wait for the `storageStop` event, then call `destroy()`: - Wait for the command to finish. The file is saved to `./output-file`. + ```cpp + LogosResult result = m_logos->storage_module.stop(); + // Wait for storageStop event... + result = m_logos->storage_module.destroy(); + ``` -1. Verify the downloaded file is identical to the original: +## Frequently asked questions - ```bash - cmp ./myfile ./output-file - ``` +### Can I run the storage module without a UI? - No output means the files match. +Yes. The storage module supports headless mode, which lets you run it from the command line: -1. Return to the first terminal and press **Enter** to shut down the uploader node. +```bash +./logos/bin/logoscore -m ./modules --load-modules storage_module \ + -c "storage_module.init(@config.json)" \ + -c "storage_module.start()" \ + -c "storage_module.importFiles(/path/to/files)" +``` \ No newline at end of file From a5c1e4e5fe02b6a8cf23bd035e9270ab40704e95 Mon Sep 17 00:00:00 2001 From: kashepavadan Date: Tue, 19 May 2026 15:17:38 -0400 Subject: [PATCH 8/8] add version --- docs/storage/libstorage-tutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/storage/libstorage-tutorial.md b/docs/storage/libstorage-tutorial.md index 683173b..0472d63 100644 --- a/docs/storage/libstorage-tutorial.md +++ b/docs/storage/libstorage-tutorial.md @@ -14,7 +14,7 @@ slug: libstorage-tutorial #### Get started building a CLI application that transfers files over the Logos Storage network. -This tutorial walks you through building a simple CLI application that uploads and downloads files over the Logos Storage network using the [Logos Storage Module API](https://logos-co.github.io/logos-storage-module/api_reference.html). It is intended for developers who are setting up a new application using the skeleton project and working through the module lifecycle for the first time. +This tutorial walks you through building a simple CLI application that uploads and downloads files over the Logos Storage network using the [Logos Storage Module API v0.3.2](https://logos-co.github.io/logos-storage-module/api_reference.html). It is intended for developers who are setting up a new application using the skeleton project and working through the module lifecycle for the first time. The tutorial uses the [Logos Storage App Skeleton](https://github.com/logos-storage/logos-storage-app-skeleton), which provides a ready-made entry point at `app_main` that uses the `LogosModules` object to access the API. The skeleton also provides a set of Qt-compatible synchronization utilities.