Skip to content

Запуск локальной сети Codex с поддержкой маркетплейса

Это руководство научит вас, как запустить небольшую сеть Codex с включенным маркетплейсом хранения; т.е. функциональностью в Codex, которая позволяет участникам предлагать и покупать хранилище на рынке, обеспечивая честное выполнение обязательств поставщиками хранилища с помощью криптографических доказательств.

В этом руководстве вы:

  1. Настроите сеть Geth PoA;
  2. Настроите маркетплейс;
  3. Запустите Codex;
  4. Купите и продайте хранилище на маркетплейсе.

Предварительные требования

Для прохождения этого руководства вам понадобится:

  • клиент Ethereum geth; Вам нужна версия 1.13.x geth, так как более новые версии больше не поддерживают Proof of Authority (PoA). Это руководство было протестировано с версией geth 1.13.15.
  • бинарный файл Codex, который можно собрать из исходного кода.

Мы также будем использовать синтаксис bash на протяжении всего руководства. Если вы используете другую оболочку, вам может потребоваться адаптировать команды под вашу платформу.

Для начала создайте новую папку, где мы будем хранить файлы, связанные с руководством, чтобы держать их отдельно от репозитория codex. Предположим, что имя папки будет marketplace-tutorial.

1. Настройка сети Geth PoA

Для этого руководства мы будем использовать простую Proof-of-Authority сеть с geth. Первым шагом является создание учетной записи подписанта: учетной записи, которая будет использоваться geth для подписи блоков в сети. Любой блок, подписанный подписантом, принимается как действительный.

1.1. Создание учетной записи подписанта

Чтобы создать учетную запись подписанта, из директории marketplace-tutorial выполните:

bash
geth account new --datadir geth-data

Генератор учетных записей попросит вас ввести пароль, который вы можете оставить пустым. Затем он выведет некоторую информацию, включая публичный адрес учетной записи:

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!

В этом примере публичный адрес учетной записи подписанта - 0x33A904Ad57D0E2CB8ffe347D3C0E83C2e875E7dB. У вас будет выведен другой адрес. Сохраните его для дальнейшего использования.

Затем установите переменную окружения для дальнейшего использования:

bash
export GETH_SIGNER_ADDR="0x0000000000000000000000000000000000000000"
echo ${GETH_SIGNER_ADDR} > geth_signer_address.txt

Здесь убедитесь, что вы заменили 0x0000000000000000000000000000000000000000 на ваш публичный адрес учетной записи подписанта (0x33A904Ad57D0E2CB8ffe347D3C0E83C2e875E7dB в нашем примере).

1.2. Настройка сети и создание генезис-блока

Следующий шаг - указать geth, какую сеть вы хотите запустить. Мы будем запускать pre-merge сеть с консенсусом Proof-of-Authority. Чтобы это работало, создайте файл network.json.

Если вы установили переменную GETH_SIGNER_ADDR выше, вы можете выполнить следующую команду для создания файла network.json:

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

Вы также можете создать файл вручную, не забыв обновить его своим публичным адресом подписанта:

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"
    }
  }
}

Обратите внимание, что адрес учетной записи подписанта встроен в два разных места:

  • внутри строки "extradata", окруженный нулями и без префикса 0x;
  • как ключ записи в секции alloc. Убедитесь, что вы заменили этот ID на ID учетной записи, который вы записали в Шаге 1.1.

После создания network.json вы можете инициализировать сеть с помощью:

bash
geth init --datadir geth-data network.json

В выводе этой команды могут быть предупреждения, например:

bash
WARN [08-21|14:48:12.305] Unknown config environment variable      envvar=GETH_SIGNER_ADDR

или даже ошибки при первом запуске команды:

bash
ERROR[08-21|14:48:12.399] Head block is not reachable

Важно, что в конце вы должны увидеть что-то похожее на:

bash
INFO [08-21|14:48:12.639] Successfully wrote genesis state         database=lightchaindata hash=768bf1..42d06a

1.3. Запуск вашего PoA узла

Теперь мы готовы запустить нашу 1-узловую приватную блокчейн-сеть. Чтобы запустить узел подписанта, откройте отдельный терминал в той же рабочей директории и убедитесь, что у вас установлена переменная GETH_SIGNER_ADDR. Для удобства используйте geth_signer_address.txt:

bash
export GETH_SIGNER_ADDR=$(cat geth_signer_address.txt)

Имея установленную переменную GETH_SIGNER_ADDR, выполните:

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

Обратите внимание, что учетная запись подписанта, созданная в Шаге 1.1, снова появляется как в --unlock, так и в --allow-insecure-unlock.

Geth попросит вас ввести пароль учетной записи при запуске. После этого он должен запуститься и начать "майнить" блоки.

Здесь также могут возникнуть ошибки, например:

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

Их можно безопасно игнорировать.

Если команда выше завершается с ошибкой:

bash
Fatal: Failed to register the Ethereum service: only PoS networks are supported, please transition old ones with Geth v1.13.x

убедитесь, что вы используете правильную версию Geth (см. раздел Предварительные требования)

2. Настройка маркетплейса

Для этого раздела вам нужно открыть новый терминал, и geth должен быть уже запущен. Настройка маркетплейса Codex включает:

  1. Развертывание контрактов маркетплейса Codex в нашу приватную блокчейн-сеть
  2. Настройку учетных записей Ethereum, которые мы будем использовать для покупки и продажи хранилища в маркетплейсе Codex
  3. Обеспечение этих учетных записей необходимыми балансами токенов

2.1. Развертывание контрактов маркетплейса Codex

Убедитесь, что вы вышли из директории marketplace-tutorial и клонируйте codex-storage/nim-codex.git:

bash
git clone https://github.com/codex-storage/nim-codex.git

Если вы хотите просто клонировать репозиторий для прохождения руководства, вы можете пропустить историю и просто скачать голову ветки master, используя опцию --depth 1: git clone --depth 1 https://github.com/codex-storage/nim-codex.git

Таким образом, структура директорий для целей этого руководства выглядит так:

bash
|
|-- nim-codex
└-- marketplace-tutorial

Вы можете клонировать codex-storage/nim-codex.git в другое место.

Теперь из папки nim-codex выполните:

bash
make update && make

Это может занять некоторое время, так как это также соберет компилятор nim. Будьте терпеливы.

Теперь, чтобы запустить локальную сеть Ethereum, выполните:

bash
cd vendor/codex-contracts-eth
npm install

При написании документа мы использовали node версии v20.17.0 и npm версии 10.8.2.

Прежде чем продолжить, вы должны дождаться, пока будет добыто 256 блоковв вашей PoA сети, иначе развертывание завершится неудачей. Это должно занять около 4 минут и 30 секунд. Вы можете проверить, на какой высоте блока вы находитесь, выполнив следующую команду из папки marketplace-tutorial:

bash
geth attach --exec web3.eth.blockNumber ./geth-data/geth.ipc

как только это превысит 256, вы готовы к работе.

Чтобы развернуть контракты, из директории codex-contracts-eth выполните:

bash
export DISTTEST_NETWORK_URL=http://localhost:8545
npx hardhat --network codexdisttestnetwork deploy

Если команда завершится успешно, вы увидите вывод, похожий на этот:

bash
Deployed Marketplace with Groth16 Verifier at:
0xCf0df6C52B02201F78E8490B6D6fFf5A82fC7BCd

конечно, ваш адрес будет другим.

Теперь вы готовы подготовить учетные записи.

2.2. Генерация необходимых учетных записей

Мы будем запускать 2 узла Codex: поставщик хранилища, который будет продавать хранилище в сети, и клиент, который будет покупать и использовать такое хранилище; поэтому нам нужны две действительные учетные записи Ethereum. Мы могли бы создать случайные учетные записи, используя один из многих доступных инструментов, но, поскольку это руководство работает в локальной приватной сети, мы просто предоставим вам две предварительно созданные учетные записи вместе с их приватными ключами, которые вы можете скопировать и вставить:

Сначала убедитесь, что вы вернулись в папку marketplace-tutorial и не находитесь в подпапке codex-contracts-eth. Затем установите эти переменные:

Хранилище:

bash
export ETH_STORAGE_ADDR=0x45BC5ca0fbdD9F920Edd12B90908448C30F32a37
export ETH_STORAGE_PK=0x06c7ac11d4ee1d0ccb53811b71802fa92d40a5a174afad9f2cb44f93498322c3
echo $ETH_STORAGE_PK > storage.pkey && chmod 0600 storage.pkey

Клиент:

bash
export ETH_CLIENT_ADDR=0x9F0C62Fe60b22301751d6cDe1175526b9280b965
export ETH_CLIENT_PK=0x5538ec03c956cb9d0bee02a25b600b0225f1347da4071d0fd70c521fdc63c2fc
echo $ETH_CLIENT_PK > client.pkey && chmod 0600 client.pkey

2.3. Обеспечение учетных записей токенами

Теперь нам нужно перевести немного ETH на каждую из учетных записей, а также предоставить им некоторые токены Codex для использования узлом хранилища в качестве залога и для клиентского узла для покупки фактического хранилища.

Хотя процесс не особенно сложен, я предлагаю вам использовать скрипт, который мы подготовили для этого. Этот скрипт, по сути:

  1. читает адрес контракта маркетплейса и его ABI из данных развертывания;
  2. переводит 1 ETH с учетной записи подписанта на целевую учетную запись, если целевая учетная запись не имеет баланса ETH;
  3. чеканит n токенов Codex и добавляет их в баланс целевой учетной записи.

Чтобы использовать скрипт, просто скачайте его в локальный файл с именем mint-tokens.js, например, используя curl (убедитесь, что вы находитесь в директории marketplace-tutorial):

bash
# скачать скрипт
curl https://raw.githubusercontent.com/gmega/codex-local-bare/main/scripts/mint-tokens.js -o mint-tokens.js

Затем выполните:

bash
# установить расположение файла контракта (мы предполагаем, что вы находитесь в директории marketplace-tutorial)
export CONTRACT_DEPLOY_FULL="../nim-codex/vendor/codex-contracts-eth/deployments/codexdisttestnetwork"
export GETH_SIGNER_ADDR=$(cat geth_signer_address.txt)
# Устанавливает Web3-js
npm install web3
# Предоставляет токены учетной записи хранилища.
node ./mint-tokens.js $CONTRACT_DEPLOY_FULL/TestToken.json $GETH_SIGNER_ADDR 0x45BC5ca0fbdD9F920Edd12B90908448C30F32a37 10000000000
# Предоставляет токены клиентской учетной записи.
node ./mint-tokens.js $CONTRACT_DEPLOY_FULL/TestToken.json $GETH_SIGNER_ADDR 0x9F0C62Fe60b22301751d6cDe1175526b9280b965 10000000000

Если вы получите сообщение типа

bash
Usage: mint-tokens.js <token-hardhat-deploy-json> <signer-account> <receiver-account> <token-ammount>

то вам нужно убедиться, что вы предоставили все необходимые аргументы. В частности, вам нужно убедиться, что переменная окружения GETH_SIGNER_ADDR содержит адрес подписанта (мы использовали export GETH_SIGNER_ADDR=$(cat geth_signer_address.txt) выше, чтобы убедиться, что она установлена).

3. Запуск Codex

С учетными записями и geth на месте, мы теперь можем запустить узлы Codex.

3.1. Узел хранилища

Узел хранилища будет тем, который хранит данные и отправляет доказательства хранения в цепочку. Для этого ему нужен доступ к:

  1. адресу контракта маркетплейса, который был развернут в локальном узле geth в Шаге 2.1;
  2. образцам файлов церемонии, которые поставляются в репозитории контрактов Codex (nim-codex/vendor/codex-contracts-eth).

Адрес контракта маркетплейса. Адрес контракта можно найти внутри файла nim-codex/vendor/codex-contracts-eth/deployments/codexdisttestnetwork/Marketplace.json. Мы захватили это расположение выше в переменной CONTRACT_DEPLOY_FULL, поэтому из папки marketplace-tutorial просто выполните:

bash
grep '"address":' ${CONTRACT_DEPLOY_FULL}/Marketplace.json

что должно вывести что-то вроде:

bash
"address": "0xCf0df6C52B02201F78E8490B6D6fFf5A82fC7BCd",

Этот адрес должен соответствовать адресу, который мы получили ранее при развертывании контракта маркетплейса выше.

Затем выполните следующее с правильным адресом маркетплейса:

bash
export MARKETPLACE_ADDRESS="0x0000000000000000000000000000000000000000"
echo ${MARKETPLACE_ADDRESS} > marketplace_address.txt

где вы заменяете 0x0000000000000000000000000000000000000000 на адрес контракта маркетплейса выше в Шаге 2.1.

Файлы церемонии провайдера. Файлы церемонии находятся в подкаталоге nim-codex/vendor/codex-contracts-eth/verifier/networks/codexdisttestnetwork. Их три: proof_main.r1cs, proof_main.zkey, и prooof_main.wasm. Нам понадобятся все они для запуска узла хранилища Codex.

Запуск узла хранилища. Пусть:

  • PROVER_ASSETS содержит директорию, где находятся файлы церемонии провайдера. Это должен быть абсолютный путь;
  • CODEX_BINARY содержит расположение вашего бинарного файла Codex;
  • MARKETPLACE_ADDRESS содержит адрес контракта маркетплейса (мы уже установили его выше).

Установите эти пути в переменные окружения (убедитесь, что вы находитесь в директории marketplace-tutorial):

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)

вы можете заметить, что мы уже установили переменную CONTRACT_DEPLOY_FULL выше. Здесь мы убеждаемся, что это абсолютный путь.

Чтобы запустить узел хранилища, выполните:

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

Запуск клиентского узла.

Клиентский узел запускается аналогично, за исключением того, что:

  • нам нужно передать SPR узла хранилища, чтобы он мог сформировать сеть с ним;
  • поскольку он не выполняет никаких доказательств, ему не требуются файлы церемонии.

Мы получаем Signed Peer Record (SPR) узла хранилища, чтобы мы могли загрузить клиентский узел с ним. Чтобы получить SPR, выполните следующий вызов:

bash
curl -H 'Accept: text/plain' 'http://localhost:8000/api/codex/v1/spr' --write-out '\n'

Вы должны получить SPR, начинающийся с spr:.

Прежде чем продолжить, откройте новый терминал и войдите в директорию marketplace-tutorial.

Затем установите эти пути в переменные окружения:

bash
# установить SPR для узла хранилища
export STORAGE_NODE_SPR=$(curl -H 'Accept: text/plain' 'http://localhost:8000/api/codex/v1/spr')
# базовые переменные
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)

и затем выполните:

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\

4. Покупка и продажа хранилища на маркетплейсе

Любые переговоры о хранилище имеют две стороны: покупатель и продавец. Поэтому, прежде чем мы сможем фактически запросить хранилище, мы должны сначала предложить его на продажу.

4.1 Продажа хранилища

Следующий запрос заставит узел хранилища выставить 50MB хранилища на продажу на 1 час по цене 1 токен Codex за слот в секунду, при этом выражая готовность принять максимум 1000 токенов Codex в качестве штрафа за невыполнение своей части контракта.[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"
}'

Это должно вернуть JSON-ответ, содержащий id (например, "id": "0xb55b3bc7aac2563d5bf08ce8a177a38b5a40254bfa7ee8f9c52debbb176d44b0"), который идентифицирует это предложение хранилища.

Чтобы сделать JSON-ответы более читаемыми, вы можете попробовать утилиту форматирования JSON jq просто добавив | jq после команды. На macOS вы можете установить с помощью brew install jq.

Чтобы проверить текущие предложения хранилища для этого узла, вы можете выполнить:

bash
curl 'http://localhost:8000/api/codex/v1/sales/availability'

или с jq:

bash
curl 'http://localhost:8000/api/codex/v1/sales/availability' | jq

Это должно вывести список предложений, с тем, который вы только что создали, среди них (для нашего руководства, в это время будет возвращено только одно предложение).

4.2. Покупка хранилища

Прежде чем мы сможем купить хранилище, у нас должны быть некоторые фактические данные для запроса хранилища. Начните с загрузки небольшого файла на ваш клиентский узел. В Linux (или macOS) вы могли бы, например, использовать dd для генерации файла размером 1M:

bash
dd if=/dev/urandom of=./data.bin bs=1M count=1

Предполагая, что ваш файл называется data.bin, вы можете загрузить его с помощью:

bash
curl --request POST http://localhost:8001/api/codex/v1/data --header 'Content-Type: application/octet-stream' --write-out '\n' -T ./data.bin

После завершения загрузки вы должны увидеть Content Identifier, или CID (например, zDvZRwzm2mK7tvDzKScRLapqGdgNTLyyEBvx1TQY37J2CdWdS6Sj) для загруженного файла, выведенный в терминал. Используйте этот CID в запросе на покупку:

bash
# убедитесь, что заменили CID перед с CID, который вы получили на предыдущем шаге
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'

Параметры под --data говорят, что:

  1. мы хотим купить хранилище для нашего файла на 5 минут ("duration": "600");
  2. мы готовы платить до 1 токена за слот в секунду ("reward": "1")
  3. наш файл будет разделен на три части ("nodes": 3). Поскольку мы установили "tolerance": 1, нам нужно только две части (nodes - tolerance) для восстановления файла; т.е. мы можем допустить, что максимум один узел перестанет хранить наши данные; либо из-за сбоя, либо по другим причинам;
  4. мы требуем 1000 токенов в качестве залога от поставщиков хранилища для каждой части. Поскольку есть 3 такие части, всего будет 3000 залога, зафиксированного поставщиком(ами) хранилища, как только наш запрос будет начат.
  5. наконец, expiry устанавливает временной лимит для заполнения всех слотов поставщиком(ами) хранилища. Если слоты не заполнены к моменту expire, запрос истечет и завершится неудачей.

4.3. Отслеживание ваших запросов на хранилище

POST-запрос на хранилище сделает его доступным на рынке хранилища, и узел хранилища в конечном итоге подберет его.

Вы можете опрашивать статус вашего запроса с помощью:

bash
export STORAGE_PURCHASE_ID="1d0ec5261e3364f8b9d1cf70324d70af21a9b5dccba380b24eb68b4762249185"
curl "http://localhost:8001/api/codex/v1/storage/purchases/${STORAGE_PURCHASE_ID}"

Например:

bash
> curl 'http://localhost:8001/api/codex/v1/storage/purchases/6c698cd0ad71c41982f83097d6fa75beb582924e08a658357a1cd4d7a2a6766d'

Это возвращает результат типа:

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
}

Показывает, что запрос был отправлен, но еще не заполнен. Ваш запрос будет успешным, как только "state" покажет "started". Все, что отличается от этого, означает, что запрос еще не полностью обработан, а состояние "error" отличное от null означает, что он завершился неудачей.

Ну что, это было довольно долгое путешествие, не так ли? Вы можете поздравить себя с успешным завершением руководства по маркетплейсу codex!


  1. Файлы Codex разделяются на части, называемые "слотами", и распределяются по различным поставщикам хранилища. Залог относится к одному такому слоту, и будет медленно уменьшаться по мере того, как поставщик хранилища не сможет предоставить своевременные доказательства, но фактическая логика более сложна, чем это. ↩︎