From 3608e95a6e81018150590a4c6fbe6e8351cac00a Mon Sep 17 00:00:00 2001
From: STEVAN Antoine <antoine.stevan@isae-supaero.fr>
Date: Thu, 1 Aug 2024 09:17:11 +0000
Subject: [PATCH] refactor repo architecture (dragoon/komodo!161)

## changelog
- `src/main.rs` has been moved to a new crate: `bins/saclin` which stands for **S**emi-**A**VID **CLI** in **N**ushell
- dependencies of `komodo` have been fixed
- Nushell and Rust tests have been split in the Makefile: by default, only Rust tests will run locally and Nushell tests and examples can be run manually if desired. The CI will still run everything.
- the README has been updated
- test images have been moved to `assets/`
- the majority of the old `./nu-utils/` module have been moved to internals of `./benchmarks/` and imports have been fixed
- `cargo.nu` has been moved to `./bins/` and a new `./bins/README.md` mentions it
- `./bins/saclin/` has been created and should be a self-contained Rust crate + Nushell module
---
 .env.nu                                       |   8 +-
 Cargo.toml                                    |   6 +-
 Makefile                                      |  17 ++-
 README.md                                     |  41 +++---
 {tests => assets}/dragoon_133x133.png         | Bin
 {tests => assets}/dragoon_32x32.png           | Bin
 benchmarks/nu-lib/commit.nu                   |   8 +-
 benchmarks/nu-lib/fec/plot.nu                 |   8 +-
 benchmarks/nu-lib/fec/run.nu                  |   4 +-
 benchmarks/nu-lib/linalg.nu                   |   8 +-
 benchmarks/nu-lib/recoding.nu                 |  10 +-
 benchmarks/nu-lib/setup.nu                    |   8 +-
 .../nu-lib/utils}/formats.nu                  |   0
 {nu-utils => benchmarks/nu-lib/utils}/fs.nu   |   0
 {nu-utils => benchmarks/nu-lib/utils}/log.nu  |   0
 {nu-utils => benchmarks/nu-lib/utils}/math.nu |   0
 {nu-utils => benchmarks/nu-lib/utils}/mod.nu  |   6 +-
 .../nu-lib/utils}/parse.nu                    |   0
 {nu-utils => benchmarks/nu-lib/utils}/plot.nu |   0
 bins/README.md                                |   7 +
 {nu-utils => bins}/cargo.nu                   |  17 ++-
 bins/saclin/Cargo.toml                        |  19 +++
 bins/saclin/README.md                         |   1 +
 {nu-utils => bins/saclin}/binary.nu           |   0
 bins/saclin/examples/cli.nu                   |  35 +++++
 komodo.nu => bins/saclin/mod.nu               | 106 +++++++-------
 {src => bins/saclin/src}/main.rs              |   0
 {tests => bins/saclin/tests}/binary.nu        |   2 +-
 {tests => bins/saclin/tests}/cli.nu           |  32 ++---
 examples/cli.nu                               |  35 -----
 nu-utils/color.nu                             | 131 ------------------
 nu-utils/error.nu                             |  15 --
 src/fec.rs                                    |   2 +-
 src/field.rs                                  |   2 +-
 src/semi_avid.rs                              |   2 +-
 tests/color.nu                                |  64 ---------
 36 files changed, 210 insertions(+), 384 deletions(-)
 rename {tests => assets}/dragoon_133x133.png (100%)
 rename {tests => assets}/dragoon_32x32.png (100%)
 rename {nu-utils => benchmarks/nu-lib/utils}/formats.nu (100%)
 rename {nu-utils => benchmarks/nu-lib/utils}/fs.nu (100%)
 rename {nu-utils => benchmarks/nu-lib/utils}/log.nu (100%)
 rename {nu-utils => benchmarks/nu-lib/utils}/math.nu (100%)
 rename {nu-utils => benchmarks/nu-lib/utils}/mod.nu (58%)
 rename {nu-utils => benchmarks/nu-lib/utils}/parse.nu (100%)
 rename {nu-utils => benchmarks/nu-lib/utils}/plot.nu (100%)
 create mode 100644 bins/README.md
 rename {nu-utils => bins}/cargo.nu (81%)
 create mode 100644 bins/saclin/Cargo.toml
 create mode 100644 bins/saclin/README.md
 rename {nu-utils => bins/saclin}/binary.nu (100%)
 create mode 100755 bins/saclin/examples/cli.nu
 rename komodo.nu => bins/saclin/mod.nu (82%)
 rename {src => bins/saclin/src}/main.rs (100%)
 rename {tests => bins/saclin/tests}/binary.nu (88%)
 rename {tests => bins/saclin/tests}/cli.nu (89%)
 delete mode 100755 examples/cli.nu
 delete mode 100644 nu-utils/color.nu
 delete mode 100644 nu-utils/error.nu
 delete mode 100644 tests/color.nu

diff --git a/.env.nu b/.env.nu
index 300f5abf..2b9488c6 100644
--- a/.env.nu
+++ b/.env.nu
@@ -1,6 +1,4 @@
 const MODULES = [
-    "nu-utils/math.nu",
-    "nu-utils/formats.nu",
     "benchmarks/",
 ]
 
@@ -9,8 +7,4 @@ def log-load [m: string] {
 }
 
 log-load $MODULES.0
-use $MODULES.0 *
-log-load $MODULES.1
-use $MODULES.1 *
-log-load $MODULES.2
-use $MODULES.2
+use $MODULES.0
diff --git a/Cargo.toml b/Cargo.toml
index 10ede538..e3fb6b31 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -16,15 +16,15 @@ rs_merkle = "1.4.1"
 thiserror = "1.0.50"
 tracing = "0.1.40"
 tracing-subscriber = "0.3.17"
-# `main.rs` dependencies
-ark-bls12-381 = "0.4.0"
-rand = "0.8.5"
 
 [workspace]
 members = [
     "benchmarks",
     "bins/rank",
+    "bins/saclin",
 ]
 
 [dev-dependencies]
+ark-bls12-381 = "0.4.0"
 itertools = "0.13.0"
+rand = "0.8.5"
diff --git a/Makefile b/Makefile
index bb44f39c..6f2a5d0e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
-.PHONY: fmt fmt-check check clippy test example show build-examples
+.PHONY: fmt fmt-check check clippy test-rs test-nu test example show build-examples
 
-DEFAULT_GOAL: fmt-check check clippy test
+DEFAULT_GOAL: fmt-check check clippy test-rs
 
 fmt-check:
 	cargo fmt --all -- --check
@@ -14,15 +14,18 @@ check:
 clippy:
 	cargo clippy --workspace --all-targets -- -D warnings
 
-test:
+test-rs:
 	cargo test --workspace --verbose
 	cargo test --examples --verbose
-	nu tests/cli.nu
-	nu tests/binary.nu
-	nu tests/color.nu
+
+test-nu:
+	nu bins/saclin/tests/cli.nu
+	nu bins/saclin/tests/binary.nu
+
+test: test-rs test-nu
 
 example:
-	nu examples/cli.nu
+	nu bins/saclin/examples/cli.nu
 
 show:
 	rustup --version
diff --git a/README.md b/README.md
index 010f179d..ad90d70b 100644
--- a/README.md
+++ b/README.md
@@ -1,33 +1,32 @@
 # Komodo: Cryptographically-proven Erasure Coding
 
-## Usage
-Komodo can either be used as a library or as a binary application.
-
 ## the library
-see `cargo doc`
+see `cargo doc` or [the library itself](src/)
 
-## the binary application
-below is an example of how to use the binary application with Nushell:
-```bash
-./examples/cli.nu
+## the tests
+```shell
+make
+```
+or
+```shell
+make check clippy test-rs
 ```
 
-> **Note**  
-> requires Nushell 0.95.0 or later
+### some extra tests
+this project defines some tests written in [Nushell](https://www.nushell.sh/) to test an
+[implementation of Komodo in a CLI application](bins/saclin/).
 
-tests for the binary application can also be run with
-```bash
-nu tests/cli.nu
+If you have [Nushell installed](https://www.nushell.sh/book/installation.html), you can run these
+with the following command:
+```shell
+make test-nu
 ```
 
-## other binaries
-Komodo provides a bunch of other binaries that might be interesting of useful to use.
-
-The easiest is to use the `cargo.nu` Nushell module as follows
-```bash
-use nu-utils cargo "cargo bin"
-help cargo bin
+## examples
+A [CLI example](bins/saclin/examples/cli.nu) is also provided and can be run with
+```shell
+make example
 ```
 
 ## the benchmarks
-see [the `README`](benchmarks/README.md)
+see [`benchmarks/`](benchmarks/README.md)
diff --git a/tests/dragoon_133x133.png b/assets/dragoon_133x133.png
similarity index 100%
rename from tests/dragoon_133x133.png
rename to assets/dragoon_133x133.png
diff --git a/tests/dragoon_32x32.png b/assets/dragoon_32x32.png
similarity index 100%
rename from tests/dragoon_32x32.png
rename to assets/dragoon_32x32.png
diff --git a/benchmarks/nu-lib/commit.nu b/benchmarks/nu-lib/commit.nu
index f43ef527..8cb0d6bb 100644
--- a/benchmarks/nu-lib/commit.nu
+++ b/benchmarks/nu-lib/commit.nu
@@ -1,7 +1,7 @@
-use ../../nu-utils log
-use ../../nu-utils math *
-use ../../nu-utils fs check-file
-use ../../nu-utils plot [ into-axis-options, COMMON_OPTIONS, gplt ]
+use utils log
+use utils math *
+use utils fs check-file
+use utils plot [ into-axis-options, COMMON_OPTIONS, gplt ]
 
 use std formats *
 
diff --git a/benchmarks/nu-lib/fec/plot.nu b/benchmarks/nu-lib/fec/plot.nu
index 615fc3a9..da3c0dc2 100644
--- a/benchmarks/nu-lib/fec/plot.nu
+++ b/benchmarks/nu-lib/fec/plot.nu
@@ -1,7 +1,7 @@
-use ../../../nu-utils math *
-use ../../../nu-utils plot [ into-axis-options, COMMON_OPTIONS ]
-use ../../../nu-utils fs check-file
-use ../../../nu-utils plot gplt
+use ../utils math *
+use ../utils plot [ into-axis-options, COMMON_OPTIONS ]
+use ../utils fs check-file
+use ../utils plot gplt
 
 use std formats *
 
diff --git a/benchmarks/nu-lib/fec/run.nu b/benchmarks/nu-lib/fec/run.nu
index 1b600189..cb814411 100644
--- a/benchmarks/nu-lib/fec/run.nu
+++ b/benchmarks/nu-lib/fec/run.nu
@@ -1,5 +1,5 @@
-use ../../../nu-utils log
-use ../../../nu-utils formats *
+use ../utils log
+use ../utils formats *
 
 use std formats *
 
diff --git a/benchmarks/nu-lib/linalg.nu b/benchmarks/nu-lib/linalg.nu
index 8699334b..3bec71f3 100644
--- a/benchmarks/nu-lib/linalg.nu
+++ b/benchmarks/nu-lib/linalg.nu
@@ -1,7 +1,7 @@
-use ../../nu-utils log
-use ../../nu-utils math *
-use ../../nu-utils fs check-file
-use ../../nu-utils plot [ into-axis-options, COMMON_OPTIONS, gplt ]
+use utils log
+use utils math *
+use utils fs check-file
+use utils plot [ into-axis-options, COMMON_OPTIONS, gplt ]
 
 use std formats *
 
diff --git a/benchmarks/nu-lib/recoding.nu b/benchmarks/nu-lib/recoding.nu
index 34eca661..c8dcec3b 100644
--- a/benchmarks/nu-lib/recoding.nu
+++ b/benchmarks/nu-lib/recoding.nu
@@ -1,8 +1,8 @@
-use ../../nu-utils log
-use ../../nu-utils formats *
-use ../../nu-utils math *
-use ../../nu-utils plot [ into-axis-options, COMMON_OPTIONS, gplt ]
-use ../../nu-utils fs check-file
+use utils log
+use utils formats *
+use utils math *
+use utils plot [ into-axis-options, COMMON_OPTIONS, gplt ]
+use utils fs check-file
 
 use std formats *
 
diff --git a/benchmarks/nu-lib/setup.nu b/benchmarks/nu-lib/setup.nu
index 0cf90357..4c747f57 100644
--- a/benchmarks/nu-lib/setup.nu
+++ b/benchmarks/nu-lib/setup.nu
@@ -1,7 +1,7 @@
-use ../../nu-utils log
-use ../../nu-utils math *
-use ../../nu-utils fs check-file
-use ../../nu-utils plot [ into-axis-options, COMMON_OPTIONS, gplt ]
+use utils log
+use utils math *
+use utils fs check-file
+use utils plot [ into-axis-options, COMMON_OPTIONS, gplt ]
 
 use std formats *
 
diff --git a/nu-utils/formats.nu b/benchmarks/nu-lib/utils/formats.nu
similarity index 100%
rename from nu-utils/formats.nu
rename to benchmarks/nu-lib/utils/formats.nu
diff --git a/nu-utils/fs.nu b/benchmarks/nu-lib/utils/fs.nu
similarity index 100%
rename from nu-utils/fs.nu
rename to benchmarks/nu-lib/utils/fs.nu
diff --git a/nu-utils/log.nu b/benchmarks/nu-lib/utils/log.nu
similarity index 100%
rename from nu-utils/log.nu
rename to benchmarks/nu-lib/utils/log.nu
diff --git a/nu-utils/math.nu b/benchmarks/nu-lib/utils/math.nu
similarity index 100%
rename from nu-utils/math.nu
rename to benchmarks/nu-lib/utils/math.nu
diff --git a/nu-utils/mod.nu b/benchmarks/nu-lib/utils/mod.nu
similarity index 58%
rename from nu-utils/mod.nu
rename to benchmarks/nu-lib/utils/mod.nu
index 69f677bf..503415a0 100644
--- a/nu-utils/mod.nu
+++ b/benchmarks/nu-lib/utils/mod.nu
@@ -1,10 +1,6 @@
-export module binary.nu
-export module cargo.nu
-export module color.nu
-export module error.nu
 export module formats.nu
 export module fs.nu
+export module log.nu
 export module math.nu
 export module parse.nu
 export module plot.nu
-export module log.nu
diff --git a/nu-utils/parse.nu b/benchmarks/nu-lib/utils/parse.nu
similarity index 100%
rename from nu-utils/parse.nu
rename to benchmarks/nu-lib/utils/parse.nu
diff --git a/nu-utils/plot.nu b/benchmarks/nu-lib/utils/plot.nu
similarity index 100%
rename from nu-utils/plot.nu
rename to benchmarks/nu-lib/utils/plot.nu
diff --git a/bins/README.md b/bins/README.md
new file mode 100644
index 00000000..334ea698
--- /dev/null
+++ b/bins/README.md
@@ -0,0 +1,7 @@
+## running binaries
+If you have [Nushell](https://www.nushell.sh/) installed, the easiest is to use the `cargo.nu`
+module as follows:
+```bash
+use ./bins/cargo.nu "cargo bin"
+help cargo bin
+```
diff --git a/nu-utils/cargo.nu b/bins/cargo.nu
similarity index 81%
rename from nu-utils/cargo.nu
rename to bins/cargo.nu
index 4314a326..896be6e5 100644
--- a/nu-utils/cargo.nu
+++ b/bins/cargo.nu
@@ -1,5 +1,20 @@
 use std log
-use error.nu "error throw"
+
+def "error throw" [err: record<
+    err: string,
+    label: string,
+    span: record<start: int, end: int>,
+    # help: string?,
+>] {
+    error make {
+        msg: $"(ansi red_bold)($err.err)(ansi reset)",
+        label: {
+            text: $err.label,
+            span: $err.span,
+        },
+        help: $err.help?,
+    }
+}
 
 def get-workspace-bins []: nothing -> table<name: string, toml: path> {
     open Cargo.toml
diff --git a/bins/saclin/Cargo.toml b/bins/saclin/Cargo.toml
new file mode 100644
index 00000000..5ac7706c
--- /dev/null
+++ b/bins/saclin/Cargo.toml
@@ -0,0 +1,19 @@
+[package]
+name = "saclin"
+version = "0.3.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+anyhow = "1.0.81"
+ark-bls12-381 = "0.4.0"
+ark-ec = "0.4.2"
+ark-ff = "0.4.2"
+ark-poly = "0.4.2"
+ark-serialize = "0.4.2"
+ark-std = "0.4.0"
+komodo = { path = "../../" }
+rand = "0.8.5"
+tracing = "0.1.40"
+tracing-subscriber = "0.3.17"
diff --git a/bins/saclin/README.md b/bins/saclin/README.md
new file mode 100644
index 00000000..53cd160d
--- /dev/null
+++ b/bins/saclin/README.md
@@ -0,0 +1 @@
+## CLI app using Semi-AVID
diff --git a/nu-utils/binary.nu b/bins/saclin/binary.nu
similarity index 100%
rename from nu-utils/binary.nu
rename to bins/saclin/binary.nu
diff --git a/bins/saclin/examples/cli.nu b/bins/saclin/examples/cli.nu
new file mode 100755
index 00000000..bdc31972
--- /dev/null
+++ b/bins/saclin/examples/cli.nu
@@ -0,0 +1,35 @@
+#!/usr/bin/env nu
+use .. [
+    "saclin build",
+    "saclin setup",
+    "saclin prove",
+    "saclin verify",
+    "saclin reconstruct",
+    "saclin ls",
+]
+use ../binary.nu [ "bytes from_int" ]
+
+use std assert
+
+const BYTES = "assets/dragoon_32x32.png"
+const FEC_PARAMS = { k: 3, n: 5 }
+
+const BLOCKS_TO_VERIFY = [0, 1]
+const BLOCKS_TO_RECONSTRUCT = [0, 2, 3]
+
+def main [] {
+    saclin build
+
+    saclin setup (open $BYTES | into binary | bytes length)
+    saclin prove $BYTES --fec-params $FEC_PARAMS
+
+    let blocks = saclin ls
+
+    saclin verify ...($BLOCKS_TO_VERIFY | each {|i| $blocks | get $i })
+
+    let actual = saclin reconstruct ...($BLOCKS_TO_RECONSTRUCT | each {|i| $blocks | get $i })
+    let expected = open $BYTES | bytes from_int
+    assert equal $actual $expected
+
+    print "reconstruction was successful"
+}
diff --git a/komodo.nu b/bins/saclin/mod.nu
similarity index 82%
rename from komodo.nu
rename to bins/saclin/mod.nu
index d1ca5d81..2080cb25 100644
--- a/komodo.nu
+++ b/bins/saclin/mod.nu
@@ -1,15 +1,17 @@
-# Welcome to Komodo, a tool to encode and prove data.
+# Welcome to SACLIN (**S**emi-**A**VID **CLI** in **N**ushell), a tool to encode and prove data.
 #
-# please run `komodo --help` or `komodo <tab>` to have a look at more information
+# please run `saclin --help` or `saclin <tab>` to have a look at more information
 
-use nu-utils binary ["bytes from_int"]
+module binary.nu
 
-const KOMODO_BINARY = "./target/release/komodo"
+use binary ["bytes from_int"]
+
+const BIN = "./target/release/saclin"
 const DEFAULT_LOG_LEVEL = "INFO"
 
 def home-dir []: nothing -> path {
-    $env.KOMODO_HOME? | default (
-        $env.XDG_DATA_HOME? | default "~/.local/share" | path join "komodo"
+    $env.SACLIN_HOME? | default (
+        $env.XDG_DATA_HOME? | default "~/.local/share" | path join "saclin"
     ) | path expand
 }
 
@@ -34,7 +36,7 @@ def "nu-complete encoding-methods" []: nothing -> list<string> {
     ]
 }
 
-def run-komodo [
+def run-saclin [
     --input: path = "",
     --nb-bytes: int = 0,
     -k: int = 0,
@@ -59,7 +61,7 @@ def run-komodo [
 
     with-env {RUST_LOG: $log_level} {
         let res = do {
-            ^$KOMODO_BINARY ...([
+            ^$BIN ...([
                 $input
                 $k
                 $n
@@ -90,9 +92,9 @@ def list-blocks []: nothing -> list<string> {
     }
 }
 
-# build Komodo from source, updating the application
-export def "komodo build" []: nothing -> nothing {
-    ^cargo build --package komodo --release
+# build SACLIN from source, updating the application
+export def "saclin build" []: nothing -> nothing {
+    ^cargo build --release --manifest-path bins/saclin/Cargo.toml
 }
 
 # create a random trusted setup for a given amount of data
@@ -100,19 +102,19 @@ export def "komodo build" []: nothing -> nothing {
 # # Examples
 # ```nushell
 # # create a trusted setup well suited for a file called `my_target_file.txt`
-# komodo setup (open my_target_file.txt | into binary | bytes length)
+# saclin setup (open my_target_file.txt | into binary | bytes length)
 # ```
 # ---
 # ```nushell
 # # create a trusted setup for 50k bytes and make sure the setup has been created
-# komodo setup 50_000
-# use std assert; assert ("~/.local/share/komodo/powers" | path exists)
-export def "komodo setup" [
+# saclin setup 50_000
+# use std assert; assert ("~/.local/share/saclin/powers" | path exists)
+export def "saclin setup" [
     nb_bytes: int, # the size of the biggest expected data during the lifetime of the application
     --log-level: string@"nu-complete log-levels" = $DEFAULT_LOG_LEVEL # change the log level
 ]: nothing -> nothing {
     (
-        run-komodo
+        run-saclin
             --log-level $log_level
             --nb-bytes $nb_bytes
             --generate-powers
@@ -123,8 +125,8 @@ export def "komodo setup" [
 #
 # # Examples
 # ```nushell
-# # encode and prove `tests/dragoon_32x32.png` with a _3 x 5_ Vandermonde encoding
-# komodo prove tests/dragoon_32x32.png --fec-params {k: 3, n: 5} --encoding-method vandermonde
+# # encode and prove `assets/dragoon_32x32.png` with a _3 x 5_ Vandermonde encoding
+# saclin prove assets/dragoon_32x32.png --fec-params {k: 3, n: 5} --encoding-method vandermonde
 # ```
 # ```
 # ─┬────────────────────────────────────────────────────────────────
@@ -135,7 +137,7 @@ export def "komodo setup" [
 # 4│7aa698f338605462205c5ff46b5463720d073de92a19f897cc4ae6c286ab87
 # ─┴────────────────────────────────────────────────────────────────
 # ```
-export def "komodo prove" [
+export def "saclin prove" [
     input: path, # the path to the input file to encode and prove
     --fec-params: record<k: int, n: int>, # the parameters of the encoding
     --encoding-method: string@"nu-complete encoding-methods" = "random", # the encoding method, e.g. _random_ or _vandermonde_
@@ -145,7 +147,7 @@ export def "komodo prove" [
     # a bug on the Nushell side
     if $fec_params == null {
         error make --unspanned {
-            msg: "`komodo prove` requires `--fec-params` to be given"
+            msg: "`saclin prove` requires `--fec-params` to be given"
         }
     }
 
@@ -162,7 +164,7 @@ export def "komodo prove" [
     }
 
     (
-        run-komodo
+        run-saclin
             --log-level $log_level
             --input $input
             -k $fec_params.k
@@ -177,10 +179,10 @@ export def "komodo prove" [
 # ```nushell
 # # verify the integrity of two blocks (note the use of the spread operator introduced in Nushell 0.89.0)
 # # > **Note**
-# # > file: `tests/dragoon_32x32.png`
+# # > file: `assets/dragoon_32x32.png`
 # # > parameters: k = 3 and n = 5
 # # > method: vandermonde
-# komodo verify ...[
+# saclin verify ...[
 #     44614daf1f5ebb86f1c69293b82c7795a5a35b4d12718b551648223441028e3,
 #     7aa698f338605462205c5ff46b5463720d073de92a19f897cc4ae6c286ab87,
 # ]
@@ -191,16 +193,16 @@ export def "komodo prove" [
 # 1│7aa698f338605462205c5ff46b5463720d073de92a19f897cc4ae6c286ab87 │true
 # ─┴───────────────────────────────────────────────────────────────┴──────
 # ```
-export def "komodo verify" [
+export def "saclin verify" [
     ...blocks: string@"list-blocks", # the list of blocks to verify
     --log-level: string@"nu-complete log-levels" = $DEFAULT_LOG_LEVEL # change the log level
 ]: nothing -> table<block: string, status: int> {
-    run-komodo --log-level $log_level --verify ...$blocks
+    run-saclin --log-level $log_level --verify ...$blocks
 }
 
 # reconstruct the original data from a subset of blocks
 #
-# `komodo reconstruct` might throw an error in some cases
+# `saclin reconstruct` might throw an error in some cases
 # - when there are too few blocks
 # - when the blocks are linearly dependant, and thus the decoding cannot be applied
 # - when the blocks belong to different data
@@ -209,10 +211,10 @@ export def "komodo verify" [
 # ```nushell
 # # applying a valid reconstruction
 # # > **Note**
-# # > file: `tests/dragoon_32x32.png`
+# # > file: `assets/dragoon_32x32.png`
 # # > parameters: k = 3 and n = 5
 # # > method: vandermonde
-# let bytes = komodo reconstruct ...[
+# let bytes = saclin reconstruct ...[
 #     44614daf1f5ebb86f1c69293b82c7795a5a35b4d12718b551648223441028e3,
 #     7aa698f338605462205c5ff46b5463720d073de92a19f897cc4ae6c286ab87,
 #     8be575889246fbc49f4c748ac2dc1cd8a4ef71d16e91c9343660a5f79f086,
@@ -227,10 +229,10 @@ export def "komodo verify" [
 # ```nushell
 # # giving too few blocks
 # # > **Note**
-# # > file: `tests/dragoon_32x32.png`
+# # > file: `assets/dragoon_32x32.png`
 # # > parameters: k = 3 and n = 5
 # # > method: vandermonde
-# komodo reconstruct ...[
+# saclin reconstruct ...[
 #     44614daf1f5ebb86f1c69293b82c7795a5a35b4d12718b551648223441028e3,
 #     7aa698f338605462205c5ff46b5463720d073de92a19f897cc4ae6c286ab87,
 # ]
@@ -240,13 +242,13 @@ export def "komodo verify" [
 # ```
 # ---
 # ```nushell
-# # after combining _44614d_ and _6de9fd_ (see [`komodo combine`]), try to decode with linear dependencies
+# # after combining _44614d_ and _6de9fd_ (see [`saclin combine`]), try to decode with linear dependencies
 # # > **Note**
-# # > file: `tests/dragoon_32x32.png`
+# # > file: `assets/dragoon_32x32.png`
 # # > parameters: k = 3 and n = 5
 # # > method: vandermonde
 # # > recoding: _44614d_ <+> _6de9fd_ => _86cdd1_
-# komodo reconstruct ...[
+# saclin reconstruct ...[
 #     44614daf1f5ebb86f1c69293b82c7795a5a35b4d12718b551648223441028e3,
 #     6de9fd5fdfe8c08b3132e0d527b14a2a4e4be9a543af1f13d2c397bd113846e4,
 #     86cdd1b7ed79618696ab82d848833cbe448719a513b850207936e4dce6294,
@@ -255,22 +257,22 @@ export def "komodo verify" [
 # ```
 # Error:   × could not decode: Matrix is not invertible at row 2 (1)
 # ```
-export def "komodo reconstruct" [
+export def "saclin reconstruct" [
     ...blocks: string@"list-blocks", # the blocks that should be used to reconstruct the original data
     --log-level: string@"nu-complete log-levels" = $DEFAULT_LOG_LEVEL # change the log level
 ]: nothing -> binary {
-    run-komodo --log-level $log_level --reconstruct ...$blocks | bytes from_int
+    run-saclin --log-level $log_level --reconstruct ...$blocks | bytes from_int
 }
 
 # combine two blocks by computing a random linear combination
 #
 # # Examples
 # # > **Note**
-# # > file: `tests/dragoon_133x133.png`
+# # > file: `assets/dragoon_133x133.png`
 # # > parameters: k = 7 and n = 23
 # # > method: random
 # ```nushell
-# komodo combine ...[
+# saclin combine ...[
 #     1b112a11cd89dad619aadc18cb2c15c315453e177f1117c79d4ae4e219922,
 #     31c9bfe2845cc430d666413d8b8b51aee0d010aa89275a8c7d9d9ca1c9e05c,
 # ]
@@ -282,10 +284,10 @@ export def "komodo reconstruct" [
 # ```nushell
 # # not giving exactly 2 blocks
 # # > **Note**
-# # > file: `tests/dragoon_133x133.png`
+# # > file: `assets/dragoon_133x133.png`
 # # > parameters: k = 7 and n = 23
 # # > method: random
-# komodo combine ...[
+# saclin combine ...[
 #     c22fe3c72cbc52fc55b46a3f9783f5c9a1e5fb59875f736332cf1b970b8,
 #     1b112a11cd89dad619aadc18cb2c15c315453e177f1117c79d4ae4e219922,
 #     f3f423df47cd7538accd38abe9ad6670b894243647af98fbfa9776e9cf7ff8e,
@@ -294,11 +296,11 @@ export def "komodo reconstruct" [
 # ```
 # Error:   × expected exactly 2 blocks, found 3 (1)
 # ```
-export def "komodo combine" [
+export def "saclin combine" [
     ...blocks: string@"list-blocks", # the blocks to combine, should contain two hashes
     --log-level: string@"nu-complete log-levels" = $DEFAULT_LOG_LEVEL # change the log level
 ]: nothing -> string {
-    run-komodo --log-level $log_level --combine ...$blocks | get 0
+    run-saclin --log-level $log_level --combine ...$blocks | get 0
 }
 
 # open one or more blocks and inspect their content
@@ -307,12 +309,12 @@ export def "komodo combine" [
 # ```nushell
 # # inspect a single block
 # # # > **Note**
-# # # > file: `tests/dragoon_133x133.png`
+# # # > file: `assets/dragoon_133x133.png`
 # # # > parameters: k = 7 and n = 23
 # # # > method: random
 # # # >
 # # # > `$.commits` and `$shard.bytes` have been truncated for readability
-# komodo inspect 374f23fd1f25ae4050c414bc169550bdd10f49f775e2af71d2aee8a87dc
+# saclin inspect 374f23fd1f25ae4050c414bc169550bdd10f49f775e2af71d2aee8a87dc
 # | into record
 # | update commits { parse --regex '\((?<f>\d{7})\d+, (?<s>\d{7})\d+\)' }
 # | update shard.bytes { length }
@@ -346,20 +348,20 @@ export def "komodo combine" [
 # m      │89
 # ───────┴──────────────────────────────────────────────────────────────────────
 # ```
-export def "komodo inspect" [
+export def "saclin inspect" [
     ...blocks: string@"list-blocks", # the blocks to inspect
     --log-level: string@"nu-complete log-levels" = $DEFAULT_LOG_LEVEL # change the log level
 ]: nothing -> table<shard: record<k: int, comb: list<any>, bytes: list<string>, hash: string, size: int>, commits: list<string>, m: int> {
-    run-komodo --log-level $log_level --inspect ...$blocks
+    run-saclin --log-level $log_level --inspect ...$blocks
 }
 
 # list all the blocks that are currently in the store
-export def "komodo ls" []: nothing -> list<string> {
+export def "saclin ls" []: nothing -> list<string> {
     list-blocks
 }
 
-# clean the Komodo home from all blocks and trusted setup
-export def "komodo clean" []: nothing -> nothing {
+# clean the SACLIN home from all blocks and trusted setup
+export def "saclin clean" []: nothing -> nothing {
     rm --force --recursive (home-dir)
 }
 
@@ -367,12 +369,12 @@ def pretty-code []: string -> string {
     $"`(ansi default_dimmed)($in)(ansi reset)`"
 }
 
-# the main entry point of Komodo, will only print some help
+# the main entry point of SACLIN, will only print some help
 export def main []: nothing -> nothing {
     let help = [
-        $"the location of the files generated by Komodo can be configured via ("$env.KOMODO_HOME" | pretty-code) which will default to",
-        $"- ("$env.XDG_DATA_HOME/komodo" | pretty-code) if ("$env.XDG_DATA_HOME" | pretty-code) is set",
-        $"- ("~/.local/share/komodo/" | pretty-code) otherwise"
+        $"the location of the files generated by SACLIN can be configured via ("$env.SACLIN_HOME" | pretty-code) which will default to",
+        $"- ("$env.XDG_DATA_HOME/saclin" | pretty-code) if ("$env.XDG_DATA_HOME" | pretty-code) is set",
+        $"- ("~/.local/share/saclin/" | pretty-code) otherwise"
     ]
 
     print ($help | str join "\n")
diff --git a/src/main.rs b/bins/saclin/src/main.rs
similarity index 100%
rename from src/main.rs
rename to bins/saclin/src/main.rs
diff --git a/tests/binary.nu b/bins/saclin/tests/binary.nu
similarity index 88%
rename from tests/binary.nu
rename to bins/saclin/tests/binary.nu
index def39bc4..0bd2669b 100644
--- a/tests/binary.nu
+++ b/bins/saclin/tests/binary.nu
@@ -1,4 +1,4 @@
-use ../nu-utils binary [ "bytes from_int", "bytes to_int" ]
+use ../binary.nu [ "bytes from_int", "bytes to_int" ]
 
 use std assert
 
diff --git a/tests/cli.nu b/bins/saclin/tests/cli.nu
similarity index 89%
rename from tests/cli.nu
rename to bins/saclin/tests/cli.nu
index 269baf3c..ac765c6f 100644
--- a/tests/cli.nu
+++ b/bins/saclin/tests/cli.nu
@@ -1,13 +1,13 @@
-use ../komodo.nu [
-    "komodo build",
-    "komodo setup",
-    "komodo prove",
-    "komodo verify",
-    "komodo reconstruct",
-    "komodo ls",
-    "komodo clean",
+use .. [
+    "saclin build",
+    "saclin setup",
+    "saclin prove",
+    "saclin verify",
+    "saclin reconstruct",
+    "saclin ls",
+    "saclin clean",
 ]
-use ../nu-utils binary [ "bytes from_int" ]
+use ../binary.nu [ "bytes from_int" ]
 
 use std assert
 
@@ -120,12 +120,12 @@ module math {
 
 use math
 
-const FILE = "tests/dragoon_32x32.png"
+const FILE = "assets/dragoon_32x32.png"
 const FEC_PARAMS = {k: 3, n: 5}
 
 def test [blocks: list<int>, --fail] {
     let actual = try {
-        komodo reconstruct ...(komodo ls)
+        saclin reconstruct ...(saclin ls)
     } catch {
         if not $fail {
             error make --unspanned { msg: "woopsie" }
@@ -139,14 +139,14 @@ def test [blocks: list<int>, --fail] {
 }
 
 def main [] {
-    komodo build
+    saclin build
 
-    komodo clean
+    saclin clean
 
-    komodo setup (open $FILE | into binary | bytes length)
-    komodo prove $FILE --fec-params $FEC_PARAMS
+    saclin setup (open $FILE | into binary | bytes length)
+    saclin prove $FILE --fec-params $FEC_PARAMS
 
-    komodo verify ...(komodo ls)
+    saclin verify ...(saclin ls)
 
     let all_k_choose_n_permutations = seq 1 $FEC_PARAMS.n
         | each {|ki|
diff --git a/examples/cli.nu b/examples/cli.nu
deleted file mode 100755
index e7765693..00000000
--- a/examples/cli.nu
+++ /dev/null
@@ -1,35 +0,0 @@
-#!/usr/bin/env nu
-use ../komodo.nu [
-    "komodo build",
-    "komodo setup",
-    "komodo prove",
-    "komodo verify",
-    "komodo reconstruct",
-    "komodo ls",
-]
-use ../nu-utils binary [ "bytes from_int" ]
-
-use std assert
-
-const BYTES = "tests/dragoon_32x32.png"
-const FEC_PARAMS = { k: 3, n: 5 }
-
-const BLOCKS_TO_VERIFY = [0, 1]
-const BLOCKS_TO_RECONSTRUCT = [0, 2, 3]
-
-def main [] {
-    komodo build
-
-    komodo setup (open $BYTES | into binary | bytes length)
-    komodo prove $BYTES --fec-params $FEC_PARAMS
-
-    let blocks = komodo ls
-
-    komodo verify ...($BLOCKS_TO_VERIFY | each {|i| $blocks | get $i })
-
-    let actual = komodo reconstruct ...($BLOCKS_TO_RECONSTRUCT | each {|i| $blocks | get $i })
-    let expected = open $BYTES | bytes from_int
-    assert equal $actual $expected
-
-    print "reconstruction was successful"
-}
diff --git a/nu-utils/color.nu b/nu-utils/color.nu
deleted file mode 100644
index af279b69..00000000
--- a/nu-utils/color.nu
+++ /dev/null
@@ -1,131 +0,0 @@
-use error.nu "error throw"
-
-export const WHITE = { r: 1.0, g: 1.0, b: 1.0 }
-export const BLACK = { r: 0.0, g: 0.0, b: 0.0 }
-export const RED = { r: 1.0, g: 0.0, b: 0.0 }
-export const GREEN = { r: 0.0, g: 1.0, b: 0.0 }
-export const BLUE = { r: 0.0, g: 0.0, b: 1.0 }
-
-export def "color from-floats" [
-    r: float,
-    g: float,
-    b: float
-]: nothing -> record<r: float, g: float, b: float> {
-    if $r < 0.0 or $r > 1.0 {
-        error throw {
-            err: "invalid RGB channel",
-            label: $"should be between 0 and 1, found ($r)",
-            span: (metadata $r).span,
-        }
-    }
-    if $g < 0.0 or $g > 1.0 {
-        error throw {
-            err: "invalid RGB channel",
-            label: $"should be between 0 and 1, found ($g)",
-            span: (metadata $g).span,
-        }
-    }
-    if $b < 0.0 or $b > 1.0 {
-        error throw {
-            err: "invalid RGB channel",
-            label: $"should be between 0 and 1, found ($b)",
-            span: (metadata $b).span,
-        }
-    }
-
-    { r: $r, g: $g, b: $b }
-}
-
-export def "color from-ints" [
-    r: int,
-    g: int,
-    b: int
-]: nothing -> record<r: float, g: float, b: float> {
-    if $r < 0 or $r > 255 {
-        error throw {
-            err: "invalid RGB channel",
-            label: $"should be between 0 and 255, found ($r)",
-            span: (metadata $r).span,
-        }
-    }
-    if $g < 0 or $g > 255 {
-        error throw {
-            err: "invalid RGB channel",
-            label: $"should be between 0 and 255, found ($g)",
-            span: (metadata $g).span,
-        }
-    }
-    if $b < 0 or $b > 255 {
-        error throw {
-            err: "invalid RGB channel",
-            label: $"should be between 0 and 255, found ($b)",
-            span: (metadata $b).span,
-        }
-    }
-
-    { r: ($r / 255 | into float), g: ($g / 255 | into float), b: ($b / 255 | into float) }
-}
-
-def try-string-to-int []: string -> int {
-    let s = $in
-    try {
-        $"0x($s)" | into int
-    } catch { |e|
-        let err = $e.debug
-            | parse --regex 'CantConvert { to_type: "(?<to>.*)", from_type: "(?<from>.*)", span: Span { (?<span>.*) }, help: Some\("(?<help>.*)"\) }'
-            | into record
-
-        let msg = $err.help | str replace --all '\"' '"'
-        error make --unspanned { msg: $"($msg), found ($s)" }
-    }
-}
-
-export def "color from-string" [s: string]: nothing -> record<r: float, g: float, b: float> {
-    let res = $s
-        | parse --regex '^#(?<r>..)(?<g>..)(?<b>..)$'
-        | into record
-
-    if $res == {} {
-        error throw {
-            err: "invalid HEX color format",
-            label: $"format should be '#RRGGBB', found ($s)",
-            span: (metadata $s).span,
-        }
-    }
-
-    {
-        r: ($res.r | try-string-to-int | $in / 255),
-        g: ($res.g | try-string-to-int | $in / 255),
-        b: ($res.b | try-string-to-int | $in / 255),
-    }
-}
-
-export def "color mix" [
-    c1: record<r: float, g: float, b: float>,
-    c2: record<r: float, g: float, b: float>,
-    c: float,
-]: nothing -> record<r: float, g: float, b: float> {
-    {
-        r: ($c * $c1.r + (1 - $c) * $c2.r),
-        g: ($c * $c1.g + (1 - $c) * $c2.g),
-        b: ($c * $c1.b + (1 - $c) * $c2.b),
-    }
-}
-
-def float-to-u8-hex []: float -> string {
-    $in * 255
-        | math round --precision 0
-        | into int
-        | fmt
-        | get lowerhex
-        | parse "0x{n}"
-        | into record
-        | get n
-        | into string
-        | fill --alignment "right" --character '0' --width 2
-}
-
-export def "color to-hex" []: record<r: float, g: float, b: float> -> string {
-    $"#($in.r | float-to-u8-hex)($in.g | float-to-u8-hex)($in.b | float-to-u8-hex)"
-}
-
diff --git a/nu-utils/error.nu b/nu-utils/error.nu
deleted file mode 100644
index 9e6a4aeb..00000000
--- a/nu-utils/error.nu
+++ /dev/null
@@ -1,15 +0,0 @@
-export def "error throw" [err: record<
-    err: string,
-    label: string,
-    span: record<start: int, end: int>,
-    # help: string?,
->] {
-    error make {
-        msg: $"(ansi red_bold)($err.err)(ansi reset)",
-        label: {
-            text: $err.label,
-            span: $err.span,
-        },
-        help: $err.help?,
-    }
-}
diff --git a/src/fec.rs b/src/fec.rs
index 07dca6ff..dbe603c3 100644
--- a/src/fec.rs
+++ b/src/fec.rs
@@ -235,7 +235,7 @@ mod tests {
     type LCExclusion = Vec<usize>;
 
     fn bytes() -> Vec<u8> {
-        include_bytes!("../tests/dragoon_32x32.png").to_vec()
+        include_bytes!("../assets/dragoon_32x32.png").to_vec()
     }
 
     fn to_curve<F: PrimeField>(n: u128) -> F {
diff --git a/src/field.rs b/src/field.rs
index cac315bc..0970b260 100644
--- a/src/field.rs
+++ b/src/field.rs
@@ -42,7 +42,7 @@ mod tests {
     use crate::field::{self, merge_elements_into_bytes};
 
     fn bytes() -> Vec<u8> {
-        include_bytes!("../tests/dragoon_32x32.png").to_vec()
+        include_bytes!("../assets/dragoon_32x32.png").to_vec()
     }
 
     fn split_data_template<F: PrimeField>(
diff --git a/src/semi_avid.rs b/src/semi_avid.rs
index ee44af38..a2bc5314 100644
--- a/src/semi_avid.rs
+++ b/src/semi_avid.rs
@@ -206,7 +206,7 @@ mod tests {
     use super::{build, prove, recode, verify};
 
     fn bytes() -> Vec<u8> {
-        include_bytes!("../tests/dragoon_133x133.png").to_vec()
+        include_bytes!("../assets/dragoon_133x133.png").to_vec()
     }
 
     macro_rules! full {
diff --git a/tests/color.nu b/tests/color.nu
deleted file mode 100644
index 1c1c119f..00000000
--- a/tests/color.nu
+++ /dev/null
@@ -1,64 +0,0 @@
-use ../nu-utils color [
-    "color from-floats",
-    "color from-ints",
-    "color from-string",
-    "color mix",
-    "color to-hex",
-    RED,
-    GREEN,
-]
-
-use std assert
-
-def "assert error" [code: closure, --msg: string, --body: string] {
-    try {
-        do $code
-    } catch { |e|
-        if $msg != null and ($e.msg | ansi strip) != $msg {
-            error make {
-                msg: $"(ansi red_bold)assertion: bad error message(ansi reset)",
-                label: {
-                    text: $"error should have message '($msg)'",
-                    span: (metadata $code).span,
-                },
-                help: $"actual: ($e.msg | ansi strip)",
-            }
-        }
-        if $body != null and not ($e.debug | ansi strip | str contains $body) {
-            let actual = $e.debug | ansi strip | parse "{foo}text: {text}, span: {bar}" | into record | get text
-            error make {
-                msg: $"(ansi red_bold)assertion: bad error body(ansi reset)",
-                label: {
-                    text: $"error should contain '($body)'",
-                    span: (metadata $code).span,
-                },
-                help: $"actual: ($actual)",
-            }
-        }
-        return
-    }
-
-    error make --unspanned { msg: "should error" }
-}
-
-assert error { || color from-floats 2 1 1 } --msg "invalid RGB channel" --body "should be between 0 and 1, found 2"
-assert error { || color from-floats 1 (-2 | into float) 1 } --msg "invalid RGB channel" --body "should be between 0 and 1, found -2"
-assert error { || color from-floats 1 1 3.4 } --msg "invalid RGB channel" --body "should be between 0 and 1, found 3.4"
-
-assert error { || color from-ints 256 0 0 } --msg "invalid RGB channel" --body "should be between 0 and 255, found 256"
-assert error { || color from-ints 0 256 0 } --msg "invalid RGB channel" --body "should be between 0 and 255, found 256"
-assert error { || color from-ints 0 0 256 } --msg "invalid RGB channel" --body "should be between 0 and 255, found 256"
-
-assert error { || color from-string "foo" } --msg "invalid HEX color format" --body "format should be '#RRGGBB', found foo"
-assert error { || color from-string "#foo" } --msg "invalid HEX color format" --body "format should be '#RRGGBB', found #foo"
-
-assert error { || color from-string "#xxxxxx" } --msg "hexadecimal digits following \"0x\" should be in 0-9, a-f, or A-F, found xx"
-assert error { || color from-string "#0123yy" } --msg "hexadecimal digits following \"0x\" should be in 0-9, a-f, or A-F, found yy"
-
-assert equal (color from-floats 0.1 0.2 0.3) { r: 0.1, g: 0.2, b: 0.3 }
-assert equal (color from-ints 1 2 3) { r: (1 / 255), g: (2 / 255), b: (3 / 255) }
-assert equal (color from-string "#010203") { r: (1 / 255), g: (2 / 255), b: (3 / 255) }
-
-assert equal (color from-string "#010203" | color to-hex) "#010203"
-
-assert equal (color mix $RED $GREEN 0.5) (color from-floats 0.5 0.5 0.0)
-- 
GitLab