docs: add spanish translation (#62)

Co-authored-by: Slava <20563034+veaceslavdoina@users.noreply.github.com>
This commit is contained in:
Marina Petrichenko 2025-08-06 09:34:59 +02:00 committed by GitHub
parent ac220c2132
commit a31eeec867
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 3627 additions and 0 deletions

3
es/codex/about.md Normal file
View File

@ -0,0 +1,3 @@
# Acerca de Codex
Trabajo en progreso :construction:

5
es/codex/disclaimer.md Normal file
View File

@ -0,0 +1,5 @@
# Descargo de Responsabilidad
El código e instrucciones proporcionados en este repositorio y repositorios relacionados se proporcionan "tal cual", sin garantía de ningún tipo, expresa o implícita, incluyendo pero no limitado a la seguridad o corrección, o rendimiento del código o instrucciones proporcionadas. No aseguramos que el código funcionará según lo previsto, y los usuarios pueden experimentar retrasos, fallos, errores, omisiones o pérdida de información transmitida mientras usan o ejecutan Codex.
La ejecución de Codex se realiza bajo su propio riesgo. Como tal, no somos responsables ni tenemos obligación por ningún daño que pueda ocurrir a su hardware, software, datos o red, ni por ninguna pérdida, reclamo, daño de cualquier naturaleza, u otra responsabilidad que surja de o en conexión con el uso del código e instrucciones proporcionadas.

View File

@ -0,0 +1,72 @@
---
lastUpdated: false
---
# Política de Privacidad
Última actualización: 9 de febrero de 2024
Esta Política de Privacidad tiene como objetivo informar a los usuarios sobre nuestro enfoque de privacidad con respecto a este sitio web ("**Sitio Web**"). En este sentido, si está visitando nuestro Sitio Web, esta Política de Privacidad se aplica a usted.
### 1) Quiénes somos
Para los propósitos de esta Política de Privacidad y la recopilación y procesamiento de datos personales como controlador, la entidad relevante es la Asociación Logos Collective, que tiene su oficina registrada en Zug y su domicilio legal en:
```
Logos Collective Association
c/o PST Consulting GmbH
Baarerstrasse 10
6300 Zug
Suiza
```
Cuando nos referimos a "Logos", "nosotros" u otras referencias similares, nos referimos a la Asociación Logos Collective.
### 2) Limitamos la recopilación y procesamiento de datos personales de su uso del Sitio Web
Nos propósitos es limitar la recopilación y procesamiento de datos personales de los usuarios del Sitio Web. Solo recopilamos y procesamos ciertos datos personales para propósitos específicos y donde tenemos la base legal para hacerlo bajo la legislación de privacidad aplicable. No recopilamos ni procesamos ningún dato personal que no necesitemos y donde almacenemos cualquier dato personal, solo lo almacenaremos durante la cantidad de tiempo mínima necesaria para el propósito indicado.
En este sentido, recopilamos y procesamos los siguientes datos personales de su uso del Sitio Web:
* **IP address**: Como parte de dicho uso del Sitio Web, procesamos temporalmente su IP address pero no tenemos forma de identificarle. Sin embargo, tenemos un interés legítimo en procesar dichos IP addresses para garantizar la funcionalidad técnica y mejorar las medidas de seguridad del Sitio Web. Este IP address no se almacena por nosotros a lo largo del tiempo.
### 3) Procesamiento de datos personales por terceros
Además de nuestra recopilación limitada y procesamiento de datos personales, los terceros pueden recoger o procesar datos personales como resultado del Sitio Web utilizando ciertas características o para proporcionar ciertos contenidos. Si interactúa con dichos contenidos o características de terceros, se aplicará la respectiva política de privacidad de dichos terceros.
### 4) Medidas de seguridad que tomamos en relación con el Sitio Web
Como enfoque general, tomamos la seguridad de los datos en serio y hemos implementado una variedad de medidas de seguridad en el Sitio Web para mantener la seguridad de sus datos personales cuando presente dicha información a nosotros.
### 5) Exportación de datos fuera de la Unión Europea y Suiza
Estamos obligados a proteger la privacidad de los datos personales que haya enviado en el improbable caso de que exportemos sus datos personales a lugares fuera de la Unión Europea o Suiza. Esto significa que los datos personales solo se procesarán en países o por partes que proporcionen un nivel adecuado de protección como lo considere Suiza o la Comisión Europea. De lo contrario, usaremos otras formas de protecciones, como formas contractuales específicas para garantizar que dichos datos personales reciban la misma protección que se requiere en Suiza o Europa. En cualquier caso, la transmisión de datos personales fuera de la Unión Europea y Suiza siempre tendrá lugar en conformidad con la legislación de privacidad aplicable.
### 6) Sus opciones y derechos
Como se explica en esta Política de Privacidad, limitamos nuestra recopilación y procesamiento de sus datos personales siempre que sea posible. Sin embargo, todavía tiene ciertas opciones y derechos en relación con los datos personales que recopilamos y procesamos. Conforme a la legislación de privacidad aplicable, tiene el derecho de:
* Solicitarle a nosotros que corrija o actualice sus datos personales (si es posible de manera razonable);
* Solicitarle a nosotros que elimine sus datos personales de nuestros sistemas;
* Solicitarle a nosotros una copia de sus datos personales, que también puede transferirse a otro controlador de datos en su solicitud;
* Revocar su consentimiento para procesar sus datos personales (solo si se solicitó consentimiento para una actividad de procesamiento), que solo afecta las actividades de procesamiento basadas en su consentimiento y no afecta la validez de dichas actividades de procesamiento antes de que haya revocado su consentimiento;
* Objeto al procesamiento de sus datos personales; y
* Presentar una queja con el Comisionado Federal de Protección de Datos e Información (FDPIC), si cree que sus datos personales se han procesado ilegalmente.
### 7) Enlaces a terceros
En este Sitio Web, puede encontrarse con enlaces a sitios web de terceros. Estos sitios web de terceros tienen políticas de privacidad independientes y separadas. Por lo tanto, no tenemos responsabilidad o responsabilidad por el contenido y actividades de estos sitios web de terceros.
### 8) Esta Política de Privacidad puede cambiar
Podemos modificar o reemplazar cualquier parte de esta Política de Privacidad en cualquier momento y sin previo aviso. Por favor, compruebe periódicamente el Sitio Web para cualquier cambio. La nueva Política de Privacidad entrará en vigor inmediatamente al momento de su publicación en nuestro Sitio Web.
### 9) Información de contacto
Para cualquier pregunta sobre la Política de Privacidad, por favor contáctenos en <a href="mailto:legal@free.technology">legal@free.technology</a>.
Este documento está licenciado bajo CC-BY-SA.

7
es/codex/security.md Normal file
View File

@ -0,0 +1,7 @@
# Seguridad
Nos tomamos la seguridad muy en serio en Codex y en todo el <a href="https://free.technology/" target="_blank">Instituto de Tecnología Libre</a> y sus afiliados.
Por favor, reporte cualquier incidente de seguridad a través de <a href="mailto:security@free.technology">security@free.technology</a>.
Por favor, reporte cualquier vulnerabilidad descubierta en nuestro programa de recompensas en <a href="https://hackenproof.com/ift" target="_blank">HackenProof</a> para ayudar a garantizar que nuestros protocolos y software permanezcan seguros.

96
es/codex/terms-of-use.md Normal file
View File

@ -0,0 +1,96 @@
---
lastUpdated: false
---
# Terms of Use
Last updated: 14 February 2024
These website terms of use ("**Website Terms of Use**") are entered into by you and us, and they govern your access and use of this Website, including any content and functionality contained in the Website.
It is your responsibility to read the Website Terms of Use carefully before your use of the Website and your use of the Website means you have agreed to be bound and comply with these Website Terms of Use.
If you do not agree with these Website Terms of Use, you must not access or use the Website.
### 1) Who we are
For the purposes of these Website Terms of Use, the relevant entity is the Logos Collective Association, which has its registered office in Zug and its legal domicile address at:
```
Logos Collective Association
c/o PST Consulting GmbH
Baarerstrasse 10
6300 Zug
Switzerland
```
Whenever we refer to "Logos", "we", "us" or any other similar references, we are referring to the Logos Collective Association.
### 2) Disclaimers
The Website is provided by us on an as is basis and you use the Website at your own sole discretion and risk.
We disclaim all warranties of any kind, express or implied, including without limitation the warranties of merchantability, fitness for a particular purpose, and non-infringement of intellectual property or other violation of rights. We do not warrant or make any representations concerning the completeness, accuracy, legality, utility, reliability, suitability or availability of the use of the Website, the content on this Website or otherwise relating to the Website, such content or on any sites linked to this site.These disclaimers will apply to the maximum extent permitted by applicable law.
We make no claims that the Website or any of its content is accessible, legally compliant or appropriate in your jurisdiction. Your access or use of the Website is at your own sole discretion and you are solely responsible for complying with any applicable local laws.
The content herein or as accessible through this website is intended to be made available for informational purposes only and should not be considered as creating any expectations or forming the basis of any contract, commitment or binding obligation with us. No information herein shall be considered to contain or be relied upon as a promise, representation, warranty or guarantee, whether express or implied and whether as to the past, present or the future in relation to the projects and matters described herein.
The information contained herein does not constitute financial, legal, tax, or other advice and should not be treated as such.
Nothing in this Website should be construed by you as an offer to buy or sell, or soliciting any offer to buy or sell any tokens or any security.
### 3) Forward looking statements
The Website may also contain forward-looking statements that are based on current expectations, estimates, forecasts, assumptions and projections about the technology, industry and markets in general.
The forward looking statements, which may include statements about the roadmap, project descriptions, technical details, functionalities, features, the development and use of tokens by projects, and any other statements related to such matters or as accessible through this website are subject to a high degree of risk and uncertainty. The forward looking statements are subject to change based on, among other things, market conditions, technical developments, and regulatory environment. The actual development and results, including the order and the timeline, might vary from whats presented. The information contained herein is a summary and does not purport to be accurate, reliable or complete and we bear no responsibility for the accuracy, reliability or completeness of information contained herein. Because of the high degree of risk and uncertainty described above, you should not place undue reliance on any matters described in this website or as accessible through this website.
While we aim to update our website regularly, all information, including the timeline and the specifics of each stage, is subject to change and may be amended or supplemented at any time, without notice and at our sole discretion.
### 4) Intellectual property rights
The Website and its contents are made available under Creative Commons Attribution 4.0 International license (CC-BY 4.0). In essence this licence allows users to copy, modify and distribute the content in any format for any purpose, including commercial use, subject to certain requirements such as attributing us. For the full terms of this licence, please refer to the following website: https://creativecommons.org/licenses/by/4.0/.
### 5) Third party website links
To the extent the Website provides any links to a third party website, then their terms and conditions, including privacy policies, govern your use of those third party websites. By linking such third party websites, Status does not represent or imply that it endorses or supports such third party websites or content therein, or that it believes such third party websites and content therein to be accurate, useful or non-harmful. We have no control over such third party websites and will not be liable for your use of or activities on any third party websites accessed through the Website. If you access such third party websites through the Website, it is at your own risk and you are solely responsible for your activities on such third party websites.
### 6) Limitation of liability
We will not be held liable to you under any contract, negligence, strict liability, or other legal or equitable theory for any lost profits, cost of procurement for substitute services, or any special, incidental, or consequential damages related to, arising from, or in any way connected with these Website Terms of Use, the Website, the content on the Website, or your use of the Website, even if we have been advised of the possibility of such damages. In any event, our aggregate liability for such claims is limited to EUR 100 (one hundred Euros). This limitation of liability will apply to the maximum extent permitted by applicable law.
### 7) Indemnity
You shall indemnify us and hold us harmless from and against any and all claims, damages and expenses, including attorneys fees, arising from or related to your use of the Website, the content on the Website, including without limitation your violation of these Website Terms of Use.
### 8) Modifications
We may modify or replace any part of this Website Terms of Use at any time and without notice. You are responsible for checking the Website periodically for any changes. The new Website Terms of Use will be effective immediately upon its posting on the Website.
### 9) Governing law
Swiss law governs these Website Terms of Use and any disputes between you and us, whether in court or arbitration, without regard to conflict of laws provisions.
### 10) Disputes
In these terms, “dispute” has the broadest meaning enforceable by law and includes any claim you make against or controversy you may have in relation to these Website Terms of Use, the Website, the content on the Website, or your use of the Website.
We prefer arbitration over litigation as we believe it meets our principle of resolving disputes in the most effective and cost effective manner. You are bound by the following arbitration clause, which waives your right to litigation and to be heard by a judge. Please note that court review of an arbitration award is limited. You also waive all your rights to a jury trial (if any) in any and all jurisdictions.
If a (potential) dispute arises, you must first use your reasonable efforts to resolve it amicably with us. If these efforts do not result in a resolution of such dispute, you shall then send us a written notice of dispute setting out (i) the nature of the dispute, and the claim you are making; and (ii) the remedy you are seeking.
If we and you are unable to further resolve this dispute within sixty (60) calendar days of us receiving this notice of dispute, then any such dispute will be referred to and finally resolved by you and us through an arbitration administered by the Swiss Chambers Arbitration Institution in accordance with the Swiss Rules of International Arbitration for the time being in force, which rules are deemed to be incorporated herein by reference. The arbitral decision may be enforced in any court. The arbitration will be held in Zug, Switzerland, and may be conducted via video conference virtual/online methods if possible. The tribunal will consist of one arbitrator, and all proceedings as well as communications between the parties will be kept confidential. The language of the arbitration will be in English. Payment of all relevant fees in respect of the arbitration, including filing, administration and arbitrator fees will be in accordance with the Swiss Rules of International Arbitration.
Regardless of any applicable statute of limitations, you must bring any claims within one year after the claim arose or the time when you should have reasonably known about the claim. You also waive the right to participate in a class action lawsuit or a classwide arbitration against us.
### 11) About these Website Terms of Use
These Website Terms of Use cover the entire agreement between you and us regarding the Website and supersede all prior and contemporaneous understandings, agreements, representations and warranties, both written and oral, with respect to the Website.
The captions and headings identifying sections and subsections of these Website Terms of Use are for reference only and do not define, modify, expand, limit, or affect the interpretation of any provisions of these Website Terms of Use.
If any part of these Website Terms of Use is held invalid or unenforceable, that part will be severable from these Website Terms of Use, and the remaining portions will remain in full force and effect. If we fail to enforce any of these Website Terms of Use, that does not mean that we have waived our right to enforce them.
If you have any specific questions about these Website Terms of Use, please contact us at <a href="mailto:legal@free.technology">llegal@free.technology</a>.
This document is licensed under CC-BY-SA.

5
es/developers/api.md Normal file
View File

@ -0,0 +1,5 @@
# API de Codex
Codex utiliza una API REST para interactuar con el nodo y podemos usar un cliente HTTP para la interacción y configuración.
La especificación de la API se puede encontrar en [api.codex.storage](https://api.codex.storage) y se genera basándose en [openapi.yaml](https://github.com/codex-storage/nim-codex/blob/master/openapi.yaml). También generamos una [Colección de Postman](https://api.codex.storage/postman.json).

33
es/index.md Normal file
View File

@ -0,0 +1,33 @@
---
# https://vitepress.dev/reference/default-theme-home-page
layout: home
hero:
name: Codex
text: Plataforma descentralizada de almacenamiento de datos
tagline: Codex es un protocolo de almacenamiento de datos descentralizado y duradero, creado para que la comunidad mundial pueda preservar su conocimiento más importante sin riesgo de censura.
actions:
- theme: brand
text: ¿Qué es Codex?
link: /learn/what-is-codex
- theme: alt
text: Inicio rápido
link: /learn/quick-start
- theme: alt
text: Unirse a la Red de Pruebas Codex
link: /networks/testnet
features:
- title: Aprender
details: Obtén más información sobre Codex
link: /learn/what-is-codex
icon: 📚
- title: Redes
details: Participa en la red Codex como operador de almacenamiento o Comprador
link: /networks/networks
icon: 🚦
- title: Desarrolladores
details: Construye con Codex
link: /developers/api
icon: 🏗️
---

89
es/learn/architecture.md Normal file
View File

@ -0,0 +1,89 @@
# Descripción y arquitectura
Codex está construyendo un motor de almacenamiento de datos duradero que es completamente descentralizado, proporcionando resistencia a la corrupción y censura para aplicaciones web3. Protege de forma innata a los participantes de la red dando a los hosts negación plausible sobre los datos que almacenan, y a los clientes garantías de durabilidad comprobables—hasta 99.99%—mientras mantiene la eficiencia en almacenamiento y ancho de banda.
Estas cuatro características clave se combinan para diferenciar a Codex de proyectos existentes en el nicho de almacenamiento descentralizado:
- **Codificación de borrado:** Proporciona redundancia de datos eficiente, lo que aumenta las garantías de durabilidad de datos.
- **Prueba de recuperabilidad basada en ZK:** Para garantías ligeras de durabilidad de datos.
- **Mecanismo de reparación perezosa:** Para reconstrucción eficiente de datos y prevención de pérdidas.
- **Incentivación:** Para fomentar el comportamiento racional, la participación generalizada en la red y la provisión eficiente de recursos finitos de la red.
### Descentralización incentivada
Los mecanismos de incentivación son una de las piezas clave que faltan en las redes tradicionales de compartición de archivos. Codex cree que una estructura de incentivos robusta basada en el mercado asegurará una amplia participación entre los tipos de nodos detallados a continuación.
El desarrollo de una estructura de incentivos adecuada está impulsado por los siguientes objetivos:
- Oferta y demanda para fomentar el uso óptimo de los recursos de la red.
- Aumentar la participación permitiendo que los nodos utilicen sus ventajas competitivas para maximizar beneficios.
- Prevenir el spam y desalentar la participación maliciosa.
Aunque aún está por finalizar, la estructura de incentivos de Codex involucrará un mercado de participantes que quieren almacenar datos, y aquellos que proveen almacenamiento publicando garantías, con estos últimos pujando por contratos de almacenamiento abiertos. Esta estructura busca asegurar que los incentivos de los participantes estén alineados, resultando en que Codex funcione según lo previsto.
### Arquitectura de la red
Codex está compuesto por múltiples tipos de nodos, cada uno tomando un rol diferente en la operación de la red. De manera similar, las demandas de hardware para cada tipo de nodo varían, permitiendo que aquellos que operan dispositivos con recursos restringidos participen.
**Nodos de almacenamiento**
Como proveedores de almacenamiento confiable a largo plazo de Codex, los nodos de almacenamiento depositan garantías basadas en las garantías publicadas en el lado de la solicitud de contratos, y el número de slots que tiene un contrato. Esto está vinculado a la durabilidad demandada por el usuario. El incumplimiento en proporcionar prueba periódica de posesión de datos resulta en penalizaciones de recorte.
**Nodo Agregador**
Un método para descargar la codificación de borrado, generación de pruebas y agregación de pruebas por un nodo cliente con bajos recursos, actualmente en desarrollo y será parte del siguiente lanzamiento de Codex Q2/Q4 del próximo año.
**Nodos cliente**
Los nodos cliente hacen solicitudes para que otros nodos almacenen, encuentren y recuperen datos. La mayoría de la red Codex serán nodos Cliente, y estos participantes pueden funcionar como nodos de caché para compensar el costo de los recursos de red que consumen.
Cuando un nodo se compromete con un contrato de almacenamiento y un usuario sube datos, la red verificará proactivamente que el nodo de almacenamiento esté en línea y que los datos sean recuperables. Los nodos de almacenamiento son entonces consultados aleatoriamente para transmitir pruebas de posesión de datos sobre un intervalo correspondiente a la duración del contrato y 9's de garantía de recuperabilidad que proporciona el protocolo.
Si el nodo de almacenamiento envía pruebas inválidas o falla en proporcionarlas a tiempo, la red expulsa al nodo de almacenamiento del slot, y el slot estará disponible para el primer nodo que genere una prueba válida para ese slot.
Cuando el contrato se vuelve a publicar, parte de la garantía del nodo defectuoso paga las tarifas de ancho de banda del nuevo nodo de almacenamiento. La codificación de borrado complementa el esquema de reparación permitiendo la reconstrucción de los fragmentos faltantes a partir de datos en otros slots dentro del mismo contrato de almacenamiento alojado por nodos sin fallas.
![arquitectura](/learn/architecture.png)
### Arquitectura del mercado ###
El mercado consiste en un contrato inteligente que se despliega en la cadena, y los módulos de compra y venta que son parte del software del nodo. El módulo de compra es responsable de publicar solicitudes de almacenamiento en el contrato inteligente. El módulo de ventas es su contraparte que los proveedores de almacenamiento usan para determinar en qué solicitudes de almacenamiento están interesados.
#### Contrato inteligente ####
El contrato inteligente facilita el emparejamiento entre proveedores de almacenamiento y clientes de almacenamiento. Un cliente de almacenamiento puede solicitar una cierta cantidad de almacenamiento por una cierta duración. Esta solicitud se publica entonces en la cadena, para que los proveedores de almacenamiento puedan verla y decidir si quieren llenar un slot en la solicitud.
Los principales parámetros de una solicitud de almacenamiento son:
- la cantidad de bytes de almacenamiento solicitados
- un identificador de contenido (CID) de los datos que deben almacenarse
- la duración durante la cual los datos deben almacenarse
- el número de slots (basado en los parámetros de codificación de borrado)
- una cantidad de tokens para pagar por el almacenamiento
A nivel de protocolo, un cliente de almacenamiento es libre de determinar estos parámetros como considere conveniente, para que pueda elegir un nivel de durabilidad que sea adecuado para los datos y ajustarse a los precios cambiantes del almacenamiento. Las aplicaciones construidas sobre Codex pueden proporcionar orientación a sus usuarios para elegir los parámetros correctos, análogo a cómo las carteras de Ethereum ayudan a determinar las tarifas de gas.
El contrato inteligente también verifica que los proveedores de almacenamiento mantengan sus promesas. Los proveedores de almacenamiento publican garantías cuando prometen llenar un slot de una solicitud de almacenamiento. Se espera que publiquen pruebas de almacenamiento periódicas al contrato, ya sea directamente o a través de un agregador. Si fallan en hacerlo repetidamente, entonces su garantía puede ser confiscada. Su slot se otorga entonces a otro proveedor de almacenamiento.
El contrato inteligente indica cuándo un determinado proveedor de almacenamiento debe proporcionar una prueba de almacenamiento. Esto no se hace en un intervalo de tiempo fijo, sino que se determina estocásticamente para asegurar que no sea posible que un proveedor de almacenamiento prediga cuándo debe proporcionar la siguiente prueba de almacenamiento.
#### Compras ####
El módulo de compra en el software del nodo interactúa con el contrato inteligente en nombre del operador del nodo. Publica solicitudes de almacenamiento y maneja cualquier otra interacción que se requiera durante la vida útil de la solicitud. Por ejemplo, cuando una solicitud se cancela porque no hay suficientes proveedores de almacenamiento interesados, entonces el módulo de compra puede retirar los tokens que estaban asociados con la solicitud.
#### Ventas ####
El módulo de ventas es la contraparte del módulo de ventas. Monitorea el contrato inteligente para ser notificado de las solicitudes de almacenamiento entrantes. Mantiene una lista de las solicitudes más prometedoras que puede cumplir. Favorecerá aquellas solicitudes que tengan una alta recompensa y baja garantía. Tan pronto como encuentra una solicitud adecuada, intentará primero reservar y luego llenar un slot descargando los datos asociados, creando una prueba de almacenamiento y publicándola en el contrato inteligente. Luego continuará monitoreando el contrato inteligente para proporcionarle pruebas de almacenamiento cuando sean requeridas.
El módulo de ventas contiene una estrategia de mejor esfuerzo para determinar en qué solicitudes de almacenamiento está interesado. Con el tiempo, esperamos que surjan estrategias más especializadas para atender las necesidades de, por ejemplo, grandes proveedores versus proveedores que ejecutan un nodo desde su casa.
### Libro Blanco ###
Lee el [libro blanco de Codex](/learn/whitepaper)

245
es/learn/build.md Normal file
View File

@ -0,0 +1,245 @@
# Build Codex
## Table of Contents
- [Install developer tools](#prerequisites)
- [Linux](#linux)
- [macOS](#macos)
- [Windows + MSYS2](#windows-msys2)
- [Other](#other)
- [Clone and prepare the Git repository](#repository)
- [Build the executable](#executable)
- [Run the example](#example-usage)
**Optional**
- [Run the tests](#tests)
## Prerequisites
To build nim-codex, developer tools need to be installed and accessible in the OS.
Instructions below correspond roughly to environmental setups in nim-codex's [CI workflow](https://github.com/codex-storage/nim-codex/blob/master/.github/workflows/ci.yml) and are known to work.
Other approaches may be viable. On macOS, some users may prefer [MacPorts](https://www.macports.org/) to [Homebrew](https://brew.sh/). On Windows, rather than use MSYS2, some users may prefer to install developer tools with [winget](https://docs.microsoft.com/en-us/windows/package-manager/winget/), [Scoop](https://scoop.sh/), or [Chocolatey](https://chocolatey.org/), or download installers for e.g. Make and CMake while otherwise relying on official Windows developer tools. Community contributions to these docs and our build system are welcome!
### Rust
The current implementation of Codex's zero-knowledge proving circuit requires the installation of rust v1.79.0 or greater. Be sure to install it for your OS and add it to your terminal's path such that the command `cargo --version` gives a compatible version.
### Linux
> [!WARNING]
> Linux builds currently require gcc $\leq$ 13. If this is not an option in your
> system, you can try [building within Docker](#building-within-docker) as a workaround.
*Package manager commands may require `sudo` depending on OS setup.*
On a bare bones installation of Debian (or a distribution derived from Debian, such as Ubuntu), run
```shell
apt-get update && apt-get install build-essential cmake curl git rustc cargo
```
Non-Debian distributions have different package managers: `apk`, `dnf`, `pacman`, `rpm`, `yum`, etc.
For example, on a bare bones installation of Fedora, run
```shell
dnf install @development-tools cmake gcc-c++ rust cargo
```
In case your distribution does not provide required Rust version, we may install it using [rustup](https://www.rust-lang.org/tools/install)
```shell
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs/ | sh -s -- --default-toolchain=1.79.0 -y
. "$HOME/.cargo/env"
```
Note that you will currently not be able to build Codex with gcc 14. To verify that
you have a supported version, run:
```shell
gcc --version
```
If you get a number that starts with 14 (e.g. `14.2.0`), then you need to either
downgrade, or try a workaround like [building within Docker](#building-within-docker).
### macOS
Install the [Xcode Command Line Tools](https://mac.install.guide/commandlinetools/index.html) by opening a terminal and running
```shell
xcode-select --install
```
Install [Homebrew (`brew`)](https://brew.sh/) and in a new terminal run
```shell
brew install bash cmake rust
```
Check that `PATH` is setup correctly
```shell
which bash cmake
# /usr/local/bin/bash
# /usr/local/bin/cmake
```
### Windows + MSYS2
*Instructions below assume the OS is 64-bit Windows and that the hardware or VM is [x86-64](https://en.wikipedia.org/wiki/X86-64) compatible.*
Download and run the installer from [msys2.org](https://www.msys2.org/).
Launch an MSYS2 [environment](https://www.msys2.org/docs/environments/). UCRT64 is generally recommended: from the Windows *Start menu* select `MSYS2 MinGW UCRT x64`.
Assuming a UCRT64 environment, in Bash run
```shell
pacman -Suy
pacman -S base-devel git unzip mingw-w64-ucrt-x86_64-toolchain mingw-w64-ucrt-x86_64-cmake mingw-w64-ucrt-x86_64-rust
```
We should downgrade GCC to version 13 [^gcc-14]
```shell
pacman -U --noconfirm \
https://repo.msys2.org/mingw/ucrt64/mingw-w64-ucrt-x86_64-gcc-13.2.0-6-any.pkg.tar.zst \
https://repo.msys2.org/mingw/ucrt64/mingw-w64-ucrt-x86_64-gcc-libs-13.2.0-6-any.pkg.tar.zst
```
<!-- #### Headless Windows container -->
<!-- add instructions re: getting setup with MSYS2 in a Windows container -->
<!-- https://github.com/StefanScherer/windows-docker-machine -->
#### Optional: VSCode Terminal integration
You can link the MSYS2-UCRT64 terminal into VSCode by modifying the configuration file as shown below.
File: `C:/Users/<username>/AppData/Roaming/Code/User/settings.json`
```json
{
...
"terminal.integrated.profiles.windows": {
...
"MSYS2-UCRT64": {
"path": "C:\\msys64\\usr\\bin\\bash.exe",
"args": [
"--login",
"-i"
],
"env": {
"MSYSTEM": "UCRT64",
"CHERE_INVOKING": "1",
"MSYS2_PATH_TYPE": "inherit"
}
}
}
}
```
### Other
It is possible that nim-codex can be built and run on other platforms supported by the [Nim](https://nim-lang.org/) language: BSD family, older versions of Windows, etc. There has not been sufficient experimentation with nim-codex on such platforms, so instructions are not provided. Community contributions to these docs and our build system are welcome!
## Repository
In Bash run
```shell
git clone https://github.com/codex-storage/nim-codex.git repos/nim-codex && cd repos/nim-codex
```
nim-codex uses the [nimbus-build-system](https://github.com/status-im/nimbus-build-system), so next run
```shell
make update
```
This step can take a while to complete because by default it builds the [Nim compiler](https://nim-lang.org/docs/nimc.html).
To see more output from `make` pass `V=1`. This works for all `make` targets in projects using the nimbus-build-system
```shell
make V=1 update
```
## Executable
In Bash run
```shell
make
```
The default `make` target creates the `build/codex` executable.
## Tools
### Circuit download tool
To build the circuit download tool located in `tools/cirdl` run:
```shell
make cirdl
```
## Example usage
See the instructions in the [Quick Start](/learn/quick-start).
## Tests
In Bash run
```shell
make test
```
### testAll
#### Prerequisites
To run the integration tests, an Ethereum test node is required. Follow these instructions to set it up.
##### Windows (do this before 'All platforms')
1. Download and install Visual Studio 2017 or newer. (Not VSCode!) In the Workloads overview, enable `Desktop development with C++`. ( https://visualstudio.microsoft.com )
##### All platforms
1. Install NodeJS (tested with v18.14.0), consider using NVM as a version manager. [Node Version Manager (`nvm`)](https://github.com/nvm-sh/nvm#readme)
1. Open a terminal
1. Go to the vendor/codex-contracts-eth folder: `cd /<git-root>/vendor/codex-contracts-eth/`
1. `npm install` -> Should complete with the number of packages added and an overview of known vulnerabilities.
1. `npm test` -> Should output test results. May take a minute.
Before the integration tests are started, you must start the Ethereum test node manually.
1. Open a terminal
1. Go to the vendor/codex-contracts-eth folder: `cd /<git-root>/vendor/codex-contracts-eth/`
1. `npm start` -> This should launch Hardhat, and output a number of keys and a warning message.
#### Run
The `testAll` target runs the same tests as `make test` and also runs tests for nim-codex's Ethereum contracts, as well a basic suite of integration tests.
To run `make testAll`.
Use a new terminal to run:
```shell
make testAll
```
## Building Within Docker
For the specific case of Linux distributions which ship with gcc 14
and a downgrade to 13 is not possible/desirable, building within a Docker
container and pulling the binaries out by copying or mounting remains an
option; e.g.:
```bash=
# Clone original repo.
git clone https://github.com/codex-storage/nim-codex
# Build inside docker
docker build -t codexstorage/nim-codex:latest -f nim-codex/docker/codex.Dockerfile nim-codex
# Extract executable
docker create --name=codex-build codexstorage/nim-codex:latest
docker cp codex-build:/usr/local/bin/codex ./codex
docker cp codex-build:/usr/local/bin/cirdl ./cirdl
```
and voilà, you should have the binaries available in the current folder.

67
es/learn/download-flow.md Normal file
View File

@ -0,0 +1,67 @@
# Download Flow
Sequence of interactions that result in dat blocks being transferred across the network.
## Local Store
When data is available in the local blockstore,
```mermaid
sequenceDiagram
actor Alice
participant API
Alice->>API: Download(CID)
API->>+Node/StoreStream: Retrieve(CID)
loop Get manifest block, then data blocks
Node/StoreStream->>NetworkStore: GetBlock(CID)
NetworkStore->>LocalStore: GetBlock(CID)
LocalStore->>NetworkStore: Block
NetworkStore->>Node/StoreStream: Block
end
Node/StoreStream->>Node/StoreStream: Handle erasure coding
Node/StoreStream->>-API: Data stream
API->>Alice: Stream download of block
```
## Network Store
When data is not found ih the local blockstore, the block-exchange engine is used to discover the location of the block within the network. Connection will be established to the node(s) that have the block, and exchange can take place.
```mermaid
sequenceDiagram
box
actor Alice
participant API
participant Node/StoreStream
participant NetworkStore
participant Discovery
participant Engine
end
box
participant OtherNode
end
Alice->>API: Download(CID)
API->>+Node/StoreStream: Retrieve(CID)
Node/StoreStream->>-API: Data stream
API->>Alice: Download stream begins
loop Get manifest block, then data blocks
Node/StoreStream->>NetworkStore: GetBlock(CID)
NetworkStore->>Engine: RequestBlock(CID)
opt CID not known
Engine->>Discovery: Discovery Block
Discovery->>Discovery: Locates peers who provide block
Discovery->>Engine: Peers
Engine->>Engine: Update peers admin
end
Engine->>Engine: Select optimal peer
Engine->>OtherNode: Send WantHave list
OtherNode->>Engine: Send BlockPresence
Engine->>Engine: Update peers admin
Engine->>Engine: Decide to buy block
Engine->>OtherNode: Send WantBlock list
OtherNode->>Engine: Send Block
Engine->>NetworkStore: Block
NetworkStore->>NetworkStore: Add to Local store
NetworkStore->>Node/StoreStream: Resolve Block
Node/StoreStream->>Node/StoreStream: Handle erasure coding
Node/StoreStream->>API: Push data to stream
end
API->>Alice: Download stream finishes
```

View File

@ -0,0 +1,669 @@
---
outline: [2, 3]
---
# Running a Local Codex Network with Marketplace Support
This tutorial will teach you how to run a small Codex network with the
_storage marketplace_ enabled; i.e., the functionality in Codex which
allows participants to offer and buy storage in a market, ensuring that
storage providers honor their part of the deal by means of cryptographic proofs.
In this tutorial, you will:
1. [Set Up a Geth PoA network](#_1-set-up-a-geth-poa-network);
2. [Set up The Marketplace](#_2-set-up-the-marketplace);
3. [Run Codex](#_3-run-codex);
4. [Buy and Sell Storage in the Marketplace](#_4-buy-and-sell-storage-on-the-marketplace).
## Prerequisites
To complete this tutorial, you will need:
* the [geth](https://github.com/ethereum/go-ethereum) Ethereum client;
You need version `1.13.x` of geth as newer versions no longer support
Proof of Authority (PoA). This tutorial was tested using geth version `1.13.15`.
* a Codex binary, which [you can compile from source](https://github.com/codex-storage/nim-codex?tab=readme-ov-file#build-and-run).
We will also be using [bash](https://en.wikipedia.org/wiki/Bash_(Unix_shell))
syntax throughout. If you use a different shell, you may need to adapt
things to your platform.
To get started, create a new folder where we will keep the tutorial-related
files so that we can keep them separate from the codex repository.
We assume the name of the folder to be `marketplace-tutorial`.
## 1. Set Up a Geth PoA Network
For this tutorial, we will use a simple
[Proof-of-Authority](https://github.com/ethereum/EIPs/issues/225) network
with geth. The first step is creating a _signer account_: an account which
will be used by geth to sign the blocks in the network.
Any block signed by a signer is accepted as valid.
### 1.1. Create a Signer Account
To create a signer account, from the `marketplace-tutorial` directory run:
```bash
geth account new --datadir geth-data
```
The account generator will ask you to input a password, which you can
leave blank. It will then print some information,
including the account's public address:
```bash
INFO [09-29|16:49:24.244] Maximum peer count ETH=50 total=50
Your new account is locked with a password. Please give a password. Do not forget this password.
Password:
Repeat password:
Your new key was generated
Public address of the key: 0x33A904Ad57D0E2CB8ffe347D3C0E83C2e875E7dB
Path of the secret key file: geth-data/keystore/UTC--2024-09-29T14-49-31.655272000Z--33a904ad57d0e2cb8ffe347d3c0e83c2e875e7db
- You can share your public address with anyone. Others need it to interact with you.
- You must NEVER share the secret key with anyone! The key controls access to your funds!
- You must BACKUP your key file! Without the key, it's impossible to access account funds!
- You must REMEMBER your password! Without the password, it's impossible to decrypt the key!
```
In this example, the public address of the signer account is
`0x33A904Ad57D0E2CB8ffe347D3C0E83C2e875E7dB`.
Yours will print a different address. Save it for later usage.
Next set an environment variable for later usage:
```bash
export GETH_SIGNER_ADDR="0x0000000000000000000000000000000000000000"
echo ${GETH_SIGNER_ADDR} > geth_signer_address.txt
```
> Here make sure you replace `0x0000000000000000000000000000000000000000`
> with your public address of the signer account
> (`0x33A904Ad57D0E2CB8ffe347D3C0E83C2e875E7dB` in our example).
### 1.2. Configure The Network and Create the Genesis Block
The next step is telling geth what kind of network you want to run.
We will be running a [pre-merge](https://ethereum.org/en/roadmap/merge/)
network with Proof-of-Authority consensus.
To get that working, create a `network.json` file.
If you set the `GETH_SIGNER_ADDR` variable above you can run the following
command to create the `network.json` file:
```bash
echo "{\"config\": { \"chainId\": 12345, \"homesteadBlock\": 0, \"eip150Block\": 0, \"eip155Block\": 0, \"eip158Block\": 0, \"byzantiumBlock\": 0, \"constantinopleBlock\": 0, \"petersburgBlock\": 0, \"istanbulBlock\": 0, \"berlinBlock\": 0, \"londonBlock\": 0, \"arrowGlacierBlock\": 0, \"grayGlacierBlock\": 0, \"clique\": { \"period\": 1, \"epoch\": 30000 } }, \"difficulty\": \"1\", \"gasLimit\": \"8000000\", \"extradata\": \"0x0000000000000000000000000000000000000000000000000000000000000000${GETH_SIGNER_ADDR:2}0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\", \"alloc\": { \"${GETH_SIGNER_ADDR}\": { \"balance\": \"10000000000000000000000\"}}}" > network.json
```
You can also manually create the file remembering update it with your
signer public address:
```json
{
"config": {
"chainId": 12345,
"homesteadBlock": 0,
"eip150Block": 0,
"eip155Block": 0,
"eip158Block": 0,
"byzantiumBlock": 0,
"constantinopleBlock": 0,
"petersburgBlock": 0,
"istanbulBlock": 0,
"berlinBlock": 0,
"londonBlock": 0,
"arrowGlacierBlock": 0,
"grayGlacierBlock": 0,
"clique": {
"period": 1,
"epoch": 30000
}
},
"difficulty": "1",
"gasLimit": "8000000",
"extradata": "0x000000000000000000000000000000000000000000000000000000000000000033A904Ad57D0E2CB8ffe347D3C0E83C2e875E7dB0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"alloc": {
"0x33A904Ad57D0E2CB8ffe347D3C0E83C2e875E7dB": {
"balance": "10000000000000000000000"
}
}
}
```
Note that the signer account address is embedded in two different places:
* inside of the `"extradata"` string, surrounded by zeroes and stripped of
its `0x` prefix;
* as an entry key in the `alloc` session.
Make sure to replace that ID with the account ID that you wrote down in
[Step 1.1](#_1-1-create-a-signer-account).
Once `network.json` is created, you can initialize the network with:
```bash
geth init --datadir geth-data network.json
```
The output of the above command you may include some warnings, like:
```bash
WARN [08-21|14:48:12.305] Unknown config environment variable envvar=GETH_SIGNER_ADDR
```
or even errors when running the command for the first time:
```bash
ERROR[08-21|14:48:12.399] Head block is not reachable
```
The important part is that at the end you should see something similar to:
```bash
INFO [08-21|14:48:12.639] Successfully wrote genesis state database=lightchaindata hash=768bf1..42d06a
```
### 1.3. Start your PoA Node
We are now ready to start our $1$-node, private blockchain.
To launch the signer node, open a separate terminal in the same working
directory and make sure you have the `GETH_SIGNER_ADDR` set.
For convenience use the `geth_signer_address.txt`:
```bash
export GETH_SIGNER_ADDR=$(cat geth_signer_address.txt)
```
Having the `GETH_SIGNER_ADDR` variable set, run:
```bash
geth\
--datadir geth-data\
--networkid 12345\
--unlock ${GETH_SIGNER_ADDR}\
--nat extip:127.0.0.1\
--netrestrict 127.0.0.0/24\
--mine\
--miner.etherbase ${GETH_SIGNER_ADDR}\
--http\
--allow-insecure-unlock
```
Note that, once again, the signer account created in
[Step 1.1](#_1-1-create-a-signer-account) appears both in
`--unlock` and `--allow-insecure-unlock`.
Geth will prompt you to insert the account's password as it starts up.
Once you do that, it should be able to start up and begin "mining" blocks.
Also here, you may encounter errors like:
```bash
ERROR[08-21|15:00:27.625] Bootstrap node filtered by netrestrict id=c845e51a5e470e44 ip=18.138.108.67
ERROR[08-21|15:00:27.625] Bootstrap node filtered by netrestrict id=f23ac6da7c02f84a ip=3.209.45.79
ERROR[08-21|15:00:27.625] Bootstrap node filtered by netrestrict id=ef2d7ab886910dc8 ip=65.108.70.101
ERROR[08-21|15:00:27.625] Bootstrap node filtered by netrestrict id=6b36f791352f15eb ip=157.90.35.166
```
You can safely ignore them.
If the command above fails with:
```bash
Fatal: Failed to register the Ethereum service: only PoS networks are supported, please transition old ones with Geth v1.13.x
```
make sure, you are running the correct Geth version
(see Section [Prerequisites](#prerequisites))
## 2. Set Up The Marketplace
You will need to open new terminal for this section and geth needs to be
running already. Setting up the Codex marketplace entails:
1. Deploying the Codex Marketplace contracts to our private blockchain
2. Setup Ethereum accounts we will use to buy and sell storage in
the Codex marketplace
3. Provisioning those accounts with the required token balances
### 2.1. Deploy the Codex Marketplace Contracts
Make sure you leave the `marketplace-tutorial` directory, and clone
the `codex-storage/nim-codex.git`:
```bash
git clone https://github.com/codex-storage/nim-codex.git
```
> If you just want to clone the repo to run the tutorial, you can
> skip the history and just download the head of the master branch by using
> `--depth 1` option: `git clone --depth 1 https://github.com/codex-storage/nim-codex.git`
Thus, our directory structure for the purpose of this tutorial looks like this:
```bash
|
|-- nim-codex
└-- marketplace-tutorial
```
> You could clone the `codex-storage/nim-codex.git` to some other location.
> Just to keeps things nicely separated it is best to make sure that
> `nim-codex` is not under `marketplace-tutorial` directory.
Now, from the `nim-codex` folder run:
```bash
make update && make
```
> This may take a moment as it will also build the `nim` compiler. Be patient.
Now, in order to start a local Ethereum network run:
```bash
cd vendor/codex-contracts-eth
npm install
```
> While writing the document we used `node` version `v20.17.0` and
> `npm` version `10.8.2`.
Before continuing you now must **wait until $256$ blocks are mined**
**in your PoAnetwork**, or deploy will fail. This should take about
$4$ minutes and $30$ seconds. You can check which block height you are
currently at by running the following command
**from the `marketplace-tutorial` folder**:
```bash
geth attach --exec web3.eth.blockNumber ./geth-data/geth.ipc
```
once that gets past $256$, you are ready to go.
To deploy contracts, from the `codex-contracts-eth` directory run:
```bash
export DISTTEST_NETWORK_URL=http://localhost:8545
npx hardhat --network codexdisttestnetwork deploy
```
If the command completes successfully, you will see the output similar
to this one:
```bash
Deployed Marketplace with Groth16 Verifier at:
0xCf0df6C52B02201F78E8490B6D6fFf5A82fC7BCd
```
> of course your address will be different.
You are now ready to prepare the accounts.
### 2.2. Generate the Required Accounts
We will run $2$ Codex nodes: a **storage provider**, which will sell storage
on the network, and a **client**, which will buy and use such storage;
we therefore need two valid Ethereum accounts. We could create random
accounts by using one of the many tools available to that end but, since
this is a tutorial running on a local private network, we will simply
provide you with two pre-made accounts along with their private keys,
which you can copy and paste instead:
First make sure you're back in the `marketplace-tutorial` folder and
not the `codex-contracts-eth` subfolder. Then set these variables:
**Storage:**
```bash
export ETH_STORAGE_ADDR=0x45BC5ca0fbdD9F920Edd12B90908448C30F32a37
export ETH_STORAGE_PK=0x06c7ac11d4ee1d0ccb53811b71802fa92d40a5a174afad9f2cb44f93498322c3
echo $ETH_STORAGE_PK > storage.pkey && chmod 0600 storage.pkey
```
**Client:**
```bash
export ETH_CLIENT_ADDR=0x9F0C62Fe60b22301751d6cDe1175526b9280b965
export ETH_CLIENT_PK=0x5538ec03c956cb9d0bee02a25b600b0225f1347da4071d0fd70c521fdc63c2fc
echo $ETH_CLIENT_PK > client.pkey && chmod 0600 client.pkey
```
### 2.3. Provision Accounts with Tokens
We now need to transfer some ETH to each of the accounts, as well as provide
them with some Codex tokens for the storage node to use as collateral and
for the client node to buy actual storage.
Although the process is not particularly complicated, I suggest you use
[the script we prepared](https://github.com/gmega/local-codex-bare/blob/main/scripts/mint-tokens.js)
for that. This script, essentially:
1. reads the Marketplace contract address and its ABI from the deployment data;
2. transfers $1$ ETH from the signer account to a target account if the target
account has no ETH balance;
3. mints $n$ Codex tokens and adds it into the target account's balance.
To use the script, just download it into a local file named `mint-tokens.js`,
for instance using `curl` (make sure you are in
the `marketplace-tutorial` directory):
```bash
# download script
curl https://raw.githubusercontent.com/gmega/codex-local-bare/main/scripts/mint-tokens.js -o mint-tokens.js
```
Then run:
```bash
# set the contract file location (we assume you are in the marketplace-tutorial directory)
export CONTRACT_DEPLOY_FULL="../nim-codex/vendor/codex-contracts-eth/deployments/codexdisttestnetwork"
export GETH_SIGNER_ADDR=$(cat geth_signer_address.txt)
# Installs Web3-js
npm install web3
# Provides tokens to the storage account.
node ./mint-tokens.js $CONTRACT_DEPLOY_FULL/TestToken.json $GETH_SIGNER_ADDR 0x45BC5ca0fbdD9F920Edd12B90908448C30F32a37 10000000000
# Provides tokens to the client account.
node ./mint-tokens.js $CONTRACT_DEPLOY_FULL/TestToken.json $GETH_SIGNER_ADDR 0x9F0C62Fe60b22301751d6cDe1175526b9280b965 10000000000
```
If you get a message like
```bash
Usage: mint-tokens.js <token-hardhat-deploy-json> <signer-account> <receiver-account> <token-ammount>
```
then you need to ensure you provided all the required arguments.
In particular you need to ensure that the `GETH_SIGNER_ADDR` env variable
holds the signer address (we used
`export GETH_SIGNER_ADDR=$(cat geth_signer_address.txt)` above to
make sure it is set).
## 3. Run Codex
With accounts and geth in place, we can now start the Codex nodes.
### 3.1. Storage Node
The storage node will be the one storing data and submitting the proofs of
storage to the chain. To do that, it needs access to:
1. the address of the Marketplace contract that has been deployed to
the local geth node in [Step 2.1](#_2-1-deploy-the-codex-marketplace-contracts);
2. the sample ceremony files which are shipped in the Codex contracts repo
(`nim-codex/vendor/codex-contracts-eth`).
**Address of the Marketplace Contract.** The contract address can be found
inside of the file `nim-codex/vendor/codex-contracts-eth/deployments/codexdisttestnetwork/Marketplace.json`.
We captured that location above in `CONTRACT_DEPLOY_FULL` variable, thus, from
the `marketplace-tutorial` folder just run:
```bash
grep '"address":' ${CONTRACT_DEPLOY_FULL}/Marketplace.json
```
which should print something like:
```bash
"address": "0xCf0df6C52B02201F78E8490B6D6fFf5A82fC7BCd",
```
> This address should match the address we got earlier when deploying
> the Marketplace contract above.
Then run the following with the correct market place address:
```bash
export MARKETPLACE_ADDRESS="0x0000000000000000000000000000000000000000"
echo ${MARKETPLACE_ADDRESS} > marketplace_address.txt
```
where you replace `0x0000000000000000000000000000000000000000` with
the Marketplace contract above in
[Step 2.1](#_2-1-deploy-the-codex-marketplace-contracts).
**Prover ceremony files.** The ceremony files are under the
`nim-codex/vendor/codex-contracts-eth/verifier/networks/codexdisttestnetwork`
subdirectory. There are three of them: `proof_main.r1cs`, `proof_main.zkey`,
and `prooof_main.wasm`. We will need all of them to start the Codex storage node.
**Starting the storage node.** Let:
* `PROVER_ASSETS` contain the directory where the prover ceremony files are
located. **This must be an absolute path**;
* `CODEX_BINARY` contain the location of your Codex binary;
* `MARKETPLACE_ADDRESS` contain the address of the Marketplace contract
(we have already set it above).
Set these paths into environment variables (make sure you are in
the `marketplace-tutorial` directory):
```bash
export CONTRACT_DEPLOY_FULL=$(realpath "../nim-codex/vendor/codex-contracts-eth/deployments/codexdisttestnetwork")
export PROVER_ASSETS=$(realpath "../nim-codex/vendor/codex-contracts-eth/verifier/networks/codexdisttestnetwork/")
export CODEX_BINARY=$(realpath "../nim-codex/build/codex")
export MARKETPLACE_ADDRESS=$(cat marketplace_address.txt)
```
> you may notice, that we have already set the `CONTRACT_DEPLOY_FULL` variable
> above. Here, we make sure it is an absolute path.
To launch the storage node, run:
```bash
${CODEX_BINARY}\
--data-dir=./codex-storage\
--listen-addrs=/ip4/0.0.0.0/tcp/8080\
--api-port=8000\
--disc-port=8090\
persistence\
--eth-provider=http://localhost:8545\
--eth-private-key=./storage.pkey\
--marketplace-address=${MARKETPLACE_ADDRESS}\
--validator\
--validator-max-slots=1000\
prover\
--circom-r1cs=${PROVER_ASSETS}/proof_main.r1cs\
--circom-wasm=${PROVER_ASSETS}/proof_main.wasm\
--circom-zkey=${PROVER_ASSETS}/proof_main.zkey
```
**Starting the client node.**
The client node is started similarly except that:
* we need to pass the SPR of the storage node so it can form a network with it;
* since it does not run any proofs, it does not require any ceremony files.
We get the Signed Peer Record (SPR) of the storage node so we can bootstrap
the client node with it. To get the SPR, issue the following call:
```bash
curl -H 'Accept: text/plain' 'http://localhost:8000/api/codex/v1/spr' --write-out '\n'
```
You should get the SPR back starting with `spr:`.
Before you proceed, open new terminal, and enter `marketplace-tutorial` directory.
Next set these paths into environment variables:
```bash
# set the SPR for the storage node
export STORAGE_NODE_SPR=$(curl -H 'Accept: text/plain' 'http://localhost:8000/api/codex/v1/spr')
# basic vars
export CONTRACT_DEPLOY_FULL=$(realpath "../nim-codex/vendor/codex-contracts-eth/deployments/codexdisttestnetwork")
export CODEX_BINARY=$(realpath "../nim-codex/build/codex")
export MARKETPLACE_ADDRESS=$(cat marketplace_address.txt)
```
and then run:
```bash
${CODEX_BINARY}\
--data-dir=./codex-client\
--listen-addrs=/ip4/0.0.0.0/tcp/8081\
--api-port=8001\
--disc-port=8091\
--bootstrap-node=${STORAGE_NODE_SPR}\
persistence\
--eth-provider=http://localhost:8545\
--eth-private-key=./client.pkey\
--marketplace-address=${MARKETPLACE_ADDRESS}
```
## 4. Buy and Sell Storage on the Marketplace
Any storage negotiation has two sides: a buyer and a seller.
Therefore, before we can actually request storage, we must first offer
some of it for sale.
### 4.1 Sell Storage
The following request will cause the storage node to put out $50\text{MB}$
of storage for sale for $1$ hour, at a price of $1$ Codex token
per slot per second, while expressing that it's willing to take at most
a $1000$ Codex token penalty for not fulfilling its part of the contract.[^1]
```bash
curl 'http://localhost:8000/api/codex/v1/sales/availability' \
--header 'Content-Type: application/json' \
--data '{
"totalSize": "50000000",
"duration": "3600",
"minPrice": "1",
"maxCollateral": "1000"
}'
```
This should return a JSON response containing an `id` (e.g. `"id": "0xb55b3bc7aac2563d5bf08ce8a177a38b5a40254bfa7ee8f9c52debbb176d44b0"`)
which identifies this storage offer.
> To make JSON responses more readable, you can try
> [jq](https://jqlang.github.io/jq/) JSON formatting utility
> by just adding `| jq` after the command.
> On macOS you can install with `brew install jq`.
To check the current storage offers for this node, you can issue:
```bash
curl 'http://localhost:8000/api/codex/v1/sales/availability'
```
or with `jq`:
```bash
curl 'http://localhost:8000/api/codex/v1/sales/availability' | jq
```
This should print a list of offers, with the one you just created figuring
among them (for our tutorial, there will be only one offer returned
at this time).
### 4.2. Buy Storage
Before we can buy storage, we must have some actual data to request
storage for. Start by uploading a small file to your client node.
On Linux (or macOS) you could, for instance, use `dd` to generate a $1M$ file:
```bash
dd if=/dev/urandom of=./data.bin bs=1M count=1
```
Assuming your file is named `data.bin`, you can upload it with:
```bash
curl --request POST http://localhost:8001/api/codex/v1/data --header 'Content-Type: application/octet-stream' --write-out '\n' -T ./data.bin
```
Once the upload completes, you should see a _Content Identifier_,
or _CID_ (e.g. `zDvZRwzm2mK7tvDzKScRLapqGdgNTLyyEBvx1TQY37J2CdWdS6Sj`)
for the uploaded file printed to the terminal.
Use that CID in the purchase request:
```bash
# make sure to replace the CID before with the CID you got in the previous step
export CID=zDvZRwzm2mK7tvDzKScRLapqGdgNTLyyEBvx1TQY37J2CdWdS6Sj
```
```bash
curl "http://localhost:8001/api/codex/v1/storage/request/${CID}" \
--header 'Content-Type: application/octet-stream' \
--data "{
\"duration\": \"600\",
\"reward\": \"1\",
\"proofProbability\": \"3\",
\"expiry\": \"500\",
\"nodes\": 3,
\"tolerance\": 1,
\"collateral\": \"1000\"
}" \
--write-out '\n'
```
The parameters under `--data` say that:
1. we want to purchase storage for our file for $5$ minutes (`"duration": "600"`);
2. we are willing to pay up to $1$ token per slot per second (`"reward": "1"`)
3. our file will be split into three pieces (`"nodes": 3`).
Because we set `"tolerance": 1` we only need two (`nodes - tolerance`)
pieces to rebuild the file; i.e., we can tolerate that at most one node
stops storing our data; either due to failure or other reasons;
4. we demand `1000` tokens in collateral from storage providers for each piece.
Since there are $3$ such pieces, there will be `3000` in total collateral
committed by the storage provider(s) once our request is started.
5. finally, the `expiry` puts a time limit for filling all the slots by
the storage provider(s). If slot are not filled by the `expire` interval,
the request will timeout and fail.
### 4.3. Track your Storage Requests
POSTing a storage request will make it available in the storage market,
and a storage node will eventually pick it up.
You can poll the status of your request by means of:
```bash
export STORAGE_PURCHASE_ID="1d0ec5261e3364f8b9d1cf70324d70af21a9b5dccba380b24eb68b4762249185"
curl "http://localhost:8001/api/codex/v1/storage/purchases/${STORAGE_PURCHASE_ID}"
```
For instance:
```bash
> curl 'http://localhost:8001/api/codex/v1/storage/purchases/6c698cd0ad71c41982f83097d6fa75beb582924e08a658357a1cd4d7a2a6766d'
```
This returns a result like:
```json
{
"requestId": "0x86501e4677a728c6a8031971d09b921c3baa268af06b9f17f1b745e7dba5d330",
"request": {
"client": "0x9f0c62fe60b22301751d6cde1175526b9280b965",
"ask": {
"slots": 3,
"slotSize": "262144",
"duration": "1000",
"proofProbability": "3",
"reward": "1",
"collateral": "1",
"maxSlotLoss": 1
},
"content": {
"cid": "zDvZRwzkyw1E7ABaUSmgtNEDjC7opzhUoHo99Vpvc98cDWeCs47u"
},
"expiry": "1711992852",
"nonce": "0x9f5e651ecd3bf73c914f8ed0b1088869c64095c0d7bd50a38fc92ebf66ff5915",
"id": "0x6c698cd0ad71c41982f83097d6fa75beb582924e08a658357a1cd4d7a2a6766d"
},
"state": "submitted",
"error": null
}
```
Shows that a request has been submitted but has not yet been filled.
Your request will be successful once `"state"` shows `"started"`.
Anything other than that means the request has not been completely
processed yet, and an `"error"` state other than `null` means it failed.
Well, it was quite a journey, wasn't it? You can congratulate yourself for
successfully finishing the codex marketplace tutorial!
[^1]: Codex files get partitioned into pieces called "slots" and distributed
to various storage providers. The collateral refers to one such slot,
and will be slowly eaten away as the storage provider fails to deliver
timely proofs, but the actual logic is [more involved than that](https://github.com/codex-storage/codex-contracts-eth/blob/6c9f797f408608958714024b9055fcc330e3842f/contracts/Marketplace.sol#L209).

View File

@ -0,0 +1,224 @@
# Codex Two-Client Test
The two-client test is a manual test you can perform to check your setup and familiarize yourself with the Codex API. These steps will guide you through running and connecting two nodes, in order to upload a file to one and then download that file from the other. This test also includes running a local blockchain node in order to have the Marketplace functionality available. However, running a local blockchain node is not strictly necessary, and you can skip steps marked as optional if you choose not start a local blockchain node.
## Prerequisite
Make sure you have [built the client](/learn/build) or obtained [compiled binary](/learn/quick-start#get-codex-binary).
## Steps
### 0. Setup blockchain node (optional)
You need to have installed NodeJS and npm in order to spinup a local blockchain node.
Go to directory `vendor/codex-contracts-eth` and run these two commands:
```
npm ci
npm start
```
This will launch a local Ganache blockchain.
### 1. Launch Node #1
Open a terminal and run:
- Mac/Linux:
```shell
codex \
--data-dir="$(pwd)/Data1" \
--api-port=8080 \
--disc-port=8090 \
--listen-addrs="/ip4/127.0.0.1/tcp/8070"
```
- Windows:
```batch
codex.exe ^
--data-dir="Data1" ^
--api-port=8080 ^
--disc-port=8090 ^
--listen-addrs="/ip4/127.0.0.1/tcp/8070"
```
Optionally, if you want to use the Marketplace blockchain functionality, you need to also include these flags: `--persistence --eth-account=<account>`, where `account` can be one following:
- `0x70997970C51812dc3A010C7d01b50e0d17dc79C8`
- `0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC`
- `0x90F79bf6EB2c4f870365E785982E1f101E93b906`
- `0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65`
**For each node use a different account!**
| Argument | Description |
|----------------|-----------------------------------------------------------------------|
| `data-dir` | We specify a relative path where the node will store its data. |
| `listen-addrs` | Multiaddress where the node will accept connections from other nodes. |
| `api-port` | Port on localhost where the node will expose its API. |
| `disc-port` | Port the node will use for its discovery service. |
| `persistence` | Enables Marketplace functionality. Requires a blockchain connection. |
| `eth-account` | Defines which blockchain account the node should use. |
Codex uses sane defaults for most of its arguments. Here we specify some explicitly for the purpose of this walk-through.
### 2. Sign of life
Run the command :
```bash
curl -X GET http://127.0.0.1:8080/api/codex/v1/debug/info
```
This GET request will return the node's debug information. The response will be in JSON and should look like:
```json
{
"id": "16Uiu2HAmJ3TSfPnrJNedHy2DMsjTqwBiVAQQqPo579DuMgGxmG99",
"addrs": [
"/ip4/127.0.0.1/tcp/8070"
],
"repo": "/Users/user/projects/nim-codex/Data1",
"spr": "spr:CiUIAhIhA1AL2J7EWfg7x77iOrR9YYBisY6CDtU2nEhuwDaQyjpkEgIDARo8CicAJQgCEiEDUAvYnsRZ-DvHvuI6tH1hgGKxjoIO1TacSG7ANpDKOmQQ2MWasAYaCwoJBH8AAAGRAh-aKkYwRAIgB2ooPfAyzWEJDe8hD2OXKOBnyTOPakc4GzqKqjM2OGoCICraQLPWf0oSEuvmSroFebVQx-3SDtMqDoIyWhjq1XFF",
"announceAddresses": [
"/ip4/127.0.0.1/tcp/8070"
],
"table": {
"localNode": {
"nodeId": "f6e6d48fa7cd171688249a57de0c1aba15e88308c07538c91e1310c9f48c860a",
"peerId": "16Uiu2HAmJ3TSfPnrJNedHy2DMsjTqwBiVAQQqPo579DuMgGxmG99",
"record": "...",
"address": "0.0.0.0:8090",
"seen": false
},
"nodes": []
},
"codex": {
"version": "untagged build",
"revision": "b3e626a5"
}
}
```
| Field | Description |
| ------------------- | ---------------------------------------------------------------------------------------- |
| `id` | Id of the node. Also referred to as 'peerId'. |
| `addrs` | Multiaddresses currently open to accept connections from other nodes. |
| `repo` | Path of this node's data folder. |
| `spr` | Signed Peer Record, encoded information about this node and its location in the network. |
| `announceAddresses` | Multiaddresses used for annoucning this node |
| `table` | Table of nodes present in the node's DHT |
| `codex` | Codex version information |
### 3. Launch Node #2
We will need the signed peer record (SPR) from the first node that you got in the previous step.
Replace `<SPR HERE>` in the following command with the SPR returned from the previous command, note that it should include the `spr:` at the beginning.
Open a new terminal and run:
- Mac/Linux:
```shell
codex \
--data-dir="$(pwd)/Data2" \
--api-port=8081 \
--disc-port=8091 \
--listen-addrs=/ip4/127.0.0.1/tcp/8071 \
--bootstrap-node=<SPR HERE>
```
- Windows:
```
codex.exe ^
--data-dir="Data2" ^
--api-port=8081 ^
--disc-port=8091 ^
--listen-addrs=/ip4/127.0.0.1/tcp/8071 ^
--bootstrap-node=<SPR HERE>
```
Alternatively on Mac, Linux, or MSYS2 and a recent Codex binary you can run it in one command like:
```shell
codex \
--data-dir="$(pwd)/Data2" \
--api-port=8081 \
--disc-port=8091 \
--listen-addrs=/ip4/127.0.0.1/tcp/8071 \
--bootstrap-node=$(curl -H "Accept: text/plain" http://127.0.0.1:8080/api/codex/v1/spr)
```
Notice we're using a new data-dir, and we've increased each port number by one. This is needed so that the new node won't try to open ports already in use by the first node.
We're now also including the `bootstrap-node` argument. This allows us to link the new node to another one, bootstrapping our own little peer-to-peer network. SPR strings always start with `spr:`.
### 4. Connect The Two
Normally the two nodes will automatically connect. If they do not automatically connect or you want to manually connect nodes you can use the peerId to connect nodes.
You can get the first node's peer id by running the following command and finding the `"peerId"` in the results:
```shell
curl -X GET \
-H "Accept: text/plain" \
http://127.0.0.1:8081/api/codex/v1/peerid
```
Next replace `<PEER ID HERE>` in the following command with the peerId returned from the previous command:
```shell
curl -X GET \
http://127.0.0.1:8080/api/codex/v1/connect/<PEER ID HERE>?addrs=/ip4/127.0.0.1/tcp/8071
```
Alternatively on Mac, Linux, or MSYS2 and a recent Codex binary you can run it in one command like:
```shell
curl -X GET \
http://127.0.0.1:8080/api/codex/v1/connect/$(curl -X GET -H "Accept: text/plain" http://127.0.0.1:8081/api/codex/v1/peerid)\?addrs=/ip4/127.0.0.1/tcp/8071
```
Notice that we are sending the "`peerId`" and the multiaddress of node 2 to the `/connect` endpoint of node 1. This provides node 1 all the information it needs to communicate with node 2. The response to this request should be `Successfully connected to peer`.
### 5. Upload The File
We're now ready to upload a file to the network. In this example we'll use node 1 for uploading and node 2 for downloading. But the reverse also works.
Next replace `<FILE PATH>` with the path to the file you want to upload in the following command:
```shell
curl -X POST \
127.0.0.1:8080/api/codex/v1/data \
-H "Content-Type: application/octet-stream" \
-H "Expect: 100-continue" \
-T "<FILE PATH>"
```
> [!TIP]
> If curl is reluctant to show you the response, add `-o <FILENAME>` to write the result to a file.
Depending on the file size this may take a moment. Codex is processing the file by cutting it into blocks and generating erasure-recovery data. When the process is finished, the request will return the content-identifier (CID) of the uploaded file. It should look something like `zdj7WVxH8HHHenKtid8Vkgv5Z5eSUbCxxr8xguTUBMCBD8F2S`.
### 6. Download The File
Replace `<CID>` with the identifier returned in the previous step. Replace `<OUTPUT FILE>` with the filename where you want to store the downloaded file:
```bash
curl -X GET \
127.0.0.1:8081/api/codex/v1/data/<CID>/network \
-o <OUTPUT FILE>
```
Notice we are connecting to the second node in order to download the file. The CID we provide contains the information needed to locate the file within the network.
### 7. Verify The Results
If your file is downloaded and identical to the file you uploaded, then this manual test has passed. Rejoice! If on the other hand that didn't happen or you were unable to complete any of these steps, please leave us a message detailing your troubles.
## Notes
When using the Ganache blockchain, there are some deviations from the expected behavior, mainly linked to how blocks are mined, which affects certain functionalities in the Sales module.
Therefore, if you are manually testing processes such as payout collection after a request is finished or proof submissions, you need to mine some blocks manually for it to work correctly. You can do this by using the following curl command:
```shell
curl -X POST \
127.0.0.1:8545 \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"evm_mine","params":[],"id":67}'
```

150
es/learn/quick-start.md Normal file
View File

@ -0,0 +1,150 @@
# Quick Start
To run Codex through this guide we would need to perform the following steps:
- [Review the disclaimer](/codex/disclaimer)
- [Get Codex binary](#get-codex-binary)
- [Run Codex](#run-codex)
- [Interact with Codex](#interact-with-codex)
## Get Codex binary
For quick a start we will use precompiled binaries from [GitHub release page](https://github.com/codex-storage/nim-codex/releases). If you prefer to compile from the sources, please check [Build Codex](/learn/build).
Please follow the steps for your OS from the list:
- [Linux/macOS](#linux-macos)
- [Windows](#windows)
### Linux/macOS
1. Install latest Codex release
```shell
curl -s https://get.codex.storage/install.sh | bash
```
2. Install dependencies
```shell
# Debian-based Linux
sudo apt update && sudo apt install libgomp1
```
3. Check the result
```shell
codex --version
```
### Windows
1. Install latest Codex release
```batch
curl -sO https://get.codex.storage/install.cmd && install.cmd
```
> [!WARNING]
> Windows antivirus software and built-in firewalls may cause steps to fail. We will cover some possible errors here, but always consider checking your setup if requests fail - in particular, if temporarily disabling your antivirus fixes it, then it is likely to be the culprit.
If you see an error like:
```batch
curl: (35) schannel: next InitializeSecurityContext failed: CRYPT_E_NO_REVOCATION_CHECK (0x80092012) - The revocation function was unable to check revocation for the certificate.
```
You may need to add the `--ssl-no-revoke` option to your curl calls, i.e., modify the calls above so they look like this:
```batch
curl -LO --ssl-no-revoke https://...
```
2. Update path using console output
- Current session only
```batch
:: Default installation directory
set "PATH=%PATH%%LOCALAPPDATA%\Codex;"
```
- Update PATH permanently
- Control Panel --> System --> Advanced System settings --> Environment Variables
- Alternatively, type `environment variables` into the Windows Search box
3. Check the result
```shell
codex --version
```
## Run Codex
We may [run Codex in different modes](/learn/run#run), and for a quick start we will run [Codex node](/learn/run#codex-node), to be able to share files in the network.
1. Run Codex
**Linux/macOS**
```shell
codex \
--data-dir=datadir \
--disc-port=8090 \
--listen-addrs=/ip4/0.0.0.0/tcp/8070 \
--nat=`curl -s https://ip.codex.storage` \
--api-cors-origin="*" \
--bootstrap-node=spr:CiUIAhIhAiJvIcA_ZwPZ9ugVKDbmqwhJZaig5zKyLiuaicRcCGqLEgIDARo8CicAJQgCEiECIm8hwD9nA9n26BUoNuarCEllqKDnMrIuK5qJxFwIaosQ3d6esAYaCwoJBJ_f8zKRAnU6KkYwRAIgM0MvWNJL296kJ9gWvfatfmVvT-A7O2s8Mxp8l9c8EW0CIC-h-H-jBVSgFjg3Eny2u33qF7BDnWFzo7fGfZ7_qc9P
```
**Windows**
> [!WARNING]
> Windows might at this stage prompt you to grant internet access to Codex. You must allow it for things to work.
> It also might be required to add incoming firewall rules for Codex and we can use `netsh` utility.
<details>
<summary>add firewall rules using netsh</summary>
```batch
:: Add rules
netsh advfirewall firewall add rule name="Allow Codex (TCP-In)" protocol=TCP dir=in localport=8070 action=allow
netsh advfirewall firewall add rule name="Allow Codex (UDP-In)" protocol=UDP dir=in localport=8090 action=allow
:: List rules
netsh advfirewall firewall show rule name=all | find /I "Codex"
:: Delete rules
netsh advfirewall firewall delete rule name="Allow Codex (TCP-In)"
netsh advfirewall firewall delete rule name="Allow Codex (UDP-In)"
```
</details>
```batch
:: Get Public IP
for /f "delims=" %a in ('curl -s --ssl-reqd ip.codex.storage') do set nat=%a
:: Run Codex
codex ^
--data-dir=datadir ^
--disc-port=8090 ^
--listen-addrs=/ip4/0.0.0.0/tcp/8070 ^
--nat=%nat% ^
--api-cors-origin="*" ^
--bootstrap-node=spr:CiUIAhIhAiJvIcA_ZwPZ9ugVKDbmqwhJZaig5zKyLiuaicRcCGqLEgIDARo8CicAJQgCEiECIm8hwD9nA9n26BUoNuarCEllqKDnMrIuK5qJxFwIaosQ3d6esAYaCwoJBJ_f8zKRAnU6KkYwRAIgM0MvWNJL296kJ9gWvfatfmVvT-A7O2s8Mxp8l9c8EW0CIC-h-H-jBVSgFjg3Eny2u33qF7BDnWFzo7fGfZ7_qc9P
```
> [!TIP]
> In the example above we use [Codex Testnet](/networks/testnet#bootstrap-nodes) bootstrap nodes and thus we join Testnet. If you would like to join a different network, please use [appropriate value](/networks/networks).
2. Configure port-forwarding for the TCP/UDP ports on your Internet router
| Protocol | Service | Port |
| -------- | --------- | ------ |
| UDP | Discovery | `8090` |
| TCP | Transport | `8070` |
If you would like to purchase or sell storage, please consider to run [Codex node with marketplace support](/learn/run#codex-node-with-marketplace-support) or [Codex storage node](/learn/run#codex-storage-node).
## Interact with Codex
When your Codex node is up and running you can interact with it using [Codex App UI](https://app.codex.storage) for files sharing.
Also, you can interact with Codex using [Codex API](/developers/api) and for a walk-through of the API, consider following the [Using Codex](/learn/using) guide.
## Stay in touch
Want to stay up-date, or looking for further assistance? Try our [discord-server](https://discord.gg/codex-storage).
Ready to explore Codex functionality? Please [Join Codex Testnet](/networks/testnet).
If you want to run Codex locally without joining the Testnet, consider trying the [Codex Two-Client Test](/learn/local-two-client-test) or the [Running a Local Codex Network with Marketplace Support](/learn/local-marketplace).

586
es/learn/run.md Normal file
View File

@ -0,0 +1,586 @@
---
outline: [2, 4]
---
# Run Codex
As for now, Codex is implemented only in [Nim](https://nim-lang.org) and can be found in [nim-codex](https://github.com/codex-storage/nim-codex) repository.
It is a command-line application which may be run in a different ways:
- [Using binary](#using-binary)
- [Run as a daemon in Linux](#run-as-a-daemon-in-linux) (not supported yet)
- [Run as a service in Windows](#run-as-a-service-in-windows) (not supported yet)
- [Using Docker](#using-docker)
- [Using Docker Compose](#using-docker-compose)
- [On Kubernetes](#on-kubernetes)
During the run, it is required to pass [configuration](#configuration) option to the application, which can be done in a different ways.
## Configuration
It is possible to configure Codex node in several ways:
1. [CLI options](#cli-options)
2. [Environment variables](#environment-variables)
3. [Configuration file](#configuration-file)
The order of priority is the same as above:
[CLI options](#cli-options) --> [Environment variables](#environment-variables) --> [Configuration file](#configuration-file).
### Common information
#### Units
For some configuration options, we can pass values in common units like following:
```shell
--cache-size=1m/1M/1mb/1MB
--storage-quota=2m/2M/2mb/2MB
--block-mi=1s/1S/1m/1M/1h/1H/1d/1D/1w/1W
--block-ttl=2s/2S/2m/2M/2h/2H/2d/2D/2w/2W
```
#### Logging
Codex uses [Chronicles](https://github.com/status-im/nim-chronicles) logging library, which allows great flexibility in working with logs.
Chronicles has the concept of topics, which categorize log entries into semantic groups.
Using the `log-level` parameter, you can set the top-level log level like `--log-level="trace"`, but more importantly,
you can set log levels for specific topics like `--log-level="info; trace: marketplace,node; error: blockexchange"`,
which sets the top-level log level to `info` and then for topics `marketplace` and `node` sets the level to `trace` and so on.
### CLI options
```shell
codex --help
Usage:
codex [OPTIONS]... command
The following options are available:
--config-file Loads the configuration from a TOML file [=none].
--log-level Sets the log level [=info].
--metrics Enable the metrics server [=false].
--metrics-address Listening address of the metrics server [=127.0.0.1].
--metrics-port Listening HTTP port of the metrics server [=8008].
-d, --data-dir The directory where codex will store configuration and data
[=/root/.cache/codex].
-i, --listen-addrs Multi Addresses to listen on [=/ip4/0.0.0.0/tcp/0].
-a, --nat IP Addresses to announce behind a NAT [=127.0.0.1].
-e, --disc-ip Discovery listen address [=0.0.0.0].
-u, --disc-port Discovery (UDP) port [=8090].
--net-privkey Source of network (secp256k1) private key file path or name [=key].
-b, --bootstrap-node Specifies one or more bootstrap nodes to use when connecting to the network.
--max-peers The maximum number of peers to connect to [=160].
--agent-string Node agent string which is used as identifier in network [=Codex].
--api-bindaddr The REST API bind address [=127.0.0.1].
-p, --api-port The REST Api port [=8080].
--api-cors-origin The REST Api CORS allowed origin for downloading data. '*' will allow all
origins, '' will allow none. [=Disallow all cross origin requests to download
data].
--repo-kind Backend for main repo store (fs, sqlite, leveldb) [=fs].
-q, --storage-quota The size of the total storage quota dedicated to the node [=$DefaultQuotaBytes].
-t, --block-ttl Default block timeout in seconds - 0 disables the ttl [=$DefaultBlockTtl].
--block-mi Time interval in seconds - determines frequency of block maintenance cycle: how
often blocks are checked for expiration and cleanup
[=$DefaultBlockMaintenanceInterval].
--block-mn Number of blocks to check every maintenance cycle [=1000].
-c, --cache-size The size of the block cache, 0 disables the cache - might help on slow hardrives
[=0].
Available sub-commands:
codex persistence [OPTIONS]... command
The following options are available:
--eth-provider The URL of the JSON-RPC API of the Ethereum node [=ws://localhost:8545].
--eth-account The Ethereum account that is used for storage contracts.
--eth-private-key File containing Ethereum private key for storage contracts.
--marketplace-address Address of deployed Marketplace contract.
--validator Enables validator, requires an Ethereum node [=false].
--validator-max-slots Maximum number of slots that the validator monitors [=1000].
--reward-recipient Address to send payouts to (eg rewards and refunds).
Available sub-commands:
codex persistence prover [OPTIONS]...
The following options are available:
-cd, --circuit-dir Directory where Codex will store proof circuit data
[=/root/.cache/codex/circuits].
--circom-r1cs The r1cs file for the storage circuit
[=/root/.cache/codex/circuits/proof_main.r1cs].
--circom-wasm The wasm file for the storage circuit
[=/root/.cache/codex/circuits/proof_main.wasm].
--circom-zkey The zkey file for the storage circuit
[=/root/.cache/codex/circuits/proof_main.zkey].
--circom-no-zkey Ignore the zkey file - use only for testing! [=false].
--proof-samples Number of samples to prove [=5].
--max-slot-depth The maximum depth of the slot tree [=32].
--max-dataset-depth The maximum depth of the dataset tree [=8].
--max-block-depth The maximum depth of the network block merkle tree [=5].
--max-cell-elements The maximum number of elements in a cell [=67].
```
### Environment variables
In order to set a configuration option using environment variables, first find the desired [CLI option](#cli-options)
and then transform it in the following way:
1. prepend it with `CODEX_`
2. make it uppercase
3. replace `-` with `_`
For example, to configure `--log-level`, use `CODEX_LOG_LEVEL` as the environment variable name.
> [!WARNING]
> Some options can't be configured via environment variables for now [^multivalue-env-var] [^sub-commands].
### Configuration file
A [TOML](https://toml.io/en/) configuration file can also be used to set configuration values. Configuration option names and corresponding values are placed in the file, separated by `=`. Configuration option names can be obtained from the [`codex --help`](#cli-options) command, and should not include the `--` prefix. For example, a node's log level (`--log-level`) can be configured using TOML as follows:
```toml
log-level = "trace"
```
For option, like `bootstrap-node` and `listen-addrs` which accept multiple values we can specify data as an array
```toml
listen-addrs = [
"/ip4/0.0.0.0/tcp/1234",
"/ip4/0.0.0.0/tcp/5678"
]
```
The Codex node can then read the configuration from this file using the `--config-file` CLI parameter, like:
```shell
codex --config-file=/path/to/your/config.toml
```
## Run
Basically, we can run Codex in three different modes:
- [Codex node](#codex-node) - useful for local testing/development and basic/files sharing.
- [Codex node with marketplace support](#codex-node-with-marketplace-support) - you can share files and buy the storage, this is the main mode and should be used by the end users.
- [Codex storage node](#codex-storage-node) - should be used by storage providers or if you would like to sell your local storage.
We also will touch in some words [Codex bootstrap node](#codex-bootstrap-node).
### Using binary
#### Codex node
We can run Codex in a simple way like following:
```shell
codex
```
> [!WARNING]
> This command may not work properly when we use GitHub releases [^data-dir].
But, it will use a default `data-dir` value and we can pass a custom one:
```shell
codex --data-dir=datadir
```
This will run Codex as an isolated instance, and if we would like to join an existing network, it is required to pass a [bootstrap node](#codex-bootstrap-node). We can pass multiple nodes as well:
```shell
codex \
--data-dir=datadir \
--bootstrap-node=spr:CiUIAhIhAiJvIcA_ZwPZ9ugVKDbmqwhJZaig5zKyLiuaicRcCGqLEgIDARo8CicAJQgCEiECIm8hwD9nA9n26BUoNuarCEllqKDnMrIuK5qJxFwIaosQ3d6esAYaCwoJBJ_f8zKRAnU6KkYwRAIgM0MvWNJL296kJ9gWvfatfmVvT-A7O2s8Mxp8l9c8EW0CIC-h-H-jBVSgFjg3Eny2u33qF7BDnWFzo7fGfZ7_qc9P \
--bootstrap-node=spr:CiUIAhIhAyUvcPkKoGE7-gh84RmKIPHJPdsX5Ugm_IHVJgF-Mmu_EgIDARo8CicAJQgCEiEDJS9w-QqgYTv6CHzhGYog8ck92xflSCb8gdUmAX4ya78QoemesAYaCwoJBES39Q2RAnVOKkYwRAIgLi3rouyaZFS_Uilx8k99ySdQCP1tsmLR21tDb9p8LcgCIG30o5YnEooQ1n6tgm9fCT7s53k6XlxyeSkD_uIO9mb3
```
> [!IMPORTANT]
> Make sure you are using a proper value for the [network](/networks/networks) you would like to join.
Also, to make your Codex node accessible for other network participants, it is required to specify a public IP address which can be used to access your node:
```shell
codex \
--data-dir=datadir \
--bootstrap-node=spr:CiUIAhIhAiJvIcA_ZwPZ9ugVKDbmqwhJZaig5zKyLiuaicRcCGqLEgIDARo8CicAJQgCEiECIm8hwD9nA9n26BUoNuarCEllqKDnMrIuK5qJxFwIaosQ3d6esAYaCwoJBJ_f8zKRAnU6KkYwRAIgM0MvWNJL296kJ9gWvfatfmVvT-A7O2s8Mxp8l9c8EW0CIC-h-H-jBVSgFjg3Eny2u33qF7BDnWFzo7fGfZ7_qc9P \
--nat=<your public IP>
```
> [!TIP]
> We can set public IP using curl and IP lookup service, like [ip.codex.storage](https://ip.codex.storage).
After that, node will announce itself using your public IP, default UDP ([discovery](https://docs.libp2p.io/concepts/discovery-routing/overview/)) and dynamic TCP port ([data transfer](https://docs.libp2p.io/concepts/transports/overview/)), which can be adjusted in the following way:
```shell
codex \
--data-dir=datadir \
--bootstrap-node=spr:CiUIAhIhAiJvIcA_ZwPZ9ugVKDbmqwhJZaig5zKyLiuaicRcCGqLEgIDARo8CicAJQgCEiECIm8hwD9nA9n26BUoNuarCEllqKDnMrIuK5qJxFwIaosQ3d6esAYaCwoJBJ_f8zKRAnU6KkYwRAIgM0MvWNJL296kJ9gWvfatfmVvT-A7O2s8Mxp8l9c8EW0CIC-h-H-jBVSgFjg3Eny2u33qF7BDnWFzo7fGfZ7_qc9P \
--nat=`curl -s https://ip.codex.storage` \
--disc-port=8090 \
--listen-addrs=/ip4/0.0.0.0/tcp/8070
```
In that way, node will announce itself using specified [multiaddress](https://docs.libp2p.io/concepts/fundamentals/addressing/) and we can check that via [API](https://api.codex.storage/#tag/Debug/operation/getDebugInfo) call:
```shell
curl -s localhost:8080/api/codex/v1/debug/info | jq -r '.announceAddresses'
```
```json
[
"/ip4/<your public IP>/tcp/8070"
]
```
Basically, for P2P communication we should specify and configure two ports:
| # | Protocol | Function | CLI option | Example |
| - | -------- | ------------------------------------------------------------------------ | ---------------- | -------------------------------------- |
| 1 | UDP | [Discovery](https://docs.libp2p.io/concepts/discovery-routing/overview/) | `--disc-port` | `--disc-port=8090` |
| 2 | TCP | [Transport](https://docs.libp2p.io/concepts/transports/overview/) | `--listen-addrs` | `--listen-addrs=/ip4/0.0.0.0/tcp/8070` |
And, also it is required to setup port-forwarding on your Internet router, to make your node accessible for participants [^port-forwarding].
So, a fully working basic configuration will looks like following:
```shell
codex \
--data-dir=datadir \
--bootstrap-node=spr:CiUIAhIhAiJvIcA_ZwPZ9ugVKDbmqwhJZaig5zKyLiuaicRcCGqLEgIDARo8CicAJQgCEiECIm8hwD9nA9n26BUoNuarCEllqKDnMrIuK5qJxFwIaosQ3d6esAYaCwoJBJ_f8zKRAnU6KkYwRAIgM0MvWNJL296kJ9gWvfatfmVvT-A7O2s8Mxp8l9c8EW0CIC-h-H-jBVSgFjg3Eny2u33qF7BDnWFzo7fGfZ7_qc9P \
--nat=`curl -s https://ip.codex.storage` \
--disc-port=8090 \
--listen-addrs=/ip4/0.0.0.0/tcp/8070 \
--api-cors-origin="*"
```
After node is up and running and port-forwarding configurations was done, we should be able to [Upload a file](/learn/using#upload-a-file)/[Download a file](/learn/using#download-a-file) in the network using [API](/developers/api).
You also can use [Codex App UI](https://app.codex.storage) for files upload/download.
And to be able to purchase a storage, we should run [Codex node with marketplace support](#codex-node-with-marketplace-support).
#### Codex node with marketplace support
[Marketplace](/learn/architecture.md#marketplace-architecture) support permits to purchase the storage in Codex network. Basically, we should add just a `persistence` sub-command and required [CLI options](#cli-options) to the [previous run](#codex-node).
> [!NOTE]
> Please ignore `--eth-account` CLI option, as it is obsolete [^eth-account].
1. For a daily use, we should consider to run a local blockchain node based on the [network](/networks/networks) you would like to join. That process is described in the [Join Codex Testnet](/networks/testnet) guide, but for a quick start we can use a public RPC endpoint.
2. Create a file with ethereum private key and set a proper permissions:
> [!CAUTION]
> Please use key generation service for demo purpose only.
```shell
response=$(curl -s https://key.codex.storage)
awk -F ': ' '/private/ {print $2}' <<<"${response}" > eth.key
awk -F ': ' '/address/ {print $2}' <<<"${response}" > eth.address
chmod 600 eth.key
```
Show your ethereum address:
```shell
cat eth.address
```
```
0x412665aFAb17768cd9aACE6E00537Cc6D5524Da9
```
3. Fill-up your ethereum address with ETH and Tokens based on the the [network](/networks/networks) you would like to join.
4. Specify bootstrap nodes and marketplace address based on the [network](/networks/networks) you would like to join.
5. Run the node:
```shell
codex \
--data-dir=datadir \
--bootstrap-node=spr:CiUIAhIhAiJvIcA_ZwPZ9ugVKDbmqwhJZaig5zKyLiuaicRcCGqLEgIDARo8CicAJQgCEiECIm8hwD9nA9n26BUoNuarCEllqKDnMrIuK5qJxFwIaosQ3d6esAYaCwoJBJ_f8zKRAnU6KkYwRAIgM0MvWNJL296kJ9gWvfatfmVvT-A7O2s8Mxp8l9c8EW0CIC-h-H-jBVSgFjg3Eny2u33qF7BDnWFzo7fGfZ7_qc9P \
--nat=`curl -s https://ip.codex.storage` \
--disc-port=8090 \
--listen-addrs=/ip4/0.0.0.0/tcp/8070 \
--api-cors-origin="*" \
persistence \
--eth-provider=https://rpc.testnet.codex.storage \
--eth-private-key=eth.key \
--marketplace-address=0xAB03b6a58C5262f530D54146DA2a552B1C0F7648
```
> [!NOTE]
> Codex also has a marketplace contract address autodiscovery mechanism based on the chain id, that mapping is done in the [source code](https://github.com/codex-storage/nim-codex/blob/master/codex/contracts/deployment.nim). In that way we can skip `--marketplace-address` argument or use it to override a hardcoded value.
After node is up and running, and your address has founds, you should be able to [Purchase storage](/learn/using#purchase-storage) using [API](/developers/api).
You also can use [Codex App UI](https://app.codex.storage) for storage purchase.
#### Codex storage node
Codex [storage node](architecture#network-architecture) should be run by storage providers or in case you would like to sell your local storage.
For that, additionally to the [Codex node with marketplace support](#codex-node-with-marketplace-support) we should use `prover` sub-command and required [CLI options](#cli-options).
That sub-command will make Codex to listen for a proof requests on the blockchain and answer them. To compute an answer for the proof request, Codex will use stored data and circuit files generated by the code in the [codex-storage-proofs-circuits](https://github.com/codex-storage/codex-storage-proofs-circuits) repository.
Every [network](/networks/networks) uses its own generated set of the files which are stored in the [codex-contracts-eth](https://github.com/codex-storage/codex-contracts-eth/tree/master/verifier/networks) repository and also uploaded to the CDN. Hash of the files set is also known by the [marketplace smart contract](/learn/architecture#smart-contract).
To download circuit files and make them available to Codex app, we have a stand-alone utility - `cirdl`. It can be [compiled from the sources](/learn/build#circuit-download-tool) or downloaded from the [GitHub release page](https://github.com/codex-storage/nim-codex/releases).
1. Create ethereum key file
<details>
<summary>example</summary>
> [!CAUTION]
> Please use key generation service for demo purpose only.
```shell
response=$(curl -s https://key.codex.storage)
awk -F ': ' '/private/ {print $2}' <<<"${response}" > eth.key
awk -F ': ' '/address/ {print $2}' <<<"${response}" > eth.address
chmod 600 eth.key
```
Show your ethereum address:
```shell
cat eth.address
```
```
0x412665aFAb17768cd9aACE6E00537Cc6D5524Da9
```
</details>
2. To download circuit files, we should pass directory, RPC endpoint and marketplace address to the circuit downloader:
```shell
# Create circuit files folder
mkdir -p datadir/circuits
chmod 700 datadir/circuits
# Download circuit files
cirdl \
datadir/circuits \
https://rpc.testnet.codex.storage \
0xAB03b6a58C5262f530D54146DA2a552B1C0F7648
```
2. Start Codex storage node
```shell
codex \
--data-dir=datadir \
--bootstrap-node=spr:CiUIAhIhAiJvIcA_ZwPZ9ugVKDbmqwhJZaig5zKyLiuaicRcCGqLEgIDARo8CicAJQgCEiECIm8hwD9nA9n26BUoNuarCEllqKDnMrIuK5qJxFwIaosQ3d6esAYaCwoJBJ_f8zKRAnU6KkYwRAIgM0MvWNJL296kJ9gWvfatfmVvT-A7O2s8Mxp8l9c8EW0CIC-h-H-jBVSgFjg3Eny2u33qF7BDnWFzo7fGfZ7_qc9P \
--nat=`curl -s https://ip.codex.storage` \
--disc-port=8090 \
--listen-addrs=/ip4/0.0.0.0/tcp/8070 \
persistence \
--eth-provider=https://rpc.testnet.codex.storage \
--eth-private-key=eth.key \
--marketplace-address=0xAB03b6a58C5262f530D54146DA2a552B1C0F7648 \
prover \
--circuit-dir=datadir/circuits
```
> [!NOTE]
> You would need to pass a bootstrap nodes, blockchain RPC endpoint and marketplace address based on the [network](/networks/networks) you would like to join.
After node is up and running, and your address has founds, you should be able to [sell the storage](/learn/using#create-storage-availability) using [API](/developers/api).
You also can use [Codex App UI](https://app.codex.storage) to sell the storage.
#### Codex bootstrap node
Bootstrap nodes are used just to help peers with the initial nodes discovery and we need to run Codex with just some basic options:
```shell
codex \
--data-dir=datadir \
--nat=`curl -s https://ip.codex.storage` \
--disc-port=8090
```
To get bootstrap node SPR we can use [API](https://api.codex.storage/#tag/Debug/operation/getDebugInfo) call:
```shell
curl -s localhost:8080/api/codex/v1/debug/info | jq -r '.spr'
```
```shell
spr:CiUIAhIhApd79-AxPqwRDmu7Pk-berTDtoIoMz0ovKjo85Tz8CUdEgIDARo8CicAJQgCEiECl3v34DE-rBEOa7s-T5t6tMO2gigzPSi8qOjzlPPwJR0Qjv_WtwYaCwoJBFxzjbKRAh-aKkYwRAIgCiTq5jBTaJJb6lUxN-0uNCj8lkV9AGY682D21kIAMiICIE1yxrjbDdiSCiARnS7I2zqJpXC2hOvjB4JoL9SAAk67
```
That SPR record then can be used then by other peers for initial nodes discovery.
We should keep in mind some important things about SPR record (see [ENR](https://eips.ethereum.org/EIPS/eip-778)):
- It uses node IP (`--nat`), discovery port (`--disc-port`) and private key (`--net-privkey`) for record creation
- Specified data is signed on each run and will be changed but still contain specified node data when decoded
- You can decode it by passing to the Codex node at run and with `--log-level=trace`
For bootstrap node, it is required to forward just discovery port on your Internet router.
### Run as a daemon in Linux
This functionality is not supported yet :construction:
### Run as a service in Windows
This functionality is not supported yet :construction:
### Using Docker
We also ship Codex in Docker containers, which can be run on `amd64` and `arm64` platforms.
#### Docker entrypoint
[Docker entrypoint](https://github.com/codex-storage/nim-codex/blob/master/docker/docker-entrypoint.sh), supports some additional options, which can be used for easier configuration:
- `ENV_PATH` - path to the file, in form `env=value` which will be sourced and available for Codex at run. That is useful for Kubernetes Pods configuration.
- `NAT_IP_AUTO` - when set to `true`, will set `CODEX_NAT` variable with container internal IP address. It also is useful for Kubernetes Pods configuration, when we perform automated tests.
- `NAT_PUBLIC_IP_AUTO` - used to set `CODEX_NAT` to public IP address using lookup services, like [ip.codex.storage](https://ip.codex.storage). Can be used for Docker/Kubernetes to set public IP in auto mode.
- `ETH_PRIVATE_KEY` - can be used to pass ethereum private key, which will be saved and passed as a value of the `CODEX_ETH_PRIVATE_KEY` variable. It should be considered as unsafe option and used for testing purposes only.
- When we set `prover` sub-command, entrypoint will run `cirdl` tool to download ceremony files, required by [Codex storage node](#codex-storage-node).
#### Docker network
When we are running Codex using Docker with default [bridge network](https://docs.docker.com/engine/network/drivers/bridge/), it will create a double NAT:
- One on the Docker side
- Second on your Internet router
If your Internet router does not support [Full Cone NAT](https://learningnetwork.cisco.com/s/question/0D56e0000CWxJ9sCQF/lets-explain-in-details-full-cone-nat-restricted-cone-nat-and-symmetric-nat-terminologies-vs-cisco-nat-terminologies), you might have an issue and peer discovery and data transport will not work or might work unexpected.
In that case, we should consider the following solutions:
- Use [host network](https://docs.docker.com/engine/network/drivers/host/) for Docker, which is supported only in Linux
- Run [Using binary](#using-binary)
- Use VM/VPS in the Cloud to run Docker with bridge or host network
#### Run using Docker
And we basically can use same options we [used for binary](#using-binary) and additionally it is required to mount volumes and map the ports.
[Codex storage node](#codex-storage-node)
1. Create ethereum key file
<details>
<summary>example</summary>
> [!CAUTION]
> Please use key generation service for demo purpose only.
```shell
response=$(curl -s https://key.codex.storage)
awk -F ': ' '/private/ {print $2}' <<<"${response}" > eth.key
awk -F ': ' '/address/ {print $2}' <<<"${response}" > eth.address
chmod 600 eth.key
```
Show your ethereum address:
```shell
cat eth.address
```
```
0x412665aFAb17768cd9aACE6E00537Cc6D5524Da9
```
</details>
2. Run Codex:
```shell
docker run \
--rm \
-v $PWD/datadir:/datadir \
-v $PWD/eth.key:/opt/eth.key \
-p 8070:8070 \
-p 8080:8080 \
-p 8090:8090/udp \
codexstorage/nim-codex:latest \
codex \
--data-dir=/datadir \
--bootstrap-node=spr:CiUIAhIhAiJvIcA_ZwPZ9ugVKDbmqwhJZaig5zKyLiuaicRcCGqLEgIDARo8CicAJQgCEiECIm8hwD9nA9n26BUoNuarCEllqKDnMrIuK5qJxFwIaosQ3d6esAYaCwoJBJ_f8zKRAnU6KkYwRAIgM0MvWNJL296kJ9gWvfatfmVvT-A7O2s8Mxp8l9c8EW0CIC-h-H-jBVSgFjg3Eny2u33qF7BDnWFzo7fGfZ7_qc9P \
--nat=`curl -s https://ip.codex.storage` \
--disc-port=8090 \
--listen-addrs=/ip4/0.0.0.0/tcp/8070 \
--api-cors-origin="*" \
--api-bindaddr=0.0.0.0 \
--api-port=8080 \
persistence \
--eth-provider=https://rpc.testnet.codex.storage \
--eth-private-key=/opt/eth.key \
--marketplace-address=0xAB03b6a58C5262f530D54146DA2a552B1C0F7648 \
prover \
--circuit-dir=/datadir/circuits
```
> [!NOTE]
> You would need to pass a bootstrap nodes, blockchain RPC endpoint and marketplace address based on the [network](/networks/networks) you would like to join.
### Using Docker Compose
For Docker Compose, it is more suitable to use [environment variables](#environment-variables) for Codex configuration and we can reuse commands from example above, for Docker.
[Codex storage node](#codex-storage-node)
1. Create ethereum key file
<details>
<summary>example</summary>
> [!CAUTION]
> Please use key generation service for demo purpose only.
```shell
response=$(curl -s https://key.codex.storage)
awk -F ': ' '/private/ {print $2}' <<<"${response}" > eth.key
awk -F ': ' '/address/ {print $2}' <<<"${response}" > eth.address
chmod 600 eth.key
```
Show your ethereum address:
```shell
cat eth.address
```
```
0x412665aFAb17768cd9aACE6E00537Cc6D5524Da9
```
</details>
2. Create `docker-compose.yaml` file:
```yaml
services:
codex:
image: codexstorage/nim-codex:latest
container_name: codex
command:
- codex
- persistence
- prover
- --bootstrap-node=spr:CiUIAhIhAiJvIcA_ZwPZ9ugVKDbmqwhJZaig5zKyLiuaicRcCGqLEgIDARo8CicAJQgCEiECIm8hwD9nA9n26BUoNuarCEllqKDnMrIuK5qJxFwIaosQ3d6esAYaCwoJBJ_f8zKRAnU6KkYwRAIgM0MvWNJL296kJ9gWvfatfmVvT-A7O2s8Mxp8l9c8EW0CIC-h-H-jBVSgFjg3Eny2u33qF7BDnWFzo7fGfZ7_qc9P
- --bootstrap-node=spr:CiUIAhIhAyUvcPkKoGE7-gh84RmKIPHJPdsX5Ugm_IHVJgF-Mmu_EgIDARo8CicAJQgCEiEDJS9w-QqgYTv6CHzhGYog8ck92xflSCb8gdUmAX4ya78QoemesAYaCwoJBES39Q2RAnVOKkYwRAIgLi3rouyaZFS_Uilx8k99ySdQCP1tsmLR21tDb9p8LcgCIG30o5YnEooQ1n6tgm9fCT7s53k6XlxyeSkD_uIO9mb3
- --bootstrap-node=spr:CiUIAhIhA6_j28xa--PvvOUxH10wKEm9feXEKJIK3Z9JQ5xXgSD9EgIDARo8CicAJQgCEiEDr-PbzFr74--85TEfXTAoSb195cQokgrdn0lDnFeBIP0QzOGesAYaCwoJBK6Kf1-RAnVEKkcwRQIhAPUH5nQrqG4OW86JQWphdSdnPA98ErQ0hL9OZH9a4e5kAiBBZmUl9KnhSOiDgU3_hvjXrXZXoMxhGuZ92_rk30sNDA
- --bootstrap-node=spr:CiUIAhIhA7E4DEMer8nUOIUSaNPA4z6x0n9Xaknd28Cfw9S2-cCeEgIDARo8CicAJQgCEiEDsTgMQx6vydQ4hRJo08DjPrHSf1dqSd3bwJ_D1Lb5wJ4Qt_CesAYaCwoJBEDhWZORAnVYKkYwRAIgFNzhnftocLlVHJl1onuhbSUM7MysXPV6dawHAA0DZNsCIDRVu9gnPTH5UkcRXLtt7MLHCo4-DL-RCMyTcMxYBXL0
- --bootstrap-node=spr:CiUIAhIhAzZn3JmJab46BNjadVnLNQKbhnN3eYxwqpteKYY32SbOEgIDARo8CicAJQgCEiEDNmfcmYlpvjoE2Np1Wcs1ApuGc3d5jHCqm14phjfZJs4QrvWesAYaCwoJBKpA-TaRAnViKkcwRQIhANuMmZDD2c25xzTbKSirEpkZYoxbq-FU_lpI0K0e4mIVAiBfQX4yR47h1LCnHznXgDs6xx5DLO5q3lUcicqUeaqGeg
- --bootstrap-node=spr:CiUIAhIhAgybmRwboqDdUJjeZrzh43sn5mp8jt6ENIb08tLn4x01EgIDARo8CicAJQgCEiECDJuZHBuioN1QmN5mvOHjeyfmanyO3oQ0hvTy0ufjHTUQh4ifsAYaCwoJBI_0zSiRAnVsKkcwRQIhAJCb_z0E3RsnQrEePdJzMSQrmn_ooHv6mbw1DOh5IbVNAiBbBJrWR8eBV6ftzMd6ofa5khNA2h88OBhMqHCIzSjCeA
- --bootstrap-node=spr:CiUIAhIhAntGLadpfuBCD9XXfiN_43-V3L5VWgFCXxg4a8uhDdnYEgIDARo8CicAJQgCEiECe0Ytp2l-4EIP1dd-I3_jf5XcvlVaAUJfGDhry6EN2dgQsIufsAYaCwoJBNEmoCiRAnV2KkYwRAIgXO3bzd5VF8jLZG8r7dcLJ_FnQBYp1BcxrOvovEa40acCIDhQ14eJRoPwJ6GKgqOkXdaFAsoszl-HIRzYcXKeb7D9
environment:
- CODEX_DATA_DIR=/datadir
- NAT_PUBLIC_IP_AUTO=https://ip.codex.storage
- CODEX_DISC_PORT=8090
- CODEX_LISTEN_ADDRS=/ip4/0.0.0.0/tcp/8070
- CODEX_API_CORS_ORIGIN="*"
- CODEX_API_PORT=8080
- CODEX_API_BINDADDR=0.0.0.0
- CODEX_ETH_PROVIDER=https://rpc.testnet.codex.storage
- CODEX_ETH_PRIVATE_KEY=/opt/eth.key
- CODEX_MARKETPLACE_ADDRESS=0xAB03b6a58C5262f530D54146DA2a552B1C0F7648
- CODEX_CIRCUIT_DIR=/datadir/circuits
ports:
- 8080:8080/tcp # API
- 8090:8090/udp # Discovery
- 8070:8070/tcp # Transport
volumes:
- ./datadir:/datadir
- ./eth.key:/opt/eth.key
logging:
driver: json-file
options:
max-size: 100m
max-file: 5
```
3. Run Codex:
```shell
docker compose up
```
> [!NOTE]
> You would need to pass a bootstrap nodes, blockchain RPC endpoint and marketplace address based on the [network](/networks/networks) you would like to join.
### On Kubernetes
Helm chart code is available in [helm-charts](https://github.com/codex-storage/helm-charts) repository, but chart was not published yet.
## Known issues
[^multivalue-env-var]: Environment variables like `CODEX_BOOTSTRAP_NODE` and `CODEX_LISTEN_ADDRS` does not support multiple values. Please check [[Feature request] Support multiple SPR records via environment variable #525](https://github.com/codex-storage/nim-codex/issues/525), for more information.
[^sub-commands]: Sub-commands `persistence` and `persistence prover` can't be set via environment variables.
[^data-dir]: We should set data-dir explicitly when we use GitHub releases - [[BUG] Change codex default datadir from compile-time to run-time #923](https://github.com/codex-storage/nim-codex/issues/923)
[^port-forwarding]: [NAT traversal #753](https://github.com/codex-storage/nim-codex/issues/753) is not implemented yet and we would need to setup port-forwarding for discovery and transport protocols.
[^eth-account]: Please ignore `--eth-account` CLI option - [Drop support for --eth-account #727](https://github.com/codex-storage/nim-codex/issues/727).

View File

@ -0,0 +1,276 @@
---
outline: [1, 3]
---
# Codex Tokenomics Litepaper - Testnet Version
**Codex: A Decentralized Storage Protocol for Durable Information**
# Legal Notices
*The information contained in this document is intended to be made available for informational purposes only and does not constitute a prospectus, nor an offer to buy, a solicitation or an invitation to buy, or a recommendation for any token or any security. Neither this document nor any of its content should be considered as creating any expectations or forming the basis of any contract, commitment or binding obligation. No information herein should be considered to contain or be relied upon as a promise, representation, warranty or guarantee, whether express or implied and whether as to the past, present or the future in relation to the projects and matters described herein. The information presented is a summary and does not purport to be accurate, reliable or complete. This document is under continuous legal review and may be amended or supplemented at any time without prior notice.  No responsibility will be borne for the accuracy, reliability or completeness of information contained herein. Because of the high degree of risk and uncertainty described above, undue reliance should not be placed by anyone on any matters described in this document. Any tokens referenced in this document have not been registered under any securities laws and may not be offered or sold in any jurisdiction where such offer or sale would be prohibited.*
*This document may contain forward-looking statements that are based only on current expectations, estimates, forecasts, assumptions and projections about the technology, industry and markets in general. The forward looking statements, projects, content and any other matters described in this document are subject to a high degree of risk and uncertainty. The roadmap, results, project descriptions, technical details, functionalities, and other features are subject to change based on, among other things, market conditions, technical developments, and regulatory environment. The actual development and results, including the order and the timeline, might differ materially from those anticipated in these forward-looking statements.*
*The information contained in this document does not constitute financial, legal, tax, investment, professional or other advice and should not be treated as such.*
# Overview
## Scope
This document describes the Codex Tokenomics with elements that reflect the Testnet deployment of the Codex Protocol.
## What Codex Does
Codex is a state-of-the-art decentralized storage platform that offers a novel solution that enhances data durability guarantees for storing vast amounts of data while eliminating any reliance on centralized institutions that could lead to a single point of failure.
While centralized storage systems such as Google Cloud tout eleven nines of durability, durable file storage in distributed systems that provide censorship resistance and privacy are a vital prerequisite to use cases such as preserving factual records of history in network states.
While no system can guarantee absolute protection against data loss, through its technical architecture, economic incentives, and algorithmic encoding, Codex is designed to provide highly decentralized data storage with high durability, resiliency to cloud failures, and resistance to censorship.
## How Codex Works
Codex operates as a network of storage nodes, referred to herein as **Storage Providers** (SP), that store user data for the duration of a contract entered into by SPs and storage users, referred to herein simply as **Clients**.
Storage contracts are initiated by a **Client** requesting to store a specified amount of data, for a specified amount of time, and at a specific price per the full contract. **Storage Providers** commit to slots to store redundant fragments of this data.
The fact that **SPs** must post collateral (stake) in order to fill a slot helps protect against Sybil attacks, promoting diversity in storage nodes fulfilling each contract. Additionally, this collateral acts as an economic incentive to ensure that **SPs** fulfill their obligations to periodically prove that they are still in possession of the data in question.
This is achieved by periodic challenges to **SPs** to provide cryptographic proofs that demonstrate the data they have contracted to store can be retrieved. Codex incorporates Zero Knowledge (ZK) and Data Availability Sampling (DAS) to achieve low-cost, highly efficient, and reliable data loss detection.
**SPs** are required to respond to these challenges, sending their proofs to **Validators,** who verify the validity of the proofs and posts to the blockchain only the absence of a proof. This reduces costs of validating proofs, while not affecting the **Protocol**s security.
Should SPs fail to prove a fixed number of times they still have the data in question, or send an invalid proof, their collateral is partially slashed. The slash penalty is a fixed percentage of the total collateral. This slashing continues until a certain number of slashings is reached, at which point the entire collateral is slashed. At this moment, the SP slot is considered “abandoned”. The slashed collateral is used as an incentive for a new **SP** to take over the failed slot through the “slot recovery mechanism” (discussed further later). This ensures the collateral provides an economic incentive to ensure the durability of the data.
Codex is thus designed such that rational behavior for **SPs** consists of storing the data in the most space-efficient manner to minimize excess storage costs, while balancing the need for enough redundancy to recover from the possibility of data loss/corruption by the penalty of forfeiture of their collateral (slashing).
While Codexs tech maximizes recoverability and durability in the event of partial data loss, Codexs economic incentives coordinate rational actors to provide a stable and predictable environment for data storage users. At the heart of these economic incentives is the Codex utility token (CDX), which serves as the collateral to protect file durability and facilitate slot repair, and the means of payment to coordinate successful storage contracts.
# Contract Lifecycle
The marketplace coordinates matching **Clients** who want to pay for storing files with **Storage Providers** who are offering storage space and posting collateral in order to earn payments for the contract.
## Contract Request Initiation
As a design principle, **Clients** should post the deal terms they are looking for, and Storage Providers prioritize which deals meet their criteria and pose the best deals to take.
When the contract request is created, the **Client** deposits the full price of the length of the contract at that time. This deposit acts as a spam prevention mechanism and ensures that **SP** time and resources are not wasted filling slots for deals that a **Client** does not complete payment for.
## Storage Providers Fill Requests
Ahead of matching with storage contracts, **Storage Providers** specify their aggregate availabilities for new contracts.
Based on each **SPs** availabilities, a queue is created for each **SP**, ranking the open **Client** request for contract deals with the most favorable deals at the top. Over time, this queue resolves by pairing **SPs** with contracts that are compatible with their availabilities, starting with the highest ranked deals first.
At launch, **SPs** will not be able to customize the queue creation algorithm, which means **SPs** with the same availabilities will have identical queues (other than differences due to a randomness function that increases **SP** diversity per each contract). In the future, **SPs** are expected to be able to customize their queue ranking algorithm.
If a **SP** matches with a storage contract and they're eligible to reserve a slot in the contract, they reserve an open slot, download the slot data from the **Client** or existing **SPs** whose data can be used to reconstruct the slots contents, create an initial storage proof, and submit this proof, along with collateral, to the **Protocol**.
Note that a slot is not considered confirmed as filled until after an **SP** both posts associated collateral and produces a proof for the slot.
## Contract Expires Before Beginning
If there are still empty slots when the timeout/expiry for the contract request expires, the deal is terminated.
The **Storage Providers** who did fill slots, if any, are compensated for the amount of time which they did store the slot data, at the contract requests specified price per TB per Month. The remainder of the **Client**s deposit is returned.
As there is a high probability of having at least a few slots occupied, there should be no need for further penalties on the **Client** to prevent spam requests and incentivise **Clients** to submit attractive deals.
## Contract Begins
The contract begins if *all* slots are occupied, that is, **SPs** have downloaded the data, posted collateral, and posted proofs before the timeout/expiry for the contract request is reached.
At this moment, a *protocol fee* is applied on the users deposit. The proceedings are burned.
The remaining of the clients deposit is held by the protocol and will be used to pay **SPs** at the end of the contract.
## Contract is Running
**Storage Providers** must submit proofs to **Validators** according to the storage requests proof frequency, a parameter set by the Client in the request.
### Missing Proofs
If an **SP** fails to submit proofs within the rolling last periods, they are partially slashed. The penalty is a fixed percentage of the collateral. Upon provision of a proof after being partially slashed, the SP should top up the missing collateral.
Should the SP be slashed enough times, their entire collateral will be slashed and confiscated, and the SP is considered to have abandoned its slot. The provision of a correct proof at this moment will not revert the start of the slot recovery mechanism.
## A Slot in the Contract is Abandoned
When an **SP** fails to submit enough proofs such that they are slashed enough times, their slot is considered abandoned. In order to incentivize a new **SP** to come in and takeover the abandoned slot (slot recovery), 50% of the collateral confiscated from the **SP** which has abandoned the slot is used as an incentive to the new **SP**. The remaining confiscated collateral is burned.
This helps align the economic incentive for **SPs** to take over abandoned slots before filling new deals, since they can effectively earn forfeited collateral for taking over and fulfilling abandoned slots.
## Contract Defaults
If, at any time during the life of the storage contract, the number of slots currently in an abandoned state (not yet recovered), meets or exceeds the maximum number of storage slots that can be lost before the data is unrecoverable, then the entire storage deal is considered to be in a *failed* state.
Each **Storage Providers** posted collateral is burned. This incentivizes **SPs** not to let storage deals to be at risk of defaulting. **SPs** are incentivized to *proactively* avoid this by diversifying their infrastructure and the storage contracts they enter, and *reactively* by backing up their own slot data, or even backing up data from other slots so they can better assist slot recovery, as the deal approaches a failed state.
Clients also receive back any leftover from their original payment.
## Contract Ends Its Full Duration
When a started contract reaches its pre-specified duration without having previously defaulted, the contract completes.
All collateral is returned to **SPs t**hat currently fill the slots (note due to slot recovery these are not necessarily the same **SPs** that filled the slots at contract inception), and all remaining payment is returned to the client.
Deals can not be automatically rolled forward or extended. If a **Client** desires to continue a deal, they must create a new storage contract request. Otherwise, Clients can retrieve their data.
# CDX Testnet Tokenomics
The CDX token does not exist in the Testnet Phase. The description below refers to the mechanics of a Testnet token and not CDX itself and will be referred to as *CDX (Testnet token)* for this purpose.
For the avoidance of doubt, the *CDX (Testnet token)* are virtual items with no value of any kind and they are not convertible to any other currency, token, or any other form of property. They are solely intended to be utilised for the purposes of enabling the tokenomics and facilitating the different roles in this Testnet Phase.
## Roles
The Codex protocol has two primary roles fulfilled by network participants.
- **Clients**: pay Storage Providers in *CDX (Testnet token)* to securely store their data on the Codex network for an agreed upon amount of time.
- **Storage Providers**: post *CDX (Testnet token)* collateral to enter into storage contracts with Clients in exchange for a *CDX (Testnet token)* denominated payment.
- **Validators**: post *CDX (Testnet token)* collateral to validate storage proofs in exchange for a *CDX (Testnet token)* denominated payment.
## Token Utility
The *CDX (Testnet token)* is used as both a form of posted collateral and a means of payment in order to secure the network and access its services.
Collateral is primarily used as a spam and sybil-attack prevention mechanism, liability insurance (e.g. compensating Clients in case of catastrophic loss of data), and to enforce rational behavior.
Payments are made by Clients to Providers for services rendered, such as for storing data for a certain amount of time or retrieving data. This is implemented through the Marketplace contract, which serves as an escrow. Data in a storage contract is distributed into slots where each is, ideally, hosted by a different Storage Provider.
### **For Clients**
- Pay storage costs and fees in *CDX (Testnet token)* for storing files.
### **For Storage Providers**
- Post collateral in *CDX (Testnet token)* when committing to new storage contracts. This collateral is slashed if they do not fulfill their agreed upon services.
- Earn *CDX (Testnet token)* from the collateral of slashed Storage Providers by participating in the slot recovery mechanism.
- Earn *CDX (Testnet token)* from Clients when successfully completing the storage service.
### For Validators
- Post collateral in *CDX (Testnet token)* to operate the validation service. This collateral is slashed if they do not mark a proof as missing within a predetermined period.
- Earn *CDX (Testnet token)* from the collateral of slashed Storage Providers by marking proofs as missed
Figure below depicts the flow of the *CDX (Testnet token)* token within the system.
![Flow of the *CDX token within the system](/learn/tokenomics-token-flow.png)
## Value Capture and Accrual Mechanisms
Codex creates *value* to participants:
- Clients can benefit from storing data with strong durability guarantees;
- Storage Providers can earn yield from their spare resources or capital by providing a service.
- Validators earn payouts for marking proofs as missing.
Clients need *CDX (Testnet token)* tokens to request storage deals. *CDX (Testnet token)* captures the value created to Clients by being a *Value Transfer Token* to them.
Storage Providers and Validators are rewarded in *CDX (Testnet token)* token and also need it as a proof of commitment to the Protocol. They risk being slashed in exchange for rewards. *CDX (Testnet token)* captures the value created to Providers by being a *Work Token* to them.
The following mechanisms describe how the value accrues to the *CDX (Testnet token)* token.
### Protocol Fee over Contracts
If the contract is canceled before it starts, Client's deposited amount is charged a small penalty and returned, aiding to prevent low quality spam deal requests.
If the contract successfully initiates, the protocol collects a fee for facilitating the transaction. The remaining amount is made available for payments to Storage Providers.
The collected fees are burned in both cases. This creates a small but constant deflationary force on the token supply, which is proportional to the product demand.
## Behavior & Motivations
### Clients
Clients have the following rational behavior:
- Requesting storage from the network with a fee at fair market rates
- Providing data to storage nodes that meet their criteria
They may also exhibit the following adversarial behavior, whether for profit driven, malicious, or censorship motivations:
- Requesting storage from the network but never making the data available for any or all slots
- Requesting storage from the network but not releasing the data within required time period to begin the contract successfully
- Requesting storage from the network but not releasing the data to specific Providers
- Attacking SPs that host their data to attempt to relieve their payment obligations at the end of the contract.
### **Storage Providers**
Storage Providers have the following rational behavior:
- Committing to slots of storage contracts to earn a fee.
- Providing proofs of storage for their committed slots to avoid collateral slashing penalties.
- Releasing the data to anyone who requests it.
- Committing to failed slots of storage contracts to maintain the integrity of the data
They may also exhibit the following adversarial behavior, whether for profit driven, malicious, or censorship motivations:
- Reserving a contract slot but never filling it (attempt to prevent contract from starting)
- Ceasing to provide proofs mid the lifespan of a contract
- Producing proofs, but not making data available for other nodes to retrieve
### Validators
Validators have the following rational behavior:
- Marking a proof as missing to earn a fee
- Tracking the history of missed proofs of a **SP**
- Triggering the Slot Recovery Mechanism when an **SP** reaches the maximum allowed number of missed proofs
They may also exhibit the following adversarial behavior, whether for profit driven, malicious, or censorship motivations:
- Colluding with SPs to ignore missed proofs
- Observing a missed proof but do not post it onchain
## Incentive Mechanisms
The following mechanisms help incentivize the expected behavior of each role and mitigate the detrimental ones.
### Clients Provide Full Payment Upfront
Clients must deposit the full amount in *CDX (Testnet token)* that covers the entirety of the storage contract duration upfront. This indicates their pledge to pay a certain amount for the storage contract, though the contract only begins when and if all data slots are filled by Storage Providers.
### Delayed Payment to Storage Providers
Storage Providers only receive payment related to the provision of services at the end of the contract duration.
### Collateral Requirement
In order to fill a data slot, Storage Providers first stake and commit the required collateral in the form of the *CDX (Testnet token)* for that slot which is then subject to slashing if they do not post a proof to confirm the slot.
Validators also need to post collateral to participate in the validation service.
### Proof of Storage
Contracts only start when all data slots are filled. Slots are only considered filled after a Storage Provider has posted collateral and the associated proof for its slot.
Once the contract begins, Storage Providers regularly provide proof of storage.
### **Slashing for Missed Proofs of Storage**
At any point during the duration of the storage contract, the storage provider is slashed if it fails to provide a certain number of proof of storage in a row. Should the SP resume providing proof of storage, it needs to top up the slashed collateral. The penalty is a fixed percentage of the total collateral.
### Slot Recovery Mechanism
If a Storage Provider does not submit the required storage proofs when required, after a number of slashings their entire collateral will be seized. A portion of the confiscated collateral is used as an incentive for the new Storage Provider who recovers and starts serving the abandoned slot. The remainder of the confiscated collateral in *CDX (Testnet token)* is burned.
### Slashing Defaulted Contract
If, at any point during the duration of the storage contract, the number of data slots currently abandoned (and not yet recovered) reaches or surpasses the maximum allowable lost slots (meaning the data becomes irretrievable), then the entire storage contract is deemed to be *failed*.
At this stage, collaterals of all Storage Providers serving data slots in the contract are entirely slashed.
### Client Reimbursement
If at any point during the contract, sufficient slots are abandoned such that the data is not fully recoverable, Clients receive back any leftover from their original payment.
## Token Lifecycle
### Burning
*CDX (Testnet token)* tokens are burned in these instances:
- When a storage deal contract fails to initiate, a small portion of the Client's payment for the storage deal is burned. This serves primarily as a mechanism to deter spam and ensure that deal requests are submitted at market-appropriate prices for storage.
- When a storage deal contract successfully initiates, the protocol applies a fee for facilitating the transaction.
- Whenever a Storage Provider misses a certain number of storage proofs, a portion of the collateral is slashed and burned.
- Once the slot recovery mechanism resolves, the remaining of the abandoning Storage Providers collateral is burned.

30
es/learn/troubleshoot.md Normal file
View File

@ -0,0 +1,30 @@
---
outline: [2, 3]
---
# Troubleshoot
Having trouble getting your Codex node connected to the testnet? Here's a list of common Codex connection conundrums and steps to diagnose and solve them. If your troubles are not addressed here, check our open issues on Github or reach out via our Discord server.
## Some basics
You've probably already considered these. But just in case:
1. Are you using a VPN? Make sure it's configured correctly to forward the right ports, and make sure you announce your node by the public IP address where you can be reached.
1. Are you using a firewall or other security software? Make sure it's configured to allow incoming connections to Codex's discovery and peer-to-peer ports.
## Check your announce address
Your node announces your public address to the network, so other nodes can connect to you. A common issue is connection failure due to incorrect announce addresses. Follow these steps to check your announce address.
1. Go to a whats-my-ip site, or `ip.codex.storage` and note the IP address.
1. Go into your router/modem WAN settings and find the public IP address.
1. These two addresses should match.
1. If they do not, it's possible that A) you're behind a VPN. In this case, it's up to you to disable the VPN or make sure all forwarding is configured correctly. or B) Your internet-service-provider has placed your uplink behind a secondary NAT. ISPs do this to save public IP addresses. The address assigned to your router/moderm is not a 'true' public internet address. Usually this issue can be solved by your ISP. Contact customer support and ask them to give you a public address (sometimes also called Dynamic IP address).
1. Call Codex's debug/info endpoint. See the [Using Codex](/learn/using) for the details.
1. In the JSON response, you'll find "announceAddresses".
1. The IP address listed there should match your public IP.
1. If the announce address in the JSON is incorrect, you can adjust it manually by changing Codex's CLI argument `--nat` or setting the environment variable `CODEX_NAT`. After you've changed your announce address and restarted your node, please allow some time (20-30mins) for the network to disseminate the updated address.
If you've performed these steps and haven't found any issues, your announce address is probably not the problem.

275
es/learn/using.md Normal file
View File

@ -0,0 +1,275 @@
---
outline: [2, 3]
---
# Using Codex
We can interact with Codex using [REST API](/developers/api). This document will show you several useful examples.
Also, we can check [Codex App UI](https://app.codex.storage).
Command line interpreter on [Linux/macOS](#linux-macos) and [Windows](#windows) works slightly different, so please use steps for your OS.
## Linux/macOS
### Overview
1. [Debug](#debug)
2. [Upload a file](#upload-a-file)
3. [Download a file](#download-a-file)
4. [Local data](#local-data)
5. [Create storage availability](#create-storage-availability)
6. [Purchase storage](#purchase-storage)
7. [View purchase status](#view-purchase-status)
### Debug
An easy way to check that your node is up and running is:
```shell
curl http://localhost:8080/api/codex/v1/debug/info \
-w '\n'
```
This will return a JSON structure with plenty of information about your local node. It contains peer information that may be useful when troubleshooting connection issues.
### Upload a file
> [!Warning]
> Once you upload a file to Codex, other nodes in the network can download it. Please do not upload anything you don't want others to access, or, properly encrypt your data *first*.
```shell
curl -X POST \
http://localhost:8080/api/codex/v1/data \
-H 'Content-Type: application/octet-stream' \
-w '\n' \
-T <FILE>
```
On successful upload, you'll receive a CID. This can be used to download the file from any node in the network.
> [!TIP]
> Are you on the [Codex Discord server](https://discord.gg/codex-storage)? Post your CID in the [# :wireless: | share-cids](https://discord.com/channels/895609329053474826/1278383098102284369) channel, see if others are able to download it. Codex does not (yet?) provide file metadata, so if you want others to be able to open your file, tell them which extension to give it.
### Download a file
When you have a CID of data you want to download, you can use the following commands:
```shell
# paste your CID from the previous step here between the quotes
CID="..."
```
```shell
curl "http://localhost:8080/api/codex/v1/data/${CID}/network/stream" \
-o "${CID}.png"
```
Please use the correct extension for the downloaded file, because Codex does not store yet content-type or extension information.
### Local data
You can view which datasets are currently being stored by your node:
```shell
curl http://localhost:8080/api/codex/v1/data \
-w '\n'
```
### Create storage availability
> [!WARNING]
> This step requires that Codex was started with the [`prover`](/learn/run#codex-storage-node) option.
In order to start selling storage space to the network, you must configure your node with the following command. Once configured, the node will monitor on-chain requests-for-storage and will automatically enter into contracts that meet these specifications. In order to enter and maintain storage contracts, your node is required to submit zero-knowledge storage proofs. The calculation of these proofs will increase the CPU and RAM usage of Codex.
```shell
curl -X POST \
http://localhost:8080/api/codex/v1/sales/availability \
-H 'Content-Type: application/json' \
-w '\n' \
-d '{
"totalSize": "8000000",
"duration": "7200",
"minPrice": "10",
"maxCollateral": "10"
}'
```
For descriptions of each parameter, please view the [spec](https://api.codex.storage/#tag/Marketplace/operation/offerStorage).
### Purchase storage
To purchase storage space from the network, first you must upload your data. Once you have the CID, use the following to create a request-for-storage.
Set your CID:
```shell
# paste your CID from the previous step here between the quotes
CID="..."
echo "CID: ${CID}"
```
Next you can run:
```shell
curl -X POST \
"http://localhost:8080/api/codex/v1/storage/request/${CID}" \
-w '\n' \
-d '{
"duration": "3600",
"reward": "1",
"proofProbability": "5",
"expiry": "1200",
"nodes": 5,
"tolerance": 2,
"collateral": "1"
}'
```
For descriptions of each parameter, please view the [spec](https://api.codex.storage/#tag/Marketplace/operation/createStorageRequest).
When successful, this request will return a Purchase-ID.
### View purchase status
Using a Purchase-ID, you can check the status of your request-for-storage contract:
```shell
# paste your PURCHASE_ID from the previous step here between the quotes
PURCHASE_ID="..."
```
Then:
```shell
curl "http://localhost:8080/api/codex/v1/storage/purchases/${PURCHASE_ID}" \
-w '\n'
```
This will display state and error information for your purchase.
| State | Description |
|-----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Pending | Request is waiting for chain confirmation. |
| Submitted | Request is on-chain. Hosts may now attempt to download the data. |
| Started | Hosts have downloaded the data and provided proof-of-storage. |
| Failed | The request was started, but (too many) hosts failed to provide proof-of-storage on time. While the data may still be available in the network, for the purpose of the purchase it is considered lost. |
| Finished | The request was started successfully and the duration has elapsed. |
| Expired | (Not enough) hosts have submitted proof-of-storage before the request's expiry elapsed. |
| Errored | An unfortunate state of affairs. The 'error' field should tell you more. |
## Windows
### Overview {#overview-windows}
1. [Debug](#debug-windows)
2. [Upload a file](#upload-a-file-windows)
3. [Download a file](#download-a-file-windows)
4. [Local data](#local-data-windows)
5. [Create storage availability](#create-storage-availability-windows)
6. [Purchase storage](#purchase-storage-windows)
7. [View purchase status](#view-purchase-status-windows)
### Debug {#debug-windows}
An easy way to check that your node is up and running is:
```batch
curl http://localhost:8080/api/codex/v1/debug/info
```
This will return a JSON structure with plenty of information about your local node. It contains peer information that may be useful when troubleshooting connection issues.
### Upload a file {#upload-a-file-windows}
> [!Warning]
> Once you upload a file to Codex, other nodes in the network can download it. Please do not upload anything you don't want others to access, or, properly encrypt your data *first*.
```batch
curl -X POST ^
http://localhost:8080/api/codex/v1/data ^
-H "Content-Type: application/octet-stream" ^
-T <FILE>
```
On successful upload, you'll receive a CID. This can be used to download the file from any node in the network.
> [!TIP]
> Are you on the [Codex Discord server](https://discord.gg/codex-storage)? Post your CID in the [# :wireless: | share-cids](https://discord.com/channels/895609329053474826/1278383098102284369) channel, see if others are able to download it. Codex does not (yet?) provide file metadata, so if you want others to be able to open your file, tell them which extension to give it.
### Download a file {#download-a-file-windows}
When you have a CID of data you want to download, you can use the following commands:
```batch
:: paste your CID from the previous step here between the quotes
set CID="..."
```
```batch
curl "http://localhost:8080/api/codex/v1/data/%CID%/network/stream" ^
-o "%CID%.png"
```
Please use the correct extension for the downloaded file, because Codex does not store yet content-type or extension information.
### Local data {#local-data-windows}
You can view which datasets are currently being stored by your node:
```batch
curl http://localhost:8080/api/codex/v1/data
```
### Create storage availability {#create-storage-availability-windows}
> [!WARNING]
> This step requires that Codex was started with the [`prover`](/learn/run#codex-storage-node) option.
In order to start selling storage space to the network, you must configure your node with the following command. Once configured, the node will monitor on-chain requests-for-storage and will automatically enter into contracts that meet these specifications. In order to enter and maintain storage contracts, your node is required to submit zero-knowledge storage proofs. The calculation of these proofs will increase the CPU and RAM usage of Codex.
```batch
curl -X POST ^
http://localhost:8080/api/codex/v1/sales/availability ^
-H "Content-Type: application/json" ^
-d "{""totalSize"": ""8000000"", ""duration"": ""7200"", ""minPrice"": ""10"", ""maxCollateral"": ""10""}"
```
For descriptions of each parameter, please view the [spec](https://api.codex.storage/#tag/Marketplace/operation/offerStorage).
### Purchase storage {#purchase-storage-windows}
To purchase storage space from the network, first you must upload your data. Once you have the CID, use the following to create a request-for-storage.
Set your CID:
```batch
:: paste your CID from the previous step here between the quotes
set CID="..."
echo CID: %CID%
```
Next you can run:
```batch
curl -X POST ^
"http://localhost:8080/api/codex/v1/storage/request/%CID%" ^
-H "Content-Type: application/json" ^
-d "{""duration"": ""3600"",""reward"": ""1"", ""proofProbability"": ""5"", ""expiry"": ""1200"", ""nodes"": 5, ""tolerance"": 2, ""collateral"": ""1""}"
```
For descriptions of each parameter, please view the [spec](https://api.codex.storage/#tag/Marketplace/operation/createStorageRequest).
When successful, this request will return a Purchase-ID.
### View purchase status {#view-purchase-status-windows}
Using a Purchase-ID, you can check the status of your request-for-storage contract:
```batch
:: paste your PURCHASE_ID from the previous step here between the quotes
set PURCHASE_ID="..."
```
Then:
```batch
curl "http://localhost:8080/api/codex/v1/storage/purchases/%PURCHASE_ID%"
```
This will display state and error information for your purchase.
| State | Description |
|-----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Pending | Request is waiting for chain confirmation. |
| Submitted | Request is on-chain. Hosts may now attempt to download the data. |
| Started | Hosts have downloaded the data and provided proof-of-storage. |
| Failed | The request was started, but (too many) hosts failed to provide proof-of-storage on time. While the data may still be available in the network, for the purpose of the purchase it is considered lost. |
| Finished | The request was started successfully and the duration has elapsed. |
| Expired | (Not enough) hosts have submitted proof-of-storage before the request's expiry elapsed. |
| Errored | An unfortunate state of affairs. The 'error' field should tell you more. |
## Known issues
1. We add a new line to the API calls to get more readable output, please check [[rest] Add line ending on responses #771](https://github.com/codex-storage/nim-codex/issues/771) for more details.

37
es/learn/what-is-codex.md Normal file
View File

@ -0,0 +1,37 @@
# ¿Qué es Codex?
Codex es un protocolo de almacenamiento de datos descentralizado. Sus características principales son una fuerte resistencia a la censura y garantías de durabilidad. Tiene una implementación de referencia con el mismo nombre, escrita en nim. Sirve como la capa de almacenamiento del stack tecnológico de [Logos](https://logos.co/). Junto con la capa de acuerdo sin confianza, [Nomos](http://nomos.tech), y la capa de comunicaciones, [Waku](http://waku.org), es uno de los proyectos fundacionales del Logos Collective.
<br/>
### Motivo
El panorama del almacenamiento remoto está dominado por un número cada vez menor de potencias de internet—Google, Microsoft, Amazon, etc. Si bien estos servicios obtienen altas puntuaciones en términos de experiencia de usuario y conveniencia, el almacenamiento de datos en la nube centralizada sufre de las siguientes desventajas:
- Censura
- Falta de propiedad de los datos
- Brechas de seguridad y interrupciones
- Alto costo
Los proveedores de almacenamiento en la nube centralizado tienen un historial establecido de censura de datos y, como propietarios de facto de dichos datos, tienen el poder de hacerlo según sus propios estándares. Además, las plataformas centralizadas han sido víctimas de importantes filtraciones de datos e interrupciones del servicio en numerosas ocasiones.
Tales incidentes han creado un hueco en el mercado para una alternativa descentralizada y resistente a la censura. Las redes existentes de almacenamiento y compartición de archivos entre pares abordan algunos de estos problemas—como la robustez frente a interrupciones de la red y una deseable resistencia a la censura. Sin embargo, sin incentivos adecuados y fuertes garantías de durabilidad de datos, no constituyen cimientos adecuados sobre los que construir aplicaciones verdaderamente imparables.
Las soluciones de almacenamiento descentralizado existentes pretenden mejorar las primeras plataformas de compartición de archivos P2P como eDonkey y Gnutella. Sin embargo, el mercado todavía carece de una solución de almacenamiento descentralizado que sea eficiente en términos de uso de almacenamiento y ancho de banda, mientras ofrece garantías de rendimiento y durabilidad comparables a los incumbentes.
<br/>
### Descentralizando el almacenamiento de datos
Codex comenzó en 2021 para abordar la necesidad de una capa de almacenamiento durable y descentralizada para el stack tecnológico web3.
El nombre "Codex" se refiere a una forma antigua de libro—una alusión a las garantías de durabilidad extremadamente robustas—99.99%—del motor de almacenamiento de datos.
Codex fue anunciado como un protocolo central del Logos Collective en junio de 2023.
### Red de pruebas
Codex se encuentra actualmente en fase de red de pruebas. La implementación del cliente es software libre y abierto. Si estás interesado, te animamos a probar Codex, conectarte a la red de pruebas y experimentar con sus características. [Comienza aquí](./quick-start.md)

536
es/learn/whitepaper.md Normal file
View File

@ -0,0 +1,536 @@
<center>
**Abstract**
</center>
<div style="display: flex; justify-content: center; align-items: center;">
<div style="text-align: justify; width: 80%">
The internet is becoming more and more centralized. As companies and individuals increasingly rely on centralized cloud providers for storage, critical concerns on privacy, censorship, and user control, as well as on the concentration of economic power in the hands of few entities become more pronounced.
While there have been several attempts at providing alternatives, modern decentralized storage networks (DSNs) often fall short on basic aspects like having strong durability guarantees, being efficient to operate, or providing scalable proofs of storage. This in turn leads to solutions that are either: _i)_ not useful, as they can lose data; _ii)_ not friendly to decentralization, as they require specialized or expensive hardware, or; _iii)_ economically unfeasible, as they burden providers with too many costs beyond those of the storage hardware itself.
In this paper, we introduce Codex, a novel Erasure Coded Decentralized Storage Network that attempts to tackle those issues. Codex leverages erasure coding as part of both redundancy and storage proofs, coupling it with zero-knowledge proofs and lazy repair to achieve tunable durability guarantees while being modest on hardware and energy requirements. Central to Codex is the concept of the Decentralized Durability Engine (DDE), a framework we formalize to systematically address data redundancy, remote auditing, repair, incentives, and data dispersal in decentralized storage systems.
We describe the architecture and mechanisms of Codex, including its marketplace and proof systems, and provide a preliminary reliability analysis using a Continuous Time Markov-Chain (CTMC) model to evaluate durability guarantees. Codex represents a step toward creating a decentralized, resilient, and economically viable storage layer critical for the broader decentralized ecosystem.
</div>
</div>
## 1. Introduction
Data production has been growing at an astounding pace, with significant implications. Data is a critical asset for businesses, driving decision-making, strategic planning, and innovation. Individuals increasingly intertwine their physical lives with the digital world, meticulously documenting every aspect of their lives, taking pictures and videos, sharing their views and perspectives on current events, using digital means for communication and artistic expression, etc. Digital personas have become as important as their physical counterparts, and this tendency is only increasing.
Yet, the current trend towards centralization on the web has led to a situation where users have little to no control over their personal data and how it is used. Large corporations collect, analyze, and monetize user data, often without consent or transparency. This lack of privacy leaves individuals vulnerable to targeted advertising, profiling, surveillance, and potential misuse of their personal information.
Moreover, the concentration of data and power in the hands of a few centralized entities creates a significant risk of censorship: platforms can unilaterally decide to remove, modify, or suppress content that they deem undesirable, effectively limiting users freedom of expression and access to information. This power imbalance undermines the open and democratic nature of the internet, creating echo chambers and curtailing the free flow of ideas.
Another undesirable aspect of centralization is economical: as bigtech dominance in this space evolves to an oligopoly, all revenues flow into the hands of a selected few, while the barrier to entry becomes higher and higher.
To address these issues, there is a growing need for decentralized technologies. Decentralized technologies enable users to: _i)_ own and control their data by providing secure and transparent mechanisms for data storage and sharing, and _ii)_ participate in the storage economy as providers, allowing individuals and organizations to take their share of revenues. Users can choose to selectively share their data with trusted parties, retain the ability to revoke access when necessary, and monetize their data and their hardware if they so desire. This paradigm shift towards user-centric data and infrastructure ownership has the potential to create a more equitable and transparent digital ecosystem.
Despite their potential benefits, however, the lack of efficient and reliable decentralized storage leaves a key gap that needs to be addressed before any notion of a decentralized technology stack can be seriously contemplated.
In response to these challenges, we introduce Codex: a novel Erasure Coded Decentralized Storage Network which relies on erasure coding for redundancy and efficient proofs of storage. This method provides unparalleled reliability and allows for the storage of large datasets, larger than any single node in the network, in a durable and secure fashion. Our compact and efficient proofs of storage can detect and prevent catastrophic data loss with great accuracy, while incurring relatively modest hardware and electricity requirements -- two preconditions for achieving true decentralization. In addition, we introduce and formalize in this paper the notion of durability in decentralized storage networks through a new concept we call the _Decentralized Durability Engine_ (DDE).
The remainder of this paper is organized as follows. First, we discuss the context on which Codex is built (Sec. 2) by expanding on the issues of centralized cloud storage, and providing background on previous takes at decentralized alternatives -- namely, p2p networks, blockchains, and DSNs. Then, we introduce the conceptual framework that underpins Codex in Sec. 3 -- the Decentralized Durability Engine (DDE) -- followed by a more detailed descriptions of the mechanisms behind Codex and how it materializes as a DDE in Sec. 4. Sec. 5 then presents a preliminary reliability analysis, which places Codex's storage parameters alongside more formal durability guarantees. Finally, Sec. 6 provides conclusions and ongoing work.
## 2. Background and Context
Codex aims at being a useful and decentralized alternative to centralized storage. In this section, we discuss the context in which this needs arises, as well as why past and current approaches to building and reasoning about decentralized storage were incomplete. This will set the stage for our introduction of the Decentralized Durability Engine -- our approach to reasoning about decentralized storage -- in Sec. 3.
### 2.1. Centralized Cloud Storage
Over the past two decades, centralized cloud storage has become the _de facto_ approach for storage services on the internet for both individuals and companies alike. Indeed, recent research places the percentage of businesses that rely on at least one cloud provider at $94\%$[^zippia_cloud_report], while most modern smartphones will backup their contents to a cloud storage provider by default.
The appeal is clear: scalable, easy-to-use elastic storage and networking coupled with a flexible pay-as-you-go model and a strong focus on durability[^s3_reinvent_19] translating to dependable infrastructure that is available immediately and at the exact scale required.
Centralization, however, carries a long list of downsides, most of them due to having a single actor in control of the whole system. This effectively puts users at the mercy of the controlling actor's commercial interests, which may and often will not coincide with the user's interests on how their data gets used, as well as their ability to stay afloat in the face of natural, political, or economical adversity. Government intervention and censorship are also important sources of concern[^liu_19]. Larger organizations are acutely aware of these risks, with $98\%$ of cloud user businesses adopting multi-cloud environments to mitigate them[^multicloud].
The final downside is economical: since very few companies can currently provide such services at the scale and quality required, the billions in customer spending gets funneled into the pockets of a handful of individuals. Oligopolies such as these can derail into an uncompetitive market which finds its equilibrium at a price point which is not necessarily in the best interest of end-users[^feng_14].
### 2.2. Decentralized Alternatives: Past and Present
Given the downsides of centralized cloud storage, it is natural to wonder if there could be alternatives, and indeed those have been extensively researched since the early 2000's. We will not attempt to cover that entire space here, and will instead focus on what we consider to be the three main technological breakthroughs that happened in decentralized systems over these past two decades, and why they have failed to make meaningful inroads thus far: P2P networks, blockchains, and Data Storage Networks (DSNs).
**P2P Networks.** P2P networks have been around for over two decades. Their premise is that users can run client software on their own machines and form a self-organizing network that enables sharing of resources like bandwidth, compute, and storage to provide higher-level services like search or decentralized file sharing without the need for a centralized controlling actor.
Early networks like BitTorrent[^cohen_01], however, only had rudimentary incentives based on a form of barter economy in which nodes providing blocks to other nodes would be rewarded with access to more blocks. This provides some basic incentives for nodes to exchange the data they hold, but whether or not a node decides to hold a given piece of data is contingent on whether or not the node operator was interested in that data to begin with; i.e., a node will likely not download a movie if they are not interested in watching it.
Files which are not popular, therefore, tend to disappear from the network as no one is interested in them, and there is no way to incentivize nodes to do otherwise. This lack of even basic durability guarantees means BitTorrent and, in fact, most of the early p2p file-sharing networks, are suitable as distribution networks at best, but not as storage networks as data can, and probably will, be eventually lost. Even more recent attempts at decentralized file sharing like IPFS[^ipfs_website] suffer from similar shortcomings: by default, IPFS offers no durability guarantees, i.e., there is no way to punish a pinning service if it fails to keep data around.
**Blockchains.** Blockchains have been introduced as part of Bitcoin in 2008[^nakamoto_08], with the next major player Ethereum[^buterin_13] going live in 2013. A blockchain consists of a series of blocks, each containing a list of transactions. These blocks are linked together in chronological order through cryptographic hashes. Each block contains a hash of the previous block, which secures the chain against tampering. This structure ensures that once a block is added to the blockchain, the information it contains cannot be altered without redoing all subsequent blocks, making it secure against fraud and revisions. For all practical purposes, once a block gets added, it can no longer be removed.
This permanence allied to the fully replicated nature of blockchain means they provide very strong durability and availability guarantees, and this has been recognized since very early on. The full-replication model of blockchains, however, also turns out to be what makes them impractical for data storage: at the date of this writing, storing as little as a gigabyte of data on a chain like Ethereum remains prohibitively expensive[^kostamis_24].
Blockchains represent nevertheless a game-changing addition to decentralized systems in that they allow system designers to build much stronger and complex incentive mechanisms based on monetary economies, and to implement key mechanisms like cryptoeconomic security[^chaudhry_24] through slashing, which were simply not possible before.
**Decentralized Storage Networks (DSNs).** Decentralized Storage Networks (DSNs) represent a natural stepping stone in decentralized storage: by combining traditional P2P technology with the strong incentive mechanisms afforded by modern blockchains and new cryptographic primitives, they provide a much more credible take on decentralized storage.
Like early P2P networks, DSNs consolidate storage capacities from various independent providers and orchestrate data storage and retrieval services for clients. Unlike early P2P networks, however, DSNs employ the much stronger mechanisms afforded by blockchains to incentivize correct operation. They typically employ remote auditing techniques like Zero-Knowledge proofs to hold participants accountable, coupled with staking/slashing mechanisms which inflict monetary losses on bad participants as they are caught.
In their seminal paper[^protocol_17], the Filecoin team characterizes a DSN as a tuple $\Pi = \left(\text{Put}, \text{Get}, \text{Manage}\right)$, where:
* $\text{Put(data)} \rightarrow \text{key}$: Clients execute the Put protocol to store data under a unique identifier key.
* $\text{Get(key)} \rightarrow \text{data}$: Clients execute the Get protocol to retrieve data that is currently stored using key.
* $\text{Manage()}$: The network of participants coordinates via the Manage protocol to: control the available storage, audit the service offered by providers and repair possible faults. The Manage protocol is run by storage providers often in conjunction with clients or a network of auditors.
While useful, we argue this definition is incomplete as it pushes a number of key elements onto an unspecified black box protocol/primitive named $\text{Manage}()$. These include:
* incentive and slashing mechanisms;
* remote auditing and repair protocols;
* strategies for data redundancy and dispersal.
Such elements are of particular importance as one attempts to reason about what would be required to construct a DSN that provides actual utility. As we set out to design Codex and asked ourselves that question, we found that the key to useful DSNs is in _durability_; i.e., a storage system is only useful if it can provide durability guarantees that can be reasoned about.
In the next section, we explore a construct we name Decentralized Durability Engines which, we argue, lead to a more principled approach to designing storage systems that provide utility.
## 3. Decentralized Durability Engines (DDE)
A Decentralized Durability Engine is a tuple $\Gamma = \text{(R, A, P, I, D)}$ where:
* $R$ is a set of redundancy mechanisms, such as erasure coding and replication, that ensure data availability and fault tolerance.
* $A$ is a set of remote auditing protocols that verify the integrity and availability of stored data.
* $P$ is a set of repair mechanisms that maintain the desired level of redundancy and data integrity by detecting and correcting data corruption and loss.
* $I$ is a set of incentive mechanisms that encourage nodes to behave honestly and reliably by rewarding good behavior and penalizing malicious or negligent actions.
* $D$ is a set of data dispersal algorithms that strategically distribute data fragments across multiple nodes to minimize the risk of data loss due to localized failures and to improve data availability and accessibility.
We argue that when designing a storage system that can keep data around, none of these elements are optional. Data needs to be redundant ($R$), there needs to be a way to detect failures and misbehavior ($A$), we must be able to repair data so it is not lost to accumulated failures $(P)$, misbehaving nodes must be penalized ($I$), and data must be placed so as fault correlation is understood ($D$).
This is a somewhat informal treatment for now, but the actual parameters that would be input into any reliability analysis of a storage system would be contingent on those choices. In a future publication, we will explore how durability is affected by the choice of each of these elements in a formal framework.
## 4. Codex: A Decentralized Durability Engine
This section describes how Codex actually works. The primary motivation behind Codex is to provide a scalable and robust decentralized storage solution which addresses the limitations of existing DSNs. This includes: i) enhanced durability guarantees that can be reasoned about, ii) scalability and performance and iii) decentralization and censorship resistance.
We start this section by laying out key concepts required to understand how Codex works (Sec. 4.1). We then discuss the redundancy ($R$), remote auditing ($A$), and repair mechanisms ($P$) of Codex and how they combine erasure codes and zero-knowledge proofs into a system that is lightweight, efficient, and amenable to decentralization. Sec. 4.4 takes a detour onto the networking layer and provides an overview of our scalable data transfer protocols. Finally, incentives ($I$) and dispersal $(D)$ are discussed in Sec. 4.5 as part of the Codex marketplace.
### 4.1. Concepts
In the context of Codex (and of storage systems in general), two properties appear as fundamental:
**Availability.** A system is said to be _available_ when it is able to provide its intended service, and _unavailable_ otherwise. The availability of a system over any given interval of time is given by [^tanembaum]:
$$
p_\text{avail} =\frac{t_a}{t_a + t_u}
$$
where $t_a$ and $t_u$ are the total times in which the system remained available and unavailable, respectively. To maintain high availability, a storage system needs to be _fault tolerant_; i.e., it should be able to correctly service storage and retrieval requests in the presence of hardware faults and malicious participants.
**Durability.** Quantified as a probability $p_\text{dur} = 1 - p_\text{loss}$ that a given unit of data _will not_ be lost over a given period of time; e.g. the probability that some file is not lost within a $1$-year period. This probability is sometimes expressed as a percentage (e.g. in S3).
If this number is very close to one, e.g. $p_\text{loss} \leq 10^{-6}$, then the system is said to be _highly durable_. Systems that are not highly durable are those that can lose data with higher or unbounded probability, or that do not quantify their loss probabilities at all.
Ideally, we would like storage systems to be highly available and highly durable. Since achieving _provable availability_ is in general not possible[^bassam_18], Codex focuses on stronger guarantees for durability and on incentivizing availability instead.
**Dataset.** A _dataset_ $D = \{c_1, \cdots c_b\}$ is defined in Codex as an ordered set of $b \in \mathbb{N}$ fixed-sized blocks. Blocks are typically small, on the order of $64\text{kB}$. For all intents and purposes, one can think of a dataset as being a regular file.
**Storage Client (SC).** A Storage Client is a node that participates in the Codex network to buy storage. These may be individuals seeking to backup the contents of their hard drives, or organizations seeking to store business data.
**Storage Provider (SP).** A Storage Provider is a node that participates in Codex by selling disk space to other nodes.
### 4.2. Overview
At a high level, storing data in Codex works as follows. Whenever a SC wishes to store a dataset $D$ into Codex, it:
1. splits $D$ into $k$ disjoint $\{S_1, \cdots, S_k\}$ partitions named **slots**, where each slot contains $s = \left\lceil \frac{b}{k} \right\rceil$ blocks;
1. erasure-codes $D$ with a Reed-Solomon Code[^reed_60] by extending it into a new dataset $D_e$ which adds an extra $m \times s$ parity blocks to $D$ (Sec. 4.3). This effectively adds $m$ new slots to the dataset. Since we use a systematic code, $D$ remains a prefix of $D_e$;
1. computes two different Merkle tree roots: one used for inclusion proofs during data exchange, based on SHA256, and another one for storage proofs, based on Poseidon2 (Sec 4.3);
1. generates a content-addressable manifest for $D_e$ and advertises it into the Codex DHT (Sec. 4.4);
1. posts a **storage request** containing a set of parameters in the Codex marketplace (on-chain), which includes things like how much the SC is willing to pay for storage, as well as expectations that may impact the profitability of candidate SPs and the durability guarantees for $D_e$, for each slot (Sec. 4.5).
The Codex marketplace (Sec. 4.5) then ensures that SPs willing to store data for a given storage request are provided a fair opportunity to do so. Eventually, for each slot $S_i \in D_e$, _some_ SP will:
1. declare its interest in it by filing a **slot reservation**;
1. download the data for the slot from the SC;
1. provide an initial proof of storage and some staking collateral for it.
Once this process completes, we say that slot $S_i$ has been **filled**. Once all slots in $D_e$ have been filled, we say that $D_e$ has been **fulfilled**. For the remainder of this section, we will dive into the architecture and mechanisms of Codex by explaining in more detail each aspect of the storage flow.
### 4.3. Erasure Coding, Repair, and Storage Proofs
Erasure coding plays two main roles in Codex: _i)_ allowing data to be recovered following loss of one or more SPs and the slots that they hold (redundancy) and _ii)_ enabling cost-effective proofs of storage. We will go through each of these aspects separately.
**Erasure Coding for Redundancy.** As described before, a dataset $D$ is initially split into $k$ slots of size $s = \left\lceil \frac{b}{k} \right\rceil$ (Figure 1). Since $b$ may not actually be divisible by $k$, Codex will add _padding blocks_ as required so that the number of blocks in $D$ is $b_p = s \times k$.
<center>
<img src="/learn/whitepaper/dataset-and-blocks.png" width=80%/>
</center>
**Figure 1.** A padded dataset $D$ split into $k$ slots.
Codex then erasure-codes $D$ by _interleaving_ blocks taken from each slot (Figure 2), one at a time. The procedure runs $s$ interleaving steps, where $s$ is the number of blocks in a slot.
<center>
<img src="/learn/whitepaper/ec-dataset-and-blocks.png" width=80%/>
</center>
**Figure 2.** Erasure-coded dataset $D_e$ with $k + m$ slots and interleaving process.
At each _interleaving step_, we collect $k$ blocks by selecting the $i^{th}$ block within each of the $k$ slots ($1 \leq i \leq s$), and feed those through the Reed-Solomon encoder. The encoder then outputs $m$ parity blocks, which get added as the $i^{th}$ block of $m$ new distinct _parity slots_. Since slots have $s$ blocks each we are left, at the end of this process, with $m$ parity slots of $s$ blocks each, or $m \times s$ new parity blocks.
The Codex marketplace (Sec. 4.5) then employs mechanisms to ensure that each one of these slots are assigned to a different node so that failure probabilities for each slot are decorrelated. This is important as, bridging back to durability guarantees, assuming that we could know the probability $p_{\text{loss}}$ with which a given SP could fail over a one year period, this would bound the probability of data loss at $p_{\text{loss}} \leq \binom{k + m}{k} p_{\text{loss}}^k(1 - p_{\text{loss}})^{m}$. We say this is a bound because in practice repair would kick in earlier, so the probability of loss is actually a lot smaller than this. We will carry a more detailed analysis taking those aspects into account in Sec. 5.
**Erasure Coding for Storage Proofs.** The other, less obvious way in which Codex employs erasure coding is _locally_ at each SP when generating storage proofs. This allows Codex to be expedient in detecting both unintentional and malicious data loss with a high level of accuracy.
To understand how this works, imagine we had an SP that has promised to store some slot $S_i \in D_e$ until a certain time instant $t_b$. How do we ensure that the SP is indeed holding its promise? One way to approach this would be by having a verifier download the whole slot $S_i$ from the SP at random instants in time. This would ensure the data is still there, but would be costly.
A smarter approach would be by _sampling_: instead of downloading the entire file, the verifier can ask for a random subset of the blocks in the file and their Merkle inclusion proofs. While this also works, the problem here is that the probability of detecting lost blocks is directly impacted by what fraction of blocks $l_i$ have been lost: if we ask the SP for $j$ samples, then the probability that we catch a missing block is $p_{\text{detect}} = 1 - (1 - l_i)^j$.
Although the decay is always geometric, the impact of having a loss fraction that is low (e.g. less than $1\%$) can be significant: as depicted in Figure 3, for $l_i = 0.01$ we get a $p_{\text{detect}}$ that is smaller than $0.5$ even after drawing $50$ samples. If that does not sound too bad, consider an adversarial setting in which an SP purposefully drops a very small fraction of a large file, perhaps one single block out of a million. For fractions that small ($10^{-6}$), one would require hundreds of thousands of samples to get reasonable detection probabilities, e.g. $p_{\text{detect}} > 0.99$.
<center>
<img src="/learn/whitepaper/p-detect-plot.png"/>
</center>
**Figure 3.** Number of samples $j$ required by a verifier to assert data loss ($p_{\text{detect}}$) for various loss fractions ($l_i$).
The reason it is hard to detect loss is because we are attempting to find the perhaps single block that is missing out of $b$ blocks by random sampling. Erasure coding completely changes that dynamic in that _any_ $k$ out of $b$ blocks is enough to recover the data, so that only loss fractions that are larger than $k/b$ matter as any smaller fraction can be compensated by the erasure code.
If we require SPs to _locally encode_ slots with a code rate [^wikipedia_code_rate] that is higher than $0.5$ so that a dataset with $b$ blocks expands to $2b$ and any $b$ blocks out of those are enough to recover the data, this means that data will only be lost if _more than half of the blocks_ are dropped, i.e., when $l_i \geq 0.5$. From Figure 3, we can see that in this case we approach $p_{\text{detect}} = 1$ with a very small number of samples: indeed, by looking at only $10$ samples, we already get $p_{\text{detect}} > 0.99$. The actual implementation in Codex borrows heavily from these ideas, though it requires SPs to use a somewhat more intrincate two-dimensional encoding structure for other technical reasons[^spanbroek_23].
The final step for Codex proofs is that they need to be _publicly verifiable_. The actual proving mechanism in Codex constructs a Groth16[^groth_16] proof so that it can be verified on-chain; i.e., the verifiers are the public blockchain nodes themselves. The implementation has therefore both an on-chain component, which contains the logic to determine when proofs are required and when they are overdue, and an off-chain component, which runs periodically to trigger those at the right instants.
Algorithm 1 depicts, in Python-pseudocode, the _proving loop_ that SPs must run for every slot $S_i$ that they fill. It starts by waiting for a period boundary (line $7$), which is a fixed time slice that is larger than the average time between consecutive blocks in the target blockchain; i.e., the loop in lines $6$ -- $15$ runs _at most once_ per block.
It then asks the on-chain contract if a proof is required for this period (line $8$). The contract will then execute Algorithm 2 (on-chain), which checks if the current blockhash modulo a `frequency` parameter (lines $3$) amounts to zero. Since hash values are approximately random, that condition will turn out to be true, on average, at every `frequency` blocks.
Going back to Algorithm 1, if a proof turns out to be required for the current period, the SP will then retrieve a random value from the contract (line $9$), which is also derived from the current blockhash.
```python=
async def proving_loop(
dataset_root: Poseidon2Hash,
slot_root: Poseidon2Hash,
contract: StorageContract,
slot_index: int):
while True:
await contract.next_period()
if contract.is_proof_required():
randomness = contract.get_randomness()
merkle_proofs = compute_merkle_proofs(slot_root, randomness)
post(
zk_proof(
public = [randomness, dataset_root, slot_index],
private = [slot_root, merkle_proofs]
))
```
**Algorithm 1.** Codex's proving loop (ran on SPs, off-chain).
It then uses this randomness to determine the indices of the blocks within the locally erasure-coded slot that it needs to provide proofs for, and computes Merkle inclusion proofs for each (line $10$). The zero-knowledge proof is then constructed by running a verification of those inclusion proofs against the dataset root in a zk-SNARK, in which the randomness, the dataset (Merkle) root, and the slot index are taken as public inputs, and the inclusion proofs and the slot (Merkle) root are private instead (lines $12$ - $15$). Once the proof is calculated, it is posted on-chain (line $11$), where it is verified.
```python=
def is_proof_required()
randomness = block.blockhash()
return randomness % frequency == 0:
```
**Algorithm 2.** Checking if a proof is required (ran on smart contract, on-chain).
Merkle trees for proof verification are built using $\text{Poseidon2}$ hashes[^grassi_23] as those are more efficient to compute inside arithmetic circuits than, say, SHA256, though this may change as we evolve the proving system.
**Repair.** The redundancy and proof mechanisms outlined so far allow Codex to _repair_ data in a relatively simple fashion: missing proofs signal lost slots, and are used as failure detectors. Whenever a threshold amount of slots are lost, a lazy repair process is triggered in which the lost slots are put back on sale. Providers are then allowed to fill such slots again but, instead of downloading the slot itself, they download enough blocks from other nodes so they can reconstruct the missing slot, say, $S_i$. They then proceed as before and submit a proof for $S_i$, causing that slot to be filled again.
The way Codex organizes its data as partitioned and erasure coded slots is largely inspired by HAIL[^bowers_09]. The use of local erasure coding and compact proofs is instead inspired by earlier work on PoRs[^juels_07] and PDPs[^ateniese_07], as well as compact PoRs[^schacham_08].
A key aspect of the Codex proving system is that it attempts to be as lightweight as possible. The final goal is to be able to run it on simple computers equipped with inexpensive CPUs and modest amounts of RAM. Current requirements for home SPs are well around what a NUC or consumer laptop can provide, but those should drop even further as we optimize it. This is key as an efficient proving system means that:
1. both non-storage hardware; e.g. CPUs and RAM, and electricity overhead costs for proofs should be small. This leads to better margins for SPs;
2. minimal requirements are modest, which favours decentralization.
### 4.4. Publishing and Retrieving Data
Datasets stored in Codex need to be advertised over a Distributed Hash Table (DHT), which is a flavour of the Kademlia DHT[^maymounkov_02], so they can be located and retrieved by other peers. At a basic level, the Codex DHT maps _Content IDentifiers_ (CIDs)[^cid_spec], which identify data, onto _provider lists_, which identify peers holding that data.
A CID unequivocally identifies a piece of data by encoding a flavour of a hash of its content together with the type of hashing method used to compute it. In the case of a Codex dataset $D_e$ (Figure 4), this hash is taken to be the root of the SHA256 Merkle tree constructed over its blocks $\{b_1, \cdots, b_{s \times (k + m)}\}$.
<div style="display: flex; justify-content: center; padding: 0 0 15px 0">
<img src="/learn/whitepaper/cid.png" width="60%" />
</div>
**Figure 4.** CIDs for Codex datasets.
Nodes that hold either part or the entirety of $D_e$ will periodically advertise a _Signed Peer Record_ (SPR) under $D_e$'s CID in the DHT to inform other peers that they are available to provide blocks for $D_e$. An SPR is a signed record[^signed_envelope_spec] which contains the peer's ID, its public key, and its supported network addresses as a list of multiaddresses[^multiaddress_spec].
This structure affords a great deal of flexibility in how peers choose to communicate and encode datasets, and is key in creating a p2p network which can support multiple concurrent p2p client versions and can therefore be upgraded seamlessly.
**Metadata.** Codex stores dataset metadata in descriptors called **manifests**. Those are currently kept separate from the dataset itself, in a manner similar to BitTorrent's _torrent files_. They contain metadata on a number of attributes required to describe and properly process the dataset, such as the Merkle roots for both the content (SHA256) and proof ($\text{Poseidon2}$) trees, the number of blocks contained in the dataset, the block size, erasure coding parameters, and the datasets' MIME-type. Although the CID of a dataset is largely independent of its manifest, a dataset can neither be decoded nor properly verified without it.
Manifests are currently stored as content-addressable blocks in Codex and treated similarly to datasets: nodes holding the manifest of a given dataset will advertise its CID onto the DHT, which is computed by taking a SHA256 hash of the manifest's contents. Since manifests are stored separate from the dataset, however, they can also be exchanged out-of-band, like torrent files can.
Other systems choose tighter coupling between the metadata and the dataset. IPFS and Swarm use cryptographic structures such as Merkle DAG and a Merkle Tree, where intermediate nodes are placed on the network and queried iteratively to retrieve the respective vertexes and leaves. Such design decisions have their own tradeoffs and advantages, for example an advantage of storing the metadata in a single addressable unit is that it eliminates intermediary network round trips, as opposed to a distributed cryptographic structure such as a tree or a DAG.
**Retrieving data.** Data retrieval in Codex follows a process similar to BitTorrent: a peer wishing to download a dataset $D_e$ must first acquire its manifest, either through Codex itself by looking up the manifest's CID on the DHT and downloading it from peers providing it, or out-of-band. Once in posession of the manifest, the peer can learn the dataset's CID (constructed from its SHA256 Merkle root) and look that up over the DHT. This is depicted Figure 5a **(1)**.
<div style="display: flex; justify-content: center;">
<div style="text-align: center;">
<img src="/learn/whitepaper/download.png"/>
<p>(a)</p>
</div>
<div style="text-align: center;">
<img src="/learn/whitepaper/swarm.png"/>
<p>(b)</p>
</div>
</div>
**Figure 5.** (a) DHT lookup and (b) download swarm.
The nodes responsible for that CID will reply with a (randomized) subset of the providers for that CID (Figure 5a **(2)**). The peer can then contact these nodes to bootstrap itself into a download swarm (Figure 5b). Once part of the swarm, the peer will engage in an exchange protocol similar to BitSwap[^bitswap_spec] by advertising the blocks it wishes to download to neighbors, and receiving requests from neighbors in return. Dropped peers are replaced by querying the DHT again. Note that SPs always participate in the swarms for the datasets they host, acting as seeders. Since the mechanism is so similar to BitTorrent, we expect Codex to scale at least as well.
Codex right now relies on simple incentive mechanisms to ensure that peers share blocks. There is current ongoing work on _bandwidth incentives_ and, in future versions, peers will be able to purchase block transfers from each other.
### 4.5. Codex Marketplace
The Codex marketplace is the set of components that run both on-chain, as smart contracts, and off-chain, as part of both SCs and SPs. Its main goal is to define and enforce the set of rules which together enable: _i)_ orderly selling and purchasing of storage; _ii)_ verification of storage proofs; _iii)_ rules for penalizing faulty actors (slashing) and compensating SP repairs and SC data loss; and _iv)_ various other aspects of the system's economics, which will be discussed as part of an upcoming Codex tokenomics litepaper.
Codex implements an ask/bid market in which SCs post **storage requests** on chain, and SPs can then act on those if they turn out to be profitable. This means that the request side; i.e., how much an SC is willing to pay, is always visible, whereas the bid side; i.e., at what price an SP is willing to sell, is not.
An SC that wishes Codex to store a dataset $D_e$ needs to provide $5$ main parameters. Those are:
1. **Size in bytes.** Specifies how many storage bytes the SC wishes to purchase.
2. **Duration.** Specifies for how long the SC wishes to purchase the storage bytes in (1); e.g. one year.
3. **Number of slots.** Contains the number of slots in $D_e$. This is derived from the erasure coding parameters $k$ and $m$ discussed in Sec. 4.3.
4. **Price.** The price this SC is willing to pay for storage, expressed as a fractional amount of Codex tokens per byte, per second. For instance, if this is set to $1$ and the SC wants to buy $1\text{MB}$ of storage for $10$ seconds, then this means the SC is willing to disburse $10$ million Codex tokens for this request.
5. **Collateral per slot.** Dictates the amount of Codex tokens that the SP is expected to put as collateral if they decide to fulfill a slot in this request (staking). Failure to provide timely proofs may result in loss of this collateral (slashing).
As discussed in Sec. 5, these parameters may impact durability guarantees directly, and the system offers complete flexibility so that applications can tailor spending and parameters to specific needs. Applications built on Codex will need to provide guidance to their users so they can pick the correct parameters for their needs, not unlike Ethereum wallets help users determine gas fees.
<center>
<img src="/learn/whitepaper/marketplace-overview.png" width=70%/>
</center>
**Figure 6.** Storage requests and their processing by SPs.
As depicted in Figure 6, every storage request posted by an SC gets recorded on-chain, and generates a blockchain event that SPs listen to. Internally, SPs will rank unfilled storage requests by their own criteria, typically profitability, and will attempt to fill the slots for requests that are most interesting to them first. As discussed in Sec. 4.2, filling a slot entails: _i)_ reserving the slot on-chain; _ii)_ downloading the data from the SC; _iii)_ providing an initial storage proof as well as the staking collateral.
**Ensuring diversity.** SPs compete for unfilled slots. If we allowed this competition to happen purely based on latency; i.e., the fastest provider to reserve a slot wins, we could easily end up with a system that is too centralized or, even worse, with multiple slots ending up at a single provider. The latter is particularly serious as failures within a provider may not be decorrelated, and we therefore want to ensure that the distribution of slots amongst providers is as randomized as possible.
To help mitigate these issues, the Codex marketplace implements a time-based, _expanding window_ mechanism to allow SPs to compete for slots. As depicted in Figure 7, each storage request is assigned a random position in a $z$-bit ID space by taking a hashing function $h$ and computing, for slot $S_i$, the value $h(u\,\|\, i)$, where $u$ is a random nonce. This will effectively disperse storage requests for slots approximately uniformly at random over the ID space.
<div style="padding: 2rem 0 4rem 0">
<img src="/learn/whitepaper/marketplace-slot-dispersal.png"/>
</div>
**Figure 7.** Slots placed at random in a $z$-bit space.
We then allow only hosts whose blockchain IDs are within a certain "distance" of a slot to compete in filling it (Figure 8).
<div style="padding: 2rem 0 4rem 0">
<img src="/learn/whitepaper/marketplace-expanding-window.png"/>
</div>
**Figure 8.** SP eligibility as a function of time and its distance to a slot.
This distance expands over time according to a _dispersal parameter_ $\mu$. Let $d: \{0,1\}^z \times \{0,1\}^z \longrightarrow [0, 2^z)$ be our distance function - we could for instance take the XOR of $a$ and $b$. A host with blockchain ID $b$ will only be allowed to fill a slot at position $a$ at time $t$ if:
$$
\begin{equation}
d(a, b) \leq \mu t
\end{equation}\tag{1}
$$
where $t = 0$ at the moment in which the storage request for $a$ is published. In the example in Figure 8, host $b$ will be allowed to fill slot $a$ when $t \geq 2$, whereas host $c$ will only be allowed to try once $t \geq 3$. We will not attempt to formally prove this but, under relatively weak assumptions, this guarantees that the assignments of slots to SPs happens approximately uniformly at random.
## 5. Reliability Analysis
In this section, we provide an initial analysis of durability for Codex. The main goal is investigating the values for $p_{\text{loss}}$, our probability of losing data over a 1-year period. In particular, we are interested in understanding what sorts of parameters are required for us to obtain very high levels of reliability (e.g. $p_{\text{loss}} = 10^{-9}$, or nine nines of availability).
Codex, as a system, stores a large amount of datasets, each encoded, distributed, verified, and repaired according to the specific parameters set up in the respective storage contract. Since datasets are set up independently and operate (mostly) independently, we can model the system at the level of the dataset. We will later discuss correlation between various datasets stored in the system.
In our first model, we use a Continuous Time Markov-Chain (CTMC) model to describe the state of the dataset at any time instance. The model considers the following aspects of Codex:
- dataset encoding;
- node failures;
- the proving process;
- dataset repair.
Before discussing the state space and the rate matix of the CTMC model, lets describe these aspects of the system.
As before, we assume a dataset $D$ split into $k$ disjoint partitions, and encoded into a new dataset $D_e$ with $n=k+m$ slots $\{S_1, \cdots, S_k , \cdots, S_{k+m}\}$. This encoding is often characterized by it's code expansion factor $e = n/k =1+m/k$, expressing the storage overhead due to code redundancy.
### 5.1. Failure Model
When discussing failures, we should differentiate between transient and permanent failures, as well as between catastrophic node failures (the slot data is entirely lost) and partial failures.
In our first model, we focus on permanent node failures. From the perspective of Codex, a node is considered lost if it cannot provide proofs. Permanent node failure can be due to disk failure, to other hardware or software failures leading to data corruption, but also due to operational risks, including hardware failures, network failures, or operational decisions.
Unrepairable hardware failures are typically characterized with their **MTTF** (Mean Time To Failure) metric, assuming an exponential distribution of the time to failure. There are various MTTF statistics available about disk failures[^schroeder_07].
As a first approximation, one could start from the above disk MTTF numbers, and try to factor in other reasons of permanent node failures. Disk MTTF is specified in the range of 1e+6 hours, however, we have good reasons to be more pessimistic, or at least err on the more unreliable side, and assume MTTF in the 1e+4 hour range, i.e. around a year.
For the sake of modeling, we also assume i.i.d. (independent and identically distributed) failures among the set of nodes storing a given dataset. This is an optimistic model compared to cases where some storage providers might fail together e.g. because of being on shared hardware, in the same data center, or being under the same administrative authority. We will model these correlated events in a separate document.
There might also be malicious nodes in the set of storage providers, e.g. withholding data when reconstruction would be required. Again, we will extend the model to these in a separate document.
### 5.2. Reconstruction Model
The next important time related parameter of the model is **MTTR** (Mean Time To Reconstruct). While we model events at the level of a single dataset, it is important to note here that a failure event most probably involves entire disks or entire nodes with multiple disks, with many datasets and a large amount of data. Therefore, in the case of reconstruction, the stochastic processes of individual datasets are not independent of each other, leading to higher and uncertain reconstruction times.
The actual repair time depends on a number of factors:
- time to start repairing the dataset,
- data transmission for the purposes of Erasure Code decoding,
- EC decoding itself,
- allocating the new nodes to hold the repaired blocks,
- distributing repaired data to the allocated nodes.
Overall, it is clearly not easy to come up with a reasonable distribution for the time of repair, not even the mean time of repair. While time to repair is most probably not an exponential distribution, we model it as such in a first approximation to allow Markov Chain based modeling.
### 5.3. Triggering Reconstruction
Reconstruction and re-allocation of slots can be triggered by the observed state, and our system "observes" state through the proving process. In our model, we assume that nodes are providing proofs according to a random process with an exponential distribution between proving times, with **MTBF** (Mean Time Between Proofs) mean, i.i.d. between nodes. Other distributions are also possible, but for the sake of modelling we start with an exponential distribution, which is also simple to implement in practice.
Reconstruction can be triggered based on the observed state in various ways:
- if an individual node is missing a slot proof (or more generally, a series of proofs), reconstruction can start. The advantage of this option is that the consequences of failing a proof only depend on the node itself, and not on other nodes.
- reconstruction can also be triggered by the observed system state, i.e. the number of nodes that have missed the last proof (or more in general some of the last proofs). In fact, thanks to the properties of RS codes, whenever a slot is being repaired, all slot's data are regenerated. As a consequence, the cost of repair is independent of the number of slots being repaired, and by triggering repair only after multiple slots are observed lost (the so called "lazy repair"), we can drastically reduce the cost of repair.
In our model, we assume reconstruction that uses a combination of the above too triggers.
- Reconstruction is triggered based on the observed system state, allowing for lazy repair, by triggering it when $l_0$ of the slots is considered lost.
- A single slot is considered lost if it was missing the last $l_1$ proofs.
Other reconstruction strategies, such as considering all the proofs from all the slots in a time window, are also possible, but we leave these for further study.
### 5.4. CTMC Model
We model the system using a CTMC with a multi-dimensional state space representing slot status and proof progress. To keep the description simple, we introduce the model for the case of $l_1 = 1$ here. An extension to $l_1 > 1$ is possible by increasing the dimensions of the state space to $1+l_1$.
**State space.** We model the system with a multi-dimensional state space $S_{l,f}$ with the following dimensions:
- losses: $l \in [0, \cdots, m+1]$: the number of lost slots. Practical values of $l$ go from $0$ to $m$. As soon as $l$ reaches $m+1$, the dataset can be considered lost.
- observations: $f \in [0, \cdots, l]$ is the number of slots with the last test failed, or in other words, observed losses. Repair is triggered when $l \ge l_0$. Since repair reallocates slots to new nodes, we can assume that repaired slots are all available after the process. Hence, $f \le l$ in all reachable states.
**State transition rates.** From a given state $S_{l,f}$ we can get to the following states:
- slot loss, $S_{l+1,f}$: slot loss is driven by MTTF, assuming i.i.d slot losses. Obviously, only available slots can be lost, so the transition probability also depends on $n-l$.
- missing proofs, $S_{l,f+1}$: we are only interested in the event of observing the loss of a slot that we haven't seen before. Thus, the state transition probability depends on $f-l$.
- repair, $S_{0,0}$: repair is only triggered once the number of observed losses reaches the lazy repair threshold $l_0$. In case of a successful repair, all slots are fully restored (even if the actual set of nodes storing the slots are changing).
States $S_{M+1,f}$ for each $f$ are absorbing states. By calculating the expected time of absorption, we can quantify the reliability of the system.
<center>
<img src="/learn/whitepaper/ploss-vs-slots.png"/>
</center>
**Figure 9.** $p_{\text{loss}}$ (y axis) as a function of $n$ for various values of $l_0$ and expansion factors ($e$).
Figure 9 shows dataset reliability ($p_{\text{loss}}$) as a function of $n$, the number of slots, assuming an MTTF of 1 year and an MTTR of 24 hours. We set the repair frequency (MTBR) to 24 hours, and explore various options on the code expansion factor $e$ and the lazy repair threshold $l_0$. Clearly, adding more redundancy (using an RS code with a higher expansion factor) allows us to store a dataset on fewer SPs. As expected lazy repair requires the use of more SPs, but reduces repair cost by delaying repair.
The figure also shows what $k$ and $m$ values are needed to reach a given reliability threshold under different expansion factors and lazy repair thresholds. For example, values for a failure probability in a year of $10^{-9}$, also called "nine nines" reliability, are summarized in Table 1.
<center>
| Expansion ($e$) | Lazy repair ($l_0$) |Required k + m|
|:---------------:|:-------------------:|:------------:|
| 1.5 | 1 | 18 + 9 |
| 2 | 1 | 7 + 7 |
| 2.5 | 1 | 4 + 6 |
| 1.5 | 5 | 28 + 14 |
| 2 | 5 | 13 + 13 |
| 2.5 | 5 | 8 + 12 |
</center>
**Table 1.** Expansion, lazy repair, and required values for $k$ and $m$ to achieve $p_{\text{loss}} = 10^{-9}$
### 5.5 Proving frequency
An important parameter to asses is the frequency of proofs, expressed in our model as MTBP, since it directly translates into proof generation and proof submission costs. If we could double MTBP, we could halve the associated costs.
<center>
<img src="/learn/whitepaper/ploss-vs-proof-freq.png"/>
</center>
**Figure 10.** $p_{\text{loss}}$ (y axis) as a function of the proof frequency (MTBP), for various slot counts ($k+m$) and lazy repair thresholds ($l_0$).
In Figure 10 we keep MTTF 1 year and MTTR 1 day, like before, and we show $p_{\text{loss}}$ as a function of MTBP (expressed in days for simplicity). Note that the x axis is logarithmic to show better the cost-benefit of changing the proving interval.
As expected, large values of MTBP (infrequent proofs) are not acceptable, the dataset could easily be lost without triggering repair. What the curves also show is that requiring proofs with an MTBF below a day does not make a significant difference. In fact, with several parameter combinations, namely, with higher $n$ values, we can afford to increase MTBF considerably, to several days.
Note however that we are still using $l_1=1$ in our model, i.e. a slot is considered lost after a single failed proof. We consider this to be too reactive, since single proofs might be missed due to temporary failures. Without going into much detail, a higher tolerance on missed proofs ($l_1 > 1$) is similar to multiplying MTBF by $l_1$ (although the model becomes more complex, with an $l_1 +1$ dimensional state space).
## 6. Conclusions and Future Work
We have presented Codex, a Decentralized Durability Engine which employs erasure coding and efficient proofs of storage to provide tunable durability guarantees and a favourable tradeoff in cost and complexity for storage providers. By having proofs that are lightweight, Codex can keep the overhead spendings on hardware and electricity to a minimal. This is important both for fostering participation, as storage provider margins can be increased while prices for clients can decrease, and decentralization, as modest requirements are more likely to encourage a more diverse set of participants ranging from hobbyist home providers to larger players.
Despite our ambitious goals, Codex is a work in progress. Ongoing efforts on improving it include:
* **Reduction of proving costs.** Verifying proofs on-chain is expensive. To bring down costs on the short-term, we are working on an in-node aggregation mechanism which allow providers to batch proofs over multiple slots. On a slightly longer time horizon, we also intend to build our own aggregation network, which will ultimately allow Codex to go on-chain very infrequentely. Finally, at the level of individual proofs, we are working on more efficient proof systems which should bring down hardware requirements even more.
* **Bandwidth incentives.** Codex is designed to provide strong incentives that favor durability. While incentivizing availability is harder as it is in general not possible to provide proofs for it[^bassam_18] we can still provide an effective, even if weaker, form of incentive by allowing providers to sell bandwidth. To that end, we are currently working on mechanisms to enable an efficient bandwidth market in Codex which should complement the storage market.
* **Privacy and encryption.** Codex will, in the future, encrypt data by default so that SPs cannot ever know what they are storing. This should also offer SCs more privacy.
* **P2P layer.** We are currently working on optimizing protocols so they scale and perform better. This includes improvements in block transfer latency and throughput, more efficient swarms and block discovery mechanism, as well as research into more secure protocols.
* **Tools and APIs.** We are currently working on creating developer tools (SDKs) and APIs to facilitate the development of decentralized applications on top of the Codex network.
Work within a longer time horizon include:
* **Support for fine-grained and mutable files.** Codex, as many other DSNs, is currently suitable for large immutable datasets, and any other use case will currently require additional middleware. We have ongoing work on exploring polynomial commitments as opposed to Merkle trees for proofs, which should allow us to incrementally change datasets without having to completely re-encode them. This will unlock a host of new use cases, and allow Codex to be used in a much more natural fashion.
* **Improvements to erasure coding.** There is a large number of different codes offering different tradeoffs, e.g. non-MDS codes like turbocodes and tornado codes, which could result in better performance than the Reed-Solomon codes we currently employ.
Codex has the potential to support a wide range of use cases, from personal data storage and decentralized web hosting to secure data backup and archival, decentralized identities, and decentralized content distribution.
Ultimately, the use case for Codex is that of a durable and functional decentralized storage layer, without which no decentralized technology stack can be seriously contemplated. As the decentralized ecosystem continues to evolve, we expect Codexs DDE-based approach to storage to play a crucial role in enabling new types of applications and services that prioritize user control, privacy, and resilience.
## References
[^tanembaum]: A. S. Tanenbaum and M. van Steen, Distributed Systems: Principles and Paradigms, 2nd ed. Upper Saddle River, NJ, USA: Pearson Education, 2007.
[^gcs]: Google Cloud Storage, "Google Cloud Storage," [Online]. Available: https://cloud.google.com/storage/docs. [Accessed: Aug. 27, 2024].
[^s3]: Amazon Web Services, "Amazon S3," [Online]. Available: https://aws.amazon.com/s3/. [Accessed: Aug. 27, 2024].
[^multicloud]: DigitalOcean, "The Business Benefits of a Multi-Cloud Strategy," [Online]. Available: https://www.digitalocean.com/community/tutorials/the-business-benefits-of-a-multi-cloud-strategy. [Accessed: Aug. 27, 2024].
[^liu_19]: J. Liu, "Government Backdoor in Cloud Services: Ethics of Data Security," USC Viterbi Conversations in Ethics, vol. 3, no. 2, 2019. [Online]. Available: https://vce.usc.edu/volume-3-issue-2/government-backdoor-in-cloud-services-ethics-of-data-security/. [Accessed: Aug. 27, 2024].
[^statista_cloud_percentage]: Statista, "Share of total spending on the cloud spent on storage in the United States and the United Kingdom 2023," Jan. 2023. [Online]. Available: https://www.statista.com/statistics/1374192/cloud-storage-cost-share/. [Accessed: Aug. 27, 2024]
[^gartner_cloud_budget]: Gartner, "Gartner forecasts worldwide public cloud end-user spending to surpass $675 billion in 2024," May 20, 2024. [Online]. Available: https://www.gartner.com/en/newsroom/press-releases/2024-05-20-gartner-forecasts-worldwide-public-cloud-end-user-spending-to-surpass-675-billion-in-2024. [Accessed: Aug. 27, 2024].
[^s3_wikipedia]: https://en.wikipedia.org/wiki/Amazon_S3
[^zippia_cloud_report]: Zippia. "25 Amazing Cloud Adoption Statistics [2023]: Cloud Migration, Computing, And More" Zippia.com. Jun. 22, 2023, https://www.zippia.com/advice/cloud-adoption-statistics/
[^s3_reinvent_19]: D. Brown, J. Smith, and A. Johnson, "Beyond eleven nines: Lessons from the Amazon S3 culture of durability," presented at AWS re:Invent 2019, 2019. [Online]. Available: https://d1.awsstatic.com/events/reinvent/2019/REPEAT_1_Beyond_eleven_nines_Lessons_from_the_Amazon_S3_culture_of_durability_STG331-R1.pdf. [Accessed: Aug. 29, 2024].
[^feng_14]: Y. Feng, B. Li and B. Li, "Price Competition in an Oligopoly Market with Multiple IaaS Cloud Providers" in IEEE Transactions on Computers, vol. 63, no. 01, pp. 59-73, 2014.
[^nakamoto_08]: S. Nakamoto, "Bitcoin: A Peer-to-Peer Electronic Cash System," 2008. [Online]. Available: https://bitcoin.org/bitcoin.pdf
[^buterin_13]: V. Buterin, "Ethereum White Paper: A Next Generation Smart Contract & Decentralized Application Platform," 2013. [Online]. Available: https://ethereum.org/en/whitepaper/
[^buterin_24]: V. Buterin, "EIP-4844: Shard Blob Transactions," Ethereum Improvement Proposals, 2024. [Online]. Available: https://www.eip4844.com. [Accessed: Sep. 3, 2024].
[^kostamis_24]: P. Kostamis, A. Sendros, and P. S. Efraimidis, "Data management in Ethereum DApps: A cost and performance analysis," Future Generation Computer Systems, vol. 145, pp. 193-205, Apr. 2024.
[^cohen_01]: B. Cohen, "BitTorrent - a new P2P app," Yahoo! Groups - decentralization, Jul. 2, 2001. [Online]. Available: https://web.archive.org/web/20080129085545/http://finance.groups.yahoo.com/group/decentralization/message/3160 [Accessed: Sep. 20, 2024]
[^chaudhry_24]: A. Chaudhry, S. Kannan and D. Tse, "STAKESURE: Proof of Stake Mechanisms with Strong Cryptoeconomic Safety," arXiv:2401.05797 [cs.CR], Jan. 2024.
[^protocol_17]: Protocol Labs, "Filecoin: A Decentralized Storage Network," Jul. 19, 2017. [Online]. Available: https://filecoin.io/filecoin.pdf
[^bassam_18]: M. Al-Bassam, A. Sonnino, and V. Buterin, "Fraud and Data Availability Proofs: Maximising Light Client Security and Scaling Blockchains with Dishonest Majorities," arXiv:1809.09044 [cs.CR], May 2019
[^reed_60]: I. S. Reed and G. Solomon, "Polynomial Codes Over Certain Finite Fields," Journal of the Society for Industrial and Applied Mathematics, vol. 8, no. 2, pp. 300-304, 1960
[^spanbroek_23]: M. Spanbroek, "Storage Proofs & Erasure Coding," https://github.com/codex-storage/codex-research/blob/master/design/proof-erasure-coding.md (accessed Sep. 26, 2024).
[^wikipedia_code_rate]: "Code rate," Wikipedia. https://en.wikipedia.org/wiki/Code_rate (accessed Sep. 26, 2024).
[^groth_16]: J. Groth, "On the Size of Pairing-based Non-interactive Arguments," in Advances in Cryptology EUROCRYPT 2016, M. Fischlin and J.-S. Coron, Eds. Berlin, Heidelberg: Springer Berlin Heidelberg, 2016, pp. 305-326.
[^ateniese_07]: G. Ateniese et al., "Provable data possession at untrusted stores," in Proceedings of the 14th ACM Conference on Computer and Communications Security (CCS '07), Alexandria, Virginia, USA, Oct. 2007, pp. 598-609.
[^juels_07]: A. Juels et al., "Pors: proofs of retrievability for large files," in Proceedings of the 14th ACM Conference on Computer and Communications Security (CCS '07), Alexandria, Virginia, USA, Oct. 2007, pp. 584-597
[^schacham_08]: H. Shacham and B. Waters, "Compact Proofs of Retrievability," in Advances in Cryptology - ASIACRYPT 2008, J. Pieprzyk, Ed. Berlin, Heidelberg: Springer Berlin Heidelberg, 2008, pp. 90-107.
[^bowers_09]: K. D. Bowers, A. Juels, and A. Oprea, "HAIL: A high-availability and integrity layer for cloud storage," in Proceedings of the 16th ACM Conference on Computer and Communications Security (CCS '09), Chicago, Illinois, USA, Nov. 2009, pp. 187-198.
[^cid_spec]: Protocol Labs. "CID (Content IDentifier) Specification," https://github.com/multiformats/cid (accessed Sep. 26, 2024)
[^signed_envelope_spec]: libp2p. "RPC 0003 - Routing Records," https://github.com/libp2p/specs/blob/master/RFC/0003-routing-records.md (accessed Sep. 26, 2024)
[^multiaddress_spec]: Protocol Labs. "Multiformats / Multiaddr," https://multiformats.io/multiaddr/ (accessed Sep. 26, 2024)
[^maymounkov_02]: P. Maymounkov and D. Mazieres, "Kademlia: A peer-to-peer information system based on the XOR metric," in Proceedings of the First International Workshop on Peer-to-Peer Systems (IPTPS), Cambridge, MA, USA, Mar. 2002, pp. 53-65.
[^grassi_23]: L. Grassi, D. Khovratovich, and M. Schofnegger, "Poseidon2: A Faster Version of the Poseidon Hash Function," Cryptology ePrint Archive, Paper 2023/323, 2023. [Online]. Available: https://eprint.iacr.org/2023/323
[^bitswap_spec]: IPFS Standards. "Bitswap Protocol," https://specs.ipfs.tech/bitswap-protocol/ (accessed Sep. 27, 2024)
[^schroeder_07]: B. Schroeder and G. A. Gibson, "Disk Failures in the Real World: What Does an MTTF of 1,000,000 Hours Mean to You?," in Proceedings of the 5th USENIX Conference on File and Storage Technologies (FAST '07), San Jose, CA, USA, 2007
[^ipfs_website]: IPFS: An open system to manage data without a central server," IPFS, 2024. [Online]. Available: https://ipfs.tech/. [Accessed: Sep. 28, 2024].

19
es/networks/networks.md Normal file
View File

@ -0,0 +1,19 @@
# Redes Codex
En Codex, estamos lanzando varias redes que se utilizan para diferentes propósitos
| Red | Estado | Blockchain | Propósito |
| ------------------ | ----------------------- | ----------------------------------------------------------------------- | ----------------------------------------------------------------------- |
| Devnet | :building_construction: | [Geth PoA](https://geth.ethereum.org/docs/fundamentals/private-network) | Dedicada a propósitos de desarrollo y siguiendo las últimas compilaciones de `master` |
| [Testnet](testnet) | :white_check_mark: | [Geth PoA](https://geth.ethereum.org/docs/fundamentals/private-network) | Una red pública para propósitos de prueba, siguiendo las últimas versiones |
| Mainnet | :construction: | :construction: | La red pública principal |
Las principales diferencias entre las redes son las siguientes:
- Propósito de la red
- Nodos de arranque
- Número de nodos de almacenamiento
- Volumen de almacenamiento disponible
- Red blockchain
- Versión del contrato del mercado
- Conjunto de archivos de circuito utilizados para la verificación de pruebas
La forma más fácil de comenzar a usar Codex es [Unirse a la Red de Pruebas](testnet).

203
es/networks/testnet.md Normal file
View File

@ -0,0 +1,203 @@
---
outline: [2, 4]
---
# Codex Testnet
The Codex Testnet has been launched and is ready to be used for testing.
Your participation in the Codex Testnet is subject to the [Codex Testnet Terms and Conditions](https://github.com/codex-storage/codex-testnet-starter/blob/master/Codex%20Testnet%20Terms%20and%20Conditions.pdf) and [Codex Testnet Privacy Policy](https://github.com/codex-storage/codex-testnet-starter/blob/master/Codex%20Testnet%20Privacy%20Policy.pdf).
**Guides.** We have basic guides covering how to set up a Storage Client which can be used to upload and persist files by buying storage in the Codex network. We recommend that you start with those.
Running a Storage Provider is more involved and is covered as a separate guide which demonstrates the storage sales side, as well as how to run Codex with its own local Ethereum execution client.
Guides are available either on Discord, as step-by-step, interactive guides, or here as simple instructions that you can follow:
- **Basic: running a storage client.** [[Discord](#sc-guide-discord) | [web](#sc-guide-web)]
- **Advanced: Running a storage provider.** [[web](#sp-guide-web)]
The guides were tested on the following operating systems:
- Linux: Ubuntu 24.04, Debian 12, Fedora 40
- macOS: 15
- Windows: 11, Server 2022
## Running a Storage Client (Discord Version) {#sc-guide-discord}
You can join [Codex Discord server](https://discord.gg/codex-storage) and jump into the [#:tv:|join-testnet](https://discord.com/channels/895609329053474826/1289923125928001702) channel.
It is mostly the same as a [Web guide](#sc-guide-web), but uses Discord capabilities so you can have an interactive, step-by-step guide, and you also can get a support in the [#:sos:|node-help](https://discord.com/channels/895609329053474826/1286205545837105224) channel.
## Running a Storage Client (Web Version) {#sc-guide-web}
**Prerequisites**
- Access to your Internet router so you can [configure port forwarding](#basic-common)
Steps for [Linux/macOS](#basic-linux-macos) and [Windows](#basic-windows) are slightly different, so please use ones for your OS.
<hr>
### Linux/macOS {#basic-linux-macos}
1. Download the master tarball from the Codex testnet starter repository, and untar its contents:
```shell
curl -LO https://github.com/codex-storage/codex-testnet-starter/archive/master.tar.gz
tar xzvf master.tar.gz
rm master.tar.gz
```
2. Navigate to the scripts folder:
```shell
cd codex-testnet-starter-master/scripts
```
3. Install dependencies when required:
```shell
# Debian-based Linux
sudo apt update && sudo apt install libgomp1
```
4. Download Codex binaries from GitHub releases:
```shell
./download_online.sh
```
5. Generate an ethereum keypair:
```shell
./generate.sh
```
Your private key will be saved to `eth.key` and address to `eth.address` file.
6. Fill-up your address shown on the screen with the tokens:
- Use the web faucets to mint some [ETH](https://faucet-eth.testnet.codex.storage) and [TST](https://faucet-tst.testnet.codex.storage) tokens.
- We can also do this using Discord [# bot](https://discord.com/channels/895609329053474826/1230785221553819669) channel
- Use `/set ethaddress` command to enter your generated address
- Use `/mint` command to receive ETH and TST tokens
- Use `/balance` command to check if you have received test tokens successfully
7. Run Codex node:
```shell
./run_client.sh
```
8. Configure [port forwarding](#basic-common) and we are ready go to.
### Windows {#basic-windows}
1. Download the master tarball from the Codex testnet starter repository, and untar its contents:
> [!WARNING]
> Windows antivirus software and built-in firewalls may cause steps to fail. We will cover some possible errors here, but always consider checking your setup if requests fail - in particular, if temporarily disabling your antivirus fixes it, then it is likely to be the culprit.
```batch
curl -LO https://github.com/codex-storage/codex-testnet-starter/archive/master.tar.gz
```
If you see an error like:
```batch
curl: (35) schannel: next InitializeSecurityContext failed: CRYPT_E_NO_REVOCATION_CHECK (0x80092012) - The revocation function was unable to check revocation for the certificate.
```
You may need to add the `--ssl-no-revoke` option to your curl call, e.g.:
```batch
curl -LO --ssl-no-revoke https://github.com/codex-storage/codex-testnet-starter/archive/master.tar.gz
```
1. Extract the contents of the tar file, and then delete it:
```batch
tar xzvf master.tar.gz
del master.tar.gz
```
2. Navigate to the scripts folder:
```batch
cd codex-testnet-starter-master\scripts\windows
```
3. Download Codex binaries from GitHub releases:
```batch
download-online.bat
```
4. Generate an ethereum keypair:
```batch
generate.bat
```
Your private key will be saved to `eth.key` and address to `eth.address` file.
5. Fill-up your address shown on the screen with the tokens:
- Use the web faucets to mint some [ETH](https://faucet-eth.testnet.codex.storage) and [TST](https://faucet-tst.testnet.codex.storage) tokens.
- We can also do this using Discord [# bot](https://discord.com/channels/895609329053474826/1230785221553819669) channel
- Use `/set ethaddress` command to enter your generated address
- Use `/mint` command to receive ETH and TST tokens
- Use `/balance` command to check if you have received test tokens successfully
6. Run Codex node:
```batch
run-client.bat
```
7. Configure [port forwarding](#basic-common) and we are ready go to.
### All OS {#basic-common}
Configure [port forwarding](https://en.wikipedia.org/wiki/Port_forwarding) on your Internet router
| # | Protocol | Port | Description |
| - | -------- | ------ | ----------------- |
| 1 | `UDP` | `8090` | `Codex Discovery` |
| 2 | `TCP` | `8070` | `Codex Transport` |
After your node is up and running, you can use the [Codex API](/developers/api) to be able to interact with your Codex node, please check our [API walk-through](/learn/using) for more details.
You also can use [Codex App UI](https://app.codex.storage) to interact with your local Codex node.
Need help? Reach out to us in [#:sos:|node-help](https://discord.com/channels/895609329053474826/1286205545837105224) channel or check [troubleshooting guide](/learn/troubleshoot.md).
## Running a Storage Provider (Web Version) {#sp-guide-web}
Work in progress :construction:
## Testnet Data
### Bootstrap Nodes
**Codex**
```shell
spr:CiUIAhIhAiJvIcA_ZwPZ9ugVKDbmqwhJZaig5zKyLiuaicRcCGqLEgIDARo8CicAJQgCEiECIm8hwD9nA9n26BUoNuarCEllqKDnMrIuK5qJxFwIaosQ3d6esAYaCwoJBJ_f8zKRAnU6KkYwRAIgM0MvWNJL296kJ9gWvfatfmVvT-A7O2s8Mxp8l9c8EW0CIC-h-H-jBVSgFjg3Eny2u33qF7BDnWFzo7fGfZ7_qc9P
spr:CiUIAhIhAyUvcPkKoGE7-gh84RmKIPHJPdsX5Ugm_IHVJgF-Mmu_EgIDARo8CicAJQgCEiEDJS9w-QqgYTv6CHzhGYog8ck92xflSCb8gdUmAX4ya78QoemesAYaCwoJBES39Q2RAnVOKkYwRAIgLi3rouyaZFS_Uilx8k99ySdQCP1tsmLR21tDb9p8LcgCIG30o5YnEooQ1n6tgm9fCT7s53k6XlxyeSkD_uIO9mb3
spr:CiUIAhIhA6_j28xa--PvvOUxH10wKEm9feXEKJIK3Z9JQ5xXgSD9EgIDARo8CicAJQgCEiEDr-PbzFr74--85TEfXTAoSb195cQokgrdn0lDnFeBIP0QzOGesAYaCwoJBK6Kf1-RAnVEKkcwRQIhAPUH5nQrqG4OW86JQWphdSdnPA98ErQ0hL9OZH9a4e5kAiBBZmUl9KnhSOiDgU3_hvjXrXZXoMxhGuZ92_rk30sNDA
spr:CiUIAhIhA7E4DEMer8nUOIUSaNPA4z6x0n9Xaknd28Cfw9S2-cCeEgIDARo8CicAJQgCEiEDsTgMQx6vydQ4hRJo08DjPrHSf1dqSd3bwJ_D1Lb5wJ4Qt_CesAYaCwoJBEDhWZORAnVYKkYwRAIgFNzhnftocLlVHJl1onuhbSUM7MysXPV6dawHAA0DZNsCIDRVu9gnPTH5UkcRXLtt7MLHCo4-DL-RCMyTcMxYBXL0
spr:CiUIAhIhAzZn3JmJab46BNjadVnLNQKbhnN3eYxwqpteKYY32SbOEgIDARo8CicAJQgCEiEDNmfcmYlpvjoE2Np1Wcs1ApuGc3d5jHCqm14phjfZJs4QrvWesAYaCwoJBKpA-TaRAnViKkcwRQIhANuMmZDD2c25xzTbKSirEpkZYoxbq-FU_lpI0K0e4mIVAiBfQX4yR47h1LCnHznXgDs6xx5DLO5q3lUcicqUeaqGeg
spr:CiUIAhIhAgybmRwboqDdUJjeZrzh43sn5mp8jt6ENIb08tLn4x01EgIDARo8CicAJQgCEiECDJuZHBuioN1QmN5mvOHjeyfmanyO3oQ0hvTy0ufjHTUQh4ifsAYaCwoJBI_0zSiRAnVsKkcwRQIhAJCb_z0E3RsnQrEePdJzMSQrmn_ooHv6mbw1DOh5IbVNAiBbBJrWR8eBV6ftzMd6ofa5khNA2h88OBhMqHCIzSjCeA
spr:CiUIAhIhAntGLadpfuBCD9XXfiN_43-V3L5VWgFCXxg4a8uhDdnYEgIDARo8CicAJQgCEiECe0Ytp2l-4EIP1dd-I3_jf5XcvlVaAUJfGDhry6EN2dgQsIufsAYaCwoJBNEmoCiRAnV2KkYwRAIgXO3bzd5VF8jLZG8r7dcLJ_FnQBYp1BcxrOvovEa40acCIDhQ14eJRoPwJ6GKgqOkXdaFAsoszl-HIRzYcXKeb7D9
```
**Geth**
```shell
enode://cff0c44c62ecd6e00d72131f336bb4e4968f2c1c1abeca7d4be2d35f818608b6d8688b6b65a18f1d57796eaca32fd9d08f15908a88afe18c1748997235ea6fe7@159.223.243.50:40010
enode://ea331eaa8c5150a45b793b3d7c17db138b09f7c9dd7d881a1e2e17a053e0d2600e0a8419899188a87e6b91928d14267949a7e6ec18bfe972f3a14c5c2fe9aecb@68.183.245.13:40030
enode://4a7303b8a72db91c7c80c8fb69df0ffb06370d7f5fe951bcdc19107a686ba61432dc5397d073571433e8fc1f8295127cabbcbfd9d8464b242b7ad0dcd35e67fc@174.138.127.95:40020
enode://36f25e91385206300d04b95a2f8df7d7a792db0a76bd68f897ec7749241b5fdb549a4eecfab4a03c36955d1242b0316b47548b87ad8291794ab6d3fecda3e85b@64.225.89.147:40040
enode://2e14e4a8092b67db76c90b0a02d97d88fc2bb9df0e85df1e0a96472cdfa06b83d970ea503a9bc569c4112c4c447dbd1e1f03cf68471668ba31920ac1d05f85e3@170.64.249.54:40050
enode://6eeb3b3af8bef5634b47b573a17477ea2c4129ab3964210afe3b93774ce57da832eb110f90fbfcfa5f7adf18e55faaf2393d2e94710882d09d0204a9d7bc6dd2@143.244.205.40:40060
enode://6ba0e8b5d968ca8eb2650dd984cdcf50acc01e4ea182350e990191aadd79897801b79455a1186060aa3818a6bc4496af07f0912f7af53995a5ddb1e53d6f31b5@209.38.160.40:40070
```
### Smart contracts
| Contract | Address |
| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| Token | [`0x34a22f3911De437307c6f4485931779670f78764`](https://explorer.testnet.codex.storage/address/0x34a22f3911De437307c6f4485931779670f78764) |
| Verifier | [`0x02dd582726F7507D7d0F8bD8bf8053d3006F9092`](https://explorer.testnet.codex.storage/address/0x02dd582726F7507D7d0F8bD8bf8053d3006F9092) |
| Marketplace | [`0xAB03b6a58C5262f530D54146DA2a552B1C0F7648`](https://explorer.testnet.codex.storage/address/0xAB03b6a58C5262f530D54146DA2a552B1C0F7648) |
### Endpoints
| # | Service | URL |
| - | --------------- | ---------------------------------------------------------------------------- |
| 1 | Geth Public RPC | [rpc.testnet.codex.storage](https://rpc.testnet.codex.storage) |
| 2 | Block explorer | [explorer.testnet.codex.storage](https://explorer.testnet.codex.storage) |
| 3 | Faucet ETH | [faucet-eth.testnet.codex.storage](https://faucet-eth.testnet.codex.storage) |
| 4 | Faucet TST | [faucet-tst.testnet.codex.storage](https://faucet-tst.testnet.codex.storage) |
| 5 | Status page | [status.testnet.codex.storage](https://status.testnet.codex.storage) |