🔦

Walrus Direct Retrievals

./walrus read dT3lREMDu4FsqVcMqTrIZY7kYu06t5jadZOzXlfOl-U --out blob.bin --rpc-url http://localhost:8080

Summary

Detailed notes

How to upload data to Walrus:

https://publish.walrus.site/

How to test retrievability of content stored on Walrus: https://github.com/CheckerNetwork/roadmap/issues/248

Here's their documentation side

https://docs.walrus.site/

Most of their stuff, including contracts are stored in this repository

https://github.com/MystenLabs/walrus-docs

As far as the notes go I did compile this at the end and published it in the github issue

https://github.com/CheckerNetwork/roadmap/issues/248#issuecomment-2674624830

Here's the exact location of walrus contracts https://github.com/MystenLabs/walrus-docs/tree/main/contracts/walrus

PoC checker: https://observablehq.com/@pyropy/walrus-poc

Setup

Download the walrus CLI from https://docs.walrus.site/usage/setup.html

Unfortunately, they don’t provide Linux+ARM64 build I could run in Docker, so I decided to take the risk and run the CLI directly on my machine.

Their CLI is not code-signed/notarized with Apple, so I cannot execute it using the default security settings. Going to try the Linux version again.

docker run -it -p 8081:8081 --name walrus-cli --platform linux/amd64 ubuntu:latest

In the container:

apt-get update
apt-get install curl
curl https://storage.googleapis.com/mysten-walrus-binaries/walrus-testnet-latest-ubuntu-x86_64 -o walrus
chmod a+x walrus

Initialisation

mkdir -p ~/.config/walrus/
curl https://raw.githubusercontent.com/MystenLabs/walrus-docs/refs/heads/main/docs/client_config.yaml \
    -o ~/.config/walrus/client_config.yaml

Grr, the binary crashes.

./walrus info
2025-03-21T07:46:20.084716Z  INFO walrus: client version: 1.18.1-bb8c53938423
2025-03-21T07:46:20.091202Z  INFO walrus_service::client::cli: using Walrus configuration from '/root/.config/walrus/client_config.yaml' with default context
2025-03-21T07:46:20.107670Z  INFO walrus_service::client::cli: using default RPC URL 'https://fullnode.testnet.sui.io:443'
Illegal instruction

Fix: In Docker Desktop config, disable [ ] Use Rosetta for x86_64/amd64 emulation on Apple Silicon

Docker image for the walrus (storage?) node:
https://hub.docker.com/r/mysten/walrus-service

Get info about a blob:

# ./walrus blob-status --blob-id dT3lREMDu4FsqVcMqTrIZY7kYu06t5jadZOzXlfOl-U
2025-03-21T08:00:05.246787Z  INFO walrus: client version: 1.18.1-bb8c53938423
2025-03-21T08:00:05.253632Z  INFO walrus_service::client::cli: using Walrus configuration from '/root/.config/walrus/client_config.yaml' with default context
2025-03-21T08:00:05.268962Z  INFO walrus_service::client::cli: using default RPC URL 'https://fullnode.testnet.sui.io:443'
There is a certified permanent Blob object for blob ID dT3lREMDu4FsqVcMqTrIZY7kYu06t5jadZOzXlfOl-U.
Expiry epoch: 34
Estimated expiry timestamp: 2025-03-23T17:08:05.553+00:00
Related event: (tx: XkRKrUGoaShyCMv8UNoP7QYdeBKkLdSjfuDEAgX5ABb, seq: 0)
Initially certified in epoch: 32
2025-03-21T08:00:07.712643Z  INFO walrus_service::client::refresh: the channel is closed, stopping the refresher

Read blob’s content:

# ./walrus read dT3lREMDu4FsqVcMqTrIZY7kYu06t5jadZOzXlfOl-U --out blob.bin
2025-03-21T08:02:37.206553Z  INFO walrus: client version: 1.18.1-bb8c53938423
2025-03-21T08:02:37.212151Z  INFO walrus_service::client::cli: using Walrus configuration from '/root/.config/walrus/client_config.yaml' with default context
2025-03-21T08:02:37.227861Z  INFO walrus_service::client::cli: using default RPC URL 'https://fullnode.testnet.sui.io:443'
 â—‰ slivers received [00:00:01] [#################################################################################################################################################################] 334/334 (0s)2025-03-21T08:02:47.668144Z  INFO walrus_service::client::cli::runner: finished reading blob blob_id=dT3lREMDu4FsqVcMqTrIZY7kYu06t5jadZOzXlfOl-U elapsed=9.037252962s blob_size=21
Success: Blob dT3lREMDu4FsqVcMqTrIZY7kYu06t5jadZOzXlfOl-U reconstructed from Walrus and written to blob.bin.
2025-03-21T08:02:47.670593Z  INFO walrus_service::client::refresh: the channel is closed, stopping the refresher

# cat blob.bin
52.707001_-152.725093

^^^ Notice the blob is tiny, only 21 bytes. ?!

Collect traffic

https://www.cyberly.org/en/how-do-you-use-tcpdump-to-capture-traffic-on-a-docker-container-network-interface/index.html

docker inspect walrus-cli | grep NetworkNode

^^^ that does not work on macOS

Add to the walrus config ~/.config/walrus/client_config.yaml:

communication_config:
  disable_proxy: true

Observe HTTP communication

https://docs.mitmproxy.org/stable/

In the container:

apt-get install mitmproxy
mitmweb --mode reverse:https://fullnode.testnet.sui.io -w read-blob-dump --web-host 0.0.0.0

https://docs.mitmproxy.org/stable/concepts-modes/#reverse-proxy

Create another session using docker exec -it walrus-cli /bin/bash and run


./walrus read dT3lREMDu4FsqVcMqTrIZY7kYu06t5jadZOzXlfOl-U --out blob.bin --rpc-url http://localhost:8080

Then on the host:

docker cp walrus-cli:/read-blob-dump .

Dump file recored:

Analysis of the HTTP traffic

  • There are many sui_getObject requests fetching different kinds of objects
    • moveObject
    • package
  • Also sui_getNormalizedMoveModulesByPackage

Debug logs

RUST_LOG=debug,walrus=debug ./walrus read dT3lREMDu4FsqVcMqTrIZY7kYu06t5jadZOzXlfOl-U --out blob.bin 2> read.log

Interesting lines found in the log:

node{index=50 committee_epoch=32 pk_prefix="rFDcqQ+q..."}:get_and_verify_metadata{walrus.blob_id=dT3lREMDu4Fsq
VcMqTrIZY7kYu06t5jadZOzXlfOl-U}:get_metadata{walrus.blob_id=dT3lREMDu4FsqVcMqTrIZY7kYu06t5jadZOzXlfOl-U}:http_request{otel.name="GET /v1/blobs/:blob_id/metadata" otel.kind="CLIENT" http.request.method="GET"
server.address="wal-storage-node-testnet.staketab.org" server.port=9185 url.full="https://wal-storage-node-testnet.staketab.org:9185/v1/blobs/dT3lREMDu4FsqVcMqTrIZY7kYu06t5jadZOzXlfOl-U/metadata"}: hyper_uti
l::client::legacy::connect::http: connected to 65.108.38.101:9185

node{index=50 committee_epoch=32 pk_prefix="rFDcqQ+q..."}:get_and_verify_metadata{walrus.blob_id=dT3lREMDu4FsqVcMqTrIZY7kYu06t5jadZOzXlfOl-U}: walrus_core: computed blob ID from metadata blob_id=dT3lREMDu4FsqVcMqTrIZY7kYu06t5jadZOzXlfOl-U

execute_weight{n_concurrent=3}: walrus_service::client::utils: return=ThresholdReached

walrus_service::client: metadata received node=50

request_slivers_and_decode: walrus_sdk::tls: requiring public key for connections walrus.node.public_key=Ax/UJ3c+FEQibDLx3d5k3l4Y4GuD0vMVHecBCLzR4nNN subject_name="walrus-testnet.redundex.com"
(...)

request_slivers_and_decode: walrus_core::encoding::blob_encoding: creating new blob decoder

request_slivers_and_decode:execute_weight{n_concurrent=334}: walrus_service::client::utils: starting to execute weighted futures

request_slivers_and_decode:node{index=5 committee_epoch=32 pk_prefix="qdl5z5ue..."}: walrus_service::client::communication::node: retrieving verified sliver walrus.shard_index=927 sliver_type="primary"

request_slivers_and_decode:node{index=66 committee_epoch=32 pk_prefix="lkB2/uPh..."}: walrus_service::client::communication::node: retrieving verified sliver walrus.shard_index=213 sliver_type="primary"

request_slivers_and_decode:node{index=74 committee_epoch=32 pk_prefix="tPZ2XT6f..."}:get_and_verify_sliver{walrus.blob_id=dT3lREMDu4FsqVcMqTrIZY7kYu06t5jadZOzXlfOl-U walrus.sliver.pair_index=105 walrus.sliver.r#type="primary"}:get_sliver{walrus.blob_id=dT3lREMDu4FsqVcMqTrIZY7kYu06t5jadZOzXlfOl-U walrus.sliver.pair_index=105 walrus.sliver.r#type="primary"}:http_request{otel.name="GET /v1/blobs/:blob_id/slivers/:sliver_pair_index/:sliver_type" otel.kind="CLIENT" http.request.method="GET" server.address="testnet.walrus.node.interestlabs.io" server.port=9185 url.full="https://testnet.walrus.node.interestlabs.io:9185/v1/blobs/dT3lREMDu4FsqVcMqTrIZY7kYu06t5jadZOzXlfOl-U/slivers/105/primary"}: hyper_util::client::legacy::connect::http: connecting to 185.156.44.81:9185

request_slivers_and_decode:BlobDecoder{blob_size=21}: walrus_core::encoding::blob_encoding: starting to decode
 axis="primary"
 
request_slivers_and_decode:BlobDecoder{blob_size=21}: walrus_core::encoding::blob_encoding: decoding finished
successfully

request_slivers_and_decode:decode_and_verify: walrus_core::encoding::blob_encoding: creating new blob encoder

request_slivers_and_decode:decode_and_verify:BlobEncoder{blob_size=21 blob="[53, 50, 46, 55, 48, ...]"}: walrus_core::encoding::blob_encoding: starting to compute metadata

request_slivers_and_decode:decode_and_verify:BlobEncoder{blob_size=21 blob="[53, 50, 46, 55, 48, ...]"}: walrus_core::encoding::blob_encoding: computing expanded message matrix

request_slivers_and_decode:decode_and_verify: walrus_core::encoding::blob_encoding: computing blob metadata and ID

request_slivers_and_decode:decode_and_verify: walrus_core: computed blob ID from metadata blob_id=dT3lREMDu4Fs
qVcMqTrIZY7kYu06t5jadZOzXlfOl-U

INFO walrus_service::client::cli::runner: finished reading blob blob_id=dT3lREMDu4FsqVcMqTrIZY7kYu06t5jadZOzXlfOl-U elapsed=8.800046753s blob_size=21
https://storage-node-walrus.inf-node.xyz:9185/v1/blobs/dT3lREMDu4FsqVcMqTrIZY7kYu06t5jadZOzXlfOl-U/metadata

Endpoints invoked:

More docs

High-level docs for the off-chain communication:

https://docs.walrus.site/design/operations-off-chain.html#read-paths

https://docs.walrus.site/dev-guide/sui-struct.html

https://github.com/MystenLabs/sui

Sui is written in Rust and supports smart contracts written in the Move programming language to define assets that may have an owner.

Python example using JSON RPC API to upload & download blob:

https://github.com/MystenLabs/walrus-docs/blob/99eefd0c24c815f2cff675ec4d35910c1598e15e/examples/python/hello_walrus_jsonapi.py

Overview of Sui structures used by Walrus smart contracts:

https://github.com/MystenLabs/walrus-docs/blob/99eefd0c24c815f2cff675ec4d35910c1598e15e/docs/dev-guide/sui-struct.md

https://github.com/sui-foundation/sui-move-intro-course