From bf10168beef1e41810a09c8728ec30d591561b9e Mon Sep 17 00:00:00 2001 From: NoahMaizels Date: Fri, 24 Jan 2025 20:04:28 +0700 Subject: [PATCH 01/16] revise quickstart guide and add shell script section --- docs/bee/installation/docker.md | 2 +- .../{install.md => package-manager.md} | 4 +- docs/bee/installation/quick-start.md | 133 +++- docs/bee/installation/shell-script.md | 599 ++++++++++++++++++ sidebars.js | 5 +- static/img/bashtop_01.png | Bin 0 -> 118095 bytes static/img/bashtop_02.png | Bin 0 -> 95385 bytes 7 files changed, 710 insertions(+), 33 deletions(-) rename docs/bee/installation/{install.md => package-manager.md} (99%) create mode 100644 docs/bee/installation/shell-script.md create mode 100644 static/img/bashtop_01.png create mode 100644 static/img/bashtop_02.png diff --git a/docs/bee/installation/docker.md b/docs/bee/installation/docker.md index 8ca0321b7..5c1051f5d 100644 --- a/docs/bee/installation/docker.md +++ b/docs/bee/installation/docker.md @@ -1,5 +1,5 @@ --- -title: Docker +title: Docker Install id: docker --- diff --git a/docs/bee/installation/install.md b/docs/bee/installation/package-manager.md similarity index 99% rename from docs/bee/installation/install.md rename to docs/bee/installation/package-manager.md index 1df3e2776..e64b543e4 100644 --- a/docs/bee/installation/install.md +++ b/docs/bee/installation/package-manager.md @@ -1,6 +1,6 @@ --- -title: Install Bee -id: install +title: Package Manager Install +id: package-manager-install --- import Tabs from '@theme/Tabs'; diff --git a/docs/bee/installation/quick-start.md b/docs/bee/installation/quick-start.md index 991f4412f..d62c0f47c 100644 --- a/docs/bee/installation/quick-start.md +++ b/docs/bee/installation/quick-start.md @@ -1,15 +1,29 @@ --- -title: Quick Start +title: Getting Started id: quick-start --- -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; +To get started working with Swarm, first you need to learn about the different types of Bee nodes, the requirements for running each type, and then choose which type is right for you. + +## Node Types Bee is a versatile piece of software that caters to a diverse array of use cases. It can be run in several different modes which each offer different features which are best suited for different users. There are three main categories of nodes: full nodes, light nodes, and ultra-light nodes. -### Comparison of Node Types -| Feature | Full Node | Light Node |Ultra-light Node| +### Ultra-Light Node + +The ultra-light configuration allows for limited access to the Swarm network and allows for a node to download only small amounts of data from the Swarm network. It does not allow for uploads. Ultra-light nodes may not earn any type of incentives. + +### Light Node + +A light node can both download and upload data over the Swarm network. Light nodes may also earn bandwidth incentives. + +### Full Node + +A full node can upload and download data over the Swarm network. Additionally, a full node can also share its disk space with the Swarm network where it will be employed by Swarm uploaders. Full nodes can earn storage incentives for sharing their disk space with the network, and can also earn bandwidth incentives just as light nodes can. + +## Features Comparison Chart + +| Feature | Full Node | Light Node |Ultra-Light Node| |--------------|-----------|------------|------------| | Downloading | ✅ | ✅ |✅ | | | Uploading | ✅ | ✅ | ❌ | @@ -22,53 +36,116 @@ Bee is a versatile piece of software that caters to a diverse array of use cases :::info -The Swarm network includes two incentives protocols which each give Bee nodes incentives to participate in maintaining the network in a healthy way. +#### **Swarm Incentives Types** +In Swarm, there are two types of incentives for node operators, **storage incentives** which reward nodes for storing data chunks over time, and **bandwidth incentives** which reward nodes for transmitting data chunks across the network. -**Storage incentives:** +**Storage incentives** - By participating in the storage incentives protocol, full nodes which store and share data chunks with the network have a chance to earn xBZZ. Staked xBZZ is required to earn storage incentives. Learn more in the [staking section](/docs/bee/working-with-bee/staking). +By participating in the storage incentives protocol, full nodes which store data chunks with the network may join in the redistribution game for a chance to earn xBZZ. Staked xBZZ is required to earn storage incentives. Learn more in the [staking section](/docs/bee/working-with-bee/staking). -**SWAP incentives:** +**Bandwidth incentives (SWAP):** - The SWAP incentives protocol encourages full or light (but not ultra-light) nodes to share bandwidth with other nodes in exchange for payments from other nodes either [in-kind](https://www.investopedia.com/terms/p/paymentinkind.asp) or as a cheque to be settled at a future date. SWAP requires a chequebook contract to be set up on Gnosis Chain for each participating node. +Bandwidth incentives (also referred to as the SWAP protocol) encourage full or light (but not ultra-light) nodes to share bandwidth with other nodes in exchange for payments from other nodes either [in-kind](https://www.investopedia.com/terms/p/paymentinkind.asp) or as a cheque to be settled at a future date. SWAP requires a chequebook contract to be set up on Gnosis Chain for each participating node. ::: +## Node Requirements by Type + +:::info +A note on RPC endpoints: + +Light and full Bee nodes require an RPC endpoint. An RPC endpoint is a "remote procedure call" endpoint that for blockchains like Ethereum or Gnosis Chain typically takes the form of an http or Websocket (wss) address. You will be able to use your own RPC endpoint if you are running your own Gnosis Chain node, however for many node operators it may be more convenient to use a third party provider such as [Infura](https://www.infura.io/). +::: + + +### Ultra-Light Node + +A light node has very minimal requirements, it will run on essentially any modern hardware or VPS with baseline specs. It can even run even on small single-board computers like Raspberry Pi's. + +Your upload and download speeds will be limited by your internet connection speed of course, and exceedingly low RAM or processing power may also slow down your node - however this should not be an issue for practically any modern hardware. + +An RPC endpoint is not required. + +### Light Node + +A light node's requirements will be similar to that of an ultra-light node, however since it can be used for uploading as well as downloading and in typical use cases will be consuming greater bandwidth, internet connections speeds will be a greater consideration. If you intend to use your light node for large amounts of uploads and downloads, you should make sure your internet connection is sufficiently fast and stable. Again, as with an ultra-light node, any modern commercially available hardware should be sufficient. + +A light node also has the additional requirement of an RPC endpoint so that it can purchase stamps to pay for uploads and so that it can participate in bandwidth incentives to earn xBZZ for data it forwards. + +### Full Node + +A full node has significantly greater requirements since it is responsible for storing and syncing data from the Swarm network, and the requirements will be even higher in case that it is staking xBZZ and participating in the redistribution system for a chance to win xBZZ rewards. + +The minimum recommended specifications for a full staking node are: +* Dual core, recent generation, 2ghz processor +* 8gb RAM +* 30gb SSD +* Stable internet connection +* HDD drives are discouraged for full nodes due to their low speeds. +Since there can be considerable variability in the performance of processors and RAM from different years and brands even with nominally similar specifications, it's recommended to [test your node's performance using the `/rchash` endpoint](https://docs.ethswarm.org/docs/bee/working-with-bee/bee-api/#rchash) to make sure that it is performant enough to participate in the redistribution game. +Note that there are additional hardware requirements if you choose to [run your own Gnosis Chain node](https://docs.gnosischain.com/node/#environment-and-hardware) in order to provide your Bee node(s) with the required RPC endpoint. + +:::info +Staking is not required to run a full node, but is necessary to earn storage incentives. An altruistic person may want to run a full node without putting up any stake, and in fact, could possibly earn enough xBZZ from bandwidth (swap/cheque) compensation to be able to stake at some point in the future. Learn more in the [staking section](/docs/bee/working-with-bee/staking) +::: ## Which type of node is the right choice? Different node types best suit different use cases: -### Interact with the Swarm network +### Basic Interactions with the Swarm network -If you want to interact with the Bee ecosystem in a decentralised way, -but not earn xBZZ by storing or forwarding chunks, simply run a Bee -[light node](/docs/bee/working-with-bee/light-nodes) in the background on -your laptop or desktop computer. This will enable direct access to the -Swarm network from your web browser and other applications. +If you only need to download a small amount of data from the Swarm network an ***ultra light node*** could be the right choice for you. This will allow you to download a limited amount of data but does not support uploading data. -If you only need to download a small amount of data from the Swarm network an [ultra light node](/docs/develop/access-the-swarm/ultra-light-nodes) could be the right choice for you. This will allow you to download a limited amount of data but does not support uploading data. - -To run a light or ultra-light node [install Bee](/docs/bee/installation/install) with the recommended configuration settings for your chosen node type. +If you want upload and download from Swarm and perhaps earn a small amount of bandwidth incentives, then running a ***light node*** in the background on your laptop or desktop computer could be the right choice for you. This will enable direct access to the Swarm network from your web browser and other applications. :::info The [Swarm Desktop app](https://www.ethswarm.org/build/desktop) offers an easy way to automatically set up a light or ultra-light node and interact with it through a graphical user interface. ::: +### Developing a DAPP on Swarm + +In order to develop a DAPP on Swarm, you will likely want to run either a ***light node*** or a ***full node***. For many use cases, a light node will be sufficient. However if you need to access certain features such as GSOC, then running a full node will be required. + ### Support the Network and Earn xBZZ by Running a Full Node -Earn [xBZZ](/docs/bee/working-with-bee/cashing-out) and help keep Swarm strong by running your own **full node**. It's easy to set up on a VPS, colocation, or any home computer that's connected to the internet. +If you wish to earn [xBZZ](/docs/bee/working-with-bee/cashing-out) storage and bandwidth incentives and contribute to the strength of the Swarm network, running a **full node** is the right choice for you. It's easy to set up on a VPS, colocation, or any home computer that's connected to the internet. -To run a full node [install Bee](/docs/bee/installation/install) with the recommended configuration settings for a full node. +Since each full Bee node shares up to 2^22 chunks (~16gb of data), and due to the economics of running a Bee node, serious node operators will likely wish to scale up their operations to run multiple Bee nodes together in a hive so that they can take advantage of all the available disk space they have to share and maximize their earnings. While there are many possible approaches to doing so, and there is no one officially recommended method, you may consider tools such as [Docker](https://www.docker.com/), [Docker Compose](https://docs.docker.com/compose/), or [Kubernetes](https://kubernetes.io/) in order to orchestrate the deployment of a larger number of Bee nodes. -:::info -Staking is not required to run a full node, but is necessary to earn storage incentives. An altruistic person may want to run a full node without putting up any stake, and in fact, could possibly earn enough xBZZ from bandwidth (swap/cheque) compensation to be able to stake at some point in the future. Learn more in the [staking section](/docs/bee/working-with-bee/staking) -::: -### Run Your Own Hive of Nodes -Take it to the next level by keeping a whole hive of Bees! We provide -tooling and monitoring to help you manage large deployments of -multiple Bee nodes: [Bee Hives](/docs/bee/installation/hive). +## Choosing Installation Method + +You can interact with the Swarm network by installing the Bee client through a variety of different methods. Below is a (non-exhaustive) list of some of the most common methods for installing a Bee client. + +### Swarm Desktop + +If you are looking to get started with exploring Swarm and interacting with the network in as simple and easy a way as possible, then [Swarm Desktop](/docs/desktop/introduction) is the way to go. + +Swarm Desktop offers an easy and convenient to use graphical user interface so that users can easily upload and download from the Swarm, host their websites, and access a variety of Swarm DAPPs which come pre-bundled with Swarm Desktop. + +### Shell Script Install + +If you're ready to go beyond the GUI based Swarm Desktop, then [the shell script install](/docs/bee/installation/shell-script-install) method may be right for you. This method uses a simple shell script to detect your operating system and environment and install the correct version of Bee for your machine. It's a convenient and minimalistic way of getting started with Swarm. + +Because the shell script install is so minimalistic, it may require some additional tinkering to get it working the way you want it to. For example, it will not come set up to run in the background as a service out of the box, and logs will not be automatically saved. + +### Docker Install + +While the [Docker based installation](/docs/bee/installation/docker) method requires additional tooling not needed with the shell script install method, it also comes with several advantages which make it easier to operate your node across multiple different types of environments and also makes it easier to spin up multiple nodes at once. Combining it with tools like [Docker Compose](https://docs.docker.com/compose/) can open up even more options. + +Unlike the shell script install method, Docker already comes with easy to use tools for running your containerized Bee node as a background process and for dealing with logs from your node. + +### Package Manager Install + +The Bee client can be [installed through a variety of package managers](/docs/bee/installation/package-manager-install) including [APT](https://en.wikipedia.org/wiki/APT_(software)), [RPM](https://en.wikipedia.org/wiki/RPM_Package_Manager), and [Homebrew](https://en.wikipedia.org/wiki/Homebrew_(package_manager)). + +In comparison with the shell script install, this installation method comes with the advantage of setting up Bee to run as a service in the background, and also sets up some basic log management with `journalctl` (APT / RPM) or with `launchd` for Homebrew. + +One of the disadvantages is that it can be less flexible than either the Docker or shell script install methods. + +### Building From Source +For the more advanced of users, you may wish to build from source. You can find instructions for doing so [here](/docs/bee/installation/build-from-source). While this may be the most flexible of all methods, it's also the most difficult and requires the most hands-on setup and so is recommended for more advanced users / use cases. \ No newline at end of file diff --git a/docs/bee/installation/shell-script.md b/docs/bee/installation/shell-script.md new file mode 100644 index 000000000..8dcbf2184 --- /dev/null +++ b/docs/bee/installation/shell-script.md @@ -0,0 +1,599 @@ +--- +title: Shell Script Install +id: shell-script-install +--- + + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +# Swarm Quickstart Shell Script + +The following is a guide to get you started running a Bee full node with staking on Swarm using [the official shell script provided by Swarm](https://github.com/ethersphere/bee/blob/master/install.sh) which automatically detects your system and installs the correct version of Bee. + + +:::warning +Note that we append 127.0.0.1 (localhost) to our Bee API's port (1633 by default), since we do not want to expose our Bee API endpoint to the public internet, as that would allow anyone to control our node. Make sure you do the same, and it's also recommended to use a firewall to protect access to your node(s). +::: + +:::info +The guide below is for a full Bee node with staking. To run a light node (uploads and downloads only), set `--full-node` to false, or to run in ultra light (downloads only) mode you can set both `--full-node` and `--swap-enable` to false. +::: + + + +## Prerequisites + +### Hardware + +:::warning +If you are running on a home Wi-Fi you may need to configure your router to use [port forwarding](https://www.noip.com/support/knowledgebase/general-port-forwarding-guide) or take other steps to ensure your node is reachable by other nodes on the network. See [here](https://docs.ethswarm.org/docs/bee/installation/connectivity/#navigating-through-the-nat) for more guidance. If you are running on a VPS or cloud based server you will likely have no issues. +::: + +:::caution +While it is possible to run multiple Bee nodes on a single machine, due to the high rate of I/O operations required by a full Bee node in operation, it is not recommended to run more than a handful of Bee nodes on the same physical disk (depending on the disk speed). +::: + + +### Software + +* A computer running a supported version of Linux (almost all commonly used distros should work). macOS will also work but you may need to slightly modify some commands. +* A Gnosis Chain RPC endpoint (either by running your own node or the [free RPC endpoint](https://xdai.fairdatasociety.org) offered from the Fair Data Society. Other free public options are available at the [Gnosis Chain docs](https://docs.gnosischain.com/tools/RPC%20Providers/). +* (Optional) [`jq` utility](https://jqlang.github.io/jq/) for formatting API output. +* (Optional) [`bashtop` utility](https://github.com/aristocratos/bashtop) for monitoring processes (such as our Bee node). + + +:::info +The [`jq` utility](https://jqlang.github.io/jq/) is used in this guide to automatically format the output from the Bee API. It can help make API output much more readable, however it is totally optional. + +The [`bashtop` utility](https://github.com/aristocratos/bashtop) is similarly optional, it is however a useful tool for monitoring our node's process so we can see that it is running properly. +::: + +### Tokens + +* A small amount of xDAI to pay for Gnosis Chain transactions, 0.1 xDAI should be enough +* 10 xBZZ (BZZ on Gnosis Chain) is required for staking + +## Run setup script + +Run the install shell script using either `curl` or `wget`: + +:::caution +In the example below, the version is specified using `TAG=v2.4.0`, make sure that you [check if there is a newer tagged version of Bee](https://github.com/ethersphere/bee/tags) and if so, modify the commands below to use the most recent tag number so that you have the latest version of Bee. +::: + + + + + + +```bash +curl -s https://raw.githubusercontent.com/ethersphere/bee/master/install.sh | TAG=v2.4.0 bash +``` + + + +**wget** + +```bash +wget -q -O - https://raw.githubusercontent.com/ethersphere/bee/master/install.sh | TAG=v2.2.0 bash +``` + + + + +Let's check that the script ran properly: + +```bash= +bee +``` + +If the script ran without any problems you should see this: + +```bash= +Ethereum Swarm Bee + +Usage: + bee [command] + +Available Commands: + start Start a Swarm node + dev Start a Swarm node in development mode + init Initialise a Swarm node + deploy Deploy and fund the chequebook contract + version Print version number + db Perform basic DB related operations + split Split a file into chunks + printconfig Print default or provided configuration in yaml format + help Help about any command + completion Generate the autocompletion script for the specified shell + +Flags: + --config string config file (default is $HOME/.bee.yaml) + -h, --help help for bee + +Use "bee [command] --help" for more information about a command. +``` + + +### Node Startup Commands + +Let's try starting up our node for the first time with the command below, make sure to pick a [strong password](https://xkcd.com/936/) of your own: + +Below are startup commands configured for each of the three Bee node types. + + + + +For the full node, we have `--full-node` and `--swap-enable` both enabled, and we've used `--blockchain-rpc-endpoint` to set our RPC endpoint ass `https://xdai.fairdatasociety.org`. You RPC endpoint may differ depending on your setup + +```bash +bee start \ + --password flummoxedgranitecarrot \ + --full-node \ + --swap-enable \ + --api-addr 127.0.0.1:1633 \ + --blockchain-rpc-endpoint https://xdai.fairdatasociety.org +``` + + +For the light node, we have removed `--full-node`, the rest remains the same as the full node setup. + +```bash +bee start \ + --password flummoxedgranitecarrot \ + --swap-enable \ + --api-addr 127.0.0.1:1633 \ + --blockchain-rpc-endpoint https://xdai.fairdatasociety.org +``` + + + For the ultra-light node, we remove all three of the relevant settings to disable them (since they default to `false`), `--full-node`, `--swap-enable`, and `--blockchain-rpc-endpoint`. + +```bash +bee start \ + --password flummoxedgranitecarrot \ + --api-addr 127.0.0.1:1633 +``` + + + + + +:::info + +Command explained: + +1. **`bee start`**: This is the command to start the Bee node. + +2. **`--password flummoxedgranitecarrot`**: The password to decrypt the private key associated with the node. Replace "flummoxedgranitecarrot" with your actual password. + +3. **`--full-node`**: This option enables the node to run in full mode, sharing its disk with the network, and becoming eligible for staking. + +4. **`--swap-enable`**: This flag enables SWAP, which is the bandwidth incentives scheme for Swarm. It will initiate a transaction to set up the SWAP chequebook on Gnosis Chain (required for light and full nodes). + +5. **`--api-addr 127.0.0.1:1633`**: Specifies that the Bee API will be accessible locally only via `127.0.0.1` on port `1633` and not accessible to the public. + +6. **`--blockchain-rpc-endpoint https://xdai.fairdatasociety.org`**: Sets the RPC endpoint for interacting with the Gnosis blockchain (required for light and full nodes). +::: + +### Example Startup Output + + + + +Here you can see that the node has started up successfully, but our node still needs to be funded with xDAI and xBZZ (xDAI for Gnosis Chain transactions and xBZZ for uploads/downloads and staking). Continue to the next section for funding instructions. + +```bash +Welcome to Swarm.... Bzzz Bzzzz Bzzzz + \ / + \ o ^ o / + \ ( ) / + ____________(%%%%%%%)____________ + ( / / )%%%%%%%( \ \ ) + (___/___/__/ \__\___\___) + ( / /(%%%%%%%)\ \ ) + (__/___/ (%%%%%%%) \___\__) + /( )\ + / (%%%%%) \ + (%%%) + ! + +DISCLAIMER: +This software is provided to you "as is", use at your own risk and without warranties of any kind. +It is your responsibility to read and understand how Swarm works and the implications of running this software. +The usage of Bee involves various risks, including, but not limited to: +damage to hardware or loss of funds associated with the Ethereum account connected to your node. +No developers or entity involved will be liable for any claims and damages associated with your use, +inability to use, or your interaction with other nodes or the software. + +version: 2.2.0-06a0aca7 - planned to be supported until 11 December 2024, please follow https://ethswarm.org/ + +"time"="2024-09-24 18:15:34.383102" "level"="info" "logger"="node" "msg"="bee version" "version"="2.2.0-06a0aca7" +"time"="2024-09-24 18:15:34.428546" "level"="info" "logger"="node" "msg"="swarm public key" "public_key"="0373fe2ab33ab836635fc35864cf708fa0f4a775c0cf76ca851551e7787b58d040" +"time"="2024-09-24 18:15:34.520686" "level"="info" "logger"="node" "msg"="pss public key" "public_key"="03a341032724f1f9bb04f1d9b22607db485cccd74174331c701f3a6957d94d95c1" +"time"="2024-09-24 18:15:34.520716" "level"="info" "logger"="node" "msg"="using ethereum address" "address"="0x1A801dd3ec955E905ca424a85C3423599bfb0E66" +"time"="2024-09-24 18:15:34.533789" "level"="info" "logger"="node" "msg"="fetching target neighborhood from suggester" "url"="https://api.swarmscan.io/v1/network/neighborhoods/suggestion" +"time"="2024-09-24 18:15:36.773501" "level"="info" "logger"="node" "msg"="mining a new overlay address to target the selected neighborhood" "target"="00100010110" +"time"="2024-09-24 18:15:36.776550" "level"="info" "logger"="node" "msg"="using overlay address" "address"="22d502d022de0f8e9d477bc61144d0d842d9d82b8241568c6fe4e41f0b466615" +"time"="2024-09-24 18:15:36.776576" "level"="info" "logger"="node" "msg"="starting with an enabled chain backend" +"time"="2024-09-24 18:15:37.388997" "level"="info" "logger"="node" "msg"="connected to blockchain backend" "version"="erigon/2.60.7/linux-amd64/go1.21.5" +"time"="2024-09-24 18:15:37.577840" "level"="info" "logger"="node" "msg"="using chain with network network" "chain_id"=100 "network_id"=1 +"time"="2024-09-24 18:15:37.593747" "level"="info" "logger"="node" "msg"="starting debug & api server" "address"="127.0.0.1:1633" +"time"="2024-09-24 18:15:37.969782" "level"="info" "logger"="node" "msg"="using default factory address" "chain_id"=100 "factory_address"="0xC2d5A532cf69AA9A1378737D8ccDEF884B6E7420" +"time"="2024-09-24 18:15:38.160249" "level"="info" "logger"="node/chequebook" "msg"="no chequebook found, deploying new one." +"time"="2024-09-24 18:15:38.728534" "level"="warning" "logger"="node/chequebook" "msg"="cannot continue until there is at least min xDAI (for Gas) available on address" "min_amount"="0.0003750000017" "address"="0x1A801dd3ec955E905ca424a85C3423599bfb0E66" +``` + + + + + +Here you can see that the node has started up successfully, but our node still needs to be funded with xDAI and xBZZ (xDAI for Gnosis Chain transactions and xBZZ for uploads/downloads). Continue to the next section for funding instructions. + +```bash +Welcome to Swarm.... Bzzz Bzzzz Bzzzz + \ / + \ o ^ o / + \ ( ) / + ____________(%%%%%%%)____________ + ( / / )%%%%%%%( \ \ ) + (___/___/__/ \__\___\___) + ( / /(%%%%%%%)\ \ ) + (__/___/ (%%%%%%%) \___\__) + /( )\ + / (%%%%%) \ + (%%%) + ! + +DISCLAIMER: +This software is provided to you "as is", use at your own risk and without warranties of any kind. +It is your responsibility to read and understand how Swarm works and the implications of running this software. +The usage of Bee involves various risks, including, but not limited to: +damage to hardware or loss of funds associated with the Ethereum account connected to your node. +No developers or entity involved will be liable for any claims and damages associated with your use, +inability to use, or your interaction with other nodes or the software. + +version: 2.2.0-06a0aca7 - planned to be supported until 11 December 2024, please follow https://ethswarm.org/ + +"time"="2025-01-24 12:57:21.274657" "level"="info" "logger"="node" "msg"="bee version" "version"="2.2.0-06a0aca7" +"time"="2025-01-24 12:57:21.274854" "level"="warning" "logger"="node" "msg"="your node is outdated, please check for the latest version" +"time"="2025-01-24 12:57:21.449064" "level"="info" "logger"="node" "msg"="swarm public key" "public_key"="03c356839a5570c758e812d0c248b135f0dc8ffa2b8404a97597e456f4fe5f7ee8" +"time"="2025-01-24 12:57:21.805033" "level"="info" "logger"="node" "msg"="pss public key" "public_key"="036c63b7c544ad401a5dbfb463f71cda265eec74c1d0d9cbc9db2abd6b3e4f11e9" +"time"="2025-01-24 12:57:21.805124" "level"="info" "logger"="node" "msg"="using ethereum address" "address"="0x5c39545873Bd663b0bB0716ED87dE0E399Aae419" +"time"="2025-01-24 12:57:21.815765" "level"="info" "logger"="node" "msg"="using overlay address" "address"="74539eab1dbd5c722bb8ba10cef55f715e38f298b706fb1866af49f4fd15d8d3" +"time"="2025-01-24 12:57:21.815855" "level"="info" "logger"="node" "msg"="starting with an enabled chain backend" +"time"="2025-01-24 12:57:21.861341" "level"="info" "logger"="node" "msg"="connected to blockchain backend" "version"="Nethermind/v1.30.1+2b75a75a/linux-x64/dotnet9.0.0" +"time"="2025-01-24 12:57:21.869117" "level"="info" "logger"="node" "msg"="using chain with network network" "chain_id"=100 "network_id"=1 +"time"="2025-01-24 12:57:21.880930" "level"="info" "logger"="node" "msg"="starting debug & api server" "address"="127.0.0.1:1633" +"time"="2025-01-24 12:57:21.897675" "level"="info" "logger"="node" "msg"="using default factory address" "chain_id"=100 "factory_address"="0xC2d5A532cf69AA9A1378737D8ccDEF884B6E7420" +"time"="2025-01-24 12:57:21.911463" "level"="info" "logger"="node/chequebook" "msg"="no chequebook found, deploying new one." +"time"="2025-01-24 12:57:21.938038" "level"="warning" "logger"="node/chequebook" "msg"="cannot continue until there is at least min xDAI (for Gas) available on address" "min_amount"="0.000250000002" "address"="0x5c39545873Bd663b0bB0716ED87dE0E399Aae419" +``` + + + + If you've started in ultra-light mode, you should see output which looks something like this, and you're done! Your node is now successfully running in ultra-light mode. You can now skip down to the final section on this page about logs and monitoring. + +```bash + root@noah-bee:~# bee start \ + --password flummoxedgranitecarrot \ + --api-addr 127.0.0.1:1633 + +Welcome to Swarm.... Bzzz Bzzzz Bzzzz + \ / + \ o ^ o / + \ ( ) / + ____________(%%%%%%%)____________ + ( / / )%%%%%%%( \ \ ) + (___/___/__/ \__\___\___) + ( / /(%%%%%%%)\ \ ) + (__/___/ (%%%%%%%) \___\__) + /( )\ + / (%%%%%) \ + (%%%) + ! + +DISCLAIMER: +This software is provided to you "as is", use at your own risk and without warranties of any kind. +It is your responsibility to read and understand how Swarm works and the implications of running this software. +The usage of Bee involves various risks, including, but not limited to: +damage to hardware or loss of funds associated with the Ethereum account connected to your node. +No developers or entity involved will be liable for any claims and damages associated with your use, +inability to use, or your interaction with other nodes or the software. + +version: 2.2.0-06a0aca7 - planned to be supported until 11 December 2024, please follow https://ethswarm.org/ + +"time"="2025-01-24 12:51:06.981505" "level"="info" "logger"="node" "msg"="bee version" "version"="2.2.0-06a0aca7" +"time"="2025-01-24 12:51:06.981658" "level"="warning" "logger"="node" "msg"="your node is outdated, please check for the latest version" +"time"="2025-01-24 12:51:07.131555" "level"="info" "logger"="node" "msg"="swarm public key" "public_key"="03c356839a5570c758e812d0c248b135f0dc8ffa2b8404a97597e456f4fe5f7ee8" +"time"="2025-01-24 12:51:07.402847" "level"="info" "logger"="node" "msg"="pss public key" "public_key"="036c63b7c544ad401a5dbfb463f71cda265eec74c1d0d9cbc9db2abd6b3e4f11e9" +"time"="2025-01-24 12:51:07.402915" "level"="info" "logger"="node" "msg"="using ethereum address" "address"="0x5c39545873Bd663b0bB0716ED87dE0E399Aae419" +"time"="2025-01-24 12:51:07.416074" "level"="info" "logger"="node" "msg"="using overlay address" "address"="74539eab1dbd5c722bb8ba10cef55f715e38f298b706fb1866af49f4fd15d8d3" +"time"="2025-01-24 12:51:07.416149" "level"="info" "logger"="node" "msg"="starting with a disabled chain backend" +"time"="2025-01-24 12:51:07.416242" "level"="info" "logger"="node" "msg"="using chain with network network" "chain_id"=100 "network_id"=1 +"time"="2025-01-24 12:51:07.428047" "level"="info" "logger"="node" "msg"="starting debug & api server" "address"="127.0.0.1:1633" +"time"="2025-01-24 12:51:07.464425" "level"="info" "logger"="node" "msg"="using datadir" "path"="/root/.bee" +"time"="2025-01-24 12:51:07.486853" "level"="info" "logger"="migration-RefCountSizeInc" "msg"="starting migration of replacing chunkstore items to increase refCnt capacity" +"time"="2025-01-24 12:51:07.486921" "level"="info" "logger"="migration-RefCountSizeInc" "msg"="migration complete" +"time"="2025-01-24 12:51:07.489133" "level"="info" "logger"="node" "msg"="starting reserve repair tool, do not interrupt or kill the process..." +"time"="2025-01-24 12:51:07.489346" "level"="info" "logger"="node" "msg"="removed all bin index entries" +"time"="2025-01-24 12:51:07.489430" "level"="info" "logger"="node" "msg"="removed all chunk bin items" "total_entries"=0 +"time"="2025-01-24 12:51:07.489482" "level"="info" "logger"="node" "msg"="counted all batch radius entries" "total_entries"=0 +"time"="2025-01-24 12:51:07.489520" "level"="info" "logger"="node" "msg"="parallel workers" "count"=2 +"time"="2025-01-24 12:51:07.489612" "level"="info" "logger"="node" "msg"="migrated all chunk entries" "new_size"=0 "missing_chunks"=0 "invalid_sharky_chunks"=0 +"time"="2025-01-24 12:51:07.489659" "level"="info" "logger"="migration-step-04" "msg"="starting sharky recovery" +"time"="2025-01-24 12:51:07.514853" "level"="info" "logger"="migration-step-04" "msg"="finished sharky recovery" +"time"="2025-01-24 12:51:07.515253" "level"="info" "logger"="migration-step-05" "msg"="start removing upload items" +"time"="2025-01-24 12:51:07.515374" "level"="info" "logger"="migration-step-05" "msg"="finished removing upload items" +"time"="2025-01-24 12:51:07.515434" "level"="info" "logger"="migration-step-06" "msg"="start adding stampHash to BatchRadiusItems, ChunkBinItems and StampIndexItems" +"time"="2025-01-24 12:51:07.515571" "level"="info" "logger"="migration-step-06" "msg"="finished migrating items" "seen"=0 "migrated"=0 +"time"="2025-01-24 12:51:07.517270" "level"="info" "logger"="node" "msg"="starting in ultra-light mode" +``` + + + + + + +### Fund node (full and light nodes only) + +Check the logs from the previous step. Look for the line which says: + +``` +"time"="2024-09-24 18:15:34.520716" "level"="info" "logger"="node" "msg"="using ethereum address" "address"="0x1A801dd3ec955E905ca424a85C3423599bfb0E66" +``` +That address is your node's address on Gnosis Chain which needs to be funded with xDAI and xBZZ. Copy it and save it for the next step. + +xDAI is widely available from many different centralized and decentralized exchanges, just make sure that you are getting xDAI on Gnosis Chain, and not DAI on some other chain. See [this page](https://www.ethswarm.org/get-bzz) for a list of resources for getting xBZZ (again, make certain that you are getting the Gnosis Chain version, and not BZZ on Ethereum). + +After acquiring some xDAI and some xBZZ, send them to the address you copied above. + +***How Much to Send?*** + +Only a very small amount of xDAI is needed to get started, 0.1 is more than enough. + +You can start with just 2 or 3 xBZZ for uploading small amounts of data, but you will need at least 10 xBZZ if you plan on staking. + + +### Initialize full node + +After sending the required tokens of ~0.1 xDAI and 10 xBZZ (or a smaller amount of xBZZ if you don't plan on staking) to your node's Gnosis Chain address, close the bee process in your terminal (`Ctrl + C`). Then start it again with the same command: + +```bash +bee start \ + --password flummoxedgranitecarrot \ + --full-node \ + --swap-enable \ + --api-addr 127.0.0.1:1633 \ + --blockchain-rpc-endpoint https://xdai.fairdatasociety.org +``` +After funding and restarting your node, the logs printed to the terminal should look something like this: + +```bash +Welcome to Swarm.... Bzzz Bzzzz Bzzzz + \ / + \ o ^ o / + \ ( ) / + ____________(%%%%%%%)____________ + ( / / )%%%%%%%( \ \ ) + (___/___/__/ \__\___\___) + ( / /(%%%%%%%)\ \ ) + (__/___/ (%%%%%%%) \___\__) + /( )\ + / (%%%%%) \ + (%%%) + ! + +DISCLAIMER: +This software is provided to you "as is", use at your own risk and without warranties of any kind. +It is your responsibility to read and understand how Swarm works and the implications of running this software. +The usage of Bee involves various risks, including, but not limited to: +damage to hardware or loss of funds associated with the Ethereum account connected to your node. +No developers or entity involved will be liable for any claims and damages associated with your use, +inability to use, or your interaction with other nodes or the software. + +version: 2.2.0-06a0aca7 - planned to be supported until 11 December 2024, please follow https://ethswarm.org/ + +"time"="2024-09-24 18:57:16.710417" "level"="info" "logger"="node" "msg"="bee version" "version"="2.2.0-06a0aca7" +"time"="2024-09-24 18:57:16.760154" "level"="info" "logger"="node" "msg"="swarm public key" "public_key"="0373fe2ab33ab836635fc35864cf708fa0f4a775c0cf76ca851551e7787b58d040" +"time"="2024-09-24 18:57:16.854594" "level"="info" "logger"="node" "msg"="pss public key" "public_key"="03a341032724f1f9bb04f1d9b22607db485cccd74174331c701f3a6957d94d95c1" +"time"="2024-09-24 18:57:16.854651" "level"="info" "logger"="node" "msg"="using ethereum address" "address"="0x1A801dd3ec955E905ca424a85C3423599bfb0E66" +"time"="2024-09-24 18:57:16.866697" "level"="info" "logger"="node" "msg"="using overlay address" "address"="22d502d022de0f8e9d477bc61144d0d842d9d82b8241568c6fe4e41f0b466615" +"time"="2024-09-24 18:57:16.866730" "level"="info" "logger"="node" "msg"="starting with an enabled chain backend" +"time"="2024-09-24 18:57:17.485408" "level"="info" "logger"="node" "msg"="connected to blockchain backend" "version"="erigon/2.60.1/linux-amd64/go1.21.5" +"time"="2024-09-24 18:57:17.672282" "level"="info" "logger"="node" "msg"="using chain with network network" "chain_id"=100 "network_id"=1 +"time"="2024-09-24 18:57:17.686479" "level"="info" "logger"="node" "msg"="starting debug & api server" "address"="127.0.0.1:1633" +"time"="2024-09-24 18:57:18.065029" "level"="info" "logger"="node" "msg"="using default factory address" "chain_id"=100 "factory_address"="0xC2d5A532cf69AA9A1378737D8ccDEF884B6E7420" +"time"="2024-09-24 18:57:18.252410" "level"="info" "logger"="node/chequebook" "msg"="no chequebook found, deploying new one." +"time"="2024-09-24 18:57:19.576100" "level"="info" "logger"="node/chequebook" "msg"="deploying new chequebook" "tx"="0xf7bc9c5b04e96954c7f70cecfe717cad9cdc5d64b6ec080b2cbe712166ce262a" +"time"="2024-09-24 18:57:27.619377" "level"="info" "logger"="node/transaction" "msg"="pending transaction confirmed" "sender_address"="0x1A801dd3ec955E905ca424a85C3423599bfb0E66" "tx"="0xf7bc9c5b04e96954c7f70cecfe717cad9cdc5d64b6ec080b2cbe712166ce262a" +"time"="2024-09-24 18:57:27.619437" "level"="info" "logger"="node/chequebook" "msg"="chequebook deployed" "chequebook_address"="0x261a07a63dC1e7200d51106155C8929b432181fb" +``` + +Here we can see that after our node has been funded, it was able to issue the transactions for deploying the chequebook contract, which is a prerequisite for running a staking node. + +Next your node will begin to sync [postage stamp data](/docs/develop/access-the-swarm/buy-a-stamp-batch), which can take ~5 to 10 minutes. You will see this log message while your node is syncing postage stamp data: + +```bash +"time"="2024-09-24 22:21:19.664897" "level"="info" "logger"="node" "msg"="waiting to sync postage contract data, this may take a while... more info available in Debug loglevel" +``` + +After your node finishes syncing postage stamp data it will start in full node mode and begin to sync all the chunks of data it is responsible for storing as a full node: + + +```bash +"time"="2024-09-24 22:30:19.154067" "level"="info" "logger"="node" "msg"="starting in full mode" +"time"="2024-09-24 22:30:19.155320" "level"="info" "logger"="node/multiresolver" "msg"="name resolver: no name resolution service provided" +"time"="2024-09-24 22:30:19.341032" "level"="info" "logger"="node/storageincentives" "msg"="entered new phase" "phase"="reveal" "round"=237974 "block"=36172090 +"time"="2024-09-24 22:30:33.610825" "level"="info" "logger"="node/kademlia" "msg"="disconnected peer" "peer_address"="6ceb30c7afc11716f866d19b7eeda9836757031ed056b61961e949f6e705b49e" +``` + +This process can take a while, up to several hours depending on your system and network. You can check the progress of your node through the logs which print out to the Bee API: + +You check your node's progress with the `/status` endpoint: + +:::info +The [`jq` utility](https://jqlang.github.io/jq/) is used here to automatically format the output from the Bee API. It can help make API output more readable. You may need to install it, the exact steps will depend on your Linux distro and package manager of choice. Also feel free to remove the `| jq` from the command as it is only a convenience, not a requirement. +::: + +```bash +curl -s http://localhost:1633/status | jq +``` + +```bash +{ + "overlay": "22dc155fe072e131449ec7ea2f77de16f4735f06257ebaa5daf2fdcf14267fd9", + "proximity": 256, + "beeMode": "full", + "reserveSize": 686217, + "reserveSizeWithinRadius": 321888, + "pullsyncRate": 497.8747754074074, + "storageRadius": 11, + "connectedPeers": 148, + "neighborhoodSize": 4, + "batchCommitment": 74510761984, + "isReachable": false, + "lastSyncedBlock": 36172390 +} +``` +We can see that our node has not yet finished syncing chunks since the `pullsyncRate` is around 497 chunks per second. Once the node is fully synced, this value will go to zero. However, we do not need to wait until our node is fully synced in order to stake our node, so we can now move immediately to the next step. + + +### Stake node + +Now we're ready to begin staking, we will slightly modify our startup command so that it now runs in the background instead of taking control of our terminal: + +```bash +nohup bee start \ + --password flummoxedgranitecarrot \ + --full-node \ + --swap-enable \ + --api-addr 127.0.0.1:1633 \ + --blockchain-rpc-endpoint https://xdai.fairdatasociety.org > bee.log 2>&1 & +``` + +:::info +1. **`nohup`**: This ensures that the `bee start` process will continue even after the terminal is closed. + +2. **`> bee.log 2>&1`**: Redirects both standard output and standard error to a log file called `bee.log`. + +3. **`&`**: This sends the process to the background, allowing the terminal to be used for other commands while the Bee node continues running. +::: + +Let's check the Bee API to confirm the node is running: + +``` +curl localhost:1633 +``` +If the node is running we should see: +``` +Ethereum Swarm Bee +``` + +Now with our node properly running in the background, we're ready to stake our node. You can use the following command to stake 10 xBZZ: + +```bash +curl -XPOST localhost:1633/stake/100000000000000000 +``` + +If the staking transaction is successful a `txHash` will be returned: + +``` +{"txHash":"0x258d64720fe7abade794f14ef3261534ff823ef3e2e0011c431c31aea75c2dd5"} +``` + +We can also confirm that our node has been staked with the `/stake` endpoint: + +```bash +curl localhost:1633/stake +``` + +The results will be displayed in PLUR units (1 PLUR is equal to 1e-16 xBZZ). If you have properly staked the minimum 10 xBZZ, you should see the output below: + +```bash +{"stakedAmount":"100000000000000000"} +``` + +Congratulations! You have now installed your Bee node and are connected to the network as a full staking node. Your node will now be in the process of syncing chunks from the network. Once it is fully synced, your node will finally be eligible for earning staking rewards. + +### Logs and monitoring + +With our previously modified command, our Bee node will now be running in the background and the logs will be written to the `bee.log` file. To review our node's logs we can simply view the file contents: + +```bash +cat bee.log +``` + +The file will continue to update with all the latest logs as they are output: + +```bash +"time"="2024-09-27 18:05:34.096641" "level"="info" "logger"="node/kademlia" "msg"="connected to peer" "peer_address"="03b48e678938d63c0761c74a805fbe0446684c9c417330c2bec600ecfd6c492f" "proximity_order"=8 +"time"="2024-09-27 18:05:35.168425" "level"="info" "logger"="node/kademlia" "msg"="connected to peer" "peer_address"="0e9388fff473a9c74535337c32cc74d8f921514d2635d0c4a49c6e8022f5594e" "proximity_order"=4 +"time"="2024-09-27 18:05:35.532723" "level"="info" "logger"="node/kademlia" "msg"="disconnected peer" "peer_address"="3c195cd8882ee537d170e92d959ad6bd72a76a50097a671c72646e83b45a1832" +``` + +There are many different ways to monitor your Bee node's process, but one convenient way to do so is the [bashtop command line tool](https://github.com/aristocratos/bashtop). The method of [installation](https://github.com/aristocratos/bashtop?tab=readme-ov-file#installation) will vary depending on your system. + +After installation, we can launch it with the `bashtop` command: + +```bash +bashtop +``` + +![](/img/bashtop_01.png) + +We can use the `f` key to filter for our Bee node's specific process by searching for the `bee` keyword (use the arrow keys to navigate and `enter` to select). From here we can view info about our node's process, or shut it down using the `t` key (for "terminate"). + +![](/img/bashtop_02.png) + +**Checking the Node's status with the Bee API** + +To check your node's status as a staking node, we can use the `/redistributionstate` endpoint: + +```bash +curl -s http://localhost:1633/redistributionstate | jq +``` + +Below is the output for a node which has been running for several days: + +```bash +{ + "minimumGasFunds": "11080889201250000", + "hasSufficientFunds": true, + "isFrozen": false, + "isFullySynced": true, + "phase": "claim", + "round": 212859, + "lastWonRound": 207391, + "lastPlayedRound": 210941, + "lastFrozenRound": 210942, + "lastSelectedRound": 212553, + "lastSampleDuration": 491687776653, + "block": 32354719, + "reward": "1804537795127017472", + "fees": "592679945236926714", + "isHealthy": true +} +``` + +For a complete breakdown of this output, check out [this section in the Bee docs](/docs/bee/working-with-bee/bee-api#redistributionstate). + +You can read more other important endpoints for monitoring your Bee node in the [official Bee docs](/docs/bee/working-with-bee/bee-api), and you can find complete information about all available endpoints in [the API reference docs](/api/). diff --git a/sidebars.js b/sidebars.js index ab63a1432..aabbf1ee8 100644 --- a/sidebars.js +++ b/sidebars.js @@ -48,10 +48,11 @@ module.exports = { label: 'Installation', items: [ 'bee/installation/quick-start', - 'bee/installation/install', + 'bee/installation/shell-script-install', + 'bee/installation/docker', + 'bee/installation/package-manager-install', 'bee/installation/build-from-source', 'bee/installation/hive', - 'bee/installation/docker', 'bee/installation/connectivity', 'bee/installation/fund-your-node', ], diff --git a/static/img/bashtop_01.png b/static/img/bashtop_01.png new file mode 100644 index 0000000000000000000000000000000000000000..bfa505819cfb91a0b1af5b08d628cdf2f617f53b GIT binary patch literal 118095 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%0D#?Y+c^E@8gdnkQ3$IJ`=t|TBKY0jbu$0Z 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�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⪼s&|zLnN@idyl>v&R(*+-0W1`39=JS#k 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 literal 0 HcmV?d00001 From a0a0ca984d621d86bb1613a004e78e24db6da38b Mon Sep 17 00:00:00 2001 From: NoahMaizels Date: Thu, 30 Jan 2025 04:23:50 +0700 Subject: [PATCH 02/16] Widespread updates --- docs/bee/faq.md | 2 +- docs/bee/installation/docker.md | 841 +++++------------- docs/bee/installation/fund-your-node.md | 65 +- .../{quick-start.md => getting-started.md} | 84 +- docs/bee/installation/package-manager.md | 528 ++--------- .../installation/set-target-neighborhood.md | 38 + docs/bee/installation/shell-script.md | 111 ++- docs/bee/working-with-bee/configuration.md | 342 +++++-- docs/bee/working-with-bee/logs-and-files.md | 4 + docs/bee/working-with-bee/uninstalling-bee.md | 2 +- docs/concepts/introduction.md | 2 +- .../access-the-swarm/store-with-encryption.md | 4 +- docusaurus.config.js | 6 +- sidebars.js | 3 +- src/config/globalVariables.js | 1 - src/pages/index.js | 2 +- 16 files changed, 800 insertions(+), 1235 deletions(-) rename docs/bee/installation/{quick-start.md => getting-started.md} (65%) create mode 100644 docs/bee/installation/set-target-neighborhood.md diff --git a/docs/bee/faq.md b/docs/bee/faq.md index 591b68eb3..1945cfdb3 100644 --- a/docs/bee/faq.md +++ b/docs/bee/faq.md @@ -13,7 +13,7 @@ Depending on your needs you can run ultra-light, light or full node. ### What are the differences between Bee node types? -A bee node can be configured to run in various modes based on specific use cases and requirements. [See here](/docs/bee/installation/quick-start) for an overview of the differences. +A bee node can be configured to run in various modes based on specific use cases and requirements. [See here](/docs/bee/installation/getting-started) for an overview of the differences. #### What are the requirements for running a Bee node? diff --git a/docs/bee/installation/docker.md b/docs/bee/installation/docker.md index 5c1051f5d..a50a6ef37 100644 --- a/docs/bee/installation/docker.md +++ b/docs/bee/installation/docker.md @@ -3,318 +3,79 @@ title: Docker Install id: docker --- -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; +# Docker Install -Docker is one option for running a Bee node, and when combined with Docker Compose, it even offers a convenient solution for spinning up and managing a small "hive" of Bee nodes. - -Docker containers for Bee are hosted at [Docker Hub](https://hub.docker.com/r/ethersphere/bee). +The following is a guide for installing a Bee node using Docker. Docker images for Bee are hosted at [Docker Hub](https://hub.docker.com/r/ethersphere/bee). Using Docker to operate your Bee node offers :::caution -While it is possible to run multiple Bee nodes on a single machine, due to the high rate of I/O operations required by a full Bee node in operation, it is not recommended to run more than a handful of Bee nodes on the same physical disk (depending on the disk speed). +In the examples below we specify the exact version number of the image using the 2.2.0 tag. It's recommended to only use the exact version number tags. Make sure to check that you're on the latest version of Bee by reviewing the tags for Bee on [Docker Hub](https://hub.docker.com/r/ethersphere/bee/tags), and replace 2.2.0 in the commands below if there is a newer full release. ::: - -## Install Docker and Docker Compose - -:::info -The steps for setting up Docker and Docker Compose may vary slightly from system to system, so take note system specific commands and make sure to modify them for your own system as needed. +:::warning +Note that in all the examples below we map the Bee API to 127.0.0.1 (localhost), since we do not want to expose our Bee API endpoint to the public internet, as that would allow anyone to control our node. Make sure you do the same, and it's also recommended to use a firewall to protect access to your node(s). ::: - - - - - -### For Debian-based Systems (e.g., Ubuntu, Debian) - -#### Step 1: Install Docker - -1. **Update the package list:** - - ```bash - sudo apt-get update - ``` - -2. **Install necessary packages:** - - ```bash - sudo apt-get install -y apt-transport-https ca-certificates curl gnupg lsb-release - ``` - -3. **Add Docker’s official GPG key:** - - ```bash - curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg - ``` - -4. **Add Docker’s official repository to APT sources:** - - ```bash - echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) latest" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null - ``` - -5. **Update the package list again:** - - ```bash - sudo apt-get update - ``` - -6. **Install Docker packages:** - - ```bash - sudo apt-get install -y docker-ce docker-ce-cli containerd.io - ``` - -#### Step 2: Install Docker Compose Plugin - :::info -Skip this section if you are running Bee with Docker only. +This guide sets options using environment variables as a part of the Docker startup commands such as `-e BEE_API_ADDR=":1633"`, however there are [several other methods available for configuring options](/docs/bee/working-with-bee/configuration). ::: -1. **Update the package list:** - - ```bash - sudo apt-get update - ``` - -2. **Install the Docker Compose plugin:** - ```bash - sudo apt-get install docker-compose-plugin - ``` - -3. **Verify the installation:** - - ```bash - docker compose version - ``` - - - - - -### For RPM-based Systems (e.g., CentOS, Fedora) - -#### Step 1: Install Docker - -1. **Install necessary packages:** - - ```bash - sudo yum install -y yum-utils device-mapper-persistent-data lvm2 - ``` - -2. **Add Docker’s official repository:** - - ```bash - sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo - ``` - -3. **Install Docker packages:** - - ```bash - sudo yum install -y docker-ce docker-ce-cli containerd.io - ``` - -4. **Start and enable Docker:** - - ```bash - sudo systemctl start docker - sudo systemctl enable docker - ``` - -#### Step 2: Install Docker Compose Plugin - -1. **Update the package list:** - - ```bash - sudo yum update - ``` - -2. **Install the Docker Compose plugin:** - - ```bash - sudo yum install docker-compose-plugin - ``` - -3. **Verify the installation:** - - ```bash - docker compose version - ``` - - - - +:::info +**Bee Modes:** +Bee nodes can be run in multiple modes with different functionalities. To run a node in full mode, both `BEE_FULL_NODE` and `BEE_SWAP_ENABLE` must be set to `true`. To run a light node (uploads and downloads only), set `BEE_FULL_NODE` to `false` and `BEE_SWAP_ENABLE` to `true`, or to run in ultra light mode (free tier downloads only) set both `BEE_FULL_NODE` and `BEE_SWAP_ENABLE` to `false`. -## Bee with Docker +For more information on the different functionalities of each mode, as well as their different system requirements, refer to the [Getting Started guide](/docs/bee/installation/getting-started). +::: -This section will guide you through setting up and running a single Bee node using Docker only without Docker Compose. -### Step 1: Create directories +## Node setup process -Create home directory: +This section will guide you through setting up and running a single full Bee node using Docker. In the guide, we use a single line command for running our Bee node, with the Bee config options being set through environment variables, and a single volume hosted for our node's data. -```bash -mkdir bee-node -cd bee-node -``` -Create data directory and change permissions +### Start node ```bash -mkdir .bee -sudo chown -R 999:999 .bee -``` - -### Step 2: Bee Node Configuration - -Based on your preferred node type, copy one of the three sample configurations below: - - - - - -#### Full node sample configuration - -```yml -# GENERAL BEE CONFIGURATION -api-addr: :1633 -p2p-addr: :1634 -password: aaa4eabb0813df71afa45d -data-dir: /home/bee/.bee -cors-allowed-origins: ["*"] - -# DEBUG CONFIGURATION -verbosity: 5 - -# BEE MAINNET CONFIGURATION -bootnode: /dnsaddr/mainnet.ethswarm.org - -# BEE MODE: FULL NODE CONFIGURATION -full-node: true -swap-enable: true -blockchain-rpc-endpoint: https://xdai.fairdatasociety.org -``` - - - - - -#### Light node sample configuration - -```yml -# GENERAL BEE CONFIGURATION -api-addr: :1633 -p2p-addr: :1634 -password: aaa4eabb0813df71afa45d -data-dir: /home/bee/.bee -cors-allowed-origins: ["*"] - -# DEBUG CONFIGURATION -verbosity: 5 - -# BEE MAINNET CONFIGURATION -bootnode: /dnsaddr/mainnet.ethswarm.org - -# BEE MODE: LIGHT CONFIGURATION -full-node: false -swap-enable: true -blockchain-rpc-endpoint: https://xdai.fairdatasociety.org -``` - - - - - -#### Ultra light node sample configuration - -```yml -# GENERAL BEE CONFIGURATION -api-addr: :1633 -p2p-addr: :1634 -password: aaa4eabb0813df71afa45d -data-dir: /home/bee/.bee -cors-allowed-origins: ["*"] - -# DEBUG CONFIGURATION -verbosity: 5 - -# BEE MAINNET CONFIGURATION -bootnode: /dnsaddr/mainnet.ethswarm.org -blockchain-rpc-endpoint: https://xdai.fairdatasociety.org - -# BEE MODE: ULTRA LIGHT CONFIGURATION -swap-enable: false -full-node: false +docker run -d --name bee-1 \ + --restart always \ + -p 127.0.0.1:1633:1633 \ + -p 1634:1634 \ + -e BEE_API_ADDR=":1633" \ + -e BEE_FULL_NODE="true" \ + -e BEE_SWAP_ENABLE="true" \ + -e BEE_PASSWORD="flummoxedgranitecarrot" \ + -e BEE_BLOCKCHAIN_RPC_ENDPOINT="https://xdai.fairdatasociety.org" \ + -v bee-1:/home/bee/.bee \ + ethersphere/bee:2.2.0 start ``` - - - - -Save the configuration into a YAML configuration file: +Here is the same command in a single line in case you run into issues with the line breaks in the command above: ```bash -sudo vi ./bee.yml +docker run -d --name bee-1 --restart always -p 127.0.0.1:1633:1633 -p 1634:1634 -e BEE_API_ADDR=":1633" -e BEE_FULL_NODE="true" -e BEE_SWAP_ENABLE="true" -e BEE_PASSWORD="flummoxedgranitecarrot" -e BEE_BLOCKCHAIN_RPC_ENDPOINT="https://xdai.fairdatasociety.org" -v bee-1:/home/bee/.bee ethersphere/bee:2.2.0 start ``` -Print out the configuration to make sure it was properly saved: - -```bash -cat ./bee.yml -``` +#### Command explained: -### Step 3: Run Bee Node with Docker +- **`-d`**: Runs the container in the background. +- **`--restart always`**: Sets the [restart policy](https://docs.docker.com/engine/containers/start-containers-automatically/) for the container to `always` +- **`--name bee-1`**: Names the container `bee-1`. +- **`-p 127.0.0.1:1633:1633`**: Exposes the API on port 1633, only accessible locally. +- **`-p 1634:1634`**: Exposes the P2P port 1634 to the public. +- **`-e BEE_API_ADDR=":1633"`**: Sets the Bee API to use port 1633. +- **`-e BEE_FULL_NODE="true"`**: Runs as a full node. +- **`-e BEE_SWAP_ENABLE="true"`**: Enables the SWAP protocol for payments. +- **`-e BEE_PASSWORD="flummoxedgranitecarrot"`**: Sets the keystore password, make sure to replace with your own. +- **`-e BEE_BLOCKCHAIN_RPC_ENDPOINT="https://xdai.fairdatasociety.org"`**: Connects to the Gnosis Chain. +- **`-v bee-1:/home/bee/.bee`**: Persists node data in the `bee-1` volume. +- **`ethersphere/bee:2.2.0 start`**: Runs Bee version 2.2.0 and starts the node. -Use the following command to start up your node: +This setup runs the Bee node in a container, with full-node functionality, SWAP enabled, and connections to the Gnosis blockchain for chequebook and postage stamp management, while persisting its data using a volume. -```bash -docker run -d --name bee-node \ - -v "$(pwd)/.bee:/home/bee/.bee" \ - -v "$(pwd)/bee.yml:/home/bee/bee.yml" \ - -p 127.0.0.1:1633:1633 \ - -p 1634:1634 \ - ethersphere/bee:2.3.0 start --config /home/bee/bee.yml -``` :::info -Command breakdown: - -1. **`docker run`**: This is the command to start a new Docker container. - -1. **`-d`**: This flag runs the container in detached mode, meaning it runs in the background. - -1. **`--name bee-node`**: This sets the name of the container to `bee-node`. Naming containers can help manage and identify them easily. - -1. **`-v "$(pwd)/.bee:/home/bee/.bee"`**: This mounts a volume. It maps the `.bee` directory in your current working directory (`$(pwd)`) to the `/home/bee/.bee` directory inside the container. This allows the container to store and access persistent data on your host machine. - -1. **`-v "$(pwd)/bee.yml:/home/bee/bee.yml"`**: This mounts another volume. It maps the `bee.yml` file in your current working directory to the `/home/bee/bee.yml` file inside the container. This allows the container to use the configuration file from your host machine. - -1. **`-p 127.0.0.1:1633:1633`**: This maps port 1633 on `127.0.0.1` (localhost) of your host machine to port 1633 inside the container. This is used for the Bee API. - -1. **`-p 1634:1634`**: This maps port 1634 on all network interfaces of your host machine to port 1634 inside the container. This is used for P2P communication. - -1. **`ethersphere/bee:2.3.0`**: This specifies the Docker image to use for the container. In this case, it is the `ethersphere/bee` image with the tag `2.3.0`. - -1. **`start --config /home/bee/bee.yml`**: This specifies the command to run inside the container. It starts the Bee node using the configuration file located at `/home/bee/bee.yml`. +We have included the password as part of the start command by setting it as an environment variable with `-e BEE_PASSWORD="flummoxedgranitecarrot"`. You may wish to use a password file instead, which can be set with the `BEE_PASSWORD_FILE` command. However this will likely require some modifications on your host machine, the details of which will vary from system to system. ::: -Note that we have mapped the Bee API and Debug API to 127.0.0.1 (localhost), this is to ensure that these APIs are not available publicly, as that would allow anyone to control our node. - -Check that the node is running: - ```bash docker ps ``` @@ -324,456 +85,292 @@ If everything is set up correctly, you should see your Bee node listed: ```bash CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -e53aaa4e76ec ethersphere/bee:2.3.0 "bee start --config …" 17 seconds ago Up 16 seconds 127.0.0.1:1633->1633/tcp, 0.0.0.0:1634->1634/tcp, :::1634->1634/tcp, bee-node +37f4ad8b4060 ethersphere/bee:2.2.0 "bee start" 6 seconds ago Up 5 seconds 127.0.0.1:1633->1633/tcp, 0.0.0.0:1634->1634/tcp, :::1634->1634/tcp bee-1 ``` And check the logs: ```bash -docker logs -f bee-node +docker logs -f bee-1 ``` -The output should contain a line which prints the address of your node. Copy this address and save it for use in the next section. +The output should contain a line which prints a message notifying you of the minimum required xDAI for running a node as well as the address of your node. Copy the address and save it for use in the next section. ```bash -"time"="2024-07-15 12:23:57.906429" "level"="warning" "logger"="node/chequebook" "msg"="cannot continue until there is at least min xDAI (for Gas) available on address" "min_amount"="0.0005750003895" "address"="0xf50Bae90a99cfD15Db5809720AC1390d09a25d60" +"time"="2024-09-24 22:06:51.363708" "level"="warning" "logger"="node/chequebook" "msg"="cannot continue until there is at least min xDAI (for Gas) available on address" "min_amount"="0.0003576874793" "address"="0x91A7e3AC06020750D32CeffbEeFD55B4c5e42bd6" ``` -### Step 4: Funding (Full and Light Nodes Only) - - - -To obtain xDAI and fund your node, you can [follow the instructions](https://docs.ethswarm.org/docs/installation/install#4-fund-node) from the main install section. +You can use `Ctrl + C` to exit the logs. -### Step 5: Add Stake - -To add stake, make a POST request to the `/stake` endpoint and input the amount you wish to stake in PLUR as a parameter after `/stake`. For example, to stake an amount equal to 10 xBZZ: +Before moving on to funding, stop your node: ```bash -curl -X POST localhost:1633/stake/100000000000000000 +docker stop bee-1 ``` -Note that since we have mapped our host and container to the same port, we can use the default `1633` port to make our request. If you are running multiple nodes, make sure to update this command for other nodes which will be mapped to different ports on the host machine. - - -## Bee with Docker Compose - -By adding Docker Compose to our setup, we can simplify the management of our configuration by saving it in a `docker-compose.yml` file rather than specifying it all in the startup command. It also lays the foundation for running multiple nodes at once. First we will review how to run a single node with Docker Compose. - -### Step 1: Create directory for node(s) +And let's confirm that it has stopped: ```bash -mkdir bee-nodes -cd bee-nodes -``` - -### Step 2: Create home directory for first node - -```shell -mkdir node_01 -``` - -### Step 3: Create data directory and change permissions - -```shell -mkdir node_01/.bee -sudo chown -R 999:999 node_01/.bee +docker ps ``` -Here we change ownership to match the UID and GID of the user specified in the [Bee Dockerfile](https://github.com/ethersphere/bee/blob/master/Dockerfile). - -### Step 4: Bee node configuration +We can confirm no Docker container processes are currently running. -Below are sample configurations for different node types. - -:::info -The `blockchain-rpc-endpoint` entry is set to use the free and public `https://xdai.fairdatasociety.org` RPC endpoint, which is fine for testing things out but may not be stable enough for extended use. If you are running your own Gnosis Node or using a RPC provider service, make sure to update this value with your own endpoint. -::: - - - - - - -#### Full node sample configuration - -```yml -# GENERAL BEE CONFIGURATION -api-addr: :1633 -p2p-addr: :1634 -password: aaa4eabb0813df71afa45d -data-dir: /home/bee/.bee -cors-allowed-origins: ["*"] +```bash +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES +```` -# DEBUG CONFIGURATION -verbosity: 5 +### Fund node -# BEE MAINNET CONFIGURATION -bootnode: /dnsaddr/mainnet.ethswarm.org +Check the logs from the previous step. Look for the line which says: -# BEE MODE: FULL NODE CONFIGURATION -full-node: true -swap-enable: true -blockchain-rpc-endpoint: https://xdai.fairdatasociety.org ``` +"time"="2024-09-24 18:15:34.520716" "level"="info" "logger"="node" "msg"="using ethereum address" "address"="0x1A801dd3ec955E905ca424a85C3423599bfb0E66" +``` +That address is your node's address on Gnosis Chain which needs to be funded with xDAI and xBZZ. Copy it and save it for the next step. - - - - -#### Light node sample configuration - -```yml -# GENERAL BEE CONFIGURATION -api-addr: :1633 -p2p-addr: :1634 -password: aaa4eabb0813df71afa45d -data-dir: /home/bee/.bee -cors-allowed-origins: ["*"] - -# DEBUG CONFIGURATION -verbosity: 5 +xDAI is widely available from many different centralized and decentralized exchanges, just make sure that you are getting xDAI on Gnosis Chain, and not DAI on some other chain. See [this page](https://www.ethswarm.org/get-bzz) for a list of resources for getting xBZZ (again, make certain that you are getting the Gnosis Chain version, and not BZZ on Ethereum). -# BEE MAINNET CONFIGURATION -bootnode: /dnsaddr/mainnet.ethswarm.org +After acquiring some xDAI and some xBZZ, send them to the address you copied above. -# BEE MODE: LIGHT CONFIGURATION -full-node: false -swap-enable: true -blockchain-rpc-endpoint: https://xdai.fairdatasociety.org -``` +***How Much to Send?*** - - - +Only a very small amount of xDAI is needed to get started, 0.1 is more than enough. -#### Ultra light node sample configuration - -```yml -# GENERAL BEE CONFIGURATION -api-addr: :1633 -p2p-addr: :1634 -password: aaa4eabb0813df71afa45d -data-dir: /home/bee/.bee -cors-allowed-origins: ["*"] - -# DEBUG CONFIGURATION -verbosity: 5 - -# BEE MAINNET CONFIGURATION -bootnode: /dnsaddr/mainnet.ethswarm.org -blockchain-rpc-endpoint: https://xdai.fairdatasociety.org - -# BEE MODE: ULTRA LIGHT CONFIGURATION -swap-enable: false -full-node: false -``` - - +You can start with just 2 or 3 xBZZ for uploading small amounts of data, but you will need at least 10 xBZZ if you plan on staking. - +### Initialize full node -Copy the Docker configuration for the node type you choose and save it into a YAML configuration file: +After you have a small amount of xDAI in your node's Gnosis Chain address, you can now restart your node using the same command as before so that it can issue the required smart contract transactions and also sync data. ```bash -sudo vi ./node_01/bee.yml +docker start bee-1 ``` -And print out the configuration to make sure it was properly saved: +Let's check the logs to see what's happening: ```bash -cat ./node_01/bee.yml +docker logs -f bee-1 ``` -### Step 5: Docker Compose configuration - -You can use the same Docker Compose configuration for all the node types. - -:::info -Note that we have specified the exact version number of the image using the 2.3.0 tag. It's recommended to always specify the exact version number you need using the version tag. You can find all available tags for Bee on [Docker Hub](https://hub.docker.com/r/ethersphere/bee/tags). -::: - -```yml -services: - bee_01: - container_name: bee-node_01 - image: ethersphere/bee:2.3.0 - command: start --config /home/bee/bee.yml - volumes: - - ./node_01/.bee:/home/bee/.bee - - ./node_01/bee.yml:/home/bee/bee.yml - ports: - - 127.0.0.1:1633:1633 # bee api port - - 1634:1634 # p2p port -``` - -:::warning -Note that we are mapping to 127.0.0.1 (localhost), since we do not want to expose our Bee API endpoint to the public internet, as that would allow anyone to control our node. Make sure you do the same, or use a firewall to protect access to your node(s). -::: - -Copy the configuration and save it in a YAML file like we did in the previous step. Make sure that you are saving it to the root directory. +Your logs should look something like this: ```bash -sudo vi ./docker-compose.yml -``` - -And print out the contents of the file to make sure it was saved properly: +Welcome to Swarm.... Bzzz Bzzzz Bzzzz + \ / + \ o ^ o / + \ ( ) / + ____________(%%%%%%%)____________ + ( / / )%%%%%%%( \ \ ) + (___/___/__/ \__\___\___) + ( / /(%%%%%%%)\ \ ) + (__/___/ (%%%%%%%) \___\__) + /( )\ + / (%%%%%) \ + (%%%) + ! + +DISCLAIMER: +This software is provided to you "as is", use at your own risk and without warranties of any kind. +It is your responsibility to read and understand how Swarm works and the implications of running this software. +The usage of Bee involves various risks, including, but not limited to: +damage to hardware or loss of funds associated with the Ethereum account connected to your node. +No developers or entity involved will be liable for any claims and damages associated with your use, +inability to use, or your interaction with other nodes or the software. + +version: 2.2.0-06a0aca7 - planned to be supported until 11 December 2024, please follow https://ethswarm.org/ + +"time"="2024-09-24 22:21:04.543661" "level"="info" "logger"="node" "msg"="bee version" "version"="2.2.0-06a0aca7" +"time"="2024-09-24 22:21:04.590823" "level"="info" "logger"="node" "msg"="swarm public key" "public_key"="02f0e59eafa3c5c06542c0a7a7fe9579c55a163cf1d28d9f6945a34469f88d1b2a" +"time"="2024-09-24 22:21:04.686430" "level"="info" "logger"="node" "msg"="pss public key" "public_key"="02ea739530bbf48eed49197f21660f3b6564709b95bf558dc3b472688c34096418" +"time"="2024-09-24 22:21:04.686464" "level"="info" "logger"="node" "msg"="using ethereum address" "address"="0x8288F1c8e3dE7c3bf42Ae67fa840EC61481D085e" +"time"="2024-09-24 22:21:04.700711" "level"="info" "logger"="node" "msg"="using overlay address" "address"="22dc155fe072e131449ec7ea2f77de16f4735f06257ebaa5daf2fdcf14267fd9" +"time"="2024-09-24 22:21:04.700741" "level"="info" "logger"="node" "msg"="starting with an enabled chain backend" +"time"="2024-09-24 22:21:05.298019" "level"="info" "logger"="node" "msg"="connected to blockchain backend" "version"="Nethermind/v1.28.0+9c4816c2/linux-x64/dotnet8.0.8" +"time"="2024-09-24 22:21:05.485287" "level"="info" "logger"="node" "msg"="using chain with network network" "chain_id"=100 "network_id"=1 +"time"="2024-09-24 22:21:05.498845" "level"="info" "logger"="node" "msg"="starting debug & api server" "address"="[::]:1633" +"time"="2024-09-24 22:21:05.871498" "level"="info" "logger"="node" "msg"="using default factory address" "chain_id"=100 "factory_address"="0xC2d5A532cf69AA9A1378737D8ccDEF884B6E7420" +"time"="2024-09-24 22:21:06.059179" "level"="info" "logger"="node/chequebook" "msg"="no chequebook found, deploying new one." +"time"="2024-09-24 22:21:07.386747" "level"="info" "logger"="node/chequebook" "msg"="deploying new chequebook" "tx"="0x375ca5a5e0510f8ab307e783cf316dc6bf698c15902a080ade3c1ea0c6059510" +"time"="2024-09-24 22:21:19.101428" "level"="info" "logger"="node/transaction" "msg"="pending transaction confirmed" "sender_address"="0x8288F1c8e3dE7c3bf42Ae67fa840EC61481D085e" "tx"="0x375ca5a5e0510f8ab307e783cf316dc6bf698c15902a080ade3c1ea0c6059510" +"time"="2024-09-24 22:21:19.101450" "level"="info" "logger"="node/chequebook" "msg"="chequebook deployed" "chequebook_address"="0x66127e4393956F11947e9f54599787f9E455173d" +"time"="2024-09-24 22:21:19.506515" "level"="info" "logger"="node" "msg"="using datadir" "path"="/home/bee/.bee" +"time"="2024-09-24 22:21:19.518258" "level"="info" "logger"="migration-RefCountSizeInc" "msg"="starting migration of replacing chunkstore items to increase refCnt capacity" +"time"="2024-09-24 22:21:19.518283" "level"="info" "logger"="migration-RefCountSizeInc" "msg"="migration complete" +"time"="2024-09-24 22:21:19.566160" "level"="info" "logger"="node" "msg"="starting reserve repair tool, do not interrupt or kill the process..." +"time"="2024-09-24 22:21:19.566232" "level"="info" "logger"="node" "msg"="removed all bin index entries" +"time"="2024-09-24 22:21:19.566239" "level"="info" "logger"="node" "msg"="removed all chunk bin items" "total_entries"=0 +"time"="2024-09-24 22:21:19.566243" "level"="info" "logger"="node" "msg"="counted all batch radius entries" "total_entries"=0 +"time"="2024-09-24 22:21:19.566247" "level"="info" "logger"="node" "msg"="parallel workers" "count"=20 +"time"="2024-09-24 22:21:19.566271" "level"="info" "logger"="node" "msg"="migrated all chunk entries" "new_size"=0 "missing_chunks"=0 "invalid_sharky_chunks"=0 +"time"="2024-09-24 22:21:19.566294" "level"="info" "logger"="migration-step-04" "msg"="starting sharky recovery" +"time"="2024-09-24 22:21:19.664643" "level"="info" "logger"="migration-step-04" "msg"="finished sharky recovery" +"time"="2024-09-24 22:21:19.664728" "level"="info" "logger"="migration-step-05" "msg"="start removing upload items" +"time"="2024-09-24 22:21:19.664771" "level"="info" "logger"="migration-step-05" "msg"="finished removing upload items" +"time"="2024-09-24 22:21:19.664786" "level"="info" "logger"="migration-step-06" "msg"="start adding stampHash to BatchRadiusItems, ChunkBinItems and StampIndexItems" +"time"="2024-09-24 22:21:19.664837" "level"="info" "logger"="migration-step-06" "msg"="finished migrating items" "seen"=0 "migrated"=0 +"time"="2024-09-24 22:21:19.664897" "level"="info" "logger"="node" "msg"="waiting to sync postage contract data, this may take a while... more info available in Debug loglevel" +``` + +Your node will take some time to finish [syncing postage contract data](https://docs.ethswarm.org/docs/develop/access-the-swarm/buy-a-stamp-batch/) as indicated by the final line: ```bash -cat ./docker-compose.yml +"msg"="waiting to sync postage contract data, this may take a while... more info available in Debug loglevel" ``` -Now check that you have everything set up properly: +You may need to wait 5 - 10 minutes for your node to finish syncing in this step. -```bash -tree -a . -``` - -Your folder structure should look like this: +Eventually you will be able to see when your node finishes syncing, and the logs will indicate your node is starting in full node mode: ```bash -. -├── docker-compose.yml -└── node_01 - ├── .bee - └── bee.yml -``` - -### Step 6: Run bee node with docker compose: - -``` -docker compose up -d +"time"="2024-09-24 22:30:19.154067" "level"="info" "logger"="node" "msg"="starting in full mode" +"time"="2024-09-24 22:30:19.155320" "level"="info" "logger"="node/multiresolver" "msg"="name resolver: no name resolution service provided" +"time"="2024-09-24 22:30:19.341032" "level"="info" "logger"="node/storageincentives" "msg"="entered new phase" "phase"="reveal" "round"=237974 "block"=36172090 +"time"="2024-09-24 22:30:33.610825" "level"="info" "logger"="node/kademlia" "msg"="disconnected peer" "peer_address"="6ceb30c7afc11716f866d19b7eeda9836757031ed056b61961e949f6e705b49e" ``` -The node is started in detached mode by using the `-d` flag so that it will run in the background. - -Check that node is running: +Your node will now begin syncing chunks from the network, this process can take several hours. You check your node's progress with the `/status` endpoint: ```bash -docker ps +curl -s http://localhost:1633/status | jq ``` -If we did everything properly we should see our node listed here: +```bash +{ + "overlay": "22dc155fe072e131449ec7ea2f77de16f4735f06257ebaa5daf2fdcf14267fd9", + "proximity": 256, + "beeMode": "full", + "reserveSize": 686217, + "reserveSizeWithinRadius": 321888, + "pullsyncRate": 497.8747754074074, + "storageRadius": 11, + "connectedPeers": 148, + "neighborhoodSize": 4, + "batchCommitment": 74510761984, + "isReachable": false, + "lastSyncedBlock": 36172390 +} +``` +We can see that our node has not yet finished syncing chunks since the `pullsyncRate` is around 497 chunks per second. Once the node is fully synced, this value will go to zero. It can take several hours for syncing to complete, but we do not need to wait until our node is full synced before staking, so we can move directly to the next step. + +### Stake node + +You can use the following command to stake 10 xBZZ: ```bash -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS - NAMES -e53aaa4e76ec ethersphere/bee:2.3.0 "bee start --config …" 17 seconds ago Up 16 seconds 127.0.0.1:1636->1633/tcp, 0.0.0.0:1637->1634/tcp, :::1637->1634/tcp, bee-node_01 +curl -XPOST localhost:1633/stake/100000000000000000 ``` -Now let's check our logs: +If the staking transaction is successful a `txHash` will be returned: -```bash -docker logs -f bee-node_01 +``` +{"txHash":"0x258d64720fe7abade794f14ef3261534ff823ef3e2e0011c431c31aea75c2dd5"} ``` -If everything went smoothly, we should see the logs from our Bee node. Unless you are running a node in ultra light mode, you should see a warning message in your logs which looks like this at the bottom of the logs: +We can also confirm that our node has been staked with the `/stake` endpoint: ```bash -"time"="2024-07-15 12:23:57.906429" "level"="warning" "logger"="node/chequebook" "msg"="cannot continue until there is at least min xDAI (for Gas) available on address" "min_amount"="0.0005750003895" "address"="0xf50Bae90a99cfD15Db5809720AC1390d09a25d60" +curl localhost:1633/stake ``` -This is because in order for a light or full node to operate, your node is required to set up a chequebook contract on Gnosis Chain, which requires xDAI in order to pay for transaction fees. Find the `address` value and copy it for the next step: - -### Step 7: xDAI funding (full and light nodes only) - -You can fund your node by transferring xDAI and xBZZ to the address you copied from the logs in the previous step. - -To obtain xDAI and fund your node, you can [follow the instructions](/docs/bee/installation/install#4-fund-node) from the main install section. - -You can also try the [node-funder](https://github.com/ethersphere/node-funder) tool, which is especially helpful when you are running multiple nodes, as is described in the next section. - -### Step 8: Add stake - -To add stake, make a POST request to the `/stake` endpoint and input the amount you wish to stake in PLUR as a parameter after `/stake`. In the example below we have input a PLUR value equal to 10 xBZZ. - -:::info -The Bee API will not be available while your node is warming up, so wait until your node is fully initialized before staking. -::: +The results will be displayed in PLUR units (1 PLUR is equal to 1e-16 xBZZ). If you have properly staked the minimum 10 xBZZ, you should see the output below: ```bash -curl -X POST localhost:1633/stake/100000000000000000 +{"stakedAmount":"100000000000000000"} ``` -Note that since we have mapped our host and container to the same port, we can use the default `1633` port to make our request. If you are running multiple Bees, make sure to update this command for other nodes which will be mapped to different ports on the host machine. - -## Running a Hive - -In order to run multiple Bee nodes as a "hive", all we need to do is repeat the process for running one node and then extend our Docker Compose configuration. - -To start with, shut down your node from the first part of this guide if it is still running: +Congratulations! You have now installed your Bee node and are connected to the network as a full staking node. Your node will now be in the process of syncing chunks from the network. Once it is fully synced, your node will finally be eligible for earning staking rewards. -```shell -docker compose down -``` +### Set Target Neighborhood -### Step 1: Create new directories for additional node(s) +When installing your Bee node it will automatically be assigned a neighborhood. However, when running a full node with staking there are benefits to periodically updating your node's neighborhood. Learn more about why and how to set your node's target neighborhood [here](/docs/bee/installation/set-target-neighborhood). -Now create a new directory for your second node: +### Logs and monitoring +Docker provides convenient built-in tools for logging and monitoring your node, which you've already encountered if you've read through earlier sections of this guide. For a more detailed guide, [refer to the section on logging](/docs/bee/working-with-bee/logs-and-files). -```shell -mkdir node_02 -``` +**Viewing node logs:** -We also create a new data directory and set ownership to match the user in the official [Bee Dockerfile](https://github.com/ethersphere/bee/blob/master/Dockerfile). +To monitor your node’s logs in real-time, use the following command: -```shell -mkdir node_02/.bee -sudo chown -R 999:999 node_02/.bee +```bash +docker logs -f bee-1 ``` -Repeat this process for however many new nodes you want to add. - -### Step 2: Create new configuration file(s) - -And add a `bee.yml` configuration file. You can use the same configuration as for your first node. Here we will use the configuration for a full node: - -```yaml -# GENERAL BEE CONFIGURATION -api-addr: :1633 -p2p-addr: :1634 -password: aaa4eabb0813df71afa45d -data-dir: /home/bee/.bee -cors-allowed-origins: ["*"] +This command will continuously output the logs of your Bee node, helping you track its operations. The `-f` flag ensures that you see new log entries as they are written. Press `Ctrl + C` to stop following the logs. -# DEBUG CONFIGURATION -verbosity: 5 +You can read more about how Docker manages container logs [in their official docs](https://docs.docker.com/reference/cli/docker/container/logs/). -# BEE MAINNET CONFIGURATION -bootnode: /dnsaddr/mainnet.ethswarm.org +**Checking the Node's status with the Bee API** -# BEE MODE: FULL NODE CONFIGURATION -full-node: true -swap-enable: true -blockchain-rpc-endpoint: https://xdai.fairdatasociety.org -``` +To check your node's status as a staking node, we can use the `/redistributionstate` endpoint: ```bash -sudo vi ./node_02/bee.yml +curl -s http://localhost:1633/redistributionstate | jq ``` -After saving the configuration, print out the configuration to make sure it was properly saved: +Below is the output for a node which has been running for several days: ```bash -cat ./node_02/bee.yml -``` - -Repeat this step for any other additional node directories you created in the previous step. - -### Step 3: Modify Docker Compose configuration - -Here is the Docker compose configuration for running a hive of two Bee nodes: - -```yaml -services: - bee_01: - container_name: bee-node_01 - image: ethersphere/bee:2.3.0 - command: start --config /home/bee/bee.yml - volumes: - - ./node_01/.bee:/home/bee/.bee - - ./node_01/bee.yml:/home/bee/bee.yml - ports: - - 127.0.0.1:1633:1633 # bee api port - - 1634:1634 # p2p port - bee_02: - container_name: bee-node_02 - image: ethersphere/bee:2.3.0 - command: start --config /home/bee/bee.yml - volumes: - - ./node_02/.bee:/home/bee/.bee - - ./node_02/bee.yml:/home/bee/bee.yml - ports: - - 127.0.0.1:1636:1633 # bee api port - - 1637:1634 # p2p port +{ + "minimumGasFunds": "11080889201250000", + "hasSufficientFunds": true, + "isFrozen": false, + "isFullySynced": true, + "phase": "claim", + "round": 212859, + "lastWonRound": 207391, + "lastPlayedRound": 210941, + "lastFrozenRound": 210942, + "lastSelectedRound": 212553, + "lastSampleDuration": 491687776653, + "block": 32354719, + "reward": "1804537795127017472", + "fees": "592679945236926714", + "isHealthy": true +} ``` -Here is a list of the changes we made to extend our setup: - - 1. Created an additional named service with a new unique name (bee_02). - 1. Created a unique name for each `container_name` value (bee-node_01 --> bee-node_02). - 1. Made sure that `volumes` has the correct directory for each node (./node_01/ --> ./node_02/). - 1. Updated the `ports` we map to so that each node has its own set of ports (ie, for node_02, we map 127.0.0.1:1636 to 1633 because node_01 is already using 127.0.0.1:1633, and do the same with the rest of the ports). +For a complete breakdown of this output, check out [this section in the Bee docs](https://docs.ethswarm.org/docs/bee/working-with-bee/bee-api#redistributionstate). -### Step 4: Start up the hive - -Start up the hive: - -```shell -docker compose up -d -``` +You can read more other important endpoints for monitoring your Bee node in the [official Bee docs](https://docs.ethswarm.org/docs/bee/working-with-bee/bee-api), and you can find complete information about all available endpoints in [the API reference docs](https://docs.ethswarm.org/api/). -After starting up the hive, check that both nodes are running: -```shell -docker ps -``` - -```shell -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS - NAMES -a62ec5143d30 ethersphere/bee:2.3.0 "bee start --config …" 2 seconds ago Up 1 second 127.0.0.1:1636->1633/tcp, 0.0.0.0:1637->1634/tcp, :::1637->1634/tcp, bee-node_02 -a3496b9bb2c8 ethersphere/bee:2.3.0 "bee start --config …" 2 seconds ago Up 1 second 127.0.0.1:1633->1633/tcp, 0.0.0.0:1634->1634/tcp, :::1634->1634/tcp bee-node_01 -``` +**Stopping Your Node** -And we can also check the logs for each node: +To gracefully stop your Bee node, use the following command: -```shell -docker logs -f bee-node_01 -``` - -Copy the address from the logs: - -```shell -"time"="2024-07-23 11:54:08.657999" "level"="warning" "logger"="node/chequebook" "msg"="cannot continue until there is at least min xDAI (for Gas) available on address" "min_xdai_amount"="0.000500000002" "address"="0x0E386401AFA8A9e23c6FFD81C7078505a36dB435" +```bash +docker stop bee-1 ``` -```shell -docker logs -f bee-node_02 -``` -And copy the second address: -```shell -"time"="2024-07-23 11:54:08.532812" "level"="warning" "logger"="node/chequebook" "msg"="cannot continue until there is at least min xDAI (for Gas) available on address" "min_xdai_amount"="0.000500000002" "address"="0xa4DBEa11CE6D089455d1397c0eC3D705f830De69" -``` +Replace `bee-1` with the name of your node if you've given it a different name. -### Step 5: Fund nodes -You can fund your nodes by sending xDAI and xBZZ the addresses you collected from the previous step. -To obtain xDAI and fund your node, you can [follow the instructions](/docs/bee/installation/install#4-fund-node) from the main install section. -Since you're running a hive, the [node-funder](https://github.com/ethersphere/node-funder) tool is recommended, as it will allow you to rapidly fund and stake multiple nodes. +## Back Up Keys -If you plan on staking, you will also want to [get some xBZZ](https://www.ethswarm.org/get-bzz) to stake. You will need 10 xBZZ for each node. +Once your node is up and running, make sure to [back up your keys](/docs/bee/working-with-bee/backups). +## Getting help -### Step 6: Add stake +The CLI has documentation built-in. Running `bee` gives you an entry point to the documentation. Running `bee start -h` from within your Docker container or `bee start --help` will tell you how you can configure your Bee node via the command line arguments. -:::info -The Bee API will not be available while your nodes are warming up, so wait until your nodes are fully initialized before staking. -::: +You may also check out the [configuration guide](/docs/bee/working-with-bee/configuration), or simply run your Bee terminal command with the `--help` flag, eg. `bee start --help` or `bee --help`. -In order to stake you simply need to call the `/stake` endpoint with an amount of stake in PLUR as a parameter for each node. +## Next Steps to Consider -For bee-node_01: -```bash -curl -X POST localhost:1633/stake/100000000000000000 -``` +### Access the Swarm +If you'd like to start uploading or downloading files to Swarm, [start here](/docs/develop/access-the-swarm/introduction). -And for bee-node_02, note that we updated the port to match the one for the Bee API address we mapped to in the Docker Compose file: +### Explore the API +The [Bee API](/docs/bee/working-with-bee/bee-api) is the primary method for interacting with Bee and getting information about Bee. After installing Bee and getting it up and running, it's a good idea to start getting familiar with the API. -```bash -curl -X POST localhost:1636/stake/100000000000000000 -``` +### Run a hive! +If you would like to run a hive of many Bees, check out the [hive operators](/docs/bee/installation/hive) section for information on how to operate and monitor many Bees at once. -You may also wish to make use of the [node-funder](https://github.com/ethersphere/node-funder) tool, which in addition to allowing you to fund multiple addresses at once, also allows you to stake multiple addresses at once. \ No newline at end of file +### Start building DAPPs on Swarm +If you would like to start building decentralised applications on Swarm, check out our section for [developing with Bee](/docs/develop/introduction). diff --git a/docs/bee/installation/fund-your-node.md b/docs/bee/installation/fund-your-node.md index 094c8b491..7d3630c82 100644 --- a/docs/bee/installation/fund-your-node.md +++ b/docs/bee/installation/fund-your-node.md @@ -3,21 +3,20 @@ title: Fund Your Node id: fund-your-node --- -In order to start your Bee node on the _mainnet_, its Ethereum wallet must be +In order to start your Bee node on the _mainnet_, its Gnosis Chain wallet must be funded with: - 1 [xBZZ](/docs/references/glossary#xbzz-token), for traffic accounting (this is optional, [see below](#basic-deployment)) -- some [xDAI](/docs/references/glossary#xdai-token), to pay the gas fees of - a couple of transactions on the [Gnosis - Chain](/docs/references/glossary#gnosis-chain). +- Some [xDAI](/docs/references/glossary#xdai-token), to pay the gas fees of + a couple of transactions on the [Gnosis Chain](/docs/references/glossary#gnosis-chain). Take note that xBZZ is the [bridged](/docs/references/glossary#bridged-tokens) version of BZZ from Ethereum to the Gnosis Chain. -### A node's wallet +### A Node's Wallet -When your Bee node is installed, an Ethereum wallet is also created. This wallet +When your Bee node is installed, a Gnosis Chain wallet is also created. This wallet is used by Bee to interact with the blockchain (e.g. for sending and receiving cheques, or for making purchases of postage stamps, etc.). @@ -27,60 +26,66 @@ When your node has downloaded enough content to exceed the free tier threshold, then _cheques_ are sent to peers to provide payment in return for their services. -In order to send these cheques, a _chequebook_ must be deployed on the +In order to send these cheques, a [_chequebook_](/docs/concepts/incentives/bandwidth-incentives#chequebook-contract) must be deployed on the blockchain for your node, and for full speed operation it can be funded with BZZ. This deployment happens when a node initialises for the first time. Your Bee node will warn you in its log if there aren't enough funds in its wallet for deploying the chequebook. You can [configure](/docs/bee/working-with-bee/configuration) the amount of xBZZ to -be sent from the node's wallet. It is 1 xBZZ by default, but it can be set to -zero. +be sent from the node's wallet using the `swap-initial-deposit` option. It is 0 xBZZ by default, but it is recommended to deposit more xBZZ it you intend to download / upload any significant amount of data, as your node will exceed its free bandwidth threshold otherwise. -## Joining the swarm (mainnet) +## Joining the Swarm (mainnet) -### Basic deployment +### Basic Deployment If you want to get your Bee node up and running as easily as possible, then you -can set its -[`--swap-initial-deposit`](/docs/bee/working-with-bee/configuration) +can set its [`swap-initial-deposit`](/docs/bee/working-with-bee/configuration) value to zero. This means that your node's chequebook will not get funded with xBZZ, meaning that other nodes will only serve it within the free tier bandwidth threshold. Since gas fees on the [Gnosis Chain](https://www.gnosis.io/) are very low, you won't need much xDAI either to get started. You may acquire a small amount -for free by using the official Gnosis Chain xDAI faucet [xDAI Faucet](https://gnosisfaucet.com/). The required amount is a function of the current transaction fee on chain, but 0.01 xDAI should be -more than enough to start up your node. +for free by using the official Gnosis Chain xDAI faucet [xDAI Faucet](https://gnosisfaucet.com/). The required amount is a function of the current transaction fee on chain, but 0.01 xDAI should be more than enough to start up your node. You can use the [Blockscout](https://blockscout.com/xdai/mainnet/) block explorer to inspect what's going on with your wallet by searching for its -Ethereum address. +Gnosis Chain address. -### Full performance node +### Full node If you want to run a full node, or upload a lot of content, then you may need more xDAI for gas. To acquire this, you may convert DAI on the main Ethereum -network to xDAI using the -[Gnosis Chain bridge](https://bridge.gnosischain.com/), -or buy xDAI -[directly using fiat](https://buyxdai.com/). +network to xDAI using the [Gnosis Chain bridge](https://bridge.gnosischain.com/), +or buy xDAI [directly using fiat](https://buyxdai.com/). -You will also need to fund your node with more xBZZ for full speed access, or to -purchase postage stamps to upload content. To bridge BZZ from the Ethereum -mainet to the [Gnosis Chain](https://www.gnosis.io/), you may use the [Gnosis Chain Bridge](https://bridge.gnosischain.com/). +To find out what your node's Gnosis Chain address is, you can use the `/addresses` endpoint (the [jq](https://jqlang.github.io/jq/) part of the command is and optional but recommended tool to make it easier to read json output): -To find out what your node's Ethereum address is, please consult your relevant -installation guide or check your logs! +```bash +curl -s localhost:1633/addresses | jq +``` + +```json +{ + "overlay": "46275b02b644a81c8776e2459531be2b2f34a94d47947feb03bc1e209678176c", + "underlay": [ + "/ip4/127.0.0.1/tcp/7072/p2p/16Uiu2HAmTbaZndBa43PdBHEekjQQEdHqcyPgPc3oQwLoB2hRf1jq", + "/ip4/192.168.0.10/tcp/7072/p2p/16Uiu2HAmTbaZndBa43PdBHEekjQQEdHqcyPgPc3oQwLoB2hRf1jq", + "/ip6/::1/tcp/7072/p2p/16Uiu2HAmTbaZndBa43PdBHEekjQQEdHqcyPgPc3oQwLoB2hRf1jq" + ], + "ethereum": "0x0b546f2817d0d889bd70e244c1227f331f2edf74", + "public_key": "03660e8dbcf3fda791e8e2e50bce658a96d766e68eb6caa00ce2bb87c1937f02a5" +} +``` + +The value in the `ethereum` field is your Gnosis Chain address (the `ethereum` keyname is used as Gnosis Chain is an Ethereum sidechain and shares the same address format). # Configure Your Wallet App To interact with the BZZ ecosystem, you will need to make a couple of small configuration additions to your wallet software. In the case of e.g. MetaMask, -you'll need to -[add the Gnosis Chain network](https://docs.gnosischain.com/tools/wallets/metamask/), -and then -[add a custom token](https://metamask.zendesk.com/hc/en-us/articles/360015489031-How-to-add-unlisted-tokens-custom-tokens-in-MetaMask). +you'll need to [add the Gnosis Chain network](https://docs.gnosischain.com/tools/wallets/metamask/), and then [add a custom token](https://support.metamask.io/manage-crypto/portfolio/how-to-import-a-token-in-metamask-portfolio/). The canonical addresses for the BZZ token on the various blockchains are as follows: diff --git a/docs/bee/installation/quick-start.md b/docs/bee/installation/getting-started.md similarity index 65% rename from docs/bee/installation/quick-start.md rename to docs/bee/installation/getting-started.md index d62c0f47c..f190206ff 100644 --- a/docs/bee/installation/quick-start.md +++ b/docs/bee/installation/getting-started.md @@ -1,13 +1,20 @@ --- title: Getting Started -id: quick-start +id: getting-started --- -To get started working with Swarm, first you need to learn about the different types of Bee nodes, the requirements for running each type, and then choose which type is right for you. + +In this guide we cover the basic background information you need to know to get started running a Bee node: + +#### [A list of Bee node types and their various features.](/docs/bee/installation/getting-started#node-types) +#### [General requirements for running Bee nodes.](/docs/bee/installation/getting-started#general-node-requirements) +#### [Specific requirements base on node type.](/docs/bee/installation/getting-started#node-requirements-by-node-type) +#### [How to choose the right node type.](/docs/bee/installation/getting-started#choosing-node-type-based-on-use-case) +#### [How to choose the appropriate installation method.](/docs/bee/installation/getting-started#choosing-installation-method) ## Node Types -Bee is a versatile piece of software that caters to a diverse array of use cases. It can be run in several different modes which each offer different features which are best suited for different users. There are three main categories of nodes: full nodes, light nodes, and ultra-light nodes. +Bee is a versatile piece of software that caters to a diverse array of use cases. It can be run in several different modes which each offer different features which are best suited for different users. There are three main categories of nodes: full nodes, light nodes, and ultra-light nodes. Node type is set by modifying the appropriate configuration options during the setup process. For the details of how to configure each node type, refer to the [node installation guides](/docs/bee/installation/getting-started#choosing-installation-method). ### Ultra-Light Node @@ -21,7 +28,7 @@ A light node can both download and upload data over the Swarm network. Light nod A full node can upload and download data over the Swarm network. Additionally, a full node can also share its disk space with the Swarm network where it will be employed by Swarm uploaders. Full nodes can earn storage incentives for sharing their disk space with the network, and can also earn bandwidth incentives just as light nodes can. -## Features Comparison Chart +### Features Comparison Chart | Feature | Full Node | Light Node |Ultra-Light Node| |--------------|-----------|------------|------------| @@ -48,28 +55,62 @@ By participating in the storage incentives protocol, full nodes which store data Bandwidth incentives (also referred to as the SWAP protocol) encourage full or light (but not ultra-light) nodes to share bandwidth with other nodes in exchange for payments from other nodes either [in-kind](https://www.investopedia.com/terms/p/paymentinkind.asp) or as a cheque to be settled at a future date. SWAP requires a chequebook contract to be set up on Gnosis Chain for each participating node. ::: -## Node Requirements by Type -:::info -A note on RPC endpoints: +## General Node Requirements + +### Software + +* [jq utility](https://jqlang.github.io/jq/) for formatting JSON API output (optional) -Light and full Bee nodes require an RPC endpoint. An RPC endpoint is a "remote procedure call" endpoint that for blockchains like Ethereum or Gnosis Chain typically takes the form of an http or Websocket (wss) address. You will be able to use your own RPC endpoint if you are running your own Gnosis Chain node, however for many node operators it may be more convenient to use a third party provider such as [Infura](https://www.infura.io/). +:::info +The [`jq` utility](https://jqlang.github.io/jq/) is widely used throughout the documentation to automatically format the output from calls to the Bee API. It can help make API output much more readable, however its usage is optional. ::: +### Tokens + +* A small amount of xDAI to pay for Gnosis Chain transactions, 0.1 xDAI should be enough +* 10 xBZZ (BZZ on Gnosis Chain) is required for staking +* A small amount of xBZZ for downloading and uploading from Swarm. You can start with 1 xBZZ and add more according to your usage needs. + +### Network Considerations + +#### RPC Endpoints + +Both full and light nodes require a Gnosis Chain RPC endpoint which can be obtained either by running your own node or from an RPC endpoint 3rd party provider such as [Infura](https://www.infura.io). You can also find some free RPC endpoints such as [this one](https://xdai.fairdatasociety.org) offered by the Fair Data Society, or from one of the other free options available at the [Gnosis Chain docs](https://docs.gnosischain.com/tools/RPC%20Providers/). + + +#### NAT and Port Forwarding + +If you are running on a home network you may need to configure your router to use [port forwarding](https://www.noip.com/support/knowledgebase/general-port-forwarding-guide) or take other steps to ensure your node is reachable by other nodes on the network. See [here](https://docs.ethswarm.org/docs/bee/installation/connectivity/#navigating-through-the-nat) for more guidance. If you are running on a VPS or cloud based server you will likely have no issues. + +## Node Requirements By Node Type + ### Ultra-Light Node +An ultra-light node has very minimal hardware requirements and can operate on practically any modern computer or VPS, including devices with baseline specs. It can even run on single-board computers like Raspberry Pi. -A light node has very minimal requirements, it will run on essentially any modern hardware or VPS with baseline specs. It can even run even on small single-board computers like Raspberry Pi's. +**Average Specs for Ultra-Light Node:** +- **Processor**: Single-core or dual-core processor, 1 GHz or higher (e.g., Intel Atom, ARM Cortex-A series). +- **RAM**: 1 GB or higher. +- **Storage**: 8 GB HDD or SSD. +- **Internet Connection**: A stable internet connection with at least 1 Mbps download/upload speed. -Your upload and download speeds will be limited by your internet connection speed of course, and exceedingly low RAM or processing power may also slow down your node - however this should not be an issue for practically any modern hardware. +No RPC endpoint is required for ultra-light nodes. -An RPC endpoint is not required. ### Light Node +A light node has slightly higher requirements than an ultra-light node due to the ability to upload and download data over the network. It consumes more bandwidth and requires a Gnosis Chain RPC endpoint for purchasing stamps and participating in bandwidth incentives. -A light node's requirements will be similar to that of an ultra-light node, however since it can be used for uploading as well as downloading and in typical use cases will be consuming greater bandwidth, internet connections speeds will be a greater consideration. If you intend to use your light node for large amounts of uploads and downloads, you should make sure your internet connection is sufficiently fast and stable. Again, as with an ultra-light node, any modern commercially available hardware should be sufficient. +**Average Specs for Light Node:** +- **Processor**: Dual-core processor, 1.5 GHz or higher (e.g., Intel Celeron, AMD Athlon, or similar). +- **RAM**: 2 GB or higher. +- **Storage**: 16 GB SSD or HDD. +- **Internet Connection**: A stable internet connection with at least 5 Mbps download/upload speed. -A light node also has the additional requirement of an RPC endpoint so that it can purchase stamps to pay for uploads and so that it can participate in bandwidth incentives to earn xBZZ for data it forwards. +These specs are achievable with most commercially available laptops, desktops, or low-cost servers. For users planning to handle high amounts of data transfers, faster internet connections and slightly more RAM (e.g., 4 GB) are recommended for optimal performance. + + +These recommendations reflect the typical capabilities of affordable, readily available hardware suitable for running light and ultra-light nodes without significant bottlenecks. ### Full Node @@ -91,8 +132,13 @@ Note that there are additional hardware requirements if you choose to [run your Staking is not required to run a full node, but is necessary to earn storage incentives. An altruistic person may want to run a full node without putting up any stake, and in fact, could possibly earn enough xBZZ from bandwidth (swap/cheque) compensation to be able to stake at some point in the future. Learn more in the [staking section](/docs/bee/working-with-bee/staking) ::: +:::caution +While it is possible to run multiple Bee nodes on a single machine, due to the high rate of I/O operations required by a full Bee node in operation, it is not recommended to run more than a handful of Bee nodes on the same physical disk (depending on the disk speed). +::: + + +## Choosing Node Type Based on Use Case -## Which type of node is the right choice? Different node types best suit different use cases: ### Basic Interactions with the Swarm network @@ -120,25 +166,25 @@ Since each full Bee node shares up to 2^22 chunks (~16gb of data), and due to th You can interact with the Swarm network by installing the Bee client through a variety of different methods. Below is a (non-exhaustive) list of some of the most common methods for installing a Bee client. -### Swarm Desktop +### [Swarm Desktop](/docs/desktop/introduction) If you are looking to get started with exploring Swarm and interacting with the network in as simple and easy a way as possible, then [Swarm Desktop](/docs/desktop/introduction) is the way to go. Swarm Desktop offers an easy and convenient to use graphical user interface so that users can easily upload and download from the Swarm, host their websites, and access a variety of Swarm DAPPs which come pre-bundled with Swarm Desktop. -### Shell Script Install +### [Shell Script Install](/docs/bee/installation/shell-script-install) If you're ready to go beyond the GUI based Swarm Desktop, then [the shell script install](/docs/bee/installation/shell-script-install) method may be right for you. This method uses a simple shell script to detect your operating system and environment and install the correct version of Bee for your machine. It's a convenient and minimalistic way of getting started with Swarm. Because the shell script install is so minimalistic, it may require some additional tinkering to get it working the way you want it to. For example, it will not come set up to run in the background as a service out of the box, and logs will not be automatically saved. -### Docker Install +### [Docker Install](/docs/bee/installation/docker) While the [Docker based installation](/docs/bee/installation/docker) method requires additional tooling not needed with the shell script install method, it also comes with several advantages which make it easier to operate your node across multiple different types of environments and also makes it easier to spin up multiple nodes at once. Combining it with tools like [Docker Compose](https://docs.docker.com/compose/) can open up even more options. Unlike the shell script install method, Docker already comes with easy to use tools for running your containerized Bee node as a background process and for dealing with logs from your node. -### Package Manager Install +### [Package Manager Install](/docs/bee/installation/package-manager-install) The Bee client can be [installed through a variety of package managers](/docs/bee/installation/package-manager-install) including [APT](https://en.wikipedia.org/wiki/APT_(software)), [RPM](https://en.wikipedia.org/wiki/RPM_Package_Manager), and [Homebrew](https://en.wikipedia.org/wiki/Homebrew_(package_manager)). @@ -146,6 +192,6 @@ In comparison with the shell script install, this installation method comes with One of the disadvantages is that it can be less flexible than either the Docker or shell script install methods. -### Building From Source +### [Building From Source](/docs/bee/installation/build-from-source) For the more advanced of users, you may wish to build from source. You can find instructions for doing so [here](/docs/bee/installation/build-from-source). While this may be the most flexible of all methods, it's also the most difficult and requires the most hands-on setup and so is recommended for more advanced users / use cases. \ No newline at end of file diff --git a/docs/bee/installation/package-manager.md b/docs/bee/installation/package-manager.md index e64b543e4..1db8d6186 100644 --- a/docs/bee/installation/package-manager.md +++ b/docs/bee/installation/package-manager.md @@ -6,65 +6,22 @@ id: package-manager-install import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; - - - - - - - - - - +The Bee client can be [installed through a variety of package managers](/docs/bee/installation/package-manager-install) including [APT](https://en.wikipedia.org/wiki/APT_(software)), [RPM](https://en.wikipedia.org/wiki/RPM_Package_Manager), and [Homebrew](https://en.wikipedia.org/wiki/Homebrew_(package_manager)). - -It is easy to set up a Bee light node on small and inexpensive computers, such as a Raspberry Pi 4, spare hardware you have lying around, or even a cheap cloud hosted VPS (we recommend small, independent providers and colocations). When running a full node however, it's important to meet the minimum required specifications. - -## Recommended Hardware Specifications - -### Full Nodes - -Minimum recommended specifications for each full node: - -- Dual core, recent generation, 2ghz processor -- 8gb RAM -- 30gb SSD -- Stable internet connection - -HDD drives are discouraged for full nodes due to their low speeds. - -Note that there are additional [hardware requirements](https://docs.gnosischain.com/node/#environment-and-hardware) if you choose to run your own Gnosis Chain node in order to provide your Bee node(s) with the required RPC endpoint. See [configuration step](/docs/bee/installation/install#set-blockchain-rpc-endpoint) for more details. - -### Light and UltraLight Nodes - -The minimum required hardware specifications for light and ultralight nodes are very low, and can be run on practically any commercially available computer or microcomputer such as a Raspberry Pi. - -## Note on Startup Methods :::caution - When a node is started using the `bee start` command the node process will be bound to the terminal session and will exit if the terminal is closed. + When installed using a package manager, Bee is set up so it can be started to run as a background service using `systemctl` or `brew services` (depending on the package manager used.) - If Bee was installed using one of the supported package managers it is set up to run as a service in the background with tools such as `systemctl` or `brew services` (which also use the `bee start` command[under the hood](https://github.com/ethersphere/bee/blob/master/packaging/bee.service)). + However, a package manager installed Bee node can also be started using the standard `bee start` command. - Depending on which of these startup methods was used, the default Bee directories will be different. See the [configuration page](/docs/bee/working-with-bee/configuration) for more information about default data and config directories. + When a node is started using the `bee start` command the node process will be bound to the terminal session and will exit if the terminal is closed. + + Depending on which of these startup methods was used, *the default Bee directories will be different*. For each startup method, a different default data directory is used, so each startup method will essentially be spinning up a totally different node. + + See the [configuration page](/docs/bee/working-with-bee/configuration) for more information about default data and config directories. ::: - -## Installation Steps - -1. [Install Bee](/docs/bee/installation/install#1-install-bee) -1. [Configure Bee](/docs/bee/installation/install#2-configure-bee) -1. [Find Bee Address](/docs/bee/installation/install#3-find-bee-address) -1. [Fund node](/docs/bee/installation/install#4-fund-node) (Not required for ultra-light nodes) -1. [Wait for Initialisation](/docs/bee/installation/install#5-wait-for-initialisation) -1. [Check Bee Status](/docs/bee/installation/install#6-check-if-bee-is-working) -1. [Back Up Keys](/docs/bee/installation/install#7-back-up-keys) -1. [Deposit Stake](/docs/bee/installation/install#8-deposit-stake-optional) (Full node only, optional) - - -## 1. Install Bee - -### Package manager install +## Install Bee Bee is available for Linux in .rpm and .deb package format for a variety of system architectures, and is available for MacOS through Homebrew. See the [releases](https://github.com/ethersphere/bee/releases) page of the Bee repo for all available packages. One of the advantages of this method is that it automatically sets up Bee to run as a service as a part of the install process. @@ -157,43 +114,16 @@ After you finish configuration run 'sudo bee-get-addr' and fund your node with X Created symlink /etc/systemd/system/multi-user.target.wants/bee.service → /lib/systemd/system/bee.service. ``` -### Shell script install -The [Bee install shell script](https://github.com/ethersphere/bee/blob/master/install.sh) for Linux automatically detects its execution environment and installs the latest stable version of Bee. +## Configure Bee -:::info -Note that this install method copies precompiled binaries directly to the `/usr/local/bin` directory, so Bee installed through this method cannot be managed or uninstalled with package manager command line tools like `dpkg`, `rpm`, and `brew`. +When Bee is installed using a package manager, a `bee.yaml` file containing the default configuration will be generated. -Also note that unlike the package install method, this install method will not set up Bee to run as a service (such as with `systemctl` or `brew services`). +:::info +While this package manager install guide uses the `bee.yaml` file for setting configuration options, there are [several other available methods for setting node options](/docs/bee/working-with-bee/configuration). ::: -Use either of the following commands to run the script and install Bee: - -#### wget - -```bash -wget -q -O - https://raw.githubusercontent.com/ethersphere/bee/master/install.sh | TAG=v2.3.0 bash -``` - -#### curl - -```bash -curl -s https://raw.githubusercontent.com/ethersphere/bee/master/install.sh | TAG=v2.3.0 bash -``` -### Build from source -If neither of the above methods works for your system, you can see our guide for [building directly from source](/docs/bee/installation/build-from-source). - -## 2. Configure Bee - -Before starting Bee for the first time you will need to make sure it is properly configured. - -See the [configuration](/docs/bee/working-with-bee/configuration) section for more details. - -### Config for the Bee Service - -When installing Bee with a package manager the configuration file for the Bee service will be automatically generated. - -Check that the file was successfully generated and contains the [default configuration](https://github.com/ethersphere/bee/blob/master/packaging) for your system: +After installation, you can check that the file was successfully generated and contains the [default configuration](https://github.com/ethersphere/bee/blob/master/packaging) for your system: -### Config for `bee start` - -When running your node using `bee start` you can set options using either command line flags, environment variables, or a YAML configuration file. See the configuration section for [more information on setting options for running a node with `bee start`](/docs/bee/working-with-bee/configuration). - -No default YAML configuration file is generated to be used with the `bee start` command, so it must be generated and placed in the default config directory if you wish to use it to set your node's options. You can view the default configuration including the default config directory for your system with the `bee printconfig` command. - -```bash -root@user-bee:~# bee printconfig -``` - -Check the configuration printed to your terminal. Note that the values for `config` and `data-dir` will vary slightly depending on your operating system. - -```bash -# allow to advertise private CIDRs to the public network -allow-private-cidrs: false -# HTTP API listen address -api-addr: 127.0.0.1:1633 -# chain block time -block-time: "15" -# rpc blockchain endpoint -blockchain-rpc-endpoint: "" -# initial nodes to connect to -bootnode: [] -# cause the node to always accept incoming connections -bootnode-mode: false -# cache capacity in chunks, multiply by 4096 to get approximate capacity in bytes -cache-capacity: "1000000" -# enable forwarded content caching -cache-retrieval: true -# enable chequebook -chequebook-enable: true -# config file (default is $HOME/.bee.yaml) -config: /root/.bee.yaml -# origins with CORS headers enabled -cors-allowed-origins: [] -# data directory -data-dir: /root/.bee -# size of block cache of the database in bytes -db-block-cache-capacity: "33554432" -# disables db compactions triggered by seeks -db-disable-seeks-compaction: true -# number of open files allowed by database -db-open-files-limit: "200" -# size of the database write buffer in bytes -db-write-buffer-size: "33554432" -# cause the node to start in full mode -full-node: false -# help for printconfig -help: false -# triggers connect to main net bootnodes. -mainnet: true -# NAT exposed address -nat-addr: "" -# suggester for target neighborhood -neighborhood-suggester: https://api.swarmscan.io/v1/network/neighborhoods/suggestion -# ID of the Swarm network -network-id: "1" -# P2P listen address -p2p-addr: :1634 -# enable P2P WebSocket transport -p2p-ws-enable: false -# password for decrypting keys -password: "" -# path to a file that contains password for decrypting keys -password-file: "" -# percentage below the peers payment threshold when we initiate settlement -payment-early-percent: 50 -# threshold in BZZ where you expect to get paid from your peers -payment-threshold: "13500000" -# excess debt above payment threshold in percentages where you disconnect from your peer -payment-tolerance-percent: 25 -# postage stamp contract address -postage-stamp-address: "" -# postage stamp contract start block number -postage-stamp-start-block: "0" -# enable pprof mutex profile -pprof-mutex: false -# enable pprof block profile -pprof-profile: false -# price oracle contract address -price-oracle-address: "" -# redistribution contract address -redistribution-address: "" -# ENS compatible API endpoint for a TLD and with contract address, can be repeated, format [tld:][contract-addr@]url -resolver-options: [] -# forces the node to resync postage contract data -resync: false -# staking contract address -staking-address: "" -# lru memory caching capacity in number of statestore entries -statestore-cache-capacity: "100000" -# protect nodes from getting kicked out on bootnode -static-nodes: [] -# enable storage incentives feature -storage-incentives-enable: true -# gas price in wei to use for deployment and funding -swap-deployment-gas-price: "" -# enable swap -swap-enable: false -# swap blockchain endpoint -swap-endpoint: "" -# swap factory addresses -swap-factory-address: "" -# initial deposit if deploying a new chequebook -swap-initial-deposit: "0" -# neighborhood to target in binary format (ex: 111111001) for mining the initial overlay -target-neighborhood: "" -# admin username to get the security token -token-encryption-key: "" -# enable tracing -tracing-enable: false -# endpoint to send tracing data -tracing-endpoint: 127.0.0.1:6831 -# host to send tracing data -tracing-host: "" -# port to send tracing data -tracing-port: "" -# service name identifier for tracing -tracing-service-name: bee -# bootstrap node using postage snapshot from the network -use-postage-snapshot: false -# log verbosity level 0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=trace -verbosity: info -# time to warmup the node before some major protocols can be kicked off -warmup-time: 5m0s -# send a welcome message string during handshakes -welcome-message: "" -# withdrawal target addresses -withdrawal-addresses-whitelist: [] -``` - -If you do wish to use a YAML file to manage your configuration, simply generate a new file in the same directory as shown for `config` from the `bee printconfig` output. For us, that is `/root/.bee.yaml` (make sure to change this directory to match the value for the `config` directory which is output from `bee printconfig` on your system). - -```bash -touch /root/.bee.yaml -vi /root/.bee.yaml -``` - -You can then populate your `.bee.yaml` file with the default config output from `bee printconfig` to get started and save the file. - -### Set Bee API Address -:::danger -Make sure that your api-addr (default 1633) is never exposed to the internet. It is good practice to employ one or more firewalls that block traffic on every port except for those you are expecting to be open. -::: - -If you are not using a firewall or other method to protect your node, it's recommended that you change your Bee API address from the default `1633` to `127.0.0.1:1633` to ensure that it is not publicly exposed to the internet. - -```yaml -## HTTP API listen address (default ":1633") -api-addr: 127.0.0.1:1633 -``` - -### Set node type - -#### Full Node, Light Node, Ultra-light Node - -See the [quick start guide](/docs/bee/installation/quick-start) if you're not sure which type of node to run. - -To run Bee as a full node both `full-node` and `swap-enable` must be set to `true`, and a valid and stable Gnosis Chain RPC endpoint must be specified with `blockchain-rpc-endpoint`. - -```yaml -## bee.yaml -full-node: true -``` - -To run Bee as a light node `full-node` must be set to `false` and `swap-enable` must both be set to `true`, and a valid and stable Gnosis Chain RPC endpoint must be specified with `blockchain-rpc-endpoint`. - -```yaml -## bee.yaml -full-node: false -``` - -To run Bee as an ultra-light node `full-node` and `swap-enable` must both be set to `false`. No Gnosis Chain endpoint is required, and `blockchain-rpc-endpoint` can be left to its default value of an empty string. - -```yaml -## bee.yaml -full-node: false -swap-enable: false -``` - -### Set blockchain RPC endpoint - -Full and light Bee nodes require a Gnosis Chain RPC endpoint so they can interact with and deploy their chequebook contract, see the latest view of the current postage stamp batches, and interact with and top-up postage stamp batches. A blockchain RPC endpoint is not required for nodes running in ultra-light mode. - -We strongly recommend you [run your own Gnosis Chain node](https://docs.gnosischain.com/node/) if you are planning to run a full node, and especially if you plan to run a [hive of nodes](/docs/bee/installation/hive). - -If you do not wish to run your own Gnosis Chain node and are willing to trust a third party, you may also consider using an RPC endpoint provider such as [GetBlock](https://getblock.io/). - -For running a light node or for testing out a single full node you may also consider using one of the [free public RPC endpoints](https://docs.gnosischain.com/tools/RPC%20Providers/) listed in the Gnosis Chain documentation. However the providers of these endpoints make no [SLA](https://business.adobe.com/blog/basics/service-level-agreements-slas-a-complete-guide#what-is-a-service-level-agreement-sla) or availability guarantees, and is therefore not recommended for full node operators. - -To set your RPC endpoint provider, specify it with the `blockchain-rpc-endpoint` value, which is set to an empty string by default. - -```yaml -## bee.yaml -blockchain-rpc-endpoint: https://rpc.gnosis.gateway.fm -``` - -:::info -The gateway.fm RPC endpoint in the example is great for learning how to set up Bee, but for the sake of security and reliability it's recommended that you run your [run your own Gnosis Chain node](https://docs.gnosischain.com/node/) rather than relying on a third party provider. -::: - +### Set Node Type -### Configure Swap Initial Deposit (Optional) +See the [Getting Started guide](/docs/bee/installation/getting-started) if you're not sure which type of node to run. + +Once you've decided which node type is appropriate for you, refer to the [configuration section](/docs/bee/working-with-bee/configuration#set-bee-node-type) for instructions on setting the options for your preferred node type. -When running your Bee node with SWAP enabled for the first time, your node will deploy a 'chequebook' contract using the canonical factory contract which is deployed by Swarm. Once the chequebook is deployed, Bee will (optionally) deposit a certain amount of xBZZ in the chequebook contract so that it can pay other nodes in return for their services. The amount of xBZZ transferred to the chequebook is set by the `swap-initial-deposit` configuration setting (it may be left at the default value of zero or commented out). +### Set Target Neighborhood -### NAT address +When installing your Bee node it will automatically be assigned a neighborhood. However, when running a full node with staking there are benefits to periodically updating your node's neighborhood. Learn more about why and how to set your node's target neighborhood [here](/docs/bee/installation/set-target-neighborhood). -Swarm is all about sharing and storing chunks of data. To enable other -Bees (also known as _peers_) to connect to your Bee, you must -broadcast your public IP address in order to ensure that Bee is reachable on -the correct p2p port (default `1634`). We recommend that you [manually -configure your external IP and check -connectivity](/docs/bee/installation/connectivity) to ensure your Bee is -able to receive connections from other peers. -First determine your public IP address: +## Start Node -```bash -curl icanhazip.com -``` - -``` -123.123.123.123 -``` - -Then configure your node, including your p2p port (default 1634). - -```yaml -## bee.yaml -nat-addr: "123.123.123.123:1634" -``` -### ENS Resolution (Optional) - -The [ENS](https://ens.domains/) domain resolution system is used to host websites on Bee, and in order to use this your Bee must be connected to a mainnet Ethereum blockchain node. We recommend you run your own ethereum node. An option for resource restricted devices is geth+nimbus and a guide can be found [here](https://ethereum-on-arm-documentation.readthedocs.io/en/latest/). Other options include [dappnode](https://dappnode.io/), [nicenode](https://www.nicenode.xyz/), [stereum](https://stereum.net/) and [avado](https://ava.do/). - - -If you do not wish to run your own Ethereum node you may use a blockchain API service provider such as Infura. After signing up for [Infura's](https://infura.io) API service, simply set your `--resolver-options` to `https://mainnet.infura.io/v3/your-api-key`. - -```yaml -## bee.yaml -resolver-options: ["https://mainnet.infura.io/v3/<>"] -``` - -### Set Target Neighborhood (Optional) - -In older versions of Bee, [neighborhood](/docs/concepts/DISC/neighborhoods) assignment was random by default. However, we can maximize a node's chances of winning xBZZ and also strengthen the resiliency of the network by strategically assigning neighborhoods to new nodes (see the [staking section](/docs/bee/working-with-bee/staking) for more details). - -Therefore the default Bee configuration now includes the `neighborhood-suggester` option which is set by default to to use the Swarmscan neighborhood suggester (`https://api.swarmscan.io/v1/network/neighborhoods/suggestion`). An alternative suggester URL could be used as long as it returns a JSON file in the same format `{"neighborhood":"101000110101"}`, however only the Swarmscan suggester is officially recommended. - - -:::info -The Swarmscan neighborhood selector will return the least populated neighborhood (or its least populated sub-neighborhood in case the sub-neighborhoods are imbalanced). Furthermore, the suggester will temporarily de-prioritize previously suggested neighborhoods based on the assumption that a new node is being created in each suggested neighborhood so that multiple nodes do not simultaneously attempt to join the same neighborhood. -::: - -#### Setting Neighborhood Manually - -It's recommended to use the default `neighborhood-suggester` configuration for choosing your node's neighborhood, however you may also set your node's neighborhood manually using the `target-neighborhood` option. - -To use this option, it's first necessary to identify potential target neighborhoods. A convenient tool for finding underpopulated neighborhoods is available at the [Swarmscan website](https://swarmscan.io/neighborhoods). This tool provides the leading binary bits of target neighborhoods in order of least populated to most. Simply copy the leading bits from one of the least populated neighborhoods (for example, `0010100001`) and use it to set `target-neighborhood`. After doing so, an overlay address within that neighborhood will be generated when starting Bee for the first time. - -```yaml -## bee.yaml -target-neighborhood: "0010100001" -``` - -There is also a [Swarmscan API endpoint](https://api.swarmscan.io/#tag/Network/paths/~1v1~1network~1neighborhoods~1suggestion/get) which you can use to get a suggested neighborhood programmatically: - -```bash -curl https://api.swarmscan.io/v1/network/neighborhoods/suggestion -``` -A suggested neighborhood will be returned: - -```bash -{"neighborhood":"1111110101"} -``` - - -## 3. Find Bee address - -:::danger - In the following section we print our `swarm.key` file contents to the terminal. Do not share the contents of your `swarm.key` or any other keys with anyone as it controls access to your Gnosis Chain account and can be used to withdraw assets. -::: - -As part of the process of starting a Bee full or light node the node must issue a Gnosis Chain transaction to set up its chequebook contract. We need to find our node's Gnosis Chain address in order to deposit xDAI which will be used to pay for this initial Gnosis Chain transaction. We can find our node's address by reading it directly from our key file. The location for your key file will differ depending on your system and startup method: - -### Bee Service - -The default keys directory for a Bee node set up with a package manager to run as a service will differ depending on your system: +Use the appropriate command for your system to start your node: - ```bash -sudo cat /var/lib/bee/keys/swarm.key -``` - -```bash -{"address":"215693a6e6cf0a27441075fd98c31d48e3a3a100","crypto":{"cipher":"aes-128-ctr","ciphertext":"9e2706f1ce135dde449af5c529e80d560fb73007f1edb1636efcf4572eed1265","cipherparams":{"iv":"64b6482b8e04881446d88f4f9003ec78"},"kdf":"scrypt","kdfparams":{"n":32768,"r":8,"p":1,"dklen":32,"salt":"3da537f2644274e3a90b1f6e1fbb722c32cbd06be56b8f55c2ff8fa7a522fb22"},"mac":"11b109b7267d28f332039768c4117b760deed626c16c9c1388103898158e583b"},"version":3,"id":"d4f7ee3e-21af-43de-880e-85b6f5fa7727"} +sudo systemctl start bee ``` -The `address` field contains the Gnosis Chain address of the node, simply add the `0x` prefix and save it for the next step (0x215693a6e6cf0a27441075fd98c31d48e3a3a100). - - - - + ```bash -sudo cat /opt/homebrew/var/lib/swarm-bee/keys/swarm.key -``` - -```bash -{"address":"215693a6e6cf0a27441075fd98c31d48e3a3a100","crypto":{"cipher":"aes-128-ctr","ciphertext":"9e2706f1ce135dde449af5c529e80d560fb73007f1edb1636efcf4572eed1265","cipherparams":{"iv":"64b6482b8e04881446d88f4f9003ec78"},"kdf":"scrypt","kdfparams":{"n":32768,"r":8,"p":1,"dklen":32,"salt":"3da537f2644274e3a90b1f6e1fbb722c32cbd06be56b8f55c2ff8fa7a522fb22"},"mac":"11b109b7267d28f332039768c4117b760deed626c16c9c1388103898158e583b"},"version":3,"id":"d4f7ee3e-21af-43de-880e-85b6f5fa7727"} +brew services start swarm-bee ``` -The `address` field contains the Gnosis Chain address of the node, simply add the `0x` prefix and save it for the next step (0x215693a6e6cf0a27441075fd98c31d48e3a3a100). - - + ```bash -sudo cat /usr/local/var/lib/swarm-bee/keys/swarm.key -``` - -```bash -{"address":"215693a6e6cf0a27441075fd98c31d48e3a3a100","crypto":{"cipher":"aes-128-ctr","ciphertext":"9e2706f1ce135dde449af5c529e80d560fb73007f1edb1636efcf4572eed1265","cipherparams":{"iv":"64b6482b8e04881446d88f4f9003ec78"},"kdf":"scrypt","kdfparams":{"n":32768,"r":8,"p":1,"dklen":32,"salt":"3da537f2644274e3a90b1f6e1fbb722c32cbd06be56b8f55c2ff8fa7a522fb22"},"mac":"11b109b7267d28f332039768c4117b760deed626c16c9c1388103898158e583b"},"version":3,"id":"d4f7ee3e-21af-43de-880e-85b6f5fa7727"} -``` -The `address` field contains the Gnosis Chain address of the node, simply add the `0x` prefix and save it for the next step (0x215693a6e6cf0a27441075fd98c31d48e3a3a100). - - - - +Welcome to Swarm.... Bzzz Bzzzz Bzzzz + \ / + \ o ^ o / + \ ( ) / + ____________(%%%%%%%)____________ + ( / / )%%%%%%%( \ \ ) + (___/___/__/ \__\___\___) + ( / /(%%%%%%%)\ \ ) + (__/___/ (%%%%%%%) \___\__) + /( )\ + / (%%%%%) \ + (%%%) + ! -### For `bee start` +DISCLAIMER: +This software is provided to you "as is", use at your own risk and without warranties of any kind. +It is your responsibility to read and understand how Swarm works and the implications of running this software. +The usage of Bee involves various risks, including, but not limited to: +damage to hardware or loss of funds associated with the Ethereum account connected to your node. +No developers or entity involved will be liable for any claims and damages associated with your use, +inability to use, or your interaction with other nodes or the software. -The default keys directory when running Bee with the `bee start` command will depend on your operating system. Run the `bee printconfig` command to see the default config directory for your operating system, and look for the `data-dir` value. +version: 2.2.0-06a0aca7 - planned to be supported until 11 December 2024, please follow https://ethswarm.org/ -```bash -data-dir: /root/.bee +"time"="2024-09-24 18:15:34.383102" "level"="info" "logger"="node" "msg"="bee version" "version"="2.2.0-06a0aca7" +"time"="2024-09-24 18:15:34.428546" "level"="info" "logger"="node" "msg"="swarm public key" "public_key"="0373fe2ab33ab836635fc35864cf708fa0f4a775c0cf76ca851551e7787b58d040" +"time"="2024-09-24 18:15:34.520686" "level"="info" "logger"="node" "msg"="pss public key" "public_key"="03a341032724f1f9bb04f1d9b22607db485cccd74174331c701f3a6957d94d95c1" +"time"="2024-09-24 18:15:34.520716" "level"="info" "logger"="node" "msg"="using ethereum address" "address"="0x1A801dd3ec955E905ca424a85C3423599bfb0E66" +"time"="2024-09-24 18:15:34.533789" "level"="info" "logger"="node" "msg"="fetching target neighborhood from suggester" "url"="https://api.swarmscan.io/v1/network/neighborhoods/suggestion" +"time"="2024-09-24 18:15:36.773501" "level"="info" "logger"="node" "msg"="mining a new overlay address to target the selected neighborhood" "target"="00100010110" +"time"="2024-09-24 18:15:36.776550" "level"="info" "logger"="node" "msg"="using overlay address" "address"="22d502d022de0f8e9d477bc61144d0d842d9d82b8241568c6fe4e41f0b466615" +"time"="2024-09-24 18:15:36.776576" "level"="info" "logger"="node" "msg"="starting with an enabled chain backend" +"time"="2024-09-24 18:15:37.388997" "level"="info" "logger"="node" "msg"="connected to blockchain backend" "version"="erigon/2.60.7/linux-amd64/go1.21.5" +"time"="2024-09-24 18:15:37.577840" "level"="info" "logger"="node" "msg"="using chain with network network" "chain_id"=100 "network_id"=1 +"time"="2024-09-24 18:15:37.593747" "level"="info" "logger"="node" "msg"="starting debug & api server" "address"="127.0.0.1:1633" +"time"="2024-09-24 18:15:37.969782" "level"="info" "logger"="node" "msg"="using default factory address" "chain_id"=100 "factory_address"="0xC2d5A532cf69AA9A1378737D8ccDEF884B6E7420" +"time"="2024-09-24 18:15:38.160249" "level"="info" "logger"="node/chequebook" "msg"="no chequebook found, deploying new one." +"time"="2024-09-24 18:15:38.728534" "level"="warning" "logger"="node/chequebook" "msg"="cannot continue until there is at least min xDAI (for Gas) available on address" "min_amount"="0.0003750000017" "address"="0x1A801dd3ec955E905ca424a85C3423599bfb0E66" ``` -Your keys folder is found in the root of the `data-dir` directory. We can print our key data to the terminal to find our node's address: +Take note of the lines: ```bash -sudo cat /root/.bee/keys/swarm.key +"time"="2024-09-24 18:15:34.520716" "level"="info" "logger"="node" "msg"="using ethereum address" "address"="0x1A801dd3ec955E905ca424a85C3423599bfb0E66" ``` +and -```bash -{"address":"215693a6e6cf0a27441075fd98c31d48e3a3a100","crypto":{"cipher":"aes-128-ctr","ciphertext":"9e2706f1ce135dde449af5c529e80d560fb73007f1edb1636efcf4572eed1265","cipherparams":{"iv":"64b6482b8e04881446d88f4f9003ec78"},"kdf":"scrypt","kdfparams":{"n":32768,"r":8,"p":1,"dklen":32,"salt":"3da537f2644274e3a90b1f6e1fbb722c32cbd06be56b8f55c2ff8fa7a522fb22"},"mac":"11b109b7267d28f332039768c4117b760deed626c16c9c1388103898158e583b"},"version":3,"id":"d4f7ee3e-21af-43de-880e-85b6f5fa7727"} +```bash +"time"="2024-09-24 18:15:38.728534" "level"="warning" "logger"="node/chequebook" "msg"="cannot continue until there is at least min xDAI (for Gas) available on address" "min_amount"="0.0003750000017" "address"="0x1A801dd3ec955E905ca424a85C3423599bfb0E66" ``` -The `address` field contains the Gnosis Chain address of the node, simply add the `0x` prefix and save it for the next step (0x215693a6e6cf0a27441075fd98c31d48e3a3a100). - -## 4. Fund Node - -:::info - We recommend not holding a high value of xBZZ or xDAI in your nodes' wallet. Please consider regularly removing accumulated funds. -::: - -To fund your node with xDAI you can use a Gnosis Chain compatible wallet such as Metamask, or a centralized exchange which supports xDAI withdrawals to Gnosis Chain. If you already have some DAI on Ethereum, you can use the [Gnosis Chain Bridge](https://bridge.gnosischain.com/) to mint xDAI on Gnosis Chain. +The address referred to in both of these lines is your node's Gnosis Chain address. The second one indicates that the address does not have enough xDAI in order to deploy your node's chequebook contract which is used to pay for bandwidth incentives. You will see this warning if you have configured your node to run as a `full` or `light` node, but it should be absent for `ultra-light` nodes. -After acquiring some xDAI, you can fund your node by sending some xDAI to the address you saved from the previous step (1 xDAI is more sufficient). You can optionally also send some xBZZ to your node which you can use to pay for storage on Swarm. +## Fund Node -While depositing xBZZ is optional, node operators who intend to download or upload large amounts of data on Swarm may wish to deposit some xBZZ in order to pay for SWAP settlements. +Depending on your chosen node type, (full, light, or ultra-light), you will want to fund your node with differing amounts of xBZZ and xDAI. See [this section](/docs/bee/installation/fund-your-node) for more information on how to fund your node. -For nodes which stake xBZZ and participate in the storage incentives system, small amounts of xDAI are used regularly to pay for staking related transactions on Gnosis Chain, so xDAI must be periodically topped up. See the [staking section](/docs/bee/working-with-bee/staking#check-redistribution-status) for more information. -After sending xDAI and optionally xBZZ to the Gnosis Chain address collected in the previous step, restart the node: +### Restart and Wait for Initialisation -### Bee Service +After funding your node, use the appropriate command for your system below and wait for it to initialize: ```bash -sudo systemctl restart bee +sudo systemctl start bee ``` @@ -678,23 +326,12 @@ sudo systemctl restart bee ```bash -brew services restart swarm-bee +brew services start swarm-bee ``` -### For `bee start` - -Restart your terminal and run `bee start`: - -```bash -bee start -``` - - -## 5. Wait for Initialisation - When first started in full or light mode, Bee must deploy a chequebook to the Gnosis Chain blockchain, and sync the postage stamp batch store so that it can check chunks for validity when storing or forwarding them. This can take a while, so please be patient! Once this is complete, you will see Bee starting to add peers and connect to the network. You can keep an eye on progress by watching the logs while this is taking place. @@ -709,8 +346,6 @@ values={[ ]}> - - ```bash sudo journalctl --lines=100 --follow --unit bee ``` @@ -762,7 +397,7 @@ either, so be sure to look after them well and [keep secure backups](/docs/bee/working-with-bee/backups). ::: -## 6. Check if Bee is Working +## Check if Bee is Working First check that the correct version of Bee is installed: @@ -776,7 +411,7 @@ bee version Once the Bee node has been funded, the chequebook deployed, and postage stamp batch store synced, its HTTP [API](/docs/bee/working-with-bee/bee-api) -will start listening at `localhost:1633`. +will start listening at `localhost:1633` (for `full` or `light` nodes - for an `ultra-light` node, it should be initialized and the API should be available more rapidly). To check everything is working as expected, send a GET request to localhost port 1633. @@ -813,11 +448,11 @@ on the Swarm network. Welcome to the swarm! 🐝 🐝 🐝 🐝 🐝 -## 7. Back Up Keys +## Back Up Keys Once your node is up and running, make sure to [back up your keys](/docs/bee/working-with-bee/backups). -## 8. Deposit Stake (Optional) +## Deposit Stake (Optional) While depositing stake is not required to run a Bee node, it is required in order for a node to receive rewards for sharing storage with the network. You will need to [deposit xBZZ to the staking contract](/docs/bee/working-with-bee/staking) for your node. To do this, send a minimum of 10 xBZZ to your nodes' wallet and run: @@ -831,14 +466,11 @@ Storage incentive rewards are only available for full nodes which are providing Note that SWAP rewards are available to all full and light nodes, regardless of whether or not they stake xBZZ in order to participate in the storage incentives system. -## Getting help -The CLI has documentation built-in. Running `bee` gives you an entry point to the documentation. Running `bee start -h` or `bee start --help` will tell you how you can configure your Bee node via the command line arguments. - -You may also check out the [configuration guide](/docs/bee/working-with-bee/configuration), or simply run your Bee terminal command with the `--help` flag, eg. `bee start --help` or `bee --help`. ## Next Steps to Consider + ### Access the Swarm If you'd like to start uploading or downloading files to Swarm, [start here](/docs/develop/access-the-swarm/introduction). @@ -850,3 +482,5 @@ If you would like to run a hive of many Bees, check out the [hive operators](/do ### Start building DAPPs on Swarm If you would like to start building decentralised applications on Swarm, check out our section for [developing with Bee](/docs/develop/introduction). + + diff --git a/docs/bee/installation/set-target-neighborhood.md b/docs/bee/installation/set-target-neighborhood.md new file mode 100644 index 000000000..8a115a748 --- /dev/null +++ b/docs/bee/installation/set-target-neighborhood.md @@ -0,0 +1,38 @@ +--- +title: Set Target Neighborhood +id: set-target-neighborhood +--- + + +### Set Target Neighborhood + +In older versions of Bee, [neighborhood](/docs/concepts/DISC/neighborhoods) assignment was random by default. However, we can maximize a node's chances of winning xBZZ and also strengthen the resiliency of the network by strategically assigning neighborhoods to new nodes (see the [staking section](/docs/bee/working-with-bee/staking) for more details). + +Therefore the default Bee configuration now includes the `neighborhood-suggester` option which is set by default to to use the Swarmscan neighborhood suggester (`https://api.swarmscan.io/v1/network/neighborhoods/suggestion`). An alternative suggester URL could be used as long as it returns a JSON file in the same format `{"neighborhood":"101000110101"}`, however only the Swarmscan suggester is officially recommended. + + +:::info +The Swarmscan neighborhood selector will return the least populated neighborhood (or its least populated sub-neighborhood in case the sub-neighborhoods are imbalanced). Furthermore, the suggester will temporarily de-prioritize previously suggested neighborhoods based on the assumption that a new node is being created in each suggested neighborhood so that multiple nodes do not simultaneously attempt to join the same neighborhood. +::: + +#### Setting Neighborhood Manually + +It's recommended to use the default `neighborhood-suggester` configuration for choosing your node's neighborhood, however you may also set your node's neighborhood manually using the `target-neighborhood` option. + +To use this option, it's first necessary to identify potential target neighborhoods. A convenient tool for finding underpopulated neighborhoods is available at the [Swarmscan website](https://swarmscan.io/neighborhoods). This tool provides the leading binary bits of target neighborhoods in order of least populated to most. Simply copy the leading bits from one of the least populated neighborhoods (for example, `0010100001`) and use it to set `target-neighborhood`. After doing so, an overlay address within that neighborhood will be generated when starting Bee for the first time. + +```yaml +## bee.yaml +target-neighborhood: "0010100001" +``` + +There is also a [Swarmscan API endpoint](https://api.swarmscan.io/#tag/Network/paths/~1v1~1network~1neighborhoods~1suggestion/get) which you can use to get a suggested neighborhood programmatically: + +```bash +curl https://api.swarmscan.io/v1/network/neighborhoods/suggestion +``` +A suggested neighborhood will be returned: + +```bash +{"neighborhood":"1111110101"} +``` diff --git a/docs/bee/installation/shell-script.md b/docs/bee/installation/shell-script.md index 8dcbf2184..9f9900c1b 100644 --- a/docs/bee/installation/shell-script.md +++ b/docs/bee/installation/shell-script.md @@ -7,54 +7,32 @@ id: shell-script-install import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -# Swarm Quickstart Shell Script - -The following is a guide to get you started running a Bee full node with staking on Swarm using [the official shell script provided by Swarm](https://github.com/ethersphere/bee/blob/master/install.sh) which automatically detects your system and installs the correct version of Bee. +# Swarm Shell Script Installation Guide +The following is a guide to get you started running a Bee node on Swarm using [the official shell script provided by Swarm](https://github.com/ethersphere/bee/blob/master/install.sh) which automatically detects your system and installs the correct version of Bee. This installation method is an excellent choice if you're looking for a minimalistic and flexible option for your Bee node installation. :::warning Note that we append 127.0.0.1 (localhost) to our Bee API's port (1633 by default), since we do not want to expose our Bee API endpoint to the public internet, as that would allow anyone to control our node. Make sure you do the same, and it's also recommended to use a firewall to protect access to your node(s). ::: :::info -The guide below is for a full Bee node with staking. To run a light node (uploads and downloads only), set `--full-node` to false, or to run in ultra light (downloads only) mode you can set both `--full-node` and `--swap-enable` to false. -::: - - - -## Prerequisites - -### Hardware - -:::warning -If you are running on a home Wi-Fi you may need to configure your router to use [port forwarding](https://www.noip.com/support/knowledgebase/general-port-forwarding-guide) or take other steps to ensure your node is reachable by other nodes on the network. See [here](https://docs.ethswarm.org/docs/bee/installation/connectivity/#navigating-through-the-nat) for more guidance. If you are running on a VPS or cloud based server you will likely have no issues. -::: - -:::caution -While it is possible to run multiple Bee nodes on a single machine, due to the high rate of I/O operations required by a full Bee node in operation, it is not recommended to run more than a handful of Bee nodes on the same physical disk (depending on the disk speed). +This guide uses command line flag options in the node startup commands such as `--blockchain-rpc-endpoint`, however there are [several other methods available for configuring options](/docs/bee/working-with-bee/configuration). ::: - -### Software - -* A computer running a supported version of Linux (almost all commonly used distros should work). macOS will also work but you may need to slightly modify some commands. -* A Gnosis Chain RPC endpoint (either by running your own node or the [free RPC endpoint](https://xdai.fairdatasociety.org) offered from the Fair Data Society. Other free public options are available at the [Gnosis Chain docs](https://docs.gnosischain.com/tools/RPC%20Providers/). -* (Optional) [`jq` utility](https://jqlang.github.io/jq/) for formatting API output. -* (Optional) [`bashtop` utility](https://github.com/aristocratos/bashtop) for monitoring processes (such as our Bee node). - - :::info -The [`jq` utility](https://jqlang.github.io/jq/) is used in this guide to automatically format the output from the Bee API. It can help make API output much more readable, however it is totally optional. +**Bee Modes** -The [`bashtop` utility](https://github.com/aristocratos/bashtop) is similarly optional, it is however a useful tool for monitoring our node's process so we can see that it is running properly. +Bee nodes can be run in multiple modes with different functionalities. To run a node in full mode, both `--full-node` and `--swap-enable` must be set to true. To run a light node (uploads and downloads only), set `--full-node` to false and `--swap-enable` to `true`, or to run in ultra light mode (free tier downloads only) set both `--full-node` and `--swap-enable` to false. + +For more information on the different functionalities of each mode, as well as their different system requirements, refer to the [Getting Started guide](/docs/bee/installation/getting-started). ::: -### Tokens + +## Install and Start Your Node +Below is a step by step guide for installing and setting up your Bee node using the shell script installation method. -* A small amount of xDAI to pay for Gnosis Chain transactions, 0.1 xDAI should be enough -* 10 xBZZ (BZZ on Gnosis Chain) is required for staking +### Run Shell Script -## Run setup script Run the install shell script using either `curl` or `wget`: @@ -81,7 +59,7 @@ curl -s https://raw.githubusercontent.com/ethersphere/bee/master/install.sh | TA **wget** ```bash -wget -q -O - https://raw.githubusercontent.com/ethersphere/bee/master/install.sh | TAG=v2.2.0 bash +wget -q -O - https://raw.githubusercontent.com/ethersphere/bee/master/install.sh | TAG=v2.4.0 bash ``` @@ -352,8 +330,13 @@ version: 2.2.0-06a0aca7 - planned to be supported until 11 December 2024, please +## Fund and Stake + +Running a full node for the purpose of earning xBZZ by sharing disk space and participating in the redistribution game requires a minimum of 10 xBZZ and a small amount of xDAI (for initializing the chequebook contract and for paying for redistribution game related transactions). -### Fund node (full and light nodes only) +While running a light note requires a small amount of xDAI to pay for initializing the chequebook contract and a smaller amount of xBZZ to pay for uploads and downloads. + +### Fund node Check the logs from the previous step. Look for the line which says: @@ -362,6 +345,28 @@ Check the logs from the previous step. Look for the line which says: ``` That address is your node's address on Gnosis Chain which needs to be funded with xDAI and xBZZ. Copy it and save it for the next step. +You can also use a `curl` command with the Bee API to find your node's address: + +```bash +curl localhost:1633/addresses | jq +``` + +```json +{ + "overlay": "b1978be389998e8c8596ef3c3a54214e2d4db764898ec17ec1ad5f19cdf7cc59", + "underlay": [ + "/ip4/127.0.0.1/tcp/1634/p2p/QmQHgcpizgoybDtrQXCWRSGdTP526ufeMFn1PyeGd1zMEZ", + "/ip4/172.25.128.69/tcp/1634/p2p/QmQHgcpizgoybDtrQXCWRSGdTP526ufeMFn1PyeGd1zMEZ", + "/ip6/::1/tcp/1634/p2p/QmQHgcpizgoybDtrQXCWRSGdTP526ufeMFn1PyeGd1zMEZ" + ], + "ethereum": "0xd22cc790e2aef341827e1e49cc631d2a16898cd9", + "publicKey": "023b26ce8b78ed8cdb07f3af3d284c95bee5e038e7c5d0c397b8a5e33424f5d790", + "pssPublicKey": "039ceb9c1f0afedf79991d86d89ccf4e96511cf656b43971dc3e878173f7462487" +} +``` + +The `ethereum` address is your node's Gnosis Chain address (while Gnosis is a distinct chain from Ethereum, it uses the same address format and is sometimes referenced as such within the Bee API.) + xDAI is widely available from many different centralized and decentralized exchanges, just make sure that you are getting xDAI on Gnosis Chain, and not DAI on some other chain. See [this page](https://www.ethswarm.org/get-bzz) for a list of resources for getting xBZZ (again, make certain that you are getting the Gnosis Chain version, and not BZZ on Ethereum). After acquiring some xDAI and some xBZZ, send them to the address you copied above. @@ -534,8 +539,17 @@ The results will be displayed in PLUR units (1 PLUR is equal to 1e-16 xBZZ). If Congratulations! You have now installed your Bee node and are connected to the network as a full staking node. Your node will now be in the process of syncing chunks from the network. Once it is fully synced, your node will finally be eligible for earning staking rewards. +### Set Target Neighborhood + +When installing your Bee node it will automatically be assigned a neighborhood. However, when running a full node with staking there are benefits to periodically updating your node's neighborhood. Learn more about why and how to set your node's target neighborhood [here](/docs/bee/installation/set-target-neighborhood). + + ### Logs and monitoring +:::info +You can learn more about Bee logs here. +::: + With our previously modified command, our Bee node will now be running in the background and the logs will be written to the `bee.log` file. To review our node's logs we can simply view the file contents: ```bash @@ -597,3 +611,30 @@ Below is the output for a node which has been running for several days: For a complete breakdown of this output, check out [this section in the Bee docs](/docs/bee/working-with-bee/bee-api#redistributionstate). You can read more other important endpoints for monitoring your Bee node in the [official Bee docs](/docs/bee/working-with-bee/bee-api), and you can find complete information about all available endpoints in [the API reference docs](/api/). + + +## Back Up Keys + +Once your node is up and running, make sure to [back up your keys](/docs/bee/working-with-bee/backups). + +## Getting help + +The CLI has documentation built-in. Running `bee` gives you an entry point to the documentation. Running `bee start -h` or `bee start --help` will tell you how you can configure your Bee node via the command line arguments. + +You may also check out the [configuration guide](/docs/bee/working-with-bee/configuration), or simply run your Bee terminal command with the `--help` flag, eg. `bee start --help` or `bee --help`. + + +## Next Steps to Consider + + +### Access the Swarm +If you'd like to start uploading or downloading files to Swarm, [start here](/docs/develop/access-the-swarm/introduction). + +### Explore the API +The [Bee API](/docs/bee/working-with-bee/bee-api) is the primary method for interacting with Bee and getting information about Bee. After installing Bee and getting it up and running, it's a good idea to start getting familiar with the API. + +### Run a hive! +If you would like to run a hive of many Bees, check out the [hive operators](/docs/bee/installation/hive) section for information on how to operate and monitor many Bees at once. + +### Start building DAPPs on Swarm +If you would like to start building decentralised applications on Swarm, check out our section for [developing with Bee](/docs/develop/introduction). diff --git a/docs/bee/working-with-bee/configuration.md b/docs/bee/working-with-bee/configuration.md index acfeaa0c8..3496cb74b 100644 --- a/docs/bee/working-with-bee/configuration.md +++ b/docs/bee/working-with-bee/configuration.md @@ -6,76 +6,12 @@ id: configuration import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; -## Default Data and Config Directories - -Depending on the operating system and startup method used, the default data and configuration directories for your node will differ. - -### Bee Service Default Directories - -When installed using a package manager, Bee is set up to run as a service with default data and configuration directories set up automatically during the installation. The examples below include default directories for Linux and macOS. You can find the complete details of default directories for different operating systems in the `bee.yaml` files included in the [packaging folder of the Bee repo](https://github.com/ethersphere/bee/tree/master/packaging). - - - - - -The default data folder and config file locations: - -```yaml -data-dir: /var/lib/bee -config: /etc/bee/bee.yaml -``` - - - - - -The default data folder and config file locations: - -```yaml -data-dir: /opt/homebrew/var/lib/swarm-bee -config: /opt/homebrew/etc/swarm-bee/bee.yaml -``` - - - - - -The default data folder and config file locations: - -```yaml -data-dir: /usr/local/var/lib/swarm-bee/ -config: /usr/local/etc/swarm-bee/bee.yaml -``` - - - - -### `bee start` Default Directories - -For all operating systems, the default data and config directories for the `bee start` startup method can be found using the `bee printconfig` command: - -This will print out a complete default Bee node configuration file to the terminal, the `config` and `data-dir` values show the default directories for your system: - -```yaml -config: /root/.bee.yaml -data-dir: /root/.bee -``` - -:::info -The default directories for your system may differ from the example above, so make sure to run the `bee printconfig` command to view the default directories for your system. -::: ## Configuration Methods and Priority There are three methods of configuration which each have different priority levels. Configuration is processed in the following ascending order of preference: -1. Command Line Arguments +1. Command Line Flags 2. Environment Variables 3. YAML Configuration File @@ -364,19 +300,223 @@ brew services restart swarm-bee -## Manually generating a config file for `bee start` +## Manually generating YAML config file for `bee start` -No YAML file is generated during installation in the default config directory used when Bee is started with `bee start`, so you must generate one if you wish to use a YAML file to specify your configuration options. To do this you can use the `bee printconfig` command to print out a set of default options and save it to a new file in the default location: +No YAML file is generated during installation when using the [shell script install method](/docs/bee/installation/shell-script-install), so you must generate one if you wish to use a YAML file to specify your configuration options. To do this you can use the `bee printconfig` command to print out a set of default options and save it to a new file in the default location: ```bash bee printconfig &> $HOME/.bee.yaml ``` -## Restoring default config files for Bee service +:::info +Note that `bee printconfig` prints the default configuration for your node, not the current configuration including any changes. +::: + +Moreover, when using `bee.yaml` together with the `bee start` command, you must use the `--config` flag to specify where you have saved your configuration file or else your node will ignore it. This can be a good option if you have changed many default options and want to have them cleanly organized in a file that can be used to specify options when running your node node directly with `bee start`. + +## Restoring default YAML config file You can find the default configurations for your system in the [packaging folder of the Bee repo](https://github.com/ethersphere/bee/tree/master/packaging). If your configuration file is missing you can simply copy the contents of the file into a new `bee.yaml` file in the default configuration directory shown in the `bee.yaml` file for your system. +## Default Data and Config Directories + +Depending on the operating system and startup method used, the default data and configuration directories for your node will differ. + +### Bee Service Default Directories + +When installed using a package manager, Bee is set up to run as a service with default data and configuration directories set up automatically during the installation. The examples below include default directories for Linux and macOS. You can find the complete details of default directories for different operating systems in the `bee.yaml` files included in the [packaging folder of the Bee repo](https://github.com/ethersphere/bee/tree/master/packaging). + + + + + +The default data folder and config file locations: + +```yaml +data-dir: /var/lib/bee +config: /etc/bee/bee.yaml +``` + + + + + +The default data folder and config file locations: + +```yaml +data-dir: /opt/homebrew/var/lib/swarm-bee +config: /opt/homebrew/etc/swarm-bee/bee.yaml +``` + + + + + +The default data folder and config file locations: + +```yaml +data-dir: /usr/local/var/lib/swarm-bee/ +config: /usr/local/etc/swarm-bee/bee.yaml +``` + + + + +### `bee start` Default Directories + +For all operating systems, the default data and config directories for the `bee start` startup method can be found using the `bee printconfig` command: + +This will print out a complete default Bee node configuration file to the terminal, the `config` and `data-dir` values show the default directories for your system: + +```yaml +config: /root/.bee.yaml +data-dir: /root/.bee +``` + +:::info +The default directories for your system may differ from the example above, so make sure to run the `bee printconfig` command to view the default directories for your system. +::: + +## Set Bee Node Type + +You can set your node's mode of operation by modifying its configuration options. There are three node types: `full`, `light`, and `ultra-light`. If you're not sure which type of node is right for you, check out the [Getting Started guide](/docs/bee/installation/getting-started). + +There are three configuration options that must be configured to set your node type. These options are: + +1. `--full-node` / `BEE_FULL_NODE` / `full-node` +2. `--swap-enable` / `BEE_SWAP_ENABLE` / `swap-enable` +3. `--blockchain-rpc-endpoint` / `BEE_BLOCKCHAIN_RPC_ENDPOINT` / `blockchain-rpc-endpoint` + +A `password` option is also required for all modes, and can either be set directly as a configuration option or alternatively a file can be used by setting the `password-file` option to the path where your password file is located. + + +:::info +In the list above, we've provided the configuration options for each node type in all three configuration formats. + +Note that configuration options are processed in this order, as mentioned above: + +1. Command Line Flags +2. Environment Variables +3. YAML Configuration File + +::: + +:::info +In the examples below, the RPC endpoint is set as `https://xdai.fairdatasociety.org`. Your RPC endpoint may differ depending on whether you are running your own Gnosis Chain node or using a third-party provider. Free RPC providers are listed in the [Gnosis Chain docs](https://docs.gnosischain.com/node/), while commercial providers such as [Infura](https://www.infura.io/) offer more reliable options. +::: + + + + + +### Full Node Configuration + +**Command Line Flags:** +```bash +bee start \ + --password flummoxedgranitecarrot \ + --full-node \ + --swap-enable \ + --api-addr 127.0.0.1:1633 \ + --blockchain-rpc-endpoint https://xdai.fairdatasociety.org +``` + +**Environment Variables:** +```bash +export BEE_PASSWORD=flummoxedgranitecarrot +export BEE_FULL_NODE=true +export BEE_SWAP_ENABLE=true +export BEE_BLOCKCHAIN_RPC_ENDPOINT=https://xdai.fairdatasociety.org +bee start +``` + +**YAML Configuration File:** +```yaml +password: flummoxedgranitecarrot +full-node: true +swap-enable: true +blockchain-rpc-endpoint: https://xdai.fairdatasociety.org +``` + + + + + +### Light Node Configuration + +**Command Line Flags:** +```bash +bee start \ + --password flummoxedgranitecarrot \ + --swap-enable \ + --api-addr 127.0.0.1:1633 \ + --blockchain-rpc-endpoint https://xdai.fairdatasociety.org +``` + +**Environment Variables:** +```bash +export BEE_PASSWORD=flummoxedgranitecarrot +export BEE_FULL_NODE=false +export BEE_SWAP_ENABLE=true +export BEE_BLOCKCHAIN_RPC_ENDPOINT=https://xdai.fairdatasociety.org +bee start +``` + +**YAML Configuration File:** +```yaml +password: flummoxedgranitecarrot +full-node: false +swap-enable: true +blockchain-rpc-endpoint: https://xdai.fairdatasociety.org +``` + + + + + +### Ultra-Light Node Configuration + +**Command Line Flags:** +```bash +bee start \ + --password flummoxedgranitecarrot \ + --api-addr 127.0.0.1:1633 +``` + +**Environment Variables:** +```bash +export BEE_PASSWORD=flummoxedgranitecarrot +export BEE_FULL_NODE=false +export BEE_SWAP_ENABLE=false +export BEE_BLOCKCHAIN_RPC_ENDPOINT= +bee start +``` + +**YAML Configuration File:** +```yaml +password: flummoxedgranitecarrot +full-node: false +swap-enable: false +blockchain-rpc-endpoint: "" +``` + + + + + ## Sepolia Testnet Configuration @@ -399,4 +539,68 @@ welcome-message: "welcome-from-the-hive" warmup-time: 30s ``` -Here `bootnode` was changed to use the testnet bootnode, `mainnet` has been set to `false`, `network-id` has been changed from the default Swarm network id of 1 to the Swarm testnet id of 10, and `blockchain-rpc-endpoint` has been changed to use an RPC endpoint for the Sepolia testnet rather than Gnosis Chain. \ No newline at end of file +Here `bootnode` was changed to use the testnet bootnode, `mainnet` has been set to `false`, `network-id` has been changed from the default Swarm network id of 1 to the Swarm testnet id of 10, and `blockchain-rpc-endpoint` has been changed to use an RPC endpoint for the Sepolia testnet rather than Gnosis Chain. + +## Setting Blockchain RPC endpoint + +Full and light Bee nodes require a Gnosis Chain RPC endpoint so they can interact with and deploy their chequebook contract, see the latest view of the current postage stamp batches, and interact with and top-up postage stamp batches. A blockchain RPC endpoint is not required for nodes running in ultra-light mode. + +We strongly recommend you [run your own Gnosis Chain node](https://docs.gnosischain.com/node/) if you are planning to run a full node, and especially if you plan to run a [hive of nodes](/docs/bee/installation/hive). + +If you do not wish to run your own Gnosis Chain node and are willing to trust a third party, you may also consider using an RPC endpoint provider such as [GetBlock](https://getblock.io/). + +For running a light node or for testing out a single full node you may also consider using one of the [free public RPC endpoints](https://docs.gnosischain.com/tools/RPC%20Providers/) listed in the Gnosis Chain documentation. However the providers of these endpoints make no [SLA](https://business.adobe.com/blog/basics/service-level-agreements-slas-a-complete-guide#what-is-a-service-level-agreement-sla) or availability guarantees, and is therefore not recommended for full node operators. + +To set your RPC endpoint provider, specify it with the `blockchain-rpc-endpoint` value, which is set to an empty string by default. + +```yaml +## bee.yaml +blockchain-rpc-endpoint: https://rpc.gnosis.gateway.fm +``` + +:::info +The gateway.fm RPC endpoint in the example is great for learning how to set up Bee, but for the sake of security and reliability it's recommended that you run your [run your own Gnosis Chain node](https://docs.gnosischain.com/node/) rather than relying on a third party provider. +::: + + +## Configuring Swap Initial Deposit (Optional) + +When running your Bee node with SWAP enabled for the first time, your node will deploy a 'chequebook' contract using the canonical factory contract which is deployed by Swarm. Once the chequebook is deployed, Bee will (optionally) deposit a certain amount of xBZZ in the chequebook contract so that it can pay other nodes in return for their services. The amount of xBZZ transferred to the chequebook is set by the `swap-initial-deposit` configuration setting (it may be left at the default value of zero or commented out). + +## NAT address + +Swarm is all about sharing and storing chunks of data. To enable other +Bees (also known as _peers_) to connect to your Bee, you must +broadcast your public IP address in order to ensure that Bee is reachable on +the correct p2p port (default `1634`). We recommend that you [manually +configure your external IP and check +connectivity](/docs/bee/installation/connectivity) to ensure your Bee is +able to receive connections from other peers. + +First determine your public IP address: + +```bash +curl icanhazip.com +``` + +``` +123.123.123.123 +``` + +Then configure your node, including your p2p port (default 1634). + +```yaml +## bee.yaml +nat-addr: "123.123.123.123:1634" +``` +## ENS Resolution (Optional) + +The [ENS](https://ens.domains/) domain resolution system is used to host websites on Bee, and in order to use this your Bee must be connected to a mainnet Ethereum blockchain node. We recommend you run your own ethereum node. An option for resource restricted devices is geth+nimbus and a guide can be found [here](https://ethereum-on-arm-documentation.readthedocs.io/en/latest/). Other options include [dappnode](https://dappnode.io/), [nicenode](https://www.nicenode.xyz/), [stereum](https://stereum.net/) and [avado](https://ava.do/). + + +If you do not wish to run your own Ethereum node you may use a blockchain API service provider such as Infura. After signing up for [Infura's](https://infura.io) API service, simply set your `--resolver-options` to `https://mainnet.infura.io/v3/your-api-key`. + +```yaml +## bee.yaml +resolver-options: ["https://mainnet.infura.io/v3/<>"] +``` \ No newline at end of file diff --git a/docs/bee/working-with-bee/logs-and-files.md b/docs/bee/working-with-bee/logs-and-files.md index 1cf8091c7..c9597013a 100644 --- a/docs/bee/working-with-bee/logs-and-files.md +++ b/docs/bee/working-with-bee/logs-and-files.md @@ -1,3 +1,7 @@ +--- +title: Logging in Bee +id: logs-and-files +--- # Logging in Bee diff --git a/docs/bee/working-with-bee/uninstalling-bee.md b/docs/bee/working-with-bee/uninstalling-bee.md index 439abe678..e26682461 100644 --- a/docs/bee/working-with-bee/uninstalling-bee.md +++ b/docs/bee/working-with-bee/uninstalling-bee.md @@ -33,7 +33,7 @@ sudo yum remove bee If Bee is installed using the [automated shell script](/docs/bee/installation/install#shell-script-install) or by [building from source](/docs/bee/installation/build-from-source), Bee can be uninstalled by directly removing the installed file. ```bash -sudo rm `/usr/local/bin/bee` +sudo rm /usr/local/bin/bee ``` ## Remove Bee Data Files diff --git a/docs/concepts/introduction.md b/docs/concepts/introduction.md index e4cefd9cc..07e85e1ea 100644 --- a/docs/concepts/introduction.md +++ b/docs/concepts/introduction.md @@ -8,7 +8,7 @@ Swarm is a peer-to-peer network of Bee nodes that collectively provide censorshi ## Bee Client -Bee is a Swarm client implemented in Go and is the basic building block for the Swarm network. Bee nodes collectively work together to form a private, decentralized, and self sustaining network for permissionless publishing and data storage. You can learn more about how Bee clients work by reading about the [concepts and protocols](/docs/concepts/what-is-swarm/) which underpin the Swarm network. To get hands on experience working with Swarm, you can start by learning how to [install and operate a Bee node](/docs/bee/installation/quick-start). +Bee is a Swarm client implemented in Go and is the basic building block for the Swarm network. Bee nodes collectively work together to form a private, decentralized, and self sustaining network for permissionless publishing and data storage. You can learn more about how Bee clients work by reading about the [concepts and protocols](/docs/concepts/what-is-swarm/) which underpin the Swarm network. To get hands on experience working with Swarm, you can start by learning how to [install and operate a Bee node](/docs/bee/installation/getting-started). ## Swarm Foundation diff --git a/docs/develop/access-the-swarm/store-with-encryption.md b/docs/develop/access-the-swarm/store-with-encryption.md index d6a26cc92..7c1c3685e 100644 --- a/docs/develop/access-the-swarm/store-with-encryption.md +++ b/docs/develop/access-the-swarm/store-with-encryption.md @@ -32,7 +32,7 @@ The second part of the reference is a 64 character decryption key which is requi It is important that this data not be sent in requests to a public gateway as this would mean that gateway would be able to decrypt your data. However, if you are running a node on your local machine, you may safely use the API bound to `localhost`. The key material is never exposed to the network so your data remains safe. :::info -Encryption is disabled by default on all Swarm Gateways to keep your data safe. [Install Bee on your computer](/docs/bee/installation/quick-start) to use the encryption feature. +Encryption is disabled by default on all Swarm Gateways to keep your data safe. [Install Bee on your computer](/docs/bee/installation/getting-started) to use the encryption feature. ::: # Download and Decrypt a File @@ -44,5 +44,5 @@ curl -OJ http://localhost:1633/bzz/f7b1a45b70ee91d3dbfd98a2a692387f24db7279a9c96 ``` :::danger -Never use public gateways when requesting full encrypted references. The hash contains sensitive key information which should be kept private. Run [your own node](/docs/bee/installation/quick-start) to use Bee's encryption features. +Never use public gateways when requesting full encrypted references. The hash contains sensitive key information which should be kept private. Run [your own node](/docs/bee/installation/getting-started) to use Bee's encryption features. ::: diff --git a/docusaurus.config.js b/docusaurus.config.js index 0f0c0f3ba..7fa54703e 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -36,10 +36,6 @@ module.exports = { to: '/docs/bee/working-with-bee/configuration', from: '/docs/working-with-bee/configuration', }, - { - to: '/docs/bee/installation/quick-start', - from: '/docs/installation/quick-start', - }, { to: '/docs/develop/access-the-swarm/buy-a-stamp-batch', from: '/docs/develop/access-the-swarm/keep-your-data-alive', @@ -159,7 +155,7 @@ module.exports = { position: 'left', items: [ { - to: 'docs/bee/installation/quick-start', + to: 'docs/bee/installation/getting-started', label: 'Installation' }, { diff --git a/sidebars.js b/sidebars.js index aabbf1ee8..e6e1f0594 100644 --- a/sidebars.js +++ b/sidebars.js @@ -47,11 +47,12 @@ module.exports = { type: 'category', label: 'Installation', items: [ - 'bee/installation/quick-start', + 'bee/installation/getting-started', 'bee/installation/shell-script-install', 'bee/installation/docker', 'bee/installation/package-manager-install', 'bee/installation/build-from-source', + 'bee/installation/set-target-neighborhood', 'bee/installation/hive', 'bee/installation/connectivity', 'bee/installation/fund-your-node', diff --git a/src/config/globalVariables.js b/src/config/globalVariables.js index a861e00c8..fdc9c33ad 100644 --- a/src/config/globalVariables.js +++ b/src/config/globalVariables.js @@ -1,5 +1,4 @@ export const globalVariables = { - exampleVariable: 'Hello, World!', postageStampContract: '0x45a1502382541Cd610CC9068e88727426b696293', stakingContract: '0x445B848e16730988F871c4a09aB74526d27c2Ce8', redistributionContract: '0xFfF73fd14537277B3F3807e1AB0F85E17c0ABea5', diff --git a/src/pages/index.js b/src/pages/index.js index ceff8bcc6..f6382e08f 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -44,7 +44,7 @@ function Home() {

Install the Swarm Desktop client to quickly spin up a Bee node and start interacting with the Swarm network.

- +
From 95a2262944ae47cd99edfce76747478bb665caa1 Mon Sep 17 00:00:00 2001 From: NoahMaizels Date: Thu, 30 Jan 2025 15:06:42 +0700 Subject: [PATCH 03/16] added corrections to parts of learn section linked to from Getting Started page, other minor changes to install section pages --- docs/bee/installation/getting-started.md | 33 ++++++----------- docs/bee/installation/hive.md | 2 -- docs/bee/installation/package-manager.md | 4 +-- docs/bee/working-with-bee/configuration.md | 2 +- docs/concepts/incentives/overview.mdx | 42 +++++++++++++--------- 5 files changed, 38 insertions(+), 45 deletions(-) diff --git a/docs/bee/installation/getting-started.md b/docs/bee/installation/getting-started.md index f190206ff..c9e6a7401 100644 --- a/docs/bee/installation/getting-started.md +++ b/docs/bee/installation/getting-started.md @@ -4,17 +4,17 @@ id: getting-started --- -In this guide we cover the basic background information you need to know to get started running a Bee node: +In this guide we cover the basic background information you need to know to get started running a Bee node, such as: -#### [A list of Bee node types and their various features.](/docs/bee/installation/getting-started#node-types) -#### [General requirements for running Bee nodes.](/docs/bee/installation/getting-started#general-node-requirements) -#### [Specific requirements base on node type.](/docs/bee/installation/getting-started#node-requirements-by-node-type) -#### [How to choose the right node type.](/docs/bee/installation/getting-started#choosing-node-type-based-on-use-case) -#### [How to choose the appropriate installation method.](/docs/bee/installation/getting-started#choosing-installation-method) +* [A list of Bee node types and their various features.](/docs/bee/installation/getting-started#node-types) +* [General requirements for running Bee nodes.](/docs/bee/installation/getting-started#general-node-requirements) +* [Specific requirements base on node type.](/docs/bee/installation/getting-started#node-requirements-by-node-type) +* [How to choose the right node type.](/docs/bee/installation/getting-started#choosing-node-type-based-on-use-case) +* [How to choose the appropriate installation method.](/docs/bee/installation/getting-started#choosing-installation-method) ## Node Types -Bee is a versatile piece of software that caters to a diverse array of use cases. It can be run in several different modes which each offer different features which are best suited for different users. There are three main categories of nodes: full nodes, light nodes, and ultra-light nodes. Node type is set by modifying the appropriate configuration options during the setup process. For the details of how to configure each node type, refer to the [node installation guides](/docs/bee/installation/getting-started#choosing-installation-method). +Bee is a versatile piece of software that caters to a diverse array of use cases. It can be run in several different modes which each offer different features which are best suited for different users. There are three main categories of nodes: full nodes, light nodes, and ultra-light nodes. Node type is set by modifying the [appropriate configuration options](/docs/bee/working-with-bee/configuration#set-bee-node-type). ### Ultra-Light Node @@ -36,25 +36,12 @@ A full node can upload and download data over the Swarm network. Additionally, a | Uploading | ✅ | ✅ | ❌ | | Can exceed free download limits by paying xBZZ | ✅ | ✅ |❌ |Sharing disk space with network|✅| ❌ |❌| -|Storage incentives|✅| ❌ |❌| -|SWAP incentives|✅| ✅ |❌| -|PSS messaging|✅| ✅ |✅ | +|[Storage incentives](/docs/concepts/incentives/overview#storage-incentives)|✅| ❌ |❌| +|[SWAP incentives](/docs/concepts/incentives/bandwidth-incentives)|✅| ✅ |❌| +|[PSS messaging](/docs/concepts/pss/)|✅| ✅ |✅ | |Gnosis Chain Connection|✅| ✅ |❌ | -:::info -#### **Swarm Incentives Types** -In Swarm, there are two types of incentives for node operators, **storage incentives** which reward nodes for storing data chunks over time, and **bandwidth incentives** which reward nodes for transmitting data chunks across the network. - -**Storage incentives** - -By participating in the storage incentives protocol, full nodes which store data chunks with the network may join in the redistribution game for a chance to earn xBZZ. Staked xBZZ is required to earn storage incentives. Learn more in the [staking section](/docs/bee/working-with-bee/staking). - -**Bandwidth incentives (SWAP):** - -Bandwidth incentives (also referred to as the SWAP protocol) encourage full or light (but not ultra-light) nodes to share bandwidth with other nodes in exchange for payments from other nodes either [in-kind](https://www.investopedia.com/terms/p/paymentinkind.asp) or as a cheque to be settled at a future date. SWAP requires a chequebook contract to be set up on Gnosis Chain for each participating node. -::: - ## General Node Requirements diff --git a/docs/bee/installation/hive.md b/docs/bee/installation/hive.md index 7c005ce68..75893e342 100644 --- a/docs/bee/installation/hive.md +++ b/docs/bee/installation/hive.md @@ -8,8 +8,6 @@ wishing to scale up their Bee operation, or set up a commercial Bee hive should seek to run many instances of Bee simultaneously. Read [The Book of Swarm](https://www.ethswarm.org/the-book-of-swarm-2.pdf) for more information on how the swarm comes together. -Swarm provides tooling to help you install many Bees at once. - ### Docker Up to date [Docker images for Bee](/docs/bee/installation/docker) are provided. diff --git a/docs/bee/installation/package-manager.md b/docs/bee/installation/package-manager.md index 1db8d6186..f64cb4285 100644 --- a/docs/bee/installation/package-manager.md +++ b/docs/bee/installation/package-manager.md @@ -15,9 +15,7 @@ The Bee client can be [installed through a variety of package managers](/docs/be When a node is started using the `bee start` command the node process will be bound to the terminal session and will exit if the terminal is closed. - Depending on which of these startup methods was used, *the default Bee directories will be different*. For each startup method, a different default data directory is used, so each startup method will essentially be spinning up a totally different node. - - See the [configuration page](/docs/bee/working-with-bee/configuration) for more information about default data and config directories. + Depending on which of these startup methods was used, [*the default Bee directories will be different*](/docs/bee/working-with-bee/configuration#default-data-and-config-directories). For each startup method, a different default data directory is used, so each startup method will essentially be spinning up a totally different node. ::: diff --git a/docs/bee/working-with-bee/configuration.md b/docs/bee/working-with-bee/configuration.md index 3496cb74b..1d4e772e6 100644 --- a/docs/bee/working-with-bee/configuration.md +++ b/docs/bee/working-with-bee/configuration.md @@ -323,7 +323,7 @@ You can find the default configurations for your system in the [packaging folder Depending on the operating system and startup method used, the default data and configuration directories for your node will differ. -### Bee Service Default Directories +### Bee Service Default Directories (Package Manager Install) When installed using a package manager, Bee is set up to run as a service with default data and configuration directories set up automatically during the installation. The examples below include default directories for Linux and macOS. You can find the complete details of default directories for different operating systems in the `bee.yaml` files included in the [packaging folder of the Bee repo](https://github.com/ethersphere/bee/tree/master/packaging). diff --git a/docs/concepts/incentives/overview.mdx b/docs/concepts/incentives/overview.mdx index 6619cc1ec..843aeae6e 100644 --- a/docs/concepts/incentives/overview.mdx +++ b/docs/concepts/incentives/overview.mdx @@ -3,34 +3,44 @@ title: Incentives Overview id: overview --- -import { globalVariables } from '/src/config/globalVariables'; +import { globalVariables } from '/src/config/globalVariables' +A key challenge in a decentralized data network is incentivizing users to store data and provide bandwidth. Swarm addresses this with two incentive mechanisms: **storage incentives**, which reward nodes for storing data over time, and **bandwidth incentives**, which reward nodes for transmitting data across the network. Together, these mechanisms establish a self-sustaining economic system where nodes are compensated for contributing resources honestly. -One of the key challenges in a decentralised data network is incentivizing users to store data and provide bandwidth. Swarm addresses this challenge with two incentives systems, one which rewards nodes for sharing their storage space and another which rewards them for sharing bandwidth. The incentives system consists of multiple elements which work together to build a self sustaining economic system where nodes are rewarded for honestly providing their resources to the network. +Swarm's storage incentives are detailed in the [Future Proof Storage](https://www.ethswarm.org/swarm-storage-incentives.pdf) paper and [The Book of Swarm](https://papers.ethswarm.org/p/book-of-swarm/). -:::info -Swarm's storage incentives protocols are defined in depth in the [Future Proof Storage](https://www.ethswarm.org/swarm-storage-incentives.pdf) paper published by the Swarm team, and are also discussed in [The Book of Swarm](https://papers.ethswarm.org/p/book-of-swarm/). -::: +## Storage Incentives -## Storage Incentives +Storage incentives reward node operators for providing disk space and reliably storing data. The system is governed by three interconnected smart contracts: -Storage incentives are used to reward node operators for providing their disk space to the network and storing the data they are responsible for storing over time. The storage incentives system is composed of three smart contracts which work together to enact a self regulating economic system. The postage stamp contract manages payments for uploading data, the redistribution contract manages the redistribution of those payments to storer nodes, and the price oracle contract uses data from the redistribution contract to set the price for postage stamps in the postage stamp contract. +- **Postage Stamp Contract** – Handles payments for uploading data by way of purchasing "postage stamp batches". +- **Redistribution Contract** – Distributes payments for postage stamps to nodes that store data. +- **Price Oracle Contract** – Uses network redundancy data to determine postage stamp prices. +If you want to dig into the code, check out the [incentives contracts repo](https://github.com/ethersphere/storage-incentives) +You can find the on-chain address for each contract within the docs [here](/docs/references/smart-contracts#storage-incentives-contracts), however since the contracts there are updated manually, they may at times fall slightly behind the most recent changes. For the most up to date address for each storage incentives contract refer to the [storage incentives ABI repo](https://github.com/ethersphere/go-storage-incentives-abi/commits/master/abi/abi_mainnet.go), and you can also find past addresses of older versions of the incentives contracts by reviewing previous commits. -### Postage Stamps +### Postage Stamps -Postage stamps are used to pre-purchase the right to upload data on storm, much in the same way that real life postage stamps are used to pre-pay for use of the postal service. Postage stamps are purchased in batches rather than one by one, and are consumed when uploading data to Swarm. Postage stamp batches are purchased using xBZZ through the postage stamp smart contract . the xBZZ used to pay for postage stamp batches serve as the funds which are redistributed as storage incentives in the redistribution game. The price of postage stamps is set by the price oracle. Read more [here](/docs/concepts/incentives/postage-stamps). +Postage stamps are required to upload data to Swarm, similar to how real-world postage stamps prepay for mail delivery. Instead of being purchased individually, they are bought in batches using xBZZ through the postage stamp smart contract. -### Redistribution Game +The xBZZ used to buy postage stamps is later redistributed as storage incentives. The **price oracle contract** adjusts postage stamp pricing based on network redundancy to ensure a sustainable level of storage. You can find more details about postage stamps [here](/docs/concepts/incentives/postage-stamps). -The redistribution game is used to redistribute the xBZZ paid into the postage stamp contract to full staking nodes which contribute their disk space to the network. The game is designed in such a way that the most profitable way to participate is to honestly store all the data for which a node is responsible. The game's rules are determined by the redistribution smart contract. The results of the game also supply the utilization signal which is used by the price oracle to set the price for postage stamps. Read more [here](/docs/concepts/incentives/postage-stamps). +### Redistribution Game -### Price Oracle +The redistribution game determines how xBZZ from postage stamp purchases is distributed among full staking nodes that store data. The system is designed so that **honestly storing assigned data** is the most profitable strategy. Rules for this process are encoded in the [redistribution smart contract](https://github.com/ethersphere/storage-incentives). -The price oracle contract uses a utilization signal derived from the redistribution contract to set the price for postage stamps through the postage stamp contract. The utilization signal is based on a measure of data redundancy in the network. The postage stamp price is increased or decreased in order to maintain a healthy degree of redundancy. Read more [here](/docs/concepts/incentives/price-oracle). +Additionally, the game generates a **utilization signal**, which the price oracle uses to regulate postage stamp prices. Read more [here](/docs/concepts/incentives/redistribution-game). +### Price Oracle -## Bandwidth Incentives +The **price oracle contract** dynamically adjusts postage stamp prices using the utilization signal from the redistribution contract. This mechanism ensures optimal redundancy by increasing or decreasing costs as needed. Read more [here](/docs/concepts/incentives/price-oracle). + +## Bandwidth Incentives + +Nodes in Swarm not only store data but also serve and relay data across the network. **Bandwidth incentives** compensate nodes for these services. + +The **Swarm Accounting Protocol (SWAP)** facilitates bandwidth payments between nodes, which can be settled either **in-kind** (data exchange) or via **cheques** processed through a **chequebook contract** on Gnosis Chain. SWAP applies to full and light nodes but not ultra-light nodes. + +Read more [here](/docs/concepts/incentives/bandwidth-incentives). -In addition to storing data over time, nodes must also serve the data they store and must also relay data and messages to other nodes in the network. -Bandwidth incentives are used to reward nodes for relaying data across the network, both by serving up the data they store themselves and by serving as an intermediary relayer of data between other peers. The Swarm Accounting Protocol (SWAP) defines how bandwidth incentives work. At the core of SWAP is the concept of cheques along with the chequebook contract. Read more [here](/docs/concepts/incentives/bandwidth-incentives). \ No newline at end of file From 588f3b5d9b5927839502c246493c6d64fb2e01dd Mon Sep 17 00:00:00 2001 From: NoahMaizels Date: Thu, 30 Jan 2025 15:58:32 +0700 Subject: [PATCH 04/16] added link to make official site in build from source page and improved software recommendations in getting started section --- docs/bee/installation/build-from-source.md | 2 +- docs/bee/installation/getting-started.md | 39 +++++++++++++++++++--- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/docs/bee/installation/build-from-source.md b/docs/bee/installation/build-from-source.md index 82e98cb43..bff443d0e 100644 --- a/docs/bee/installation/build-from-source.md +++ b/docs/bee/installation/build-from-source.md @@ -11,7 +11,7 @@ Prerequisites for installing direct from source are: - **go** - download the latest release from [golang.org](https://golang.org/dl). - **git** - download from [git-scm.com](https://git-scm.com/). -- **make** - usually included in most operating systems. +- **make** - [make](https://www.gnu.org/software/make/) is usually included by default in most UNIX operating systems, and can be installed and used on almost any other operating system where it is not included by default. ### Build from Source diff --git a/docs/bee/installation/getting-started.md b/docs/bee/installation/getting-started.md index c9e6a7401..c4c64b331 100644 --- a/docs/bee/installation/getting-started.md +++ b/docs/bee/installation/getting-started.md @@ -45,13 +45,42 @@ A full node can upload and download data over the Swarm network. Additionally, a ## General Node Requirements -### Software +### Software Recommendations -* [jq utility](https://jqlang.github.io/jq/) for formatting JSON API output (optional) +Bee is a very flexible piece of software and plays well with many different systems and tools. The recommendations below are not absolute requirements, but following them will likely make your journey with Bee a bit easier. -:::info -The [`jq` utility](https://jqlang.github.io/jq/) is widely used throughout the documentation to automatically format the output from calls to the Bee API. It can help make API output much more readable, however its usage is optional. -::: +1. + We recommend using the [jq utility](https://jqlang.github.io/jq/) for formatting JSON API output if you intend to interact directly with the Bee API(optional). + + :::info + The [`jq` utility](https://jqlang.github.io/jq/) is widely used throughout the documentation to automatically format the output from calls to the Bee API. It can help make API output much more readable, however its usage is optional. + ::: + + *Recommended for anyone working directly with the Bee API.* +1. + Preferably use one of the officially supported operating systems. Refer to the [Bee repo releases section](https://github.com/ethersphere/bee/releases) for a list of releases for each supported operating system. It is also possible to [build Bee from source](/docs/bee/installation/build-from-source) for operating systems not included on the official release list in case you have this requirement. + + If you are using [Swarm Desktop](/docs/desktop/introduction/) rather than running the core Bee client directly, any commonly available operating system is a good choice (macOS, Windows, Ubuntu, etc.). + + :::info + A note on operating systems. While it is possible to run Bee on a wide variety of different operating system, much of the existing tooling and documentation is designed primarily for Unix based systems, so generally speaking, some flavor of Linux is probably the best choice. + ::: + + *These recommendations apply to all Bee users* +1. + We recommend using [`curl`](https://curl.se/) for making http requests to the BEE api, and it is widely used throughout the documentation for example interactions with the Bee API. It comes installed by default on many UNIX based operating systems, and is even now available on newer versions of Windows by default. You can also install [`curl` for Windows](https://curl.se/windows/) on your machine if it isn't included by default. Another similar option you may consider is [`wget`](https://www.gnu.org/software/wget/). + + You may also wish to use more feature rich tools for interacting with the Bee API such as [Insomnia](https://insomnia.rest/) or [Postman](https://www.postman.com/). While they are not open source, they do offer free versions and come with some useful features such as the ability to save and organize your commonly used fully formatted API requests. + + *These tools are not relevant for most Swarm Desktop users and are rather for users who wish to interact directly with their Bee client.* +1. + You may wish to use [Swarm CLI](https://docs.ethswarm.org/docs/bee/working-with-bee/swarm-cli/) for interacting with your Bee node from the command line rather than interacting directly with the Bee API through tools like `curl`, `wget`, `insomnia`, etc. Swarm CLI is built using [Bee JS](/docs/develop/tools-and-features/bee-js), a JavaScript library which greatly simplifies interaction with the Bee API. + + *Swarm CLI is not generally recommended for Swarm Desktop users, but rather for node operators or developers who wish to interact directly with their Bee client* +1. + Speaking of [Bee JS](/docs/develop/tools-and-features/bee-js), it is another tool you may consider using as a developer working with Bee as it significantly simplifies the process of interacting with the Bee API. + + *The same as Swarm CLI, Bee JS is not generally recommended for Swarm Desktop users, but rather for node operators or developers who wish to interact directly with their Bee client* ### Tokens From e242b9fb121d2c72ad244e7171c5c390a9831103 Mon Sep 17 00:00:00 2001 From: NoahMaizels Date: Mon, 3 Feb 2025 22:58:52 +0700 Subject: [PATCH 05/16] updates to getting started software recommendations and shell script supported systems info --- docs/bee/installation/getting-started.md | 13 +++++++------ docs/bee/installation/shell-script.md | 19 ++++++++++++++++++- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/docs/bee/installation/getting-started.md b/docs/bee/installation/getting-started.md index c4c64b331..1ddbfa2a4 100644 --- a/docs/bee/installation/getting-started.md +++ b/docs/bee/installation/getting-started.md @@ -45,6 +45,7 @@ A full node can upload and download data over the Swarm network. Additionally, a ## General Node Requirements + ### Software Recommendations Bee is a very flexible piece of software and plays well with many different systems and tools. The recommendations below are not absolute requirements, but following them will likely make your journey with Bee a bit easier. @@ -78,17 +79,17 @@ Bee is a very flexible piece of software and plays well with many different syst *Swarm CLI is not generally recommended for Swarm Desktop users, but rather for node operators or developers who wish to interact directly with their Bee client* 1. - Speaking of [Bee JS](/docs/develop/tools-and-features/bee-js), it is another tool you may consider using as a developer working with Bee as it significantly simplifies the process of interacting with the Bee API. - - *The same as Swarm CLI, Bee JS is not generally recommended for Swarm Desktop users, but rather for node operators or developers who wish to interact directly with their Bee client* + [Bee JS](/docs/develop/tools-and-features/bee-js) is an npm package can you may consider using as a developer working with Bee as it significantly simplifies the process of interacting with the Bee API. It can be easily integrated into any NodeJS app as an easy method of integrating Swarm into your DAPP. + + *The same as Swarm CLI, Bee JS is not generally recommended for Swarm Desktop users, but rather for developers who wish to interact directly with their Bee client* -### Tokens +### Token Requirements * A small amount of xDAI to pay for Gnosis Chain transactions, 0.1 xDAI should be enough * 10 xBZZ (BZZ on Gnosis Chain) is required for staking * A small amount of xBZZ for downloading and uploading from Swarm. You can start with 1 xBZZ and add more according to your usage needs. -### Network Considerations +### Network Requirements #### RPC Endpoints @@ -99,7 +100,7 @@ Both full and light nodes require a Gnosis Chain RPC endpoint which can be obtai If you are running on a home network you may need to configure your router to use [port forwarding](https://www.noip.com/support/knowledgebase/general-port-forwarding-guide) or take other steps to ensure your node is reachable by other nodes on the network. See [here](https://docs.ethswarm.org/docs/bee/installation/connectivity/#navigating-through-the-nat) for more guidance. If you are running on a VPS or cloud based server you will likely have no issues. -## Node Requirements By Node Type +## Node Requirements By Specific Node Type ### Ultra-Light Node diff --git a/docs/bee/installation/shell-script.md b/docs/bee/installation/shell-script.md index 9f9900c1b..d4ffcd288 100644 --- a/docs/bee/installation/shell-script.md +++ b/docs/bee/installation/shell-script.md @@ -40,6 +40,23 @@ Run the install shell script using either `curl` or `wget`: In the example below, the version is specified using `TAG=v2.4.0`, make sure that you [check if there is a newer tagged version of Bee](https://github.com/ethersphere/bee/tags) and if so, modify the commands below to use the most recent tag number so that you have the latest version of Bee. ::: +:::info +Note that while this shell script supports many commonly used Unix-like systems, it is not quite a universal installer tool. The architectures it supports include: + +**1. Linux:** +- `linux-386` (32-bit x86) +- `linux-amd64` (64-bit x86) +- `linux-arm64` (64-bit ARM) +- `linux-armv6` (32-bit ARM v6) + +**2. macOS (Darwin):** +- `darwin-arm64` (Apple Silicon, M1/M2/M3) +- `darwin-amd64` (Intel-based Mac) + +This means the script should work on most modern Linux distributions and macOS versions that match the supported architectures. +::: + + Date: Tue, 4 Feb 2025 19:13:01 +0700 Subject: [PATCH 06/16] various updates --- docs/bee/installation/getting-started.md | 66 ++++++--- docs/bee/installation/shell-script.md | 6 +- docs/bee/working-with-bee/backups.md | 56 +++++--- docs/bee/working-with-bee/configuration.md | 2 +- docs/bee/working-with-bee/uninstalling-bee.md | 130 ++++++++++++++++-- 5 files changed, 209 insertions(+), 51 deletions(-) diff --git a/docs/bee/installation/getting-started.md b/docs/bee/installation/getting-started.md index 1ddbfa2a4..aec63889a 100644 --- a/docs/bee/installation/getting-started.md +++ b/docs/bee/installation/getting-started.md @@ -3,7 +3,6 @@ title: Getting Started id: getting-started --- - In this guide we cover the basic background information you need to know to get started running a Bee node, such as: * [A list of Bee node types and their various features.](/docs/bee/installation/getting-started#node-types) @@ -12,6 +11,8 @@ In this guide we cover the basic background information you need to know to get * [How to choose the right node type.](/docs/bee/installation/getting-started#choosing-node-type-based-on-use-case) * [How to choose the appropriate installation method.](/docs/bee/installation/getting-started#choosing-installation-method) +This guide will walk you through how to choose the appropriate the node type, installation method, operating system, tools, and network setup for your particular needs. For new Bee users, it's recommended to read through this entire guide without skipping any sections before moving on to other pages. + ## Node Types Bee is a versatile piece of software that caters to a diverse array of use cases. It can be run in several different modes which each offer different features which are best suited for different users. There are three main categories of nodes: full nodes, light nodes, and ultra-light nodes. Node type is set by modifying the [appropriate configuration options](/docs/bee/working-with-bee/configuration#set-bee-node-type). @@ -41,47 +42,68 @@ A full node can upload and download data over the Swarm network. Additionally, a |[PSS messaging](/docs/concepts/pss/)|✅| ✅ |✅ | |Gnosis Chain Connection|✅| ✅ |❌ | +## General Node Requirements / Recommendations + +The requirements and recommendations outlined below all depend on your intended node type and intended use case. Review them carefully in order to determine with ones best suit your needs. +### Recommended Operating Systems -## General Node Requirements +Preferably use one of the officially supported operating systems. Refer to the [Bee repo releases section](https://github.com/ethersphere/bee/releases) for a list of releases for each supported operating system. It is also possible to [build Bee from source](/docs/bee/installation/build-from-source) for operating systems not included on the official release list in case you have this requirement. + +If you are using [Swarm Desktop](/docs/desktop/introduction/) rather than running the core Bee client directly, any commonly available operating system is a good choice (macOS, Windows, Ubuntu, etc.). + +:::info +A note on operating systems. While it is possible to run Bee on a wide variety of different operating system, much of the existing tooling and documentation is designed primarily for Unix based systems, so generally speaking, some flavor of Linux or macOS is probably the best choice. +::: +:::info +In case you only have access to Windows, [WSL](https://learn.microsoft.com/en-us/windows/wsl/install) is an excellent option which will allow you to run a Linux terminal which you can use to follow along with the guides in these docs. +::: ### Software Recommendations -Bee is a very flexible piece of software and plays well with many different systems and tools. The recommendations below are not absolute requirements, but following them will likely make your journey with Bee a bit easier. +Bee is a very flexible piece of software and plays well with many different systems and tools. The recommendations below are not absolute requirements, but following them will likely make your journey with Bee a bit easier. Some of them, such as `jq` and `curl`, will be required in order to follow along with the guides presented throughout these docs. + +:::info +Working with the [Bee API](/api/) is a requirement for Swarm developers and node operators. Several of the tools listed below make working with the Bee API easier, so while not required, it's still strongly recommended to install and try out each of these tools in order to determine which ones are most suitable for your use case. +::: -1. - We recommend using the [jq utility](https://jqlang.github.io/jq/) for formatting JSON API output if you intend to interact directly with the Bee API(optional). +#### 1. `jq` Utility + + The [`jq` utility](https://jqlang.github.io/jq/) is widely used throughout the documentation to automatically format the output from calls to the Bee API. It can help make API output much more readable, however its usage is optional. :::info - The [`jq` utility](https://jqlang.github.io/jq/) is widely used throughout the documentation to automatically format the output from calls to the Bee API. It can help make API output much more readable, however its usage is optional. + ***STRONGLY*** recommended for anyone working directly with the Bee API. ::: - *Recommended for anyone working directly with the Bee API.* -1. - Preferably use one of the officially supported operating systems. Refer to the [Bee repo releases section](https://github.com/ethersphere/bee/releases) for a list of releases for each supported operating system. It is also possible to [build Bee from source](/docs/bee/installation/build-from-source) for operating systems not included on the official release list in case you have this requirement. - If you are using [Swarm Desktop](/docs/desktop/introduction/) rather than running the core Bee client directly, any commonly available operating system is a good choice (macOS, Windows, Ubuntu, etc.). - :::info - A note on operating systems. While it is possible to run Bee on a wide variety of different operating system, much of the existing tooling and documentation is designed primarily for Unix based systems, so generally speaking, some flavor of Linux is probably the best choice. - ::: +#### 2. `curl` for API Interaction - *These recommendations apply to all Bee users* -1. - We recommend using [`curl`](https://curl.se/) for making http requests to the BEE api, and it is widely used throughout the documentation for example interactions with the Bee API. It comes installed by default on many UNIX based operating systems, and is even now available on newer versions of Windows by default. You can also install [`curl` for Windows](https://curl.se/windows/) on your machine if it isn't included by default. Another similar option you may consider is [`wget`](https://www.gnu.org/software/wget/). + We recommend using [`curl`](https://curl.se/) for making http requests to the Bee API, and it is widely used throughout the documentation for example interactions with the Bee API. It comes installed by default on many UNIX based operating systems, and is even now available on newer versions of Windows by default. You can also install [`curl` for Windows](https://curl.se/windows/) on your machine if it isn't included by default. Another similar option you may consider is [`wget`](https://www.gnu.org/software/wget/). You may also wish to use more feature rich tools for interacting with the Bee API such as [Insomnia](https://insomnia.rest/) or [Postman](https://www.postman.com/). While they are not open source, they do offer free versions and come with some useful features such as the ability to save and organize your commonly used fully formatted API requests. *These tools are not relevant for most Swarm Desktop users and are rather for users who wish to interact directly with their Bee client.* -1. - You may wish to use [Swarm CLI](https://docs.ethswarm.org/docs/bee/working-with-bee/swarm-cli/) for interacting with your Bee node from the command line rather than interacting directly with the Bee API through tools like `curl`, `wget`, `insomnia`, etc. Swarm CLI is built using [Bee JS](/docs/develop/tools-and-features/bee-js), a JavaScript library which greatly simplifies interaction with the Bee API. - *Swarm CLI is not generally recommended for Swarm Desktop users, but rather for node operators or developers who wish to interact directly with their Bee client* -1. + :::info + ***REQUIRED*** to use one of these tools or another tool with similar functionalities in order to send the the API requests required for working directly with the Bee API. + ::: + +#### 3. Swarm CLI for Command Line Control + [Swarm CLI](https://docs.ethswarm.org/docs/bee/working-with-bee/swarm-cli/) is an excellent choice for interacting with your Bee node from the command line using simple terminal commands. Swarm CLI is built using [Bee JS](/docs/develop/tools-and-features/bee-js), a JavaScript library which greatly simplifies interaction with the Bee API. + + :::info + Swarm CLI is not generally recommended for Swarm Desktop users, but rather for node operators or developers who wish to interact directly with their Bee client. It will allow you to access Bee node features using simple terminal commands as an alternative to formatting complete http requests with `curl` / `wget` / `insomnia`/ `postman`, etc. + ::: + +#### 4. Bee JS for App Integration + [Bee JS](/docs/develop/tools-and-features/bee-js) is an npm package can you may consider using as a developer working with Bee as it significantly simplifies the process of interacting with the Bee API. It can be easily integrated into any NodeJS app as an easy method of integrating Swarm into your DAPP. - *The same as Swarm CLI, Bee JS is not generally recommended for Swarm Desktop users, but rather for developers who wish to interact directly with their Bee client* + :::info + As with the Swarm CLI, Bee JS is not generally recommended for Swarm Desktop users. Bee JS is ideal for NodeJS developers who wish to interact directly with a Bee client without the need to format http requests and send them with tools like `curl` / `wget` / `insomnia`/ `postman`, etc. + ::: ### Token Requirements @@ -172,6 +194,8 @@ The [Swarm Desktop app](https://www.ethswarm.org/build/desktop) offers an easy w In order to develop a DAPP on Swarm, you will likely want to run either a ***light node*** or a ***full node***. For many use cases, a light node will be sufficient. However if you need to access certain features such as GSOC, then running a full node will be required. +Depending on your specific needs as a developer, even the [Swarm Desktop app](https://www.ethswarm.org/build/desktop) may be sufficient. + ### Support the Network and Earn xBZZ by Running a Full Node If you wish to earn [xBZZ](/docs/bee/working-with-bee/cashing-out) storage and bandwidth incentives and contribute to the strength of the Swarm network, running a **full node** is the right choice for you. It's easy to set up on a VPS, colocation, or any home computer that's connected to the internet. diff --git a/docs/bee/installation/shell-script.md b/docs/bee/installation/shell-script.md index d4ffcd288..09af85e03 100644 --- a/docs/bee/installation/shell-script.md +++ b/docs/bee/installation/shell-script.md @@ -53,10 +53,12 @@ Note that while this shell script supports many commonly used Unix-like systems, - `darwin-arm64` (Apple Silicon, M1/M2/M3) - `darwin-amd64` (Intel-based Mac) -This means the script should work on most modern Linux distributions and macOS versions that match the supported architectures. +This means the script should work on most modern Linux distributions and macOS versions that match the supported architectures, but not on Windows. However, you may consider using [WSL](https://learn.microsoft.com/en-us/windows/wsl/install) to run Linux on Windows as an alternative. ::: - +:::caution +You may need to install [`curl`](https://curl.se/) or [`wget`](https://www.gnu.org/software/wget/) if your system doesn't have one of them pre-installed and the shell script command fails to run. +::: /.bee` and for package manager installs it is `/var/lib/bee`. The directory structure is as follows: ``` ├── kademlia-metrics @@ -106,8 +127,11 @@ sudo cp -r /var/lib/bee/ backup ### Back-up your password -Depending on your configuration, your password may not be located in the `/bee` data directory which was copied in the previous step. If it has been specified in an environment variable or in your [`bee.yaml` configuration file](/docs/bee/working-with-bee/configuration#default-data-and-config-directories), make sure to copy it and save it together with the rest of your backup files or write it down in a safe place. +Depending on your [configuration](/docs/bee/working-with-bee/configuration) method, your password may be located in a variety of different locations. If you use a `.yaml` file for your configuration, then it might be found directly under the `password` option, or it could be that the location of your password file is recorded by the `password-file` option. In either case, make sure to record the password or password file as a part of your backup. + +The same holds true for the to other configuration methods. If you use environment variables for specifying your configuration options, your password itself will likely be specified in a `.env` file somewhere which contains either the password itself in the `BEE_PASSWORD` variable or the location of your password file in the `BEE_PASSWORD_FILE` variable. +The same again holds true for the command line flag method. Make sure you have the password you use with the `--password` command line flag or the password file specified by the `--password-file` flag saved in your backup. ### Back-up blockchain keys only diff --git a/docs/bee/working-with-bee/configuration.md b/docs/bee/working-with-bee/configuration.md index 1d4e772e6..7acbf131b 100644 --- a/docs/bee/working-with-bee/configuration.md +++ b/docs/bee/working-with-bee/configuration.md @@ -388,7 +388,7 @@ The default directories for your system may differ from the example above, so ma You can set your node's mode of operation by modifying its configuration options. There are three node types: `full`, `light`, and `ultra-light`. If you're not sure which type of node is right for you, check out the [Getting Started guide](/docs/bee/installation/getting-started). -There are three configuration options that must be configured to set your node type. These options are: +There are three configuration options that must be configured to set your node type. These options are listed below in each of the supported formats (command line flags, environment variables, and yaml values.): 1. `--full-node` / `BEE_FULL_NODE` / `full-node` 2. `--swap-enable` / `BEE_SWAP_ENABLE` / `swap-enable` diff --git a/docs/bee/working-with-bee/uninstalling-bee.md b/docs/bee/working-with-bee/uninstalling-bee.md index e26682461..de693e3aa 100644 --- a/docs/bee/working-with-bee/uninstalling-bee.md +++ b/docs/bee/working-with-bee/uninstalling-bee.md @@ -7,7 +7,7 @@ id: uninstalling-bee Choose the appropriate uninstall method based on the install method used: -### Package Manager Install +### Package Manager This method can be used for package manager based [installs](/docs/bee/installation/install#shell-script-install) of the official Debian, RPM, and Homebrew packages. @@ -29,23 +29,131 @@ sudo apt-get purge bee sudo yum remove bee ``` -### Binary Install -If Bee is installed using the [automated shell script](/docs/bee/installation/install#shell-script-install) or by [building from source](/docs/bee/installation/build-from-source), Bee can be uninstalled by directly removing the installed file. + +## Uninstalling Bee (Shell Script / Binary Install) + +If Bee was installed using the [automated shell script](/docs/bee/installation/shell-script-install) or as a binary by [building from source](/docs/bee/installation/build-from-source), it can be uninstalled by manually removing the installed binary, configuration files, and data directories. + + +### Identify Data and Config Locations + +The shell script install method may result in slightly different default data and configuration locations based on your system. The easiest way to find these locations is to check the default configuration using the `bee printconfig` command: ```bash -sudo rm /usr/local/bin/bee +bee printconfig ``` -## Remove Bee Data Files +The output from this command contains several dozen default configuration values, however we only include the two we need in the example output below, `config` and `data-dir`. These will reveal the default locations for the configuration files and data directory according to our specific system. -To completely remove all Bee files from your system you will also need to remove the config and data files. +These values will look something like this: -:::danger -Node keys, password, chunks and state files are stored in the data folder. [Make backups](/docs/bee/working-with-bee/backups) of your data folder to prevent losing keys and data. +```bash +# config file (default is $HOME/.bee.yaml) +config: /home/noah/.bee.yaml +# data directory +data-dir: /home/noah/.bee +``` + +### Backup Files (Optional) + + +**1. Remove the Bee Binary** + +First, check if the Bee binary exists: + +```bash +ls -l /usr/local/bin/bee +``` + +If it exists, remove it: + +```bash +sudo rm -f /usr/local/bin/bee +``` + +Verify that the binary has been removed: + +```bash +ls -l /usr/local/bin/bee +``` + +If Bee was built from source but not moved [as described in step 6](/docs/bee/installation/build-from-source) of the instructions for building from source, check the default build directory: + +```bash +ls -l ~/bee +``` + +If it exists, remove it: + +```bash +rm -rf ~/bee +``` + +Verify removal: + +```bash +ls -l ~/bee +``` + + +### **2. Backup Important Data First** + +Before proceeding, ensure you have backed up any necessary data. + +Bee stores **node keys, passwords, chunks, and state files** in its data directory. Without a backup, you will lose access to any funds managed by your node’s **Gnosis Chain account**, and you will also lose any **postage stamps** you have purchased. + +Follow the [official backup guide](https://docs.ethswarm.org/docs/bee/working-with-bee/backups) to avoid permanent data loss. + + + +### **3. Remove Configuration Files** + +Bee does not automatically generate a configuration file, but it looks for one at **`$HOME/.bee.yaml`** by default. If you have created a configuration file, you will need to remove it. + +### **Check for Configuration Files** + +**Default location for shell script installs:** + ```bash + ls -l $HOME/.bee.yaml + ``` + +### **Remove Configuration Files** +If the files exist, remove them: + +- **Remove user-level config file:** + ```bash + rm -f $HOME/.bee.yaml + ``` + + +### **Verify Removal** +Run the following commands to ensure the configuration files have been deleted: + +```bash +ls -l $HOME/.bee.yaml +``` + +If the command returns **"No such file or directory"**, the configuration file has been successfully removed. + +:::caution +If you have generated a config file and saved it to a non default location which you specify when starting your node using a command line flag (`--config`) or environment variable (`BEE_CONFIG`), then it is up to you to keep track of where you saved it and remove it yourself. ::: -### Bee +## **4. Remove Data Files** + +Bee stores its **node data, blockchain state, and other persistent files** in a data directory. If you want to fully remove Bee, this directory must be deleted. + + + + +## **6. Verify Uninstallation** + +Ensure Bee has been completely removed by running: + +```bash +command -v bee +``` + +If the command does **not return anything**, Bee has been successfully uninstalled. 🎉 -**Config folder:** Configuration file is stored in `/etc/bee/` -**Data folder:** State, keys, chunks, and other data are stored in `/var/lib/bee/` From b326537a8906b4aded0858a224008e30aa165b2b Mon Sep 17 00:00:00 2001 From: NoahMaizels Date: Thu, 6 Feb 2025 07:33:26 +0700 Subject: [PATCH 07/16] Spelling and grammar --- docs/bee/installation/getting-started.md | 32 ++++++++++++------------ docs/bee/installation/shell-script.md | 28 ++++++++++----------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/docs/bee/installation/getting-started.md b/docs/bee/installation/getting-started.md index aec63889a..755330ee0 100644 --- a/docs/bee/installation/getting-started.md +++ b/docs/bee/installation/getting-started.md @@ -7,7 +7,7 @@ In this guide we cover the basic background information you need to know to get * [A list of Bee node types and their various features.](/docs/bee/installation/getting-started#node-types) * [General requirements for running Bee nodes.](/docs/bee/installation/getting-started#general-node-requirements) -* [Specific requirements base on node type.](/docs/bee/installation/getting-started#node-requirements-by-node-type) +* [Specific requirements based on node type.](/docs/bee/installation/getting-started#node-requirements-by-node-type) * [How to choose the right node type.](/docs/bee/installation/getting-started#choosing-node-type-based-on-use-case) * [How to choose the appropriate installation method.](/docs/bee/installation/getting-started#choosing-installation-method) @@ -15,7 +15,7 @@ This guide will walk you through how to choose the appropriate the node type, in ## Node Types -Bee is a versatile piece of software that caters to a diverse array of use cases. It can be run in several different modes which each offer different features which are best suited for different users. There are three main categories of nodes: full nodes, light nodes, and ultra-light nodes. Node type is set by modifying the [appropriate configuration options](/docs/bee/working-with-bee/configuration#set-bee-node-type). +Bee is a versatile piece of software that caters to a diverse array of use cases. It can be run in several different modes each of which offers different features which are best suited for different users. There are three main categories of nodes: full nodes, light nodes, and ultra-light nodes. Node type is set by modifying the [appropriate configuration options](/docs/bee/working-with-bee/configuration#set-bee-node-type). ### Ultra-Light Node @@ -44,7 +44,7 @@ A full node can upload and download data over the Swarm network. Additionally, a ## General Node Requirements / Recommendations -The requirements and recommendations outlined below all depend on your intended node type and intended use case. Review them carefully in order to determine with ones best suit your needs. +The requirements and recommendations outlined below all depend on your intended node type and intended use case. Review them carefully in order to determine which ones best suit your needs. ### Recommended Operating Systems @@ -53,7 +53,7 @@ Preferably use one of the officially supported operating systems. Refer to the [ If you are using [Swarm Desktop](/docs/desktop/introduction/) rather than running the core Bee client directly, any commonly available operating system is a good choice (macOS, Windows, Ubuntu, etc.). :::info -A note on operating systems. While it is possible to run Bee on a wide variety of different operating system, much of the existing tooling and documentation is designed primarily for Unix based systems, so generally speaking, some flavor of Linux or macOS is probably the best choice. +A note on operating systems. While it is possible to run Bee on a wide variety of different operating systems, much of the existing tooling and documentation is designed primarily for Unix-based systems. So generally speaking, some flavor of Linux or macOS is probably the best choice. ::: :::info @@ -70,7 +70,7 @@ Working with the [Bee API](/api/) is a requirement for Swarm developers and node #### 1. `jq` Utility - The [`jq` utility](https://jqlang.github.io/jq/) is widely used throughout the documentation to automatically format the output from calls to the Bee API. It can help make API output much more readable, however its usage is optional. + The [`jq` utility](https://jqlang.github.io/jq/) is widely used throughout the documentation to automatically format the output from calls to the Bee API. It can help make API output much more readable; however, its usage is optional. :::info ***STRONGLY*** recommended for anyone working directly with the Bee API. @@ -82,12 +82,12 @@ Working with the [Bee API](/api/) is a requirement for Swarm developers and node We recommend using [`curl`](https://curl.se/) for making http requests to the Bee API, and it is widely used throughout the documentation for example interactions with the Bee API. It comes installed by default on many UNIX based operating systems, and is even now available on newer versions of Windows by default. You can also install [`curl` for Windows](https://curl.se/windows/) on your machine if it isn't included by default. Another similar option you may consider is [`wget`](https://www.gnu.org/software/wget/). - You may also wish to use more feature rich tools for interacting with the Bee API such as [Insomnia](https://insomnia.rest/) or [Postman](https://www.postman.com/). While they are not open source, they do offer free versions and come with some useful features such as the ability to save and organize your commonly used fully formatted API requests. + You may also wish to use more feature rich tools for interacting with the Bee API such as [Insomnia](https://insomnia.rest/) or [Postman](https://www.postman.com/). While they are not open source, they do offer free versions and come with some useful features such as the ability to save and organize your commonly used, fully formatted API requests. *These tools are not relevant for most Swarm Desktop users and are rather for users who wish to interact directly with their Bee client.* :::info - ***REQUIRED*** to use one of these tools or another tool with similar functionalities in order to send the the API requests required for working directly with the Bee API. + ***REQUIRED*** to use one of these tools or another tool with similar functionalities in order to send the API requests required for working directly with the Bee API. ::: #### 3. Swarm CLI for Command Line Control @@ -99,7 +99,7 @@ Working with the [Bee API](/api/) is a requirement for Swarm developers and node #### 4. Bee JS for App Integration - [Bee JS](/docs/develop/tools-and-features/bee-js) is an npm package can you may consider using as a developer working with Bee as it significantly simplifies the process of interacting with the Bee API. It can be easily integrated into any NodeJS app as an easy method of integrating Swarm into your DAPP. + [Bee JS](/docs/develop/tools-and-features/bee-js) is an npm package you may consider using as a developer working with Bee as it significantly simplifies the process of interacting with the Bee API. It can be easily integrated into any NodeJS app as an easy method of integrating Swarm into your DAPP. :::info As with the Swarm CLI, Bee JS is not generally recommended for Swarm Desktop users. Bee JS is ideal for NodeJS developers who wish to interact directly with a Bee client without the need to format http requests and send them with tools like `curl` / `wget` / `insomnia`/ `postman`, etc. @@ -120,13 +120,13 @@ Both full and light nodes require a Gnosis Chain RPC endpoint which can be obtai #### NAT and Port Forwarding -If you are running on a home network you may need to configure your router to use [port forwarding](https://www.noip.com/support/knowledgebase/general-port-forwarding-guide) or take other steps to ensure your node is reachable by other nodes on the network. See [here](https://docs.ethswarm.org/docs/bee/installation/connectivity/#navigating-through-the-nat) for more guidance. If you are running on a VPS or cloud based server you will likely have no issues. +If you are running on a home network, you may need to configure your router to use [port forwarding](https://www.noip.com/support/knowledgebase/general-port-forwarding-guide) or take other steps to ensure your node is reachable by other nodes on the network. See [here](https://docs.ethswarm.org/docs/bee/installation/connectivity/#navigating-through-the-nat) for more guidance. If you are running on a VPS or cloud based server you will likely have no issues. ## Node Requirements By Specific Node Type ### Ultra-Light Node -An ultra-light node has very minimal hardware requirements and can operate on practically any modern computer or VPS, including devices with baseline specs. It can even run on single-board computers like Raspberry Pi. +An ultra-light node has minimal hardware requirements and can operate on practically any modern computer or VPS, including devices with baseline specs. It can even run on single-board computers like Raspberry Pi. **Average Specs for Ultra-Light Node:** - **Processor**: Single-core or dual-core processor, 1 GHz or higher (e.g., Intel Atom, ARM Cortex-A series). @@ -153,7 +153,7 @@ These recommendations reflect the typical capabilities of affordable, readily av ### Full Node -A full node has significantly greater requirements since it is responsible for storing and syncing data from the Swarm network, and the requirements will be even higher in case that it is staking xBZZ and participating in the redistribution system for a chance to win xBZZ rewards. +A full node has significantly greater requirements since it is responsible for storing and syncing data from the Swarm network, and the requirements will be even higher if it is staking xBZZ and participating in the redistribution system for a chance to win xBZZ rewards. The minimum recommended specifications for a full staking node are: @@ -200,7 +200,7 @@ Depending on your specific needs as a developer, even the [Swarm Desktop app](ht If you wish to earn [xBZZ](/docs/bee/working-with-bee/cashing-out) storage and bandwidth incentives and contribute to the strength of the Swarm network, running a **full node** is the right choice for you. It's easy to set up on a VPS, colocation, or any home computer that's connected to the internet. -Since each full Bee node shares up to 2^22 chunks (~16gb of data), and due to the economics of running a Bee node, serious node operators will likely wish to scale up their operations to run multiple Bee nodes together in a hive so that they can take advantage of all the available disk space they have to share and maximize their earnings. While there are many possible approaches to doing so, and there is no one officially recommended method, you may consider tools such as [Docker](https://www.docker.com/), [Docker Compose](https://docs.docker.com/compose/), or [Kubernetes](https://kubernetes.io/) in order to orchestrate the deployment of a larger number of Bee nodes. +Since each full Bee node shares up to 2^22 chunks (~16GB of data), and due to the economics of running a Bee node, serious node operators will likely wish to scale up their operations to run multiple Bee nodes together in a hive so that they can take advantage of all the available disk space they have to share and maximize their earnings. While there are many possible approaches to doing so, and there is no one officially recommended method, you may consider tools such as [Docker](https://www.docker.com/), [Docker Compose](https://docs.docker.com/compose/), or [Kubernetes](https://kubernetes.io/) in order to orchestrate the deployment of a larger number of Bee nodes. ## Choosing Installation Method @@ -211,19 +211,19 @@ You can interact with the Swarm network by installing the Bee client through a v If you are looking to get started with exploring Swarm and interacting with the network in as simple and easy a way as possible, then [Swarm Desktop](/docs/desktop/introduction) is the way to go. -Swarm Desktop offers an easy and convenient to use graphical user interface so that users can easily upload and download from the Swarm, host their websites, and access a variety of Swarm DAPPs which come pre-bundled with Swarm Desktop. +Swarm Desktop offers an easy and convenient-to-use graphical user interface so that users can easily upload and download from the Swarm, host their websites, and access a variety of Swarm DAPPs that come pre-bundled with Swarm Desktop. ### [Shell Script Install](/docs/bee/installation/shell-script-install) If you're ready to go beyond the GUI based Swarm Desktop, then [the shell script install](/docs/bee/installation/shell-script-install) method may be right for you. This method uses a simple shell script to detect your operating system and environment and install the correct version of Bee for your machine. It's a convenient and minimalistic way of getting started with Swarm. -Because the shell script install is so minimalistic, it may require some additional tinkering to get it working the way you want it to. For example, it will not come set up to run in the background as a service out of the box, and logs will not be automatically saved. +Because the shell script installation is so minimalistic, it may require some additional tinkering to get it working the way you want it to. For example, it will not come set up to run in the background as a service out of the box, and logs will not be automatically saved. ### [Docker Install](/docs/bee/installation/docker) While the [Docker based installation](/docs/bee/installation/docker) method requires additional tooling not needed with the shell script install method, it also comes with several advantages which make it easier to operate your node across multiple different types of environments and also makes it easier to spin up multiple nodes at once. Combining it with tools like [Docker Compose](https://docs.docker.com/compose/) can open up even more options. -Unlike the shell script install method, Docker already comes with easy to use tools for running your containerized Bee node as a background process and for dealing with logs from your node. +Unlike the shell script installation method, Docker already comes with easy-to-use tools for running your containerized Bee node as a background process and for dealing with logs from your node. ### [Package Manager Install](/docs/bee/installation/package-manager-install) @@ -235,4 +235,4 @@ One of the disadvantages is that it can be less flexible than either the Docker ### [Building From Source](/docs/bee/installation/build-from-source) -For the more advanced of users, you may wish to build from source. You can find instructions for doing so [here](/docs/bee/installation/build-from-source). While this may be the most flexible of all methods, it's also the most difficult and requires the most hands-on setup and so is recommended for more advanced users / use cases. \ No newline at end of file +For more advanced users, you may wish to build from source. You can find instructions for doing so [here](/docs/bee/installation/build-from-source). While this may be the most flexible of all methods, it's also the most difficult and requires the most hands-on setup and so is recommended for more advanced users / use cases. \ No newline at end of file diff --git a/docs/bee/installation/shell-script.md b/docs/bee/installation/shell-script.md index 09af85e03..25f742f9b 100644 --- a/docs/bee/installation/shell-script.md +++ b/docs/bee/installation/shell-script.md @@ -12,7 +12,7 @@ import TabItem from '@theme/TabItem'; The following is a guide to get you started running a Bee node on Swarm using [the official shell script provided by Swarm](https://github.com/ethersphere/bee/blob/master/install.sh) which automatically detects your system and installs the correct version of Bee. This installation method is an excellent choice if you're looking for a minimalistic and flexible option for your Bee node installation. :::warning -Note that we append 127.0.0.1 (localhost) to our Bee API's port (1633 by default), since we do not want to expose our Bee API endpoint to the public internet, as that would allow anyone to control our node. Make sure you do the same, and it's also recommended to use a firewall to protect access to your node(s). +Note that we append 127.0.0.1 (localhost) to our Bee API's port (1633 by default), since we do not want to expose our Bee API endpoint to the public internet, as that would allow anyone to control our node. Make sure you do the same, and it's also recommended to use a firewall to restrict access to your node(s). ::: :::info @@ -22,14 +22,14 @@ This guide uses command line flag options in the node startup commands such as ` :::info **Bee Modes** -Bee nodes can be run in multiple modes with different functionalities. To run a node in full mode, both `--full-node` and `--swap-enable` must be set to true. To run a light node (uploads and downloads only), set `--full-node` to false and `--swap-enable` to `true`, or to run in ultra light mode (free tier downloads only) set both `--full-node` and `--swap-enable` to false. +Bee nodes can be run in multiple modes with different functionalities. To run a node in full mode, both `--full-node` and `--swap-enable` must be set to `true`. To run a light node (uploads and downloads only), set `--full-node` to false and `--swap-enable` to `true`, or to run in ultra-light mode (free tier downloads only) set both `--full-node` and `--swap-enable` to false. For more information on the different functionalities of each mode, as well as their different system requirements, refer to the [Getting Started guide](/docs/bee/installation/getting-started). ::: ## Install and Start Your Node -Below is a step by step guide for installing and setting up your Bee node using the shell script installation method. +Below is a step-by-step guide for installing and setting up your Bee node using the shell script installation method. ### Run Shell Script @@ -37,7 +37,7 @@ Below is a step by step guide for installing and setting up your Bee node using Run the install shell script using either `curl` or `wget`: :::caution -In the example below, the version is specified using `TAG=v2.4.0`, make sure that you [check if there is a newer tagged version of Bee](https://github.com/ethersphere/bee/tags) and if so, modify the commands below to use the most recent tag number so that you have the latest version of Bee. +In the example below, the version is specified using `TAG=v2.4.0`. Make sure that you [check if there is a newer tagged version of Bee](https://github.com/ethersphere/bee/tags) and if so, modify the commands below to use the most recent tag number so that you have the latest version of Bee. ::: :::info @@ -120,7 +120,7 @@ Use "bee [command] --help" for more information about a command. ### Node Startup Commands -Let's try starting up our node for the first time with the command below, make sure to pick a [strong password](https://xkcd.com/936/) of your own: +Let's try starting up our node for the first time with the command below. Make sure to pick a [strong password](https://xkcd.com/936/) of your own: Below are startup commands configured for each of the three Bee node types. @@ -133,7 +133,7 @@ values={[ ]}> -For the full node, we have `--full-node` and `--swap-enable` both enabled, and we've used `--blockchain-rpc-endpoint` to set our RPC endpoint ass `https://xdai.fairdatasociety.org`. You RPC endpoint may differ depending on your setup +For the full node, we have `--full-node` and `--swap-enable` both enabled, and we've used `--blockchain-rpc-endpoint` to set our RPC endpoint as `https://xdai.fairdatasociety.org`. Your RPC endpoint may differ depending on your setup. ```bash bee start \ @@ -156,7 +156,7 @@ bee start \ ``` - For the ultra-light node, we remove all three of the relevant settings to disable them (since they default to `false`), `--full-node`, `--swap-enable`, and `--blockchain-rpc-endpoint`. + For the ultra-light node, we omit all three of the relevant settings to disable them (since they default to `false`), `--full-node`, `--swap-enable`, and `--blockchain-rpc-endpoint`. ```bash bee start \ @@ -351,9 +351,9 @@ version: 2.2.0-06a0aca7 - planned to be supported until 11 December 2024, please ## Fund and Stake -Running a full node for the purpose of earning xBZZ by sharing disk space and participating in the redistribution game requires a minimum of 10 xBZZ and a small amount of xDAI (for initializing the chequebook contract and for paying for redistribution game related transactions). +Running a full node for the purpose of earning xBZZ by sharing disk space and participating in the redistribution game requires a minimum of 10 xBZZ and a small amount of xDAI (for initializing the chequebook contract and for paying for redistribution-related transactions). -While running a light note requires a small amount of xDAI to pay for initializing the chequebook contract and a smaller amount of xBZZ to pay for uploads and downloads. +While running a light node requires a small amount of xDAI to pay for initializing the chequebook contract and a smaller amount of xBZZ to pay for uploads and downloads. ### Fund node @@ -392,7 +392,7 @@ After acquiring some xDAI and some xBZZ, send them to the address you copied abo ***How Much to Send?*** -Only a very small amount of xDAI is needed to get started, 0.1 is more than enough. +Only a very small amount of xDAI is needed to get started, 0.1 xDAI is more than enough. You can start with just 2 or 3 xBZZ for uploading small amounts of data, but you will need at least 10 xBZZ if you plan on staking. @@ -503,7 +503,7 @@ We can see that our node has not yet finished syncing chunks since the `pullsync ### Stake node -Now we're ready to begin staking, we will slightly modify our startup command so that it now runs in the background instead of taking control of our terminal: +Now we're ready to begin staking. We will slightly modify our startup command so that it now runs in the background instead of taking control of our terminal: ```bash nohup bee start \ @@ -556,7 +556,7 @@ The results will be displayed in PLUR units (1 PLUR is equal to 1e-16 xBZZ). If {"stakedAmount":"100000000000000000"} ``` -Congratulations! You have now installed your Bee node and are connected to the network as a full staking node. Your node will now be in the process of syncing chunks from the network. Once it is fully synced, your node will finally be eligible for earning staking rewards. +Congratulations! You have now installed your Bee node and are connected to the network as a full staking node. Your node will now be in the process of syncing chunks from the network. Once the node is fully synced, your node will finally be eligible to earn staking rewards. ### Set Target Neighborhood @@ -605,7 +605,7 @@ To check your node's status as a staking node, we can use the `/redistributionst curl -s http://localhost:1633/redistributionstate | jq ``` -Below is the output for a node which has been running for several days: +Below is the output for a node that has been running for several days: ```bash { @@ -638,7 +638,7 @@ Once your node is up and running, make sure to [back up your keys](/docs/bee/wor ## Getting help -The CLI has documentation built-in. Running `bee` gives you an entry point to the documentation. Running `bee start -h` or `bee start --help` will tell you how you can configure your Bee node via the command line arguments. +The CLI has built-in documentation. Running `bee` gives you an entry point to the documentation. Running `bee start -h` or `bee start --help` will tell you how you can configure your Bee node via the command line arguments. You may also check out the [configuration guide](/docs/bee/working-with-bee/configuration), or simply run your Bee terminal command with the `--help` flag, eg. `bee start --help` or `bee --help`. From 35d468bf50d49ffa9575d95097e16a0d1d324b5a Mon Sep 17 00:00:00 2001 From: NoahMaizels Date: Tue, 11 Feb 2025 07:57:56 +0700 Subject: [PATCH 08/16] major updates to getting-started and fund-your-node pages --- docs/bee/installation/fund-your-node.md | 118 ++++++++++++++++-- docs/bee/installation/getting-started.md | 65 +++++----- .../incentives/redistribution-game.md | 2 +- 3 files changed, 143 insertions(+), 42 deletions(-) diff --git a/docs/bee/installation/fund-your-node.md b/docs/bee/installation/fund-your-node.md index 7d3630c82..ff661989c 100644 --- a/docs/bee/installation/fund-your-node.md +++ b/docs/bee/installation/fund-your-node.md @@ -3,16 +3,120 @@ title: Fund Your Node id: fund-your-node --- -In order to start your Bee node on the _mainnet_, its Gnosis Chain wallet must be -funded with: +Bee nodes require varying amounts of either [xDAI](/docs/references/tokens#xdai) or [xBZZ](/docs/references/tokens#xbzz) funds depending on the node type and use case. The amount and type of tokens required depend on these factors: + * Whether the node is an ultra-light, light, or full node + * Whether the node operator wishes to download or upload data, and how much data they wish to download or upload + * Whether the node operator wishes to participate in the storage incentives system and/or bandwidth incentives system -- 1 [xBZZ](/docs/references/glossary#xbzz-token), for traffic - accounting (this is optional, [see below](#basic-deployment)) +### **xDAI Requirements** + -- Some [xDAI](/docs/references/glossary#xdai-token), to pay the gas fees of - a couple of transactions on the [Gnosis Chain](/docs/references/glossary#gnosis-chain). +xDAI is required to pay for gas fees on the Gnosis Chain. There are ***four categories of transactions*** which require xDAI for on-chain transactions: + + 1. **Buying postage stamp batches (light / full nodes):** + + Postage stamp batches must be purchased in order to upload data to Swarm. Fees for issuing stamp batches are very low. For example, [this stamp batch creation transaction](https://gnosisscan.io/tx/0xdc350c059b7bfc10de3d71be71774dda395e2ff770ed6dc83a63c14a418d2be8) cost was only 0.00050416 xDAI. There will be an additional cost in xBZZ which will depend on the volume of storage purchased - see section below for details. -Take note that xBZZ is the [bridged](/docs/references/glossary#bridged-tokens) version of BZZ from Ethereum to the Gnosis Chain. + 1. **Stake management related transactions (full nodes only):** + + Transactions to manage stake require small amounts of xDAI. These types of transactions include adding stake, migrating stake, and withdrawing stake (partial stake withdrawal is only allowed [under certain conditions](/docs/bee/working-with-bee/staking/#partial-stake-withdrawals)). For example, this [staking transaction](https://gnosisscan.io/tx/0x3a3a5119e54c59f76b60c05bf434ef3d5ec1a3ec47875c3bf1da66dafccf5f72) was used to add 10 xBZZ stake (denominated in [PLUR](/docs/references/glossary/#plur) as 100000000000000000 PLUR). The xDAI cost for the transaction was very minimal, only 0.00026872 xDAI was spent. See section below which describes how much xBZZ stake is required. + + 1. **Storage incentives related transactions (full nodes only):** + + Full nodes which have staked the minimum required 10 xBZZ stake are eligible to earn [storage incentives](/docs/concepts/incentives/overview). They may even choose to [double their reserve size and stake a total of 20 xBZZ](/docs/bee/working-with-bee/staking/#reserve-doubling) in order to maximize their node's earning potential. Participating in storage incentives requires that nodes wait for their neighborhood to be chosen, and then send the required on-chain transactions for a chance to win some xBZZ. There are three types of storage incentives related transactions, [commit, reveal, and claim](/docs/concepts/incentives/redistribution-game/#redistribution-game-details). Each of these transactions require only a small amount of xDAI and typically are required only several times per month based on the current network situation, however over time they may add up, and xDAI may need to be topped up if it runs out. These [claim](https://gnosisscan.io/tx/0x88f83b0267539c663461e449f87118864ff9b801eaf6ea0fedadc1d824685181), [commit](https://gnosisscan.io/tx/0x91bdf7363535fb405547c50742d6070cd249dd4c2fc00d494c79b3dbf516b1f3), and [reveal](https://gnosisscan.io/tx/0x625dd6cd3cf8f9c1dfe27335884994b43519b0a59e0bb3968bd663d200d1772b) transactions each require 0.0009953, 0.0002918, and 0.0002918 xDAI respectively. + + 1. Bandwidth incentives related transactions (light and full nodes): + + When a new light or full node is initialized, the deployment of a bandwidth incentives contract (AKA SWAP contract) is required. Again, the xDAI fees are very small. For example, [this SWAP contract deployment transaction](https://gnosisscan.io/tx/0xc17b023ba22a9b2c2c27a40ce88d68caf95eb02e17ae57e9c56810b7b33a6ebc) cost only 0.00058154 xDAI. + +### **xBZZ Requirements** + + +xBZZ is required to purchase storage space on the Swarm network in the form of [postage stamps](/docs/concepts/incentives/postage-stamps). + + 1. **Buying postage stamp batches (light / full nodes):** + + Postage stamp batches must be purchased in order to upload data to Swarm. The amount of xBZZ required can vary widely depending on the amount storage volume required, as well as the required duration of storage time. Stamp batches have two inputs, `depth` and `amount`. The `depth` parameter determines how much data the batch can be used to upload while the `amount` parameter determines the duration of storage time. For example. + + :::info + The storage volume and duration are both non-deterministic. Volume is non-deterministic due to the details of how [postage stamp batch utilization](/docs/concepts/incentives/postage-stamps#batch-utilisation) works. While duration is non-deterministic due to price changes made by the [price oracle contract](/docs/concepts/incentives/price-oracle). + + **Storage volume and `depth`:** + + When purchasing stamp batches for larger volumes of data (by increasing the `depth` value), the amount of data which can be stored becomes increasingly more predictable. For example, at `depth` 22 a batch can store between 4.93 GB and 17.18 GB, while at `depth` 28, a batch can store between 1.0 and 1.1 TB of data, and at higher depths the difference between the minimum and maximum storage volumes approach the same value. + + **Storage duration and `amount`:** + + The duration of time for which a batch can store data is also non-deterministic since the price of storage is automatically adjusted over time by the [price oracle contract](/docs/concepts/incentives/price-oracle). However, limits have been placed on how swiftly the price of storage can change, so there is no danger of a rapid change in price causing postage batches to unexpectedly expire due to a rapid increase in price. + ::: + + 1. **Stake management related transactions (full nodes only):** + + Transactions to manage stake require small amounts of xDAI. These types of transactions include adding stake, migrating stake, and withdrawing stake (partial stake withdrawal is only allowed [under certain conditions](/docs/bee/working-with-bee/staking/#partial-stake-withdrawals)). For example, this [staking transaction](https://gnosisscan.io/tx/0x3a3a5119e54c59f76b60c05bf434ef3d5ec1a3ec47875c3bf1da66dafccf5f72) was used to add 10 xBZZ stake (denominated in [PLUR](/docs/references/glossary/#plur) as 100000000000000000 PLUR). The xDAI cost for the transaction was very minimal, only 0.00026872 xDAI was spent. See section below which describes how much xBZZ stake is required. + + 1. **Storage incentives related transactions (full nodes only):** + + Full nodes which have staked the minimum required 10 xBZZ stake are eligible to earn [storage incentives](/docs/concepts/incentives/overview). They may even choose to [double their reserve size and stake a total of 20 xBZZ](/docs/bee/working-with-bee/staking/#reserve-doubling) in order to maximize their node's earning potential. Participating in storage incentives requires that nodes wait for their neighborhood to be chosen, and then send the required on-chain transactions for a chance to win some xBZZ. There are three types of storage incentives related transactions, [commit, reveal, and claim](/docs/concepts/incentives/redistribution-game/#redistribution-game-details). Each of these transactions require only a small amount of xDAI and typically are required only several times per month based on the current network situation, however over time they may add up, and xDAI may need to be topped up if it runs out. These [claim](https://gnosisscan.io/tx/0x88f83b0267539c663461e449f87118864ff9b801eaf6ea0fedadc1d824685181), [commit](https://gnosisscan.io/tx/0x91bdf7363535fb405547c50742d6070cd249dd4c2fc00d494c79b3dbf516b1f3), and [reveal](https://gnosisscan.io/tx/0x625dd6cd3cf8f9c1dfe27335884994b43519b0a59e0bb3968bd663d200d1772b) transactions each require 0.0009953, 0.0002918, and 0.0002918 xDAI respectively. + + 1. Bandwidth incentives related transactions (light and full nodes): + + When a new light or full node is initialized, the deployment of a bandwidth incentives contract (AKA SWAP contract) is required. Again, the xDAI fees are very small. For example, [this SWAP contract deployment transaction](https://gnosisscan.io/tx/0xc17b023ba22a9b2c2c27a40ce88d68caf95eb02e17ae57e9c56810b7b33a6ebc) cost only 0.00058154 xDAI. + + +You can check exactly how much is required to get started from the `/redistributionstate` endpoint: + +```bash +root@noah-bee:~# curl localhost:1633/redistributionstate | jq + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed +100 304 100 304 0 0 15258 0 --:--:-- --:--:-- --:--:-- 16000 +{ + "minimumGasFunds": "3750000030000000", + "hasSufficientFunds": true, + "isFrozen": false, + "isFullySynced": false, + "phase": "reveal", + "round": 253280, + "lastWonRound": 0, + "lastPlayedRound": 0, + "lastFrozenRound": 0, + "lastSelectedRound": 0, + "lastSampleDurationSeconds": 0, + "block": 38498620, + "reward": "0", + "fees": "0", + "isHealthy": true +} +``` +The `3750000030000000` value listed for `minimumGasFunds` is the minimum required amount of xDAI denominated in Wei ($1 \text{xDAI} = 10^{18} \text{ Wei}$ +) required for staking + +- **For uploading/downloading**: Light and full nodes require xDAI for various transactions, such as issuing a chequebook contract and purchasing postage stamps. The required amount depends on usage. + +### **xBZZ Requirements** +xBZZ is required for Swarm storage and bandwidth incentives. +- **For staking**: A minimum of **10 xBZZ** is required as a stake for a **full node** participating in storage incentives. +- **For basic uploads**: **0.1 xBZZ** is a reasonable minimum to get started, though it is possible to begin with even less. However, significantly more will be needed for frequent or large uploads. +- **For downloading**: Some xBZZ is required to exceed the free download limits. + + + +## Token Requirements Based on Node Type and Use Case + +The amount of **xDAI** and **xBZZ** required to run a Bee node depends on the node type and intended use case. While **no tokens** are required to run an **ultra-light node**, both **light and full nodes** require some **xDAI** for gas fees and **xBZZ** for data transactions. + +### **Token Requirement Table** + +| **Use Case** | **Supported Node Type** | **xDAI Required** | **xBZZ Required** | +|--------------------------------------|--------------------|--------------------------|----------------------------| +| Free tier downloads (no uploads) | All | None | None | +| Downloading past free tier | Light / Full | None | ~0.1 xBZZ to get started, amount scales up with amount of downloaded data. | +| Basic uploading | Light / Full | ~0.1 xDAI is plenty to get started. For example, this | **~0.1 xBZZ**, [amount scales up with volume of uploaded data](/docs/develop/access-the-swarm/buy-a-stamp-batch). | +| Frequent/Large uploads | Light / Full | More xDAI recommended | **More xBZZ required** | +| Staking | Full | **0.1 xDAI** (minimum) | **10 xBZZ** (required) | +| Long-term staking | Full | More xDAI recommended | **10 xBZZ+** | + +This table provides a general guideline, but actual xDAI and xBZZ usage will depend on individual node activity and transaction fees at the time. ### A Node's Wallet diff --git a/docs/bee/installation/getting-started.md b/docs/bee/installation/getting-started.md index 755330ee0..bbc6bced5 100644 --- a/docs/bee/installation/getting-started.md +++ b/docs/bee/installation/getting-started.md @@ -3,7 +3,7 @@ title: Getting Started id: getting-started --- -In this guide we cover the basic background information you need to know to get started running a Bee node, such as: +In this guide, we cover the basic background information you need to know to start running a Bee node, such as: * [A list of Bee node types and their various features.](/docs/bee/installation/getting-started#node-types) * [General requirements for running Bee nodes.](/docs/bee/installation/getting-started#general-node-requirements) @@ -15,11 +15,11 @@ This guide will walk you through how to choose the appropriate the node type, in ## Node Types -Bee is a versatile piece of software that caters to a diverse array of use cases. It can be run in several different modes each of which offers different features which are best suited for different users. There are three main categories of nodes: full nodes, light nodes, and ultra-light nodes. Node type is set by modifying the [appropriate configuration options](/docs/bee/working-with-bee/configuration#set-bee-node-type). +Bee is a versatile piece of software that caters to a diverse array of use cases. It can be run in several different modes, each of which offers different features which are best suited for different users. There are three main categories of nodes: full nodes, light nodes, and ultra-light nodes. Node type is set by modifying the [appropriate configuration options](/docs/bee/working-with-bee/configuration#set-bee-node-type). ### Ultra-Light Node -The ultra-light configuration allows for limited access to the Swarm network and allows for a node to download only small amounts of data from the Swarm network. It does not allow for uploads. Ultra-light nodes may not earn any type of incentives. +The ultra-light configuration allows for limited access to the Swarm network and enables a node to download only small amounts of data from the Swarm network. It does not allow for uploads. Ultra-light nodes may not earn any type of incentives. ### Light Node @@ -27,7 +27,7 @@ A light node can both download and upload data over the Swarm network. Light nod ### Full Node -A full node can upload and download data over the Swarm network. Additionally, a full node can also share its disk space with the Swarm network where it will be employed by Swarm uploaders. Full nodes can earn storage incentives for sharing their disk space with the network, and can also earn bandwidth incentives just as light nodes can. +Full nodes offer the highest potential for earning xBZZ rewards. Like light nodes, a full node can upload and download data over the Swarm network and earn bandwidth incentives. Additionally, a full node can also earn xBZZ by sharing its disk space with the network. ### Features Comparison Chart @@ -44,11 +44,11 @@ A full node can upload and download data over the Swarm network. Additionally, a ## General Node Requirements / Recommendations -The requirements and recommendations outlined below all depend on your intended node type and intended use case. Review them carefully in order to determine which ones best suit your needs. +The requirements and recommendations outlined below depend on your intended node type and intended use case. Review them carefully in order to determine which ones best suit your needs. ### Recommended Operating Systems -Preferably use one of the officially supported operating systems. Refer to the [Bee repo releases section](https://github.com/ethersphere/bee/releases) for a list of releases for each supported operating system. It is also possible to [build Bee from source](/docs/bee/installation/build-from-source) for operating systems not included on the official release list in case you have this requirement. +It is preferable to use one of the officially supported operating systems. Refer to the [Bee repo releases section](https://github.com/ethersphere/bee/releases) for a list of releases for each supported operating system. It is also possible to [build Bee from source](/docs/bee/installation/build-from-source) for operating systems not included on the official release list in case you have this requirement. If you are using [Swarm Desktop](/docs/desktop/introduction/) rather than running the core Bee client directly, any commonly available operating system is a good choice (macOS, Windows, Ubuntu, etc.). @@ -60,50 +60,47 @@ A note on operating systems. While it is possible to run Bee on a wide variety o In case you only have access to Windows, [WSL](https://learn.microsoft.com/en-us/windows/wsl/install) is an excellent option which will allow you to run a Linux terminal which you can use to follow along with the guides in these docs. ::: -### Software Recommendations -Bee is a very flexible piece of software and plays well with many different systems and tools. The recommendations below are not absolute requirements, but following them will likely make your journey with Bee a bit easier. Some of them, such as `jq` and `curl`, will be required in order to follow along with the guides presented throughout these docs. +### Essential Tools -:::info -Working with the [Bee API](/api/) is a requirement for Swarm developers and node operators. Several of the tools listed below make working with the Bee API easier, so while not required, it's still strongly recommended to install and try out each of these tools in order to determine which ones are most suitable for your use case. -::: +While the tools listed below are not strictly required, they are highly recommended as they simplify interacting with Bee nodes. Some, like `jq` and `curl`, are essential for following the examples in these docs. Others, such as `swarm-cli` and `bee-js`, provide convenient ways to manage Bee nodes without manually constructing complex HTTP requests. -#### 1. `jq` Utility - - The [`jq` utility](https://jqlang.github.io/jq/) is widely used throughout the documentation to automatically format the output from calls to the Bee API. It can help make API output much more readable; however, its usage is optional. +#### 1. `jq` – JSON Formatting - :::info - ***STRONGLY*** recommended for anyone working directly with the Bee API. - ::: +[`jq`](https://jqlang.github.io/jq/) is widely used in this documentation to format API responses, making them more readable. +:::caution +***Strongly recommended*** for anyone working directly with the Bee API. +::: +#### 2. `curl` – API Requests -#### 2. `curl` for API Interaction +[`curl`](https://curl.se/) is the primary tool used in this documentation for interacting with the Bee API. It is pre-installed on most UNIX-based systems and newer Windows versions. If unavailable, you can install [`curl for Windows`](https://curl.se/windows/). - We recommend using [`curl`](https://curl.se/) for making http requests to the Bee API, and it is widely used throughout the documentation for example interactions with the Bee API. It comes installed by default on many UNIX based operating systems, and is even now available on newer versions of Windows by default. You can also install [`curl` for Windows](https://curl.se/windows/) on your machine if it isn't included by default. Another similar option you may consider is [`wget`](https://www.gnu.org/software/wget/). +An alternative is [`wget`](https://www.gnu.org/software/wget/), though feature-rich API clients like [Insomnia](https://insomnia.rest/) or [Postman](https://www.postman.com/) may also be useful for saving and organizing requests. - You may also wish to use more feature rich tools for interacting with the Bee API such as [Insomnia](https://insomnia.rest/) or [Postman](https://www.postman.com/). While they are not open source, they do offer free versions and come with some useful features such as the ability to save and organize your commonly used, fully formatted API requests. +*These tools are generally not relevant for Swarm Desktop users but are essential for those interacting directly with their Bee client.* - *These tools are not relevant for most Swarm Desktop users and are rather for users who wish to interact directly with their Bee client.* +:::caution +`curl` or one of its alternatives is ***Required*** for sending API requests to the Bee client. +::: - :::info - ***REQUIRED*** to use one of these tools or another tool with similar functionalities in order to send the API requests required for working directly with the Bee API. - ::: +#### 3. Swarm CLI – Command Line Control -#### 3. Swarm CLI for Command Line Control - [Swarm CLI](https://docs.ethswarm.org/docs/bee/working-with-bee/swarm-cli/) is an excellent choice for interacting with your Bee node from the command line using simple terminal commands. Swarm CLI is built using [Bee JS](/docs/develop/tools-and-features/bee-js), a JavaScript library which greatly simplifies interaction with the Bee API. +[Swarm CLI](https://docs.ethswarm.org/docs/bee/working-with-bee/swarm-cli/) provides an easy way to interact with Bee nodes via terminal commands. It is built on [Bee JS](/docs/develop/tools-and-features/bee-js) and serves as a simpler alternative to manually crafting HTTP requests. - :::info - Swarm CLI is not generally recommended for Swarm Desktop users, but rather for node operators or developers who wish to interact directly with their Bee client. It will allow you to access Bee node features using simple terminal commands as an alternative to formatting complete http requests with `curl` / `wget` / `insomnia`/ `postman`, etc. - ::: +:::info +Recommended for node operators and developers, not Swarm Desktop users. +::: -#### 4. Bee JS for App Integration +#### 4. Bee JS – API Integration for Developers - [Bee JS](/docs/develop/tools-and-features/bee-js) is an npm package you may consider using as a developer working with Bee as it significantly simplifies the process of interacting with the Bee API. It can be easily integrated into any NodeJS app as an easy method of integrating Swarm into your DAPP. +[Bee JS](/docs/develop/tools-and-features/bee-js) is an npm package for integrating Bee functionality into Node.js applications. It abstracts API interactions, eliminating the need for manual HTTP requests except for a small number of edge cases (such as new features which have not yet been added to `bee-js`). - :::info - As with the Swarm CLI, Bee JS is not generally recommended for Swarm Desktop users. Bee JS is ideal for NodeJS developers who wish to interact directly with a Bee client without the need to format http requests and send them with tools like `curl` / `wget` / `insomnia`/ `postman`, etc. - ::: +:::info +Best suited for Node.js developers who want to interact with Bee programmatically. +::: + ### Token Requirements diff --git a/docs/concepts/incentives/redistribution-game.md b/docs/concepts/incentives/redistribution-game.md index 75dae81e7..9646259f5 100644 --- a/docs/concepts/incentives/redistribution-game.md +++ b/docs/concepts/incentives/redistribution-game.md @@ -10,7 +10,7 @@ The redistribution game is used to redistribute the xBZZ which is accumulated by ### Redistribution Game Details -When someone wants to upload data to Swarm, they do so by buying postage stamp batches with xBZZ. The xBZZ is collected and later paid out to storage provider nodes as a part of the redistribution game. Every 152 Gnosis Chain blocks a single [neighborhood](/docs/concepts/DISC/neighborhoods) is selected to play the redistribution game. For each round of the game, one node from the selected neighborhood will have the chance to win a reward which is paid out from the accumulated xBZZ. +When someone wants to upload data to Swarm, they do so by buying postage stamp batches with xBZZ. The xBZZ is collected and later paid out to storage provider nodes as a part of the redistribution game. Every 152 Gnosis Chain blocks ***a single [neighborhood](/docs/concepts/DISC/neighborhoods)*** is selected to play the redistribution game. For each round of the game, one node from the selected neighborhood will have the chance to win a reward which is paid out from the accumulated xBZZ. The game has 3 phases, `commit`, `reveal`, and `claim`. In the `reveal` phase of a previous game, an "anchor" address is randomly generated and used to determine the neighborhood for the current round. From 431a59805fc1e970b577427441627cfae7b221ac Mon Sep 17 00:00:00 2001 From: NoahMaizels Date: Tue, 11 Feb 2025 08:39:04 +0700 Subject: [PATCH 09/16] update fund-your-node and buy-a-stamp-batch pages with new info / reorg --- docs/bee/installation/fund-your-node.md | 38 +++---------------- .../access-the-swarm/buy-a-stamp-batch.md | 37 ++++++++++++++++++ 2 files changed, 43 insertions(+), 32 deletions(-) diff --git a/docs/bee/installation/fund-your-node.md b/docs/bee/installation/fund-your-node.md index ff661989c..ece09759d 100644 --- a/docs/bee/installation/fund-your-node.md +++ b/docs/bee/installation/fund-your-node.md @@ -32,37 +32,17 @@ xDAI is required to pay for gas fees on the Gnosis Chain. There are ***four cate ### **xBZZ Requirements** -xBZZ is required to purchase storage space on the Swarm network in the form of [postage stamps](/docs/concepts/incentives/postage-stamps). + xBZZ is required to purchase storage space in order to upload data on the Swarm network in the form of [postage stamps](/docs/concepts/incentives/postage-stamps), and is also required to pay for bandwidth costs when downloading data. 1. **Buying postage stamp batches (light / full nodes):** - Postage stamp batches must be purchased in order to upload data to Swarm. The amount of xBZZ required can vary widely depending on the amount storage volume required, as well as the required duration of storage time. Stamp batches have two inputs, `depth` and `amount`. The `depth` parameter determines how much data the batch can be used to upload while the `amount` parameter determines the duration of storage time. For example. - - :::info - The storage volume and duration are both non-deterministic. Volume is non-deterministic due to the details of how [postage stamp batch utilization](/docs/concepts/incentives/postage-stamps#batch-utilisation) works. While duration is non-deterministic due to price changes made by the [price oracle contract](/docs/concepts/incentives/price-oracle). - - **Storage volume and `depth`:** - - When purchasing stamp batches for larger volumes of data (by increasing the `depth` value), the amount of data which can be stored becomes increasingly more predictable. For example, at `depth` 22 a batch can store between 4.93 GB and 17.18 GB, while at `depth` 28, a batch can store between 1.0 and 1.1 TB of data, and at higher depths the difference between the minimum and maximum storage volumes approach the same value. - - **Storage duration and `amount`:** - - The duration of time for which a batch can store data is also non-deterministic since the price of storage is automatically adjusted over time by the [price oracle contract](/docs/concepts/incentives/price-oracle). However, limits have been placed on how swiftly the price of storage can change, so there is no danger of a rapid change in price causing postage batches to unexpectedly expire due to a rapid increase in price. - ::: - - 1. **Stake management related transactions (full nodes only):** - - Transactions to manage stake require small amounts of xDAI. These types of transactions include adding stake, migrating stake, and withdrawing stake (partial stake withdrawal is only allowed [under certain conditions](/docs/bee/working-with-bee/staking/#partial-stake-withdrawals)). For example, this [staking transaction](https://gnosisscan.io/tx/0x3a3a5119e54c59f76b60c05bf434ef3d5ec1a3ec47875c3bf1da66dafccf5f72) was used to add 10 xBZZ stake (denominated in [PLUR](/docs/references/glossary/#plur) as 100000000000000000 PLUR). The xDAI cost for the transaction was very minimal, only 0.00026872 xDAI was spent. See section below which describes how much xBZZ stake is required. - - 1. **Storage incentives related transactions (full nodes only):** - - Full nodes which have staked the minimum required 10 xBZZ stake are eligible to earn [storage incentives](/docs/concepts/incentives/overview). They may even choose to [double their reserve size and stake a total of 20 xBZZ](/docs/bee/working-with-bee/staking/#reserve-doubling) in order to maximize their node's earning potential. Participating in storage incentives requires that nodes wait for their neighborhood to be chosen, and then send the required on-chain transactions for a chance to win some xBZZ. There are three types of storage incentives related transactions, [commit, reveal, and claim](/docs/concepts/incentives/redistribution-game/#redistribution-game-details). Each of these transactions require only a small amount of xDAI and typically are required only several times per month based on the current network situation, however over time they may add up, and xDAI may need to be topped up if it runs out. These [claim](https://gnosisscan.io/tx/0x88f83b0267539c663461e449f87118864ff9b801eaf6ea0fedadc1d824685181), [commit](https://gnosisscan.io/tx/0x91bdf7363535fb405547c50742d6070cd249dd4c2fc00d494c79b3dbf516b1f3), and [reveal](https://gnosisscan.io/tx/0x625dd6cd3cf8f9c1dfe27335884994b43519b0a59e0bb3968bd663d200d1772b) transactions each require 0.0009953, 0.0002918, and 0.0002918 xDAI respectively. - - 1. Bandwidth incentives related transactions (light and full nodes): - - When a new light or full node is initialized, the deployment of a bandwidth incentives contract (AKA SWAP contract) is required. Again, the xDAI fees are very small. For example, [this SWAP contract deployment transaction](https://gnosisscan.io/tx/0xc17b023ba22a9b2c2c27a40ce88d68caf95eb02e17ae57e9c56810b7b33a6ebc) cost only 0.00058154 xDAI. + Postage stamp batches must be purchased in order to upload data to Swarm. The amount of xBZZ required can vary widely depending on the amount storage volume required, as well as the required duration of storage time. Stamp batches have two inputs, `depth` and `amount`. The `depth` parameter determines how much data the batch can be used to upload while the `amount` parameter determines the duration of storage time. Refer to [this page](/docs/develop/access-the-swarm/buy-a-stamp-batch) for more information about how `depth` and `amount` affect the storage volume and duration, and how to choose an appropriate `depth` and `amount` for your postage stamp batch. + + 1. **Staking (full nodes):** + A minimum of 10 xBZZ is required to be staked in order to be eligible for earning storage incentives. If [reserve doubling](/docs/bee/working-with-bee/staking/#reserve-doubling) is used, an additional 10 xBZZ for a total of 20 xBZZ may be staked in order to optimize storage incentives earning potential for a node. You can [read more about staking here](/docs/bee/working-with-bee/staking/). + 1. **Bandwidth Payments (SWAP / Chequebook Payments):** You can check exactly how much is required to get started from the `/redistributionstate` endpoint: ```bash @@ -93,12 +73,6 @@ The `3750000030000000` value listed for `minimumGasFunds` is the minimum require - **For uploading/downloading**: Light and full nodes require xDAI for various transactions, such as issuing a chequebook contract and purchasing postage stamps. The required amount depends on usage. -### **xBZZ Requirements** -xBZZ is required for Swarm storage and bandwidth incentives. -- **For staking**: A minimum of **10 xBZZ** is required as a stake for a **full node** participating in storage incentives. -- **For basic uploads**: **0.1 xBZZ** is a reasonable minimum to get started, though it is possible to begin with even less. However, significantly more will be needed for frequent or large uploads. -- **For downloading**: Some xBZZ is required to exceed the free download limits. - ## Token Requirements Based on Node Type and Use Case diff --git a/docs/develop/access-the-swarm/buy-a-stamp-batch.md b/docs/develop/access-the-swarm/buy-a-stamp-batch.md index 5118b9512..882deaf4e 100644 --- a/docs/develop/access-the-swarm/buy-a-stamp-batch.md +++ b/docs/develop/access-the-swarm/buy-a-stamp-batch.md @@ -12,6 +12,41 @@ import TabItem from '@theme/TabItem'; A postage batch is required to upload data to Swarm. Postage stamp batches represent _right to write_ data on Swarm's [DISC (Distributed Immutable Store of Chunks)](/docs/concepts/DISC/). The parameters which control the duration and quantity of data that can be stored by a postage batch are `depth` and `amount`, with `depth` determining data volume that can be uploaded by the batch and `amount` determining storage duration of data uploaded with the batch. +:::info + The storage volume and duration are both non-deterministic. Volume is non-deterministic due to the details of how [postage stamp batch utilization](/docs/concepts/incentives/postage-stamps#batch-utilisation) works. While duration is non-deterministic due to price changes made by the [price oracle contract](/docs/concepts/incentives/price-oracle). + + **Storage volume and `depth`:** + + When purchasing stamp batches for larger volumes of data (by increasing the `depth` value), the amount of data which can be stored becomes increasingly more predictable. For example, at `depth` 22 a batch can store between 4.93 GB and 17.18 GB, while at `depth` 28, a batch can store between 1.0 and 1.1 TB of data, and at higher depths the difference between the minimum and maximum storage volumes approach the same value. + + **Storage duration and `amount`:** + + The duration of time for which a batch can store data is also non-deterministic since the price of storage is automatically adjusted over time by the [price oracle contract](/docs/concepts/incentives/price-oracle). However, limits have been placed on how swiftly the price of storage can change, so there is no danger of a rapid change in price causing postage batches to unexpectedly expire due to a rapid increase in price. You can view a history of price changes by inspecting [the events emitted by the oracle contract](https://gnosisscan.io/address/0x47EeF336e7fE5bED98499A4696bce8f28c1B0a8b#events), or also through the [Swarmscan API](https://api.swarmscan.io/v1/events/storage-price-oracle/price-update). As you can see, if and when postage batch prices are updated, the updates are quite small. Still, since it is not entirely deterministic, it is important to monitor your stamp batch TTL (time to live) as it will change along with price oracle changes. You can inspect your batch's TTL using the `/stamps` endpoint of the API: + + ```bash + root@noah-bee:~# curl -s localhost:1633/stamps | jq + { + "stamps": [ + { + "batchID": "f56af59cc2c785a3b45bbf3e46c3c4b20f80379339ef337b5bbf45ebe5629a66", + "utilization": 0, + "usable": true, + "label": "", + "depth": 17, + "amount": "432072000", + "bucketDepth": 16, + "blockNumber": 38498819, + "immutableFlag": true, + "exists": true, + "batchTTL": 82943 + } + ] + } + ``` + Here we can see from the `batchTTL` that `82943` seconds remain, or approximately 23 hours. + ::: + + For a deeper understanding of how `depth` and `amount` parameters determine the data volume and storage duration of a postage batch, see the [postage stamp page](/docs/concepts/incentives/postage-stamps/). ## Fund your node's wallet. @@ -22,6 +57,8 @@ xBZZ can be obtained from a variety of different centralized and decentralized e xDAI can be obtained from a wide range of centralized and decentralized exchanges. See [this list of exchanges](https://docs.gnosischain.com/about/tokens/xdai) from the Gnosis Chain documentation to get started. +You can learn more details from the [Fund Your Node](/docs/bee/installation/fund-your-node/) section. + ## Buying a stamp batch When interacting with the Bee API directly, `amount` and `depth` are passed as path parameters: From 82f3bbc6a0226d904a5fdc21effbd030c0428273 Mon Sep 17 00:00:00 2001 From: NoahMaizels Date: Tue, 11 Feb 2025 18:13:48 +0700 Subject: [PATCH 10/16] funding and staking pages --- docs/bee/installation/fund-your-node.md | 147 ++++++++++++++---------- docs/bee/working-with-bee/staking.md | 45 +++++++- 2 files changed, 127 insertions(+), 65 deletions(-) diff --git a/docs/bee/installation/fund-your-node.md b/docs/bee/installation/fund-your-node.md index ece09759d..f97ecf7ba 100644 --- a/docs/bee/installation/fund-your-node.md +++ b/docs/bee/installation/fund-your-node.md @@ -3,92 +3,115 @@ title: Fund Your Node id: fund-your-node --- -Bee nodes require varying amounts of either [xDAI](/docs/references/tokens#xdai) or [xBZZ](/docs/references/tokens#xbzz) funds depending on the node type and use case. The amount and type of tokens required depend on these factors: - * Whether the node is an ultra-light, light, or full node - * Whether the node operator wishes to download or upload data, and how much data they wish to download or upload - * Whether the node operator wishes to participate in the storage incentives system and/or bandwidth incentives system -### **xDAI Requirements** - -xDAI is required to pay for gas fees on the Gnosis Chain. There are ***four categories of transactions*** which require xDAI for on-chain transactions: +## **Fund Your Node** + +Bee nodes require varying amounts of either [xDAI](/docs/references/tokens#xdai) or [xBZZ](/docs/references/tokens#xbzz) funds, depending on the node type and use case. The amount and type of tokens required depend on the following factors: + +- Whether the node is an [ultra-light, light, or full node](/docs/bee/installation/getting-started#node-types). +- Whether the node operator wishes to [download](/docs/develop/access-the-swarm/upload-and-download/#download-a-file) or [upload data](/docs/develop/access-the-swarm/buy-a-stamp-batch) and how much data they intend to handle. +- Whether the node operator wishes to participate in the [storage incentives system](/docs/bee/working-with-bee/staking/) and/or the [bandwidth incentives system](/docs/concepts/incentives/bandwidth-incentives/). + + +## **xDAI Requirements** + +xDAI is required to pay for gas fees on the Gnosis Chain. There are ***four categories of transactions*** that require xDAI for on-chain interactions: - 1. **Buying postage stamp batches (light / full nodes):** - - Postage stamp batches must be purchased in order to upload data to Swarm. Fees for issuing stamp batches are very low. For example, [this stamp batch creation transaction](https://gnosisscan.io/tx/0xdc350c059b7bfc10de3d71be71774dda395e2ff770ed6dc83a63c14a418d2be8) cost was only 0.00050416 xDAI. There will be an additional cost in xBZZ which will depend on the volume of storage purchased - see section below for details. - 1. **Stake management related transactions (full nodes only):** +### **1. [Buying Postage Stamp Batches](/docs/concepts/incentives/postage-stamps) (Light / Full Nodes)** - Transactions to manage stake require small amounts of xDAI. These types of transactions include adding stake, migrating stake, and withdrawing stake (partial stake withdrawal is only allowed [under certain conditions](/docs/bee/working-with-bee/staking/#partial-stake-withdrawals)). For example, this [staking transaction](https://gnosisscan.io/tx/0x3a3a5119e54c59f76b60c05bf434ef3d5ec1a3ec47875c3bf1da66dafccf5f72) was used to add 10 xBZZ stake (denominated in [PLUR](/docs/references/glossary/#plur) as 100000000000000000 PLUR). The xDAI cost for the transaction was very minimal, only 0.00026872 xDAI was spent. See section below which describes how much xBZZ stake is required. +Postage stamp batches must be purchased to upload data to Swarm. The fees for issuing stamp batches are minimal. For example, [this stamp batch creation transaction](https://gnosisscan.io/tx/0xdc350c059b7bfc10de3d71be71774dda395e2ff770ed6dc83a63c14a418d2be8) cost only **0.00050416 xDAI**. - 1. **Storage incentives related transactions (full nodes only):** +Additionally, xBZZ is required based on the volume of storage purchased—see [the xBZZ section below](/docs/bee/installation/fund-your-node#xbzz-requirements) for details. - Full nodes which have staked the minimum required 10 xBZZ stake are eligible to earn [storage incentives](/docs/concepts/incentives/overview). They may even choose to [double their reserve size and stake a total of 20 xBZZ](/docs/bee/working-with-bee/staking/#reserve-doubling) in order to maximize their node's earning potential. Participating in storage incentives requires that nodes wait for their neighborhood to be chosen, and then send the required on-chain transactions for a chance to win some xBZZ. There are three types of storage incentives related transactions, [commit, reveal, and claim](/docs/concepts/incentives/redistribution-game/#redistribution-game-details). Each of these transactions require only a small amount of xDAI and typically are required only several times per month based on the current network situation, however over time they may add up, and xDAI may need to be topped up if it runs out. These [claim](https://gnosisscan.io/tx/0x88f83b0267539c663461e449f87118864ff9b801eaf6ea0fedadc1d824685181), [commit](https://gnosisscan.io/tx/0x91bdf7363535fb405547c50742d6070cd249dd4c2fc00d494c79b3dbf516b1f3), and [reveal](https://gnosisscan.io/tx/0x625dd6cd3cf8f9c1dfe27335884994b43519b0a59e0bb3968bd663d200d1772b) transactions each require 0.0009953, 0.0002918, and 0.0002918 xDAI respectively. +### **2. [Stake Management Transactions](/docs/bee/working-with-bee/staking/#maximize-rewards) (Full Nodes Only)** - 1. Bandwidth incentives related transactions (light and full nodes): +Stake management transactions include: - When a new light or full node is initialized, the deployment of a bandwidth incentives contract (AKA SWAP contract) is required. Again, the xDAI fees are very small. For example, [this SWAP contract deployment transaction](https://gnosisscan.io/tx/0xc17b023ba22a9b2c2c27a40ce88d68caf95eb02e17ae57e9c56810b7b33a6ebc) cost only 0.00058154 xDAI. +- [Adding stake](/docs/bee/working-with-bee/staking/#add-stake). +- [Partial stake withdrawals](/docs/bee/working-with-bee/staking/#partial-stake-withdrawals). +- [Stake migration](/api/#tag/Staking/paths/~1stake/delete) when a new staking contract is deployed. -### **xBZZ Requirements** - +Each of these transactions requires a small amount of xDAI to pay for Gnosis Chain gas fees. For example, this [staking transaction](https://gnosisscan.io/tx/0x3a3a5119e54c59f76b60c05bf434ef3d5ec1a3ec47875c3bf1da66dafccf5f72) added **10 xBZZ** in stake (denominated in [PLUR](/docs/references/glossary/#plur) as 1e16 PLUR (100,000,000,000,000,000 PLUR). The xDAI cost for the transaction was minimal—only **0.00026872 xDAI**. - xBZZ is required to purchase storage space in order to upload data on the Swarm network in the form of [postage stamps](/docs/concepts/incentives/postage-stamps), and is also required to pay for bandwidth costs when downloading data. - - 1. **Buying postage stamp batches (light / full nodes):** - - Postage stamp batches must be purchased in order to upload data to Swarm. The amount of xBZZ required can vary widely depending on the amount storage volume required, as well as the required duration of storage time. Stamp batches have two inputs, `depth` and `amount`. The `depth` parameter determines how much data the batch can be used to upload while the `amount` parameter determines the duration of storage time. Refer to [this page](/docs/develop/access-the-swarm/buy-a-stamp-batch) for more information about how `depth` and `amount` affect the storage volume and duration, and how to choose an appropriate `depth` and `amount` for your postage stamp batch. +See the section below for details on required xBZZ stake amounts. - +### **3. [Storage Incentives Transactions](/docs/concepts/incentives/overview) (Full Nodes Only)** - 1. **Staking (full nodes):** - A minimum of 10 xBZZ is required to be staked in order to be eligible for earning storage incentives. If [reserve doubling](/docs/bee/working-with-bee/staking/#reserve-doubling) is used, an additional 10 xBZZ for a total of 20 xBZZ may be staked in order to optimize storage incentives earning potential for a node. You can [read more about staking here](/docs/bee/working-with-bee/staking/). - 1. **Bandwidth Payments (SWAP / Chequebook Payments):** -You can check exactly how much is required to get started from the `/redistributionstate` endpoint: +Full nodes with at least **10 xBZZ** in stake are eligible to earn storage incentives. They may choose to [double their reserve size and stake a total of 20 xBZZ](/docs/bee/working-with-bee/staking/#reserve-doubling) to maximize earning potential. -```bash -root@noah-bee:~# curl localhost:1633/redistributionstate | jq - % Total % Received % Xferd Average Speed Time Time Time Current - Dload Upload Total Spent Left Speed -100 304 100 304 0 0 15258 0 --:--:-- --:--:-- --:--:-- 16000 -{ - "minimumGasFunds": "3750000030000000", - "hasSufficientFunds": true, - "isFrozen": false, - "isFullySynced": false, - "phase": "reveal", - "round": 253280, - "lastWonRound": 0, - "lastPlayedRound": 0, - "lastFrozenRound": 0, - "lastSelectedRound": 0, - "lastSampleDurationSeconds": 0, - "block": 38498620, - "reward": "0", - "fees": "0", - "isHealthy": true -} -``` -The `3750000030000000` value listed for `minimumGasFunds` is the minimum required amount of xDAI denominated in Wei ($1 \text{xDAI} = 10^{18} \text{ Wei}$ -) required for staking +Participating in storage incentives requires nodes to wait for their neighborhood to be selected and then send on-chain transactions for a chance to earn xBZZ. + +There are three types of storage incentive transactions: **commit, reveal, and claim** ([details here](/docs/concepts/incentives/redistribution-game/#redistribution-game-details)). Each requires only a small amount of xDAI and typically occurs a few times per month. However, over time, xDAI may need to be replenished if depleted. + +As an example reference, the gas costs from several months ago were: + +- [Claim](https://gnosisscan.io/tx/0x88f83b0267539c663461e449f87118864ff9b801eaf6ea0fedadc1d824685181): **0.0009953 xDAI** +- [Commit](https://gnosisscan.io/tx/0x91bdf7363535fb405547c50742d6070cd249dd4c2fc00d494c79b3dbf516b1f3): **0.0002918 xDAI** +- [Reveal](https://gnosisscan.io/tx/0x625dd6cd3cf8f9c1dfe27335884994b43519b0a59e0bb3968bd663d200d1772b): **0.0002918 xDAI** + +*Note that while the gas costs today are roughly similar to the examples above, gas fees may change over time due to potential network congestion and a variety of other factors.* + + +### **4. [Bandwidth Incentives Transactions](/docs/concepts/incentives/bandwidth-incentives) (Light and Full Nodes)** -- **For uploading/downloading**: Light and full nodes require xDAI for various transactions, such as issuing a chequebook contract and purchasing postage stamps. The required amount depends on usage. +When initializing a new light or full node, deploying a bandwidth incentives contract (also called a **SWAP contract**) is required. The xDAI gas fees for this are minimal. +For example, [this SWAP contract deployment transaction](https://gnosisscan.io/tx/0xc17b023ba22a9b2c2c27a40ce88d68caf95eb02e17ae57e9c56810b7b33a6ebc) cost only **0.00058154 xDAI**. +## **xBZZ Requirements** + +xBZZ is used to pay for storing and retrieving data on Swarm. It is required for ***three categories of transactions***: + +### **1. [Buying Postage Stamp Batches](/docs/concepts/incentives/postage-stamps) (Light / Full Nodes)** + +To upload data, postage stamp batches must be purchased. The required xBZZ amount varies based on: + +- **Storage volume** needed. +- **Storage duration** required. + +Stamp batches use two parameters: **depth** (determines data capacity) and **amount** (determines storage duration). See [this page](/docs/develop/access-the-swarm/buy-a-stamp-batch) for details on selecting appropriate values. + +### **2. [Staking](/docs/bee/working-with-bee/staking/) (Full Nodes Only)** + +A **minimum stake of 10 xBZZ** is required to participate in storage incentives. Nodes opting for [reserve doubling](/docs/bee/working-with-bee/staking/#reserve-doubling) may stake **20 xBZZ** to optimize earnings. + +### **3. [Bandwidth (SWAP) Payments](/docs/concepts/incentives/bandwidth-incentives) (Light / Full Nodes)** + +Bandwidth payments are required for downloading and uploading data. + +- **Ultra-light nodes**: Free-tier downloads only; no uploads. +- **Light and full nodes**: Must deploy a [SWAP contract](/docs/concepts/incentives/bandwidth-incentives) before making bandwidth payments. + +The **SWAP contract deployment fee** is minimal—for example, [this transaction](https://gnosisscan.io/tx/0x09438217f75516df1319eb772d503126ab38ecf52e6d9fd626411a238e0d687a) cost **0.00018542 xDAI**. + + +:::info +**Cost Estimates for Bandwidth Payments** + +- **Downloading 1GB**: ~**0.5 xBZZ** in SWAP payments. +- **Uploading**: Requires a funded SWAP contract. + +Running a **full/light node** with `swap-enable` turned on allows nodes to **earn bandwidth incentives** by providing bandwidth to others. Actual xBZZ costs depend on network activity and should be actively monitored. +::: + ## Token Requirements Based on Node Type and Use Case The amount of **xDAI** and **xBZZ** required to run a Bee node depends on the node type and intended use case. While **no tokens** are required to run an **ultra-light node**, both **light and full nodes** require some **xDAI** for gas fees and **xBZZ** for data transactions. ### **Token Requirement Table** -| **Use Case** | **Supported Node Type** | **xDAI Required** | **xBZZ Required** | -|--------------------------------------|--------------------|--------------------------|----------------------------| -| Free tier downloads (no uploads) | All | None | None | -| Downloading past free tier | Light / Full | None | ~0.1 xBZZ to get started, amount scales up with amount of downloaded data. | -| Basic uploading | Light / Full | ~0.1 xDAI is plenty to get started. For example, this | **~0.1 xBZZ**, [amount scales up with volume of uploaded data](/docs/develop/access-the-swarm/buy-a-stamp-batch). | -| Frequent/Large uploads | Light / Full | More xDAI recommended | **More xBZZ required** | -| Staking | Full | **0.1 xDAI** (minimum) | **10 xBZZ** (required) | -| Long-term staking | Full | More xDAI recommended | **10 xBZZ+** | + +| **Use Case** | **Supported Node Type** | **Amount of xDAI Required** | **Amount of xBZZ Required** | +|--------------------------------------|------------------------------|-----------------------------------------------------|-----------------------------------------------------| +| **Free tier downloads (no uploads)** | Ultra-Light, Light, Full | None | None | +| **Downloading beyond free tier** | Light, Full | A small amount such as **~0.1 xDAI** is more than enough to deploy the [SWAP/chequebook contract](/docs/concepts/incentives/bandwidth-incentives) | **~0.1 xBZZ** is enough to get started uploading smaller amounts of data, but more will be required once entering the GB range | +| **Uploading Data** | Light, Full | **~0.1 xDAI** is more than enough for both the initial SWAP/chequebook deployment transaction and the postage stamp batch purchase gas fees | **~0.1 xBZZ** will be enough to upload and store a small amount of data for a short period, but [considerably more xBZZ is required](/docs/develop/access-the-swarm/buy-a-stamp-batch#setting-stamp-batch-parameters-and-options) to store larger amounts of data for a longer time(scales with uploaded volume) | +| **Staking** | Full | **0.1 xDAI** is a reasonable minimum for getting started, more is recommended for long term operation. Staking related transactions occur several times a month and can cost up to around 0.001 xBZZ per transaction. | **10 xBZZ** (minimum required stake, **20 xBZZ** is required for staking with a [doubled reserve](/docs/bee/working-with-bee/staking/#reserve-doubling)). Stake is generally speaking not withdrawable. | +| **Participating in storage incentives** | Full | **Small amount of xDAI** (for commit, reveal, claim transactions) | **10 xBZZ** (minimum required stake) | +| **Bandwidth (SWAP) payments** | Light, Full | **~0.0005 xDAI** (for initial SWAP contract deployment) | **Scales with bandwidth usage** (~0.5 xBZZ per GB downloaded) | | This table provides a general guideline, but actual xDAI and xBZZ usage will depend on individual node activity and transaction fees at the time. diff --git a/docs/bee/working-with-bee/staking.md b/docs/bee/working-with-bee/staking.md index 8b2b05c4e..8f1def8c9 100644 --- a/docs/bee/working-with-bee/staking.md +++ b/docs/bee/working-with-bee/staking.md @@ -3,20 +3,59 @@ title: Staking id: staking --- -In order to participate in the redistribution of xBZZ from uploaders to storers, storers must first deposit a non-refundable xBZZ stake with a smart contract. Then, they are going to be chosen for payout with a probability proportional to their stake in their neighborhood, as long as they can log storing the part of the content that they are supposed to be storing according to protocol rules. +In order to earn storage incentives by participating in the redistribution of xBZZ from uploaders to storers, storers must first deposit a non-refundable xBZZ stake with a smart contract. Then, they are going to be chosen for payout with a probability proportional to their stake in their neighborhood, as long as they can log storing the part of the content that they are supposed to be storing according to protocol rules. + +:::danger +Staked xBZZ CANNOT be withdrawn after being staked under typical circumstances. Only stake your xBZZ if you really plan on participating in staking as a full node, as you will not be able to withdraw it later. +::: In order to participate in redistribution, storers need to do the following: -- Join the network and download all the data that the protocol assigns to them. They can only participate if they are fully synchronised with the network. +- Join the network and download all the data that the protocol assigns to them. They can only participate if they are fully synchronized with the network. - Deposit a stake with the staking contract. There is a minimum staking requirement, presently 10 xBZZ. It can change in the future. - Stay online and fully synced, so that when a redistribution round comes, their node can check whether their neighborhood (nodes that are assigned the same content to store) has been selected and if so, they can perform a certain calculation (a random sampling) on their content and submit the result to the redistribution contract. This happens in two phases (commit and reveal), so that the nodes cannot know the results of others’ calculations when committing to their own. - Round length is estimated around 15 minutes (152 blocks to be precise), though it can be extended. Amongst the nodes that agree with the correct result, one is chosen — with a probability in proportion to their stake — as the winner. The winner must execute an on-chain transaction claiming their reward, which is the entire pot of storage rent paid since the previous round, or even more, if the previous pot has not been claimed at that time. +## Add xDAI + +In order to stake and continue to participate in the storage incentives system your node will need to continually issue related transactions on the Gnosis Chain blockchain. Therefore you will need to fund your node with some xDAI before you can get started with staking. + +:::info +You can check exactly how much xDAI is required to get started with staking from the `/redistributionstate` endpoint: + +```bash +root@noah-bee:~# curl localhost:1633/redistributionstate | jq + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed +100 304 100 304 0 0 15258 0 --:--:-- --:--:-- --:--:-- 16000 +{ + "minimumGasFunds": "3750000030000000", + "hasSufficientFunds": true, + "isFrozen": false, + "isFullySynced": false, + "phase": "reveal", + "round": 253280, + "lastWonRound": 0, + "lastPlayedRound": 0, + "lastFrozenRound": 0, + "lastSelectedRound": 0, + "lastSampleDurationSeconds": 0, + "block": 38498620, + "reward": "0", + "fees": "0", + "isHealthy": true +} +``` +The `"3750000030000000"` value listed for `"minimumGasFunds"` is the minimum required amount of xDAI denominated in Wei ($1 \text{xDAI} = 10^{18} \text{ Wei}$) required for staking. That is equivalent to 0.00375000003 xDAI. However, it's recommended to add more than just the minimum amount, since it will quickly be used up by storage incentives related transaction fees. As little as a 1 xDAI should last for quite a while since an average incentives related transaction fee is as small as around 0.001 xDAI or even considerably less. +::: + + ## Add stake -Bee has builtin endpoints for depositing the stake. Currently the minimum staking requirement is 10 xBZZ, so make sure that there is enough tokens in the node's wallet and you must have some native token as well for paying the gas. +Bee has builtin endpoints for depositing the stake. Currently the minimum staking requirement is 10 xBZZ, so make sure that there is enough xBZZ tokens in the node's wallet. You must also have some native xDAI tokens as well for paying the gas fees for staking and storage incentives related transactions. + Then you can run the following command to stake 10 xBZZ. The amount is given in PLUR which is the smallest denomination of xBZZ and `1 xBZZ == 1e16 PLUR`. From af0b65bb17fbc2a8644661b94ac88494ab330ce6 Mon Sep 17 00:00:00 2001 From: tamas6 <81620050+tamas6@users.noreply.github.com> Date: Wed, 12 Feb 2025 20:46:49 +0100 Subject: [PATCH 11/16] pinning updated swarm-cli method --- docs/develop/access-the-swarm/pinning.md | 107 +++++++++++++++++------ 1 file changed, 78 insertions(+), 29 deletions(-) diff --git a/docs/develop/access-the-swarm/pinning.md b/docs/develop/access-the-swarm/pinning.md index ce7d4f77b..0490fbc42 100644 --- a/docs/develop/access-the-swarm/pinning.md +++ b/docs/develop/access-the-swarm/pinning.md @@ -3,43 +3,68 @@ title: Pinning id: pinning --- -Each Bee node is configured to reserve a certain amount of memory on your computer's hard drive to store and serve chunks within their _neighborhood of responsibility_ for other nodes in the Swarm network. Once this alloted space has been filled, each Bee node deletes older chunks to make way for newer ones as they are uploaded by the network. +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + +Each Bee node is configured to reserve a certain amount of memory on your computer's hard drive to store and serve chunks within their _neighborhood of responsibility_ for other nodes in the Swarm network. Once this allotted space has been filled, each Bee node deletes older chunks to make way for newer ones as they are uploaded by the network. Each time a chunk is accessed, it is moved back to the end of the deletion queue, so that regularly accessed content stays alive in the network and is not deleted by a node's garbage collection routine. Bee nodes provide a facility to **pin** important content so that it is not deleted by the node's garbage collection routine. Chunks can be _pinned_ either during upload, or retrospectively using the Swarm reference. - ## Pin During Upload + + + + To store content so that it will persist even when Bee's garbage collection routine is deleting old chunks, we simply pass the `Swarm-Pin` header set to `true` when uploading. ```bash -curl -H "Swarm-Pin: true" -H "Swarm-Postage-Batch-Id: 78a26be9b42317fe6f0cbea3e47cbd0cf34f533db4e9c91cf92be40eb2968264" --data-binary @bee.mp4 localhost:1633/bzz\?bee.mp4 +curl -H "Swarm-Pin: true" -H "Swarm-Postage-Batch-Id: 78a26be9b42317fe6f0cbea3e47cbd0cf34f533db4e9c91cf92be40eb2968264" --data-binary @bee.mp4 localhost:1633/bzz?bee.mp4 ``` -```json -{ - "reference": "1bfe7c3ce4100ae7f02b62e38d3e8d4c3a86ea368349614a87827402f20cbb30" -} + + + +To pin content during upload using swarm-cli: + +```bash +swarm-cli pinning pin --file bee.mp4 --stamp 78a26be9b42317fe6f0cbea3e47cbd0cf34f533db4e9c91cf92be40eb2968264 ``` + + + + ## Administer Pinned Content + + + To check what content is currently pinned on your node, query the `pins` endpoint of your Bee API: ```bash curl localhost:1633/pins ``` -```json -{ - "references": [ - "1bfe7c3ce4100ae7f02b62e38d3e8d4c3a86ea368349614a87827402f20cbb30" - ] -} + + + +To check pinned content using swarm-cli: + +```bash +swarm-cli pinning list ``` + + + or, to check for specific references: ```bash @@ -48,19 +73,32 @@ curl localhost:1633/pins/1bfe7c3ce4100ae7f02b62e38d3e8d4c3a86ea368349614a8782740 A `404` response indicates the content is not available. -### Unpinning Content +## Unpinning Content + + + We can unpin content by sending a `DELETE` request to the pinning endpoint using the same reference: -````bash -curl -XDELETE http://localhost:1633/pins/1bfe7c3ce4100ae7f02b62e38d3e8d4c3a86ea368349614a87827402f20cbb30 -`` +```bash +curl -X DELETE http://localhost:1633/pins/1bfe7c3ce4100ae7f02b62e38d3e8d4c3a86ea368349614a87827402f20cbb30 -```json -{"message":"OK","code":200} -```` +``` + + -Now, when check again, we will get a `404` error as the content is no longer pinned. + +To unpin content using swarm-cli: + +```bash +swarm-cli pinning unpin --hash 1bfe7c3ce4100ae7f02b62e38d3e8d4c3a86ea368349614a87827402f20cbb30 +``` + + + + + +Now, when checking again, we will get a `404` error as the content is no longer pinned. ```bash curl localhost:1633/pins/1bfe7c3ce4100ae7f02b62e38d3e8d4c3a86ea368349614a87827402f20cbb30 @@ -71,11 +109,13 @@ curl localhost:1633/pins/1bfe7c3ce4100ae7f02b62e38d3e8d4c3a86ea368349614a8782740 ``` :::info -Pinning and unpinning is possible for files (as in the example) and also the chunks, directories, and bytes endpoints. See the [API](/api/) documentation for more details. -::: +Pinning and unpinning is possible for files (as in the example) and also the chunks, directories, and bytes endpoints. See the [API](/api/) documentation for more details.::: + +## Pinning Already Uploaded Content -### Pinning Already Uploaded Content + + The previous example showed how we can pin content upon upload. It is also possible to pin content that is already uploaded and present in the Swarm. To do so, we can send a `POST` request including the swarm reference to the files pinning endpoint. @@ -84,11 +124,20 @@ To do so, we can send a `POST` request including the swarm reference to the file curl -X POST http://localhost:1633/pins/7b344ea68c699b0eca8bb4cfb3a77eb24f5e4e8ab50d38165e0fb48368350e8f ``` -```json -{ "message": "OK", "code": 200 } + + + +To pin already uploaded content using swarm-cli: + +```bash +swarm-cli pinning pin --hash 7b344ea68c699b0eca8bb4cfb3a77eb24f5e4e8ab50d38165e0fb48368350e8f ``` -The `pins` operation will attempt to fetch the content from the network if it is not available on the local node. + + + + +The pins operation will attempt to fetch the content from the network if it is not available on the local node. Now, if we query our files pinning endpoint again, the swarm reference will be returned. @@ -98,10 +147,10 @@ curl http://localhost:1633/pins/7b344ea68c699b0eca8bb4cfb3a77eb24f5e4e8ab50d3816 ```json { - "reference": "7b344ea68c699b0eca8bb4cfb3a77eb24f5e4e8ab50d38165e0fb48368350e8f" + "reference": "7b344ea68c699b0eca8bb4cfb3a77eb24f5e4e8ab50d38165e0fb48368350e8f" } ``` -:::warning +::::warning While the pin operation will attempt to fetch content from the network if it is not available locally, we advise you to ensure that the content is available locally before calling the pin operation. If the content, for whatever reason, is only fetched partially from the network, the pin operation only partly succeeds and leaves the internal administration of pinning in an inconsistent state. ::: From 515ceef02116ca2e03a9d1560daaaf128d33c37f Mon Sep 17 00:00:00 2001 From: tamas6 <81620050+tamas6@users.noreply.github.com> Date: Thu, 13 Feb 2025 16:09:09 +0100 Subject: [PATCH 12/16] faucets edit --- docs/bee/installation/fund-your-node.md | 124 +++++++----------- docs/bee/working-with-bee/configuration.md | 57 ++++---- .../starting-a-test-network.md | 34 +++-- docs/references/glossary.md | 86 ++++++------ 4 files changed, 130 insertions(+), 171 deletions(-) diff --git a/docs/bee/installation/fund-your-node.md b/docs/bee/installation/fund-your-node.md index f97ecf7ba..b98c23121 100644 --- a/docs/bee/installation/fund-your-node.md +++ b/docs/bee/installation/fund-your-node.md @@ -3,8 +3,6 @@ title: Fund Your Node id: fund-your-node --- - - ## **Fund Your Node** Bee nodes require varying amounts of either [xDAI](/docs/references/tokens#xdai) or [xBZZ](/docs/references/tokens#xbzz) funds, depending on the node type and use case. The amount and type of tokens required depend on the following factors: @@ -13,19 +11,17 @@ Bee nodes require varying amounts of either [xDAI](/docs/references/tokens#xdai) - Whether the node operator wishes to [download](/docs/develop/access-the-swarm/upload-and-download/#download-a-file) or [upload data](/docs/develop/access-the-swarm/buy-a-stamp-batch) and how much data they intend to handle. - Whether the node operator wishes to participate in the [storage incentives system](/docs/bee/working-with-bee/staking/) and/or the [bandwidth incentives system](/docs/concepts/incentives/bandwidth-incentives/). - ## **xDAI Requirements** -xDAI is required to pay for gas fees on the Gnosis Chain. There are ***four categories of transactions*** that require xDAI for on-chain interactions: - +xDAI is required to pay for gas fees on the Gnosis Chain. There are **_four categories of transactions_** that require xDAI for on-chain interactions: -### **1. [Buying Postage Stamp Batches](/docs/concepts/incentives/postage-stamps) (Light / Full Nodes)** +### **1. [Buying Postage Stamp Batches](/docs/concepts/incentives/postage-stamps) (Light / Full Nodes)** -Postage stamp batches must be purchased to upload data to Swarm. The fees for issuing stamp batches are minimal. For example, [this stamp batch creation transaction](https://gnosisscan.io/tx/0xdc350c059b7bfc10de3d71be71774dda395e2ff770ed6dc83a63c14a418d2be8) cost only **0.00050416 xDAI**. +Postage stamp batches must be purchased to upload data to Swarm. The fees for issuing stamp batches are minimal. For example, [this stamp batch creation transaction](https://gnosisscan.io/tx/0xdc350c059b7bfc10de3d71be71774dda395e2ff770ed6dc83a63c14a418d2be8) cost only **0.00050416 xDAI**. Additionally, xBZZ is required based on the volume of storage purchased—see [the xBZZ section below](/docs/bee/installation/fund-your-node#xbzz-requirements) for details. -### **2. [Stake Management Transactions](/docs/bee/working-with-bee/staking/#maximize-rewards) (Full Nodes Only)** +### **2. [Stake Management Transactions](/docs/bee/working-with-bee/staking/#maximize-rewards) (Full Nodes Only)** Stake management transactions include: @@ -33,17 +29,17 @@ Stake management transactions include: - [Partial stake withdrawals](/docs/bee/working-with-bee/staking/#partial-stake-withdrawals). - [Stake migration](/api/#tag/Staking/paths/~1stake/delete) when a new staking contract is deployed. -Each of these transactions requires a small amount of xDAI to pay for Gnosis Chain gas fees. For example, this [staking transaction](https://gnosisscan.io/tx/0x3a3a5119e54c59f76b60c05bf434ef3d5ec1a3ec47875c3bf1da66dafccf5f72) added **10 xBZZ** in stake (denominated in [PLUR](/docs/references/glossary/#plur) as 1e16 PLUR (100,000,000,000,000,000 PLUR). The xDAI cost for the transaction was minimal—only **0.00026872 xDAI**. +Each of these transactions requires a small amount of xDAI to pay for Gnosis Chain gas fees. For example, this [staking transaction](https://gnosisscan.io/tx/0x3a3a5119e54c59f76b60c05bf434ef3d5ec1a3ec47875c3bf1da66dafccf5f72) added **10 xBZZ** in stake (denominated in [PLUR](/docs/references/glossary/#plur) as 1e16 PLUR (100,000,000,000,000,000 PLUR). The xDAI cost for the transaction was minimal—only **0.00026872 xDAI**. See the section below for details on required xBZZ stake amounts. -### **3. [Storage Incentives Transactions](/docs/concepts/incentives/overview) (Full Nodes Only)** +### **3. [Storage Incentives Transactions](/docs/concepts/incentives/overview) (Full Nodes Only)** -Full nodes with at least **10 xBZZ** in stake are eligible to earn storage incentives. They may choose to [double their reserve size and stake a total of 20 xBZZ](/docs/bee/working-with-bee/staking/#reserve-doubling) to maximize earning potential. +Full nodes with at least **10 xBZZ** in stake are eligible to earn storage incentives. They may choose to [double their reserve size and stake a total of 20 xBZZ](/docs/bee/working-with-bee/staking/#reserve-doubling) to maximize earning potential. -Participating in storage incentives requires nodes to wait for their neighborhood to be selected and then send on-chain transactions for a chance to earn xBZZ. +Participating in storage incentives requires nodes to wait for their neighborhood to be selected and then send on-chain transactions for a chance to earn xBZZ. -There are three types of storage incentive transactions: **commit, reveal, and claim** ([details here](/docs/concepts/incentives/redistribution-game/#redistribution-game-details)). Each requires only a small amount of xDAI and typically occurs a few times per month. However, over time, xDAI may need to be replenished if depleted. +There are three types of storage incentive transactions: **commit, reveal, and claim** ([details here](/docs/concepts/incentives/redistribution-game/#redistribution-game-details)). Each requires only a small amount of xDAI and typically occurs a few times per month. However, over time, xDAI may need to be replenished if depleted. As an example reference, the gas costs from several months ago were: @@ -51,21 +47,19 @@ As an example reference, the gas costs from several months ago were: - [Commit](https://gnosisscan.io/tx/0x91bdf7363535fb405547c50742d6070cd249dd4c2fc00d494c79b3dbf516b1f3): **0.0002918 xDAI** - [Reveal](https://gnosisscan.io/tx/0x625dd6cd3cf8f9c1dfe27335884994b43519b0a59e0bb3968bd663d200d1772b): **0.0002918 xDAI** -*Note that while the gas costs today are roughly similar to the examples above, gas fees may change over time due to potential network congestion and a variety of other factors.* - +_Note that while the gas costs today are roughly similar to the examples above, gas fees may change over time due to potential network congestion and a variety of other factors._ -### **4. [Bandwidth Incentives Transactions](/docs/concepts/incentives/bandwidth-incentives) (Light and Full Nodes)** +### **4. [Bandwidth Incentives Transactions](/docs/concepts/incentives/bandwidth-incentives) (Light and Full Nodes)** -When initializing a new light or full node, deploying a bandwidth incentives contract (also called a **SWAP contract**) is required. The xDAI gas fees for this are minimal. +When initializing a new light or full node, deploying a bandwidth incentives contract (also called a **SWAP contract**) is required. The xDAI gas fees for this are minimal. For example, [this SWAP contract deployment transaction](https://gnosisscan.io/tx/0xc17b023ba22a9b2c2c27a40ce88d68caf95eb02e17ae57e9c56810b7b33a6ebc) cost only **0.00058154 xDAI**. +## **xBZZ Requirements** -## **xBZZ Requirements** +xBZZ is used to pay for storing and retrieving data on Swarm. It is required for **_three categories of transactions_**: -xBZZ is used to pay for storing and retrieving data on Swarm. It is required for ***three categories of transactions***: - -### **1. [Buying Postage Stamp Batches](/docs/concepts/incentives/postage-stamps) (Light / Full Nodes)** +### **1. [Buying Postage Stamp Batches](/docs/concepts/incentives/postage-stamps) (Light / Full Nodes)** To upload data, postage stamp batches must be purchased. The required xBZZ amount varies based on: @@ -74,44 +68,42 @@ To upload data, postage stamp batches must be purchased. The required xBZZ amoun Stamp batches use two parameters: **depth** (determines data capacity) and **amount** (determines storage duration). See [this page](/docs/develop/access-the-swarm/buy-a-stamp-batch) for details on selecting appropriate values. -### **2. [Staking](/docs/bee/working-with-bee/staking/) (Full Nodes Only)** +### **2. [Staking](/docs/bee/working-with-bee/staking/) (Full Nodes Only)** A **minimum stake of 10 xBZZ** is required to participate in storage incentives. Nodes opting for [reserve doubling](/docs/bee/working-with-bee/staking/#reserve-doubling) may stake **20 xBZZ** to optimize earnings. -### **3. [Bandwidth (SWAP) Payments](/docs/concepts/incentives/bandwidth-incentives) (Light / Full Nodes)** +### **3. [Bandwidth (SWAP) Payments](/docs/concepts/incentives/bandwidth-incentives) (Light / Full Nodes)** -Bandwidth payments are required for downloading and uploading data. +Bandwidth payments are required for downloading and uploading data. - **Ultra-light nodes**: Free-tier downloads only; no uploads. - **Light and full nodes**: Must deploy a [SWAP contract](/docs/concepts/incentives/bandwidth-incentives) before making bandwidth payments. -The **SWAP contract deployment fee** is minimal—for example, [this transaction](https://gnosisscan.io/tx/0x09438217f75516df1319eb772d503126ab38ecf52e6d9fd626411a238e0d687a) cost **0.00018542 xDAI**. - +The **SWAP contract deployment fee** is minimal—for example, [this transaction](https://gnosisscan.io/tx/0x09438217f75516df1319eb772d503126ab38ecf52e6d9fd626411a238e0d687a) cost **0.00018542 xDAI**. :::info -**Cost Estimates for Bandwidth Payments** +**Cost Estimates for Bandwidth Payments** -- **Downloading 1GB**: ~**0.5 xBZZ** in SWAP payments. -- **Uploading**: Requires a funded SWAP contract. +- **Downloading 1GB**: ~**0.5 xBZZ** in SWAP payments. +- **Uploading**: Requires a funded SWAP contract. Running a **full/light node** with `swap-enable` turned on allows nodes to **earn bandwidth incentives** by providing bandwidth to others. Actual xBZZ costs depend on network activity and should be actively monitored. ::: -## Token Requirements Based on Node Type and Use Case +## Token Requirements Based on Node Type and Use Case -The amount of **xDAI** and **xBZZ** required to run a Bee node depends on the node type and intended use case. While **no tokens** are required to run an **ultra-light node**, both **light and full nodes** require some **xDAI** for gas fees and **xBZZ** for data transactions. +The amount of **xDAI** and **xBZZ** required to run a Bee node depends on the node type and intended use case. While **no tokens** are required to run an **ultra-light node**, both **light and full nodes** require some **xDAI** for gas fees and **xBZZ** for data transactions. -### **Token Requirement Table** +### **Token Requirement Table** - -| **Use Case** | **Supported Node Type** | **Amount of xDAI Required** | **Amount of xBZZ Required** | -|--------------------------------------|------------------------------|-----------------------------------------------------|-----------------------------------------------------| -| **Free tier downloads (no uploads)** | Ultra-Light, Light, Full | None | None | -| **Downloading beyond free tier** | Light, Full | A small amount such as **~0.1 xDAI** is more than enough to deploy the [SWAP/chequebook contract](/docs/concepts/incentives/bandwidth-incentives) | **~0.1 xBZZ** is enough to get started uploading smaller amounts of data, but more will be required once entering the GB range | -| **Uploading Data** | Light, Full | **~0.1 xDAI** is more than enough for both the initial SWAP/chequebook deployment transaction and the postage stamp batch purchase gas fees | **~0.1 xBZZ** will be enough to upload and store a small amount of data for a short period, but [considerably more xBZZ is required](/docs/develop/access-the-swarm/buy-a-stamp-batch#setting-stamp-batch-parameters-and-options) to store larger amounts of data for a longer time(scales with uploaded volume) | -| **Staking** | Full | **0.1 xDAI** is a reasonable minimum for getting started, more is recommended for long term operation. Staking related transactions occur several times a month and can cost up to around 0.001 xBZZ per transaction. | **10 xBZZ** (minimum required stake, **20 xBZZ** is required for staking with a [doubled reserve](/docs/bee/working-with-bee/staking/#reserve-doubling)). Stake is generally speaking not withdrawable. | -| **Participating in storage incentives** | Full | **Small amount of xDAI** (for commit, reveal, claim transactions) | **10 xBZZ** (minimum required stake) | -| **Bandwidth (SWAP) payments** | Light, Full | **~0.0005 xDAI** (for initial SWAP contract deployment) | **Scales with bandwidth usage** (~0.5 xBZZ per GB downloaded) | | +| **Use Case** | **Supported Node Type** | **Amount of xDAI Required** | **Amount of xBZZ Required** | +| --------------------------------------- | ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --- | +| **Free tier downloads (no uploads)** | Ultra-Light, Light, Full | None | None | +| **Downloading beyond free tier** | Light, Full | A small amount such as **~0.1 xDAI** is more than enough to deploy the [SWAP/chequebook contract](/docs/concepts/incentives/bandwidth-incentives) | **~0.1 xBZZ** is enough to get started uploading smaller amounts of data, but more will be required once entering the GB range | +| **Uploading Data** | Light, Full | **~0.1 xDAI** is more than enough for both the initial SWAP/chequebook deployment transaction and the postage stamp batch purchase gas fees | **~0.1 xBZZ** will be enough to upload and store a small amount of data for a short period, but [considerably more xBZZ is required](/docs/develop/access-the-swarm/buy-a-stamp-batch#setting-stamp-batch-parameters-and-options) to store larger amounts of data for a longer time(scales with uploaded volume) | +| **Staking** | Full | **0.1 xDAI** is a reasonable minimum for getting started, more is recommended for long term operation. Staking related transactions occur several times a month and can cost up to around 0.001 xBZZ per transaction. | **10 xBZZ** (minimum required stake, **20 xBZZ** is required for staking with a [doubled reserve](/docs/bee/working-with-bee/staking/#reserve-doubling)). Stake is generally speaking not withdrawable. | +| **Participating in storage incentives** | Full | **Small amount of xDAI** (for commit, reveal, claim transactions) | **10 xBZZ** (minimum required stake) | +| **Bandwidth (SWAP) payments** | Light, Full | **~0.0005 xDAI** (for initial SWAP contract deployment) | **Scales with bandwidth usage** (~0.5 xBZZ per GB downloaded) | | This table provides a general guideline, but actual xDAI and xBZZ usage will depend on individual node activity and transaction fees at the time. @@ -169,14 +161,14 @@ curl -s localhost:1633/addresses | jq ```json { - "overlay": "46275b02b644a81c8776e2459531be2b2f34a94d47947feb03bc1e209678176c", - "underlay": [ - "/ip4/127.0.0.1/tcp/7072/p2p/16Uiu2HAmTbaZndBa43PdBHEekjQQEdHqcyPgPc3oQwLoB2hRf1jq", - "/ip4/192.168.0.10/tcp/7072/p2p/16Uiu2HAmTbaZndBa43PdBHEekjQQEdHqcyPgPc3oQwLoB2hRf1jq", - "/ip6/::1/tcp/7072/p2p/16Uiu2HAmTbaZndBa43PdBHEekjQQEdHqcyPgPc3oQwLoB2hRf1jq" - ], - "ethereum": "0x0b546f2817d0d889bd70e244c1227f331f2edf74", - "public_key": "03660e8dbcf3fda791e8e2e50bce658a96d766e68eb6caa00ce2bb87c1937f02a5" + "overlay": "46275b02b644a81c8776e2459531be2b2f34a94d47947feb03bc1e209678176c", + "underlay": [ + "/ip4/127.0.0.1/tcp/7072/p2p/16Uiu2HAmTbaZndBa43PdBHEekjQQEdHqcyPgPc3oQwLoB2hRf1jq", + "/ip4/192.168.0.10/tcp/7072/p2p/16Uiu2HAmTbaZndBa43PdBHEekjQQEdHqcyPgPc3oQwLoB2hRf1jq", + "/ip6/::1/tcp/7072/p2p/16Uiu2HAmTbaZndBa43PdBHEekjQQEdHqcyPgPc3oQwLoB2hRf1jq" + ], + "ethereum": "0x0b546f2817d0d889bd70e244c1227f331f2edf74", + "public_key": "03660e8dbcf3fda791e8e2e50bce658a96d766e68eb6caa00ce2bb87c1937f02a5" } ``` @@ -191,11 +183,11 @@ you'll need to [add the Gnosis Chain network](https://docs.gnosischain.com/tools The canonical addresses for the BZZ token on the various blockchains are as follows: -| Blockchain | Contract address | -| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | -| Ethereum, BZZ | [`0x19062190b1925b5b6689d7073fdfc8c2976ef8cb`](https://ethplorer.io/address/0x19062190b1925b5b6689d7073fdfc8c2976ef8cb) | -| Gnosis Chain, xBZZ | [`0xdBF3Ea6F5beE45c02255B2c26a16F300502F68da`](https://blockscout.com/xdai/mainnet/tokens/0xdBF3Ea6F5beE45c02255B2c26a16F300502F68da/) | -| Sepolia (testnet), sBZZ | [`0x543dDb01Ba47acB11de34891cD86B675F04840db`](https://sepolia.etherscan.io/address/0x543dDb01Ba47acB11de34891cD86B675F04840db) | +| Blockchain | Contract address | +| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | +| Ethereum, BZZ | [`0x19062190b1925b5b6689d7073fdfc8c2976ef8cb`](https://ethplorer.io/address/0x19062190b1925b5b6689d7073fdfc8c2976ef8cb) | +| Gnosis Chain, xBZZ | [`0xdBF3Ea6F5beE45c02255B2c26a16F300502F68da`](https://blockscout.com/xdai/mainnet/tokens/0xdBF3Ea6F5beE45c02255B2c26a16F300502F68da/) | +| Sepolia (testnet), sBZZ | [`0x543dDb01Ba47acB11de34891cD86B675F04840db`](https://sepolia.etherscan.io/address/0x543dDb01Ba47acB11de34891cD86B675F04840db) | # Accessing Your Node's Wallet @@ -214,29 +206,7 @@ sudo cat /var/lib/bee/password # Testnet -A Bee node needs Sepolia ETH and sBZZ in its wallet to be able to properly -interact with the test network. One way to acquire these funds is to -sign into our Discord and request Sepolia ETH and sBZZ test tokens from the -*faucet bot* to your node's Ethereum address. +A Bee node needs Sepolia ETH and sBZZ in its wallet to properly interact with the test network. To acquire these funds, you can use one of the faucets from [this list](https://faucetlink.to/sepolia) to request Sepolia ETH. To get Sepolia BZZ (sBZZ), you can use this [Uniswap market](https://app.uniswap.org/swap?outputCurrency=0x543dDb01Ba47acB11de34891cD86B675F04840db&inputCurrency=ETH), just make sure that you've switched to the Sepolia network in your browser wallet. To find out what your node's Ethereum address is, please consult the installation guide or check the logs! - -Once you have the address: - -1. join our [Discord server](https://discord.gg/wdghaQsGq5) -2. navigate to the [#faucet](https://discord.gg/TVgKhsGEbc) channel -3. [verify your username](https://discord.gg/tXGPdzZQaV) -4. request test tokens from the *faucet bot* - -To request the tokens you must **type** (not copy paste) the following, replacing the address with your own: - -``` -/faucet sprinkle 0xabeeecdef123452a40f6ea9f598596ca8556bd57 -``` - -If you have problems, please let us know by making a post in the [#faucet](https://discord.gg/TVgKhsGEbc) channel, we will do our best to provide tokens to everyone. - -Note that you should use a Chromium-based client (e.g., Chrome, native Discord client) to type the faucet command, as support for other browsers is spotty. It's reported to not work on Firefox, for example. - -Transactions may take a while to complete, please be patient. We're also keen for you to join us in the swarm, and indeed you soon will! 🐝   🐝   🐝 diff --git a/docs/bee/working-with-bee/configuration.md b/docs/bee/working-with-bee/configuration.md index 7acbf131b..1e5c209c0 100644 --- a/docs/bee/working-with-bee/configuration.md +++ b/docs/bee/working-with-bee/configuration.md @@ -6,22 +6,20 @@ id: configuration import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; - ## Configuration Methods and Priority There are three methods of configuration which each have different priority levels. Configuration is processed in the following ascending order of preference: -1. Command Line Flags +1. Command Line Flags 2. Environment Variables 3. YAML Configuration File :::info -All three methods may be used when running Bee using `bee start`. +All three methods may be used when running Bee using `bee start`. However when Bee is started as a service with tools like `systemctl` or `brew services`, only the YAML configuration file is supported by default. ::: - ### Command Line Arguments Run `bee start --help` in your Terminal to list the available command line arguments as follows: @@ -92,7 +90,7 @@ Flags: --withdrawal-addresses-whitelist strings withdrawal target addresses Global Flags: - --config string config file (default is $HOME/.bee.yaml) + --config string config file (default is $HOME/.bee.yaml) ``` ### Environment variables @@ -240,10 +238,10 @@ withdrawal-addresses-whitelist: [] ``` :::info -Note that depending on whether Bee is started directly with the `bee start` command or started as a service with `systemctl` / `brew services`, the default directory for the YAML configuration file (shown in the `config` option above) [will be different](/docs/bee/working-with-bee/configuration). +Note that depending on whether Bee is started directly with the `bee start` command or started as a service with `systemctl` / `brew services`, the default directory for the YAML configuration file (shown in the `config` option above) [will be different](/docs/bee/working-with-bee/configuration). ::: -To change your node's configuration, simply edit the YAML file and restart Bee: +To change your node's configuration, simply edit the YAML file and restart Bee: @@ -318,15 +318,13 @@ Moreover, when using `bee.yaml` together with the `bee start` command, you must You can find the default configurations for your system in the [packaging folder of the Bee repo](https://github.com/ethersphere/bee/tree/master/packaging). If your configuration file is missing you can simply copy the contents of the file into a new `bee.yaml` file in the default configuration directory shown in the `bee.yaml` file for your system. - ## Default Data and Config Directories -Depending on the operating system and startup method used, the default data and configuration directories for your node will differ. +Depending on the operating system and startup method used, the default data and configuration directories for your node will differ. ### Bee Service Default Directories (Package Manager Install) -When installed using a package manager, Bee is set up to run as a service with default data and configuration directories set up automatically during the installation. The examples below include default directories for Linux and macOS. You can find the complete details of default directories for different operating systems in the `bee.yaml` files included in the [packaging folder of the Bee repo](https://github.com/ethersphere/bee/tree/master/packaging). - +When installed using a package manager, Bee is set up to run as a service with default data and configuration directories set up automatically during the installation. The examples below include default directories for Linux and macOS. You can find the complete details of default directories for different operating systems in the `bee.yaml` files included in the [packaging folder of the Bee repo](https://github.com/ethersphere/bee/tree/master/packaging). +## Sepolia Testnet Configuration -## Sepolia Testnet Configuration - -In order to operate a Bee node on the Sepolia testnet, update your configuration to use the options shown in the example below. Make sure that you replace the `blockchain-rpc-endpoint` option value with your own valid Sepolia RPC endpoint. If you choose to use a 3rd party RPC provider like [Infura](https://www.infura.io/), make sure to [check in the docs](https://docs.infura.io/api/network-endpoints) that the endpoint format is up to date, and also make sure that you have filled in your own API key which you can find from the [Infura web app](https://app.infura.io). +In order to operate a Bee node on the Sepolia testnet, update your configuration to use the options shown in the example below. Make sure that you replace the `blockchain-rpc-endpoint` option value with your own valid Sepolia RPC endpoint. If you choose to use a 3rd party RPC provider like [Infura](https://www.infura.io/), make sure to [check in the docs](https://docs.infura.io/api/network-endpoints) that the endpoint format is up to date, and also make sure that you have filled in your own API key which you can find from the [Infura web app](https://app.infura.io). -Also make sure to fund your node with Sepolia ETH rather than xDAI to pay for gas on the Sepolia testnet. There are many public faucets you can use to obtain Sepolia ETH, such as [this one from Infura](https://www.infura.io/faucet/sepolia). - -To get Sepolia BZZ (sBZZ) you can use [this Uniswap market](https://app.uniswap.org/swap?outputCurrency=0x543dDb01Ba47acB11de34891cD86B675F04840db&inputCurrency=ETH), just make sure that you've switched to the Sepolia network in your browser wallet. +Also make sure to fund your node with Sepolia ETH rather than xDAI to pay for gas on the Sepolia testnet. There are many public faucets you can use to obtain Sepolia ETH, [here is a curated list](https://faucetlink.to/sepolia). +To get Sepolia BZZ (sBZZ) you can use [this Uniswap market](https://app.uniswap.org/swap?outputCurrency=0x543dDb01Ba47acB11de34891cD86B675F04840db&inputCurrency=ETH), just make sure that you've switched to the Sepolia network in your browser wallet. ```yaml data-dir: /home/username/bee/sepolia @@ -543,9 +547,9 @@ Here `bootnode` was changed to use the testnet bootnode, `mainnet` has been set ## Setting Blockchain RPC endpoint -Full and light Bee nodes require a Gnosis Chain RPC endpoint so they can interact with and deploy their chequebook contract, see the latest view of the current postage stamp batches, and interact with and top-up postage stamp batches. A blockchain RPC endpoint is not required for nodes running in ultra-light mode. +Full and light Bee nodes require a Gnosis Chain RPC endpoint so they can interact with and deploy their chequebook contract, see the latest view of the current postage stamp batches, and interact with and top-up postage stamp batches. A blockchain RPC endpoint is not required for nodes running in ultra-light mode. -We strongly recommend you [run your own Gnosis Chain node](https://docs.gnosischain.com/node/) if you are planning to run a full node, and especially if you plan to run a [hive of nodes](/docs/bee/installation/hive). +We strongly recommend you [run your own Gnosis Chain node](https://docs.gnosischain.com/node/) if you are planning to run a full node, and especially if you plan to run a [hive of nodes](/docs/bee/installation/hive). If you do not wish to run your own Gnosis Chain node and are willing to trust a third party, you may also consider using an RPC endpoint provider such as [GetBlock](https://getblock.io/). @@ -562,10 +566,9 @@ blockchain-rpc-endpoint: https://rpc.gnosis.gateway.fm The gateway.fm RPC endpoint in the example is great for learning how to set up Bee, but for the sake of security and reliability it's recommended that you run your [run your own Gnosis Chain node](https://docs.gnosischain.com/node/) rather than relying on a third party provider. ::: - ## Configuring Swap Initial Deposit (Optional) -When running your Bee node with SWAP enabled for the first time, your node will deploy a 'chequebook' contract using the canonical factory contract which is deployed by Swarm. Once the chequebook is deployed, Bee will (optionally) deposit a certain amount of xBZZ in the chequebook contract so that it can pay other nodes in return for their services. The amount of xBZZ transferred to the chequebook is set by the `swap-initial-deposit` configuration setting (it may be left at the default value of zero or commented out). +When running your Bee node with SWAP enabled for the first time, your node will deploy a 'chequebook' contract using the canonical factory contract which is deployed by Swarm. Once the chequebook is deployed, Bee will (optionally) deposit a certain amount of xBZZ in the chequebook contract so that it can pay other nodes in return for their services. The amount of xBZZ transferred to the chequebook is set by the `swap-initial-deposit` configuration setting (it may be left at the default value of zero or commented out). ## NAT address @@ -593,14 +596,14 @@ Then configure your node, including your p2p port (default 1634). ## bee.yaml nat-addr: "123.123.123.123:1634" ``` -## ENS Resolution (Optional) -The [ENS](https://ens.domains/) domain resolution system is used to host websites on Bee, and in order to use this your Bee must be connected to a mainnet Ethereum blockchain node. We recommend you run your own ethereum node. An option for resource restricted devices is geth+nimbus and a guide can be found [here](https://ethereum-on-arm-documentation.readthedocs.io/en/latest/). Other options include [dappnode](https://dappnode.io/), [nicenode](https://www.nicenode.xyz/), [stereum](https://stereum.net/) and [avado](https://ava.do/). +## ENS Resolution (Optional) +The [ENS](https://ens.domains/) domain resolution system is used to host websites on Bee, and in order to use this your Bee must be connected to a mainnet Ethereum blockchain node. We recommend you run your own ethereum node. An option for resource restricted devices is geth+nimbus and a guide can be found [here](https://ethereum-on-arm-documentation.readthedocs.io/en/latest/). Other options include [dappnode](https://dappnode.io/), [nicenode](https://www.nicenode.xyz/), [stereum](https://stereum.net/) and [avado](https://ava.do/). If you do not wish to run your own Ethereum node you may use a blockchain API service provider such as Infura. After signing up for [Infura's](https://infura.io) API service, simply set your `--resolver-options` to `https://mainnet.infura.io/v3/your-api-key`. ```yaml ## bee.yaml resolver-options: ["https://mainnet.infura.io/v3/<>"] -``` \ No newline at end of file +``` diff --git a/docs/develop/tools-and-features/starting-a-test-network.md b/docs/develop/tools-and-features/starting-a-test-network.md index 3fbf8e59b..6331a8e93 100644 --- a/docs/develop/tools-and-features/starting-a-test-network.md +++ b/docs/develop/tools-and-features/starting-a-test-network.md @@ -24,7 +24,7 @@ swap-enable: false mainnet: false blockchain-rpc-endpoint: https://sepolia.dev.fairdatasociety.org verbosity: 5 -full-node: true +full-node: true ``` **config_2.yaml** @@ -41,7 +41,7 @@ swap-enable: false mainnet: false blockchain-rpc-endpoint: https://sepolia.dev.fairdatasociety.org verbosity: 5 -full-node: true +full-node: true ``` Note that for each node, we provide a different `api-addr`. If we had not specified different addresses here, we @@ -106,15 +106,15 @@ curl localhost:1633/addresses | jq ```json { - "overlay": "b1978be389998e8c8596ef3c3a54214e2d4db764898ec17ec1ad5f19cdf7cc59", - "underlay": [ - "/ip4/127.0.0.1/tcp/1634/p2p/QmQHgcpizgoybDtrQXCWRSGdTP526ufeMFn1PyeGd1zMEZ", - "/ip4/172.25.128.69/tcp/1634/p2p/QmQHgcpizgoybDtrQXCWRSGdTP526ufeMFn1PyeGd1zMEZ", - "/ip6/::1/tcp/1634/p2p/QmQHgcpizgoybDtrQXCWRSGdTP526ufeMFn1PyeGd1zMEZ" - ], - "ethereum": "0xd22cc790e2aef341827e1e49cc631d2a16898cd9", - "publicKey": "023b26ce8b78ed8cdb07f3af3d284c95bee5e038e7c5d0c397b8a5e33424f5d790", - "pssPublicKey": "039ceb9c1f0afedf79991d86d89ccf4e96511cf656b43971dc3e878173f7462487" + "overlay": "b1978be389998e8c8596ef3c3a54214e2d4db764898ec17ec1ad5f19cdf7cc59", + "underlay": [ + "/ip4/127.0.0.1/tcp/1634/p2p/QmQHgcpizgoybDtrQXCWRSGdTP526ufeMFn1PyeGd1zMEZ", + "/ip4/172.25.128.69/tcp/1634/p2p/QmQHgcpizgoybDtrQXCWRSGdTP526ufeMFn1PyeGd1zMEZ", + "/ip6/::1/tcp/1634/p2p/QmQHgcpizgoybDtrQXCWRSGdTP526ufeMFn1PyeGd1zMEZ" + ], + "ethereum": "0xd22cc790e2aef341827e1e49cc631d2a16898cd9", + "publicKey": "023b26ce8b78ed8cdb07f3af3d284c95bee5e038e7c5d0c397b8a5e33424f5d790", + "pssPublicKey": "039ceb9c1f0afedf79991d86d89ccf4e96511cf656b43971dc3e878173f7462487" } ``` @@ -135,7 +135,7 @@ welcome-message: "Bzz Bzz Bzz" swap-enable: false blockchain-rpc-endpoint: https://sepolia.dev.fairdatasociety.org verbosity: 5 -full-node: true +full-node: true ``` Now, we can shut our second node and reboot with the new configuration. @@ -154,14 +154,12 @@ curl -s http://localhost:1733/peers | jq Congratulations! You have made your own tiny two bee Swarm! 🐝 🐝 - ## Funding Nodes -While you have successfully set up two nodes, they are currently unfunded with either sETH or sBZZ. Sepolia ETH (sETH) is required for issuing transactions on the Sepolia testnet, and Sepolia BZZ (sBZZ) is required for your node to operate as a full staking node. +While you have successfully set up two nodes, they are currently unfunded with either sETH or sBZZ. Sepolia ETH (sETH) is required for issuing transactions on the Sepolia testnet, and Sepolia BZZ (sBZZ) is required for your node to operate as a full staking node. To fund our nodes, we need to first collect the blockchain addresses for each node. We can use the `/addresses` endpoint for this: - ```bash curl localhost:1633/addresses | jq ``` @@ -180,12 +178,12 @@ curl localhost:1633/addresses | jq } ``` -Then copy the address in the "ethereum" field. This is the address you need to send sETH and sBZZ to. There are many public faucets you can use to obtain Sepolia ETH, such as [this one](https://www.infura.io/faucet/sepolia) from Infura. +Then copy the address in the "ethereum" field. This is the address you need to send sETH and sBZZ to. There are many public faucets you can use to obtain Sepolia ETH, [here is a curated list](https://faucetlink.to/sepolia). To get Sepolia BZZ (sBZZ) you can use [this Uniswap market](https://app.uniswap.org/swap?outputCurrency=0x543dDb01Ba47acB11de34891cD86B675F04840db&inputCurrency=ETH), just make sure that you've switched to the Sepolia network in your browser wallet. You will need to send only a very small amount of sETH such as 0.01 sETH, to get started. You will need 10 sBZZ to run a full node with staking. -After sending sETH and sBZZ to your node's address which you copied above, restart your node and it should begin operating properly as a full node. +After sending sETH and sBZZ to your node's address which you copied above, restart your node and it should begin operating properly as a full node. -Repeat these same steps with the other node in order to complete a private test network of two full nodes. \ No newline at end of file +Repeat these same steps with the other node in order to complete a private test network of two full nodes. diff --git a/docs/references/glossary.md b/docs/references/glossary.md index 1bebf0675..40a7d8cc0 100644 --- a/docs/references/glossary.md +++ b/docs/references/glossary.md @@ -3,10 +3,9 @@ title: Glossary id: glossary --- - ## Swarm -The Swarm network consists of a collection of [Bee nodes](#bee) which work together to enable decentralised data storage for the next generation of censorship-resistant, unstoppable, serverless dapps. +The Swarm network consists of a collection of [Bee nodes](#bee) which work together to enable decentralised data storage for the next generation of censorship-resistant, unstoppable, serverless dapps. Swarm is also the name of the core organization that oversees the development and success of the Bee Swarm as a whole. They can be found at [ethswarm.org](https://www.ethswarm.org/). @@ -26,7 +25,7 @@ Bee nodes can act as both client and service provider, or solely as client or se ## Overlay -An overlay network is a virtual or logical network built on top of some lower level "underlay" network. Examples include the Internet as an overlay network built on top of the telephone network, and the p2p Bittorent network built on top of the Internet. +An overlay network is a virtual or logical network built on top of some lower level "underlay" network. Examples include the Internet as an overlay network built on top of the telephone network, and the p2p Bittorent network built on top of the Internet. With Swarm, the overlay network is based on a [Kademlia DHT](https://en.wikipedia.org/wiki/Kademlia) with overlay addresses derived from each node's [Gnosis](#gnosis-chain) address. Swarm's overlay network addresses are permanent identifiers for each node and do not change over time. @@ -36,11 +35,11 @@ Overlay addresses are a Keccak256 hash of a node’s Gnosis Chain address and th ## Neighborhood -[Neighborhoods](/docs/concepts/DISC/neighborhoods) are nodes which are grouped together based on their overlay addresses and are responsible for storing the same chunks of data. The chunks which each neighborhood are responsible for storing are defined by the proximity order of the nodes and the chunks. +[Neighborhoods](/docs/concepts/DISC/neighborhoods) are nodes which are grouped together based on their overlay addresses and are responsible for storing the same chunks of data. The chunks which each neighborhood are responsible for storing are defined by the proximity order of the nodes and the chunks. ## Sister Neighborhood -A sister neighborhood is composed of nodes in the other half of an old neighborhood after a neighborhood split. +A sister neighborhood is composed of nodes in the other half of an old neighborhood after a neighborhood split. ## Parent Neighborhood @@ -48,25 +47,23 @@ A parent neighborhood is the neighborhood one proximity order shallower than the ## Underlay -An underlay network is the low level network on which an overlay network is built. It allows nodes to find each other, communicate, and transfer data. Swarm's underlay network is a p2p network built with [libp2p](https://libp2p.io/). Nodes are assigned underlay addresses which in contrast to their overlay addresses are not permanent and may change over time. +An underlay network is the low level network on which an overlay network is built. It allows nodes to find each other, communicate, and transfer data. Swarm's underlay network is a p2p network built with [libp2p](https://libp2p.io/). Nodes are assigned underlay addresses which in contrast to their overlay addresses are not permanent and may change over time. ## Swap -Swap is the p2p accounting protocol used for Bee nodes. It allows for the automated accounting and settlement of services between Bee nodes in the Swarm network. In the case that services exchanged between nodes is balanced equally, no settlement is necessary. In the case that one node is unequally indebted to another, settlement is made to clear the node's debts. Two key elements of the Swap protocol are [cheques and the chequebook contract](#cheques--chequebook). - +Swap is the p2p accounting protocol used for Bee nodes. It allows for the automated accounting and settlement of services between Bee nodes in the Swarm network. In the case that services exchanged between nodes is balanced equally, no settlement is necessary. In the case that one node is unequally indebted to another, settlement is made to clear the node's debts. Two key elements of the Swap protocol are [cheques and the chequebook contract](#cheques--chequebook). ## Cheques & Chequebook -Cheques are the off-chain method of accounting used by the Swap protocol where the issuing node signs a cheque specifying a beneficiary, a date, and an amount, and gives it to the recipient node as a token of promise to pay at a later date. +Cheques are the off-chain method of accounting used by the Swap protocol where the issuing node signs a cheque specifying a beneficiary, a date, and an amount, and gives it to the recipient node as a token of promise to pay at a later date. -The chequebook is the smart contract where the cheque issuer's funds are stored and where the beneficiary can cash the cheque received. +The chequebook is the smart contract where the cheque issuer's funds are stored and where the beneficiary can cash the cheque received. -The cheque and chequebook system reduces the number of required on-chain transactions by allowing multiple cheques to accumulate and be settled together as a group, and in the case that the balance of cheques between nodes is equal, no settlement transaction is required at all. +The cheque and chequebook system reduces the number of required on-chain transactions by allowing multiple cheques to accumulate and be settled together as a group, and in the case that the balance of cheques between nodes is equal, no settlement transaction is required at all. ## Postage Stamps -Postage stamps can be purchased with [xBZZ](#xbzz-token) and represent the right to store data on the Swarm network. In order to upload data to Swarm, a user must purchase a batch of stamps which they can then use to upload an equivalent amount of data to the network. - +Postage stamps can be purchased with [xBZZ](#xbzz-token) and represent the right to store data on the Swarm network. In order to upload data to Swarm, a user must purchase a batch of stamps which they can then use to upload an equivalent amount of data to the network. ## Kademlia @@ -74,11 +71,11 @@ Kademlia is a distributed hash table (DHT) which is commonly used in distributed ## Kademlia distance -Kademlia introduces an XOR based distance metric to define the relatedness of two addresses. In Kademlia nodes have numeric ids with the same length and format taken from the same namespace as the keys of the key/value pairs. Kademlia distance between node ids and keys is calculated through the XOR bitwise operation done over any ids or keys. +Kademlia introduces an XOR based distance metric to define the relatedness of two addresses. In Kademlia nodes have numeric ids with the same length and format taken from the same namespace as the keys of the key/value pairs. Kademlia distance between node ids and keys is calculated through the XOR bitwise operation done over any ids or keys. Note: For a Kademlia DHT, any standardized numerical format can be used for ids. However, within Swarm, ids are derived from a Keccak256 digest and are represented as 256 bit hexadecimal numbers. They are referred to as addresses or hashes. -Swarm hash: +Swarm hash: > eada6722670c6de6da7d0470167bf14f6e4dc1b98476da94a7330041adec26a3 @@ -86,12 +83,12 @@ In the examples which follow, we use short binary numbers to increase example cl Example: We have a Kademlia DHT consisting of only ten nodes with ids of 1 - 10. We want to find the distance between node 4 and 7. In order to do that, we perform the XOR bitwise operation: -4 | 0100 +4 | 0100 7 | 0111 ————XOR -3 | 0011 +3 | 0011 -And we find that the distance between the two nodes is 3. +And we find that the distance between the two nodes is 3. ## Chunk @@ -101,39 +98,37 @@ When data is uploaded to Swarm, it is broken down into 4kb sized pieces which ar Proximity Order is a concept defined in The Book of Swarm and is closely related to Kademlia distance. In contrast to distance which is an exact measure of the relatedness of two nodes, PO is a discrete measure relatedness between two nodes. By "discrete", we mean that PO is a general measure of relatedness rather than an exact measure of relatedness like the XOR distance metric of Kademlia. -Proximity order is defined as the number of shared prefix bits of any two addresses. It is found by performing the XOR bitwise operation on the two addresses and counting how many leading 0 there are before the first 1. +Proximity order is defined as the number of shared prefix bits of any two addresses. It is found by performing the XOR bitwise operation on the two addresses and counting how many leading 0 there are before the first 1. Taking the previous example used in the Kademlia distance definition: -4 | 0100 +4 | 0100 7 | 0111 ————XOR -3 | 0011 +3 | 0011 In the result we find that the distance is 3, and that there are two leading zeros. Therefore for the PO of these two nodes is 2. +Both Proximity Order and distance are measures of the relatedness of ids, however Kademlia distance is a more exact measurement. -Both Proximity Order and distance are measures of the relatedness of ids, however Kademlia distance is a more exact measurement. - - -Taking the previous example used in the Kademlia distance definition: +Taking the previous example used in the Kademlia distance definition: -5 | 0101 +5 | 0101 7 | 0111 ————XOR -2 | 0010 +2 | 0010 -Here we find that the distance between 5 and 7 is 2, and the PO is also two. Although 5 is closer to 7 than 4 is to 7, they both fall within the same PO, since PO is only concerned with the shared leading bits. PO is a fundamental concept to Swarm’s design and is used as the basic unit of relatedness when discussing the addresses of chunks and nodes. PO is also closely related to the concept of depth. +Here we find that the distance between 5 and 7 is 2, and the PO is also two. Although 5 is closer to 7 than 4 is to 7, they both fall within the same PO, since PO is only concerned with the shared leading bits. PO is a fundamental concept to Swarm’s design and is used as the basic unit of relatedness when discussing the addresses of chunks and nodes. PO is also closely related to the concept of depth. ## Depth types There are three fundamental categories of depth: - + ### 1. Topology related depth This depth is defined in relation to the connection topology of a single node as the subject in relation to all the other nodes it is connected to. It is referred to using several different terms which all refer to the same concept (Connectivity depth / Kademlia depth / neighborhood depth / physical depth) -Connectivity depth refers to the saturation level of the node’s topology - the level to which the topology of a node’s connections has Kademlia connectivity. Defined as one level deeper than the deepest fully saturated level. A PO is defined as saturated if it has at least the minimum required level of connected nodes, which is set at 8 nodes in the current implementation of Swarm. +Connectivity depth refers to the saturation level of the node’s topology - the level to which the topology of a node’s connections has Kademlia connectivity. Defined as one level deeper than the deepest fully saturated level. A PO is defined as saturated if it has at least the minimum required level of connected nodes, which is set at 8 nodes in the current implementation of Swarm. The output from the Bee API's `topology` endpoint: @@ -141,36 +136,36 @@ The output from the Bee API's `topology` endpoint: Here we can see the depth is 8, meaning that PO bin 7 is the deepest fully saturated PO bin: -![](/img/depths2.png) +![](/img/depths2.png) Here we can confirm that at least 8 nodes are connected in bin 7. -Connectivity depth is defined from the point of view of individual nodes, it is not defined as characteristic of the entire network. However, given a uniform distribution of node ids within the namespace and given enough nodes, all nodes should converge towards the same connectivity depth. +Connectivity depth is defined from the point of view of individual nodes, it is not defined as characteristic of the entire network. However, given a uniform distribution of node ids within the namespace and given enough nodes, all nodes should converge towards the same connectivity depth. While this is sometimes referred to as Kademlia depth, the term “Kademlia depth” is not defined within the original Kademlia paper, rather it refers to the depth at which the network in question (Swarms) has the characteristics which fulfill the requirements described in the Kademlia paper. - + ### 2. Area of responsibility related depths -Area of responsibility refers to which chunks a node is responsible for storing. There are two concepts of depth related to a node’s area of responsibility - storage depth and reserve depth. Both reserve depth and storage depth are measures of PO which define the chunks a node is responsible for storing. - +Area of responsibility refers to which chunks a node is responsible for storing. There are two concepts of depth related to a node’s area of responsibility - storage depth and reserve depth. Both reserve depth and storage depth are measures of PO which define the chunks a node is responsible for storing. + ### 2a. Reserve Depth The PO which measures the node’s area of responsibility based on the theoretical 100% utilisation of all postage stamp batches (all the chunks which are eligible to be uploaded and stored are uploaded and stored). Has an inverse relationship with area of responsibility - as depth grows, area of responsibility gets smaller. ### 2b. Storage Depth -The PO which measures the node’s effective area of responsibility. Storage depth will equal reserve depth in the case of 100% utilisation - however 100% utilisation is uncommon. If after syncing all the chunks within the node’s area of responsibility at its reserve depth and the node still has sufficient space left, then the storage depth will decrease so that the area of responsibility doubles. - +The PO which measures the node’s effective area of responsibility. Storage depth will equal reserve depth in the case of 100% utilisation - however 100% utilisation is uncommon. If after syncing all the chunks within the node’s area of responsibility at its reserve depth and the node still has sufficient space left, then the storage depth will decrease so that the area of responsibility doubles. ### 3. Postage stamp batch and chunk related depths ### 3a. Batch depth + Batch depth is the value `d` which is defined in relation to the size of a postage stamp batch. The size of a batch is defined as the number of chunks which can be stamped by that batch (also referred to as the number of slots per batch, with one chunk per slot). The size is calculated by: -* $$2^{d}$$ -* $$d$$ is a value selected by the batch issuer which determines how much data can be stamped with the batch +- $$2^{d}$$ +- $$d$$ is a value selected by the batch issuer which determines how much data can be stamped with the batch -### 3b. Bucket depth +### 3b. Bucket depth Bucket depth is the constant value which defines how many buckets the address space for chunks is divided into for postage stamp batches. Bucket depth is set to 16, and the number of buckets is defined as $$2^{bucket depth}$$ @@ -180,12 +175,11 @@ PLUR (name inspired by the [PLUR principles](https://en.wikipedia.org/wiki/PLUR) ## Bridged Tokens -Bridged tokens are tokens from one blockchain which have been _bridged_ to another chain through a smart contract powered bridge. For example, xDAI and xBZZ on Gnosis Chain are the bridged version of DAI and BZZ on Ethereum. +Bridged tokens are tokens from one blockchain which have been _bridged_ to another chain through a smart contract powered bridge. For example, xDAI and xBZZ on Gnosis Chain are the bridged version of DAI and BZZ on Ethereum. ## BZZ Token -BZZ is Swarm's [ERC-20](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/) token issued on Ethereum. - +BZZ is Swarm's [ERC-20](https://ethereum.org/en/developers/docs/standards/tokens/erc-20/) token issued on Ethereum. ## xBZZ Token @@ -204,9 +198,3 @@ xDAI is [DAI](https://developer.makerdao.com/dai/1/) [bridged](#bridged-tokens) ## Sepolia Sepolia is an Ethereum testnet. It is an environment where smart contracts can be developed and tested without spending cryptocurrency with real value, and without putting valuable assets at risk. Tokens on Sepolia are often prefixed with a lower-case 's', example: 'sBZZ' and because this is a test network carry no monetary value. It is an environment where Bee smart contracts can be tested and interacted with without any risk of monetary loss. - -## Faucet - -A cryptocurrency faucet supplies small amounts of cryptocurrency to requestors (typically for testing purposes). - -It supplies small amounts of sBZZ and Sepolia ETH for anyone who submits a request at the [Swarm Discord](https://discord.gg/wdghaQsGq5) server by using the `/faucet` command in the #develop-on-swarm channel. From 22083ced048791a9bc3ee4c080f00aa833b9e44b Mon Sep 17 00:00:00 2001 From: tamas6 <81620050+tamas6@users.noreply.github.com> Date: Thu, 13 Feb 2025 16:54:41 +0100 Subject: [PATCH 13/16] updated faucet link --- docs/bee/working-with-bee/configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/bee/working-with-bee/configuration.md b/docs/bee/working-with-bee/configuration.md index 2d01990d4..ddefbfe85 100644 --- a/docs/bee/working-with-bee/configuration.md +++ b/docs/bee/working-with-bee/configuration.md @@ -525,7 +525,7 @@ blockchain-rpc-endpoint: "" ## Sepolia Testnet Configuration -Connecting to the Swarm testnet is as simple as adding the flag `--mainnet false` to your bee commandline, or `mainnet: false` to your configuration file. Swarm testnet smart contracts are deployed on Sepolia, so if you want to run a light or full node you will need to add a Sepolia RPC to your configuration and fund your node with Sepolia ETH. There are many public faucets you can use to obtain Sepolia ETH, such as [this one from Infura](https://www.infura.io/faucet/sepolia). +Connecting to the Swarm testnet is as simple as adding the flag `--mainnet false` to your bee commandline, or `mainnet: false` to your configuration file. Swarm testnet smart contracts are deployed on Sepolia, so if you want to run a light or full node you will need to add a Sepolia RPC to your configuration and fund your node with Sepolia ETH. There are many public [faucets](https://faucetlink.to/sepolia)you can use to obtain Sepolia ETH. To get Sepolia BZZ (sBZZ) you can use [this Uniswap market](https://app.uniswap.org/swap?outputCurrency=0x543dDb01Ba47acB11de34891cD86B675F04840db&inputCurrency=ETH); just make sure that you've switched to the Sepolia network in your browser wallet. From 38e133b0d97983954b486cafa839a6b0670eb141 Mon Sep 17 00:00:00 2001 From: tamas6 <81620050+tamas6@users.noreply.github.com> Date: Thu, 13 Mar 2025 16:12:02 +0100 Subject: [PATCH 14/16] feat: url change on faucet --- docs/bee/installation/fund-your-node.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/bee/installation/fund-your-node.md b/docs/bee/installation/fund-your-node.md index b98c23121..97e66e605 100644 --- a/docs/bee/installation/fund-your-node.md +++ b/docs/bee/installation/fund-your-node.md @@ -140,7 +140,7 @@ threshold. Since gas fees on the [Gnosis Chain](https://www.gnosis.io/) are very low, you won't need much xDAI either to get started. You may acquire a small amount -for free by using the official Gnosis Chain xDAI faucet [xDAI Faucet](https://gnosisfaucet.com/). The required amount is a function of the current transaction fee on chain, but 0.01 xDAI should be more than enough to start up your node. +for free by using the official Gnosis Chain xDAI faucet [xDAI Faucet](https://faucet.gnosischain.com/). The required amount is a function of the current transaction fee on chain, but 0.01 xDAI should be more than enough to start up your node. You can use the [Blockscout](https://blockscout.com/xdai/mainnet/) block explorer to inspect what's going on with your wallet by searching for its From da95dfe8335033d12dcefbc34e2a156852197daf Mon Sep 17 00:00:00 2001 From: tamas6 <81620050+tamas6@users.noreply.github.com> Date: Wed, 26 Mar 2025 13:55:56 +0100 Subject: [PATCH 15/16] feat: buy a stamp batch API calls removal, tweak version --- docs/bee/installation/docker.md | 2 +- .../access-the-swarm/buy-a-stamp-batch.md | 278 ++---------------- 2 files changed, 20 insertions(+), 260 deletions(-) diff --git a/docs/bee/installation/docker.md b/docs/bee/installation/docker.md index b4246a31f..f758abf32 100644 --- a/docs/bee/installation/docker.md +++ b/docs/bee/installation/docker.md @@ -350,7 +350,7 @@ services: - 1634:1634 # p2p port bee_02: container_name: bee-node_02 - image: ethersphere/bee:2.4.0 + image: ethersphere/bee:2.5.0 command: start --config /home/bee/bee.yml volumes: - ./node_02/.bee:/home/bee/.bee diff --git a/docs/develop/access-the-swarm/buy-a-stamp-batch.md b/docs/develop/access-the-swarm/buy-a-stamp-batch.md index 882deaf4e..e74b9385a 100644 --- a/docs/develop/access-the-swarm/buy-a-stamp-batch.md +++ b/docs/develop/access-the-swarm/buy-a-stamp-batch.md @@ -2,24 +2,23 @@ title: Buy a Batch of Stamps id: buy-a-stamp-batch --- + import VolumeAndDurationCalc from '@site/src/components/VolumeAndDurationCalc.js'; import AmountAndDepthCalc from '@site/src/components/AmountAndDepthCalc.js'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; - - -A postage batch is required to upload data to Swarm. Postage stamp batches represent _right to write_ data on Swarm's [DISC (Distributed Immutable Store of Chunks)](/docs/concepts/DISC/). The parameters which control the duration and quantity of data that can be stored by a postage batch are `depth` and `amount`, with `depth` determining data volume that can be uploaded by the batch and `amount` determining storage duration of data uploaded with the batch. +A postage batch is required to upload data to Swarm. Postage stamp batches represent _right to write_ data on Swarm's [DISC (Distributed Immutable Store of Chunks)](/docs/concepts/DISC/). The parameters which control the duration and quantity of data that can be stored by a postage batch are `depth` and `amount`, with `depth` determining data volume that can be uploaded by the batch and `amount` determining storage duration of data uploaded with the batch. :::info - The storage volume and duration are both non-deterministic. Volume is non-deterministic due to the details of how [postage stamp batch utilization](/docs/concepts/incentives/postage-stamps#batch-utilisation) works. While duration is non-deterministic due to price changes made by the [price oracle contract](/docs/concepts/incentives/price-oracle). +The storage volume and duration are both non-deterministic. Volume is non-deterministic due to the details of how [postage stamp batch utilization](/docs/concepts/incentives/postage-stamps#batch-utilisation) works. While duration is non-deterministic due to price changes made by the [price oracle contract](/docs/concepts/incentives/price-oracle). **Storage volume and `depth`:** When purchasing stamp batches for larger volumes of data (by increasing the `depth` value), the amount of data which can be stored becomes increasingly more predictable. For example, at `depth` 22 a batch can store between 4.93 GB and 17.18 GB, while at `depth` 28, a batch can store between 1.0 and 1.1 TB of data, and at higher depths the difference between the minimum and maximum storage volumes approach the same value. - **Storage duration and `amount`:** + **Storage duration and `amount`:** The duration of time for which a batch can store data is also non-deterministic since the price of storage is automatically adjusted over time by the [price oracle contract](/docs/concepts/incentives/price-oracle). However, limits have been placed on how swiftly the price of storage can change, so there is no danger of a rapid change in price causing postage batches to unexpectedly expire due to a rapid increase in price. You can view a history of price changes by inspecting [the events emitted by the oracle contract](https://gnosisscan.io/address/0x47EeF336e7fE5bED98499A4696bce8f28c1B0a8b#events), or also through the [Swarmscan API](https://api.swarmscan.io/v1/events/storage-price-oracle/price-update). As you can see, if and when postage batch prices are updated, the updates are quite small. Still, since it is not entirely deterministic, it is important to monitor your stamp batch TTL (time to live) as it will change along with price oracle changes. You can inspect your batch's TTL using the `/stamps` endpoint of the API: @@ -43,10 +42,9 @@ A postage batch is required to upload data to Swarm. Postage stamp batches repre ] } ``` - Here we can see from the `batchTTL` that `82943` seconds remain, or approximately 23 hours. + Here we can see from the `batchTTL` that `82943` seconds remain, or approximately 23 hours. ::: - For a deeper understanding of how `depth` and `amount` parameters determine the data volume and storage duration of a postage batch, see the [postage stamp page](/docs/concepts/incentives/postage-stamps/). ## Fund your node's wallet. @@ -61,43 +59,12 @@ You can learn more details from the [Fund Your Node](/docs/bee/installation/fund ## Buying a stamp batch -When interacting with the Bee API directly, `amount` and `depth` are passed as path parameters: - -```bash -curl -s -X POST http://localhost:1633/stamps// -``` - -And with Swarm CLI, they are set using option flags: +When interacting with Swarm CLI, the parameters amount and depth are set using option flags: ```bash swarm-cli stamp buy --depth --amount ``` - - - -#### API - -```bash -curl -s -X POST http://localhost:1633/stamps/100000000/20 -``` - -```bash -{ - "batchID": "8fcec40c65841e0c3c56679315a29a6495d32b9ed506f2757e03cdd778552c6b", - "txHash": "0x51c77ac171efd930eca8f3a77e3fcd5aca0a7353b84d5562f8e9c13f5907b675" -} -``` - - - - - #### Swarm CLI ```bash @@ -113,30 +80,24 @@ When a mutable stamp reaches full capacity, it still permits new content uploads ? Confirm the purchase Yes Stamp ID: f4b9830676f4eeed4982c051934e64113dc348d7f5d2ab4398d371be0fbcdbf5 ``` - - - - :::info Once your batch has been purchased, it will take a few minutes for other Bee nodes in the Swarm to catch up and register your batch. Allow some time for your batch to propagate in the network before proceeding to the next step. ::: - ## Setting stamp batch parameters and options When purchasing a batch of stamps there are several parameters and options which must be considered. The `depth` parameter will control how many chunks can be uploaded with a batch of stamps. The `amount` parameter determines how much xBZZ will be allocated per chunk, and therefore also controls how long the chunks will be stored. While the `immutable` header option sets the batch as either mutable or immutable, which can significantly alter the behavior of the batch utilisation (more details below). - ### Choosing `depth` :::caution The minimum value for `depth` is 17, however a higher depth value is recommended for most use cases due to the [mechanics of stamp batch utilisation](/docs/concepts/incentives/postage-stamps/#batch-utilisation). See [the depths utilisation table](/docs/concepts/incentives/postage-stamps/#effective-utilisation-table) to help decide which depth is best for your use case. ::: -One notable aspect of batch utilisation is that the entire batch is considered fully utilised as soon as any one of its buckets are filled. This means that the actual amount of chunks storable by a batch is less than the nominal maximum amount. +One notable aspect of batch utilisation is that the entire batch is considered fully utilised as soon as any one of its buckets are filled. This means that the actual amount of chunks storable by a batch is less than the nominal maximum amount. -See the [postage stamp page](/docs/concepts/incentives/postage-stamps) for a more complete explanation of how batch utilisation works and a [table](/docs/concepts/incentives/postage-stamps#effective-utilisation-table) with the specific amounts of data which can be safely uploaded for each `depth` value. +See the [postage stamp page](/docs/concepts/incentives/postage-stamps) for a more complete explanation of how batch utilisation works and a [table](/docs/concepts/incentives/postage-stamps#effective-utilisation-table) with the specific amounts of data which can be safely uploaded for each `depth` value. ### Choosing `amount` @@ -152,10 +113,10 @@ Depending on the use case, uploaders may desire to use mutable or immutable batc ## Calculators -The following postage batch calculators allow you to conveniently find the depth and amount values for a given storage duration and storage volume, or to find the storage duration and storage volume for a given depth and amount. The results will display the cost in xBZZ for the postage batch. The current pricing information is sourced from the Swarmscan API and will vary over time. +The following postage batch calculators allow you to conveniently find the depth and amount values for a given storage duration and storage volume, or to find the storage duration and storage volume for a given depth and amount. The results will display the cost in xBZZ for the postage batch. The current pricing information is sourced from the Swarmscan API and will vary over time. :::info -The 'effective volume' is the volume of data that can safely stored for each storage depth. The 'theoretical max volume' is significantly lower than the effective volume at lower depths and the two values trend towards the same value at higher depths. The lowest depth with an effective volume above zero is 22, with an effective depth of 4.93 GB. Lower depth values can be used for smaller uploads but do not come with the same storage guarantees. [Learn more here](/docs/concepts/incentives/postage-stamps#effective-utilisation-table). +The 'effective volume' is the volume of data that can safely stored for each storage depth. The 'theoretical max volume' is significantly lower than the effective volume at lower depths and the two values trend towards the same value at higher depths. The lowest depth with an effective volume above zero is 22, with an effective depth of 4.93 GB. Lower depth values can be used for smaller uploads but do not come with the same storage guarantees. [Learn more here](/docs/concepts/incentives/postage-stamps#effective-utilisation-table). ::: ### Depth & Amount to Time & Volume Calculator @@ -164,55 +125,10 @@ The 'effective volume' is the volume of data that can safely stored for each sto ### Time & Volume to Depth & Amount Calculator -The recommended depth in this calculator's results is the lowest depth value whose [effective volume](/docs/concepts/incentives/postage-stamps#effective-utilisation-table) is greater than the entered volume. +The recommended depth in this calculator's results is the lowest depth value whose [effective volume](/docs/concepts/incentives/postage-stamps#effective-utilisation-table) is greater than the entered volume. -## Viewing Stamps - -To check on your stamps, send a GET request to the stamp endpoint. - - - - - -#### API - - -```bash -curl http://localhost:1633/stamps -``` - -```bash -{ - "stamps": [ - { - "batchID": "f4b9830676f4eeed4982c051934e64113dc348d7f5d2ab4398d371be0fbcdbf5", - "utilization": 0, - "usable": true, - "label": "", - "depth": 20, - "amount": "100000000", - "bucketDepth": 16, - "blockNumber": 30643611, - "immutableFlag": true, - "exists": true, - "batchTTL": 20588, - "expired": false - } - ] -} -``` - - - - - #### Swarm CLI ```bash @@ -227,65 +143,20 @@ TTL: 5 hours 42 minutes 18 seconds Expires: 2023-10-26 ``` - - - :::info -It is not possible to reupload unencrypted content which was stamped using an expired postage stamp. +It is not possible to reupload unencrypted content which was stamped using an expired postage stamp. ::: - ## Checking the remaining TTL (time to live) of your batch :::info At present, TTL is a primitive calculation based on the current storage price and the assumption that storage price will remain static in the future. As more data is uploaded into Swarm, the price of storage will begin to increase. For data that it is important to keep alive, make sure your batches have plenty of time to live! ::: -In order to make sure your *batch* has sufficient *remaining balance* to be stored and served by nodes in its [*area of responsibility*](/docs/references/glossary#2-area-of-responsibility-related-depths), you must regularly check on its _time to live_ and act accordingly. The *time to live* is the number of seconds before the chunks will be considered for garbage collection by nodes in the network. - -The remaining *time to live* in seconds is shown in the API in the returned json object as the value for `batchTTL`, and with Swarm CLI you will see the formatted TTL as the `TTL` value. +In order to make sure your _batch_ has sufficient _remaining balance_ to be stored and served by nodes in its [_area of responsibility_](/docs/references/glossary#2-area-of-responsibility-related-depths), you must regularly check on its _time to live_ and act accordingly. The _time to live_ is the number of seconds before the chunks will be considered for garbage collection by nodes in the network. - - - - -#### API - - -```bash -curl http://localhost:1633/stamps -``` - -```bash -{ - "stamps": [ - { - "batchID": "f4b9830676f4eeed4982c051934e64113dc348d7f5d2ab4398d371be0fbcdbf5", - "utilization": 0, - "usable": true, - "label": "", - "depth": 20, - "amount": "100000000", - "bucketDepth": 16, - "blockNumber": 30643611, - "immutableFlag": true, - "exists": true, - "batchTTL": 20588, - "expired": false - } - ] -} -``` - - - - +The remaining _time to live_ in seconds is shown in the API in the returned json object as the value for `batchTTL`, and with Swarm CLI you will see the formatted TTL as the `TTL` value. #### Swarm CLI @@ -301,8 +172,6 @@ TTL: 5 hours 42 minutes 18 seconds Expires: 2023-10-26 ``` - - ## Top up your batch @@ -312,25 +181,6 @@ Don't let your batch run out! If it does, you will need to restamp and resync yo If your batch is starting to run out, or you would like to extend the life of your batch to protect against storage price rises, you can increase the batch TTL by topping up your batch using the stamps endpoint, passing in the relevant batchID into the HTTP PATCH request. - - - - -#### API - -```bash -curl -X PATCH "http://localhost:1633/stamps/topup/6d32e6f1b724f8658830e51f8f57aa6029f82ee7a30e4fc0c1bfe23ab5632b27/10000000" -``` - - - - - #### Swarm CLI List available stamps. @@ -340,6 +190,7 @@ swarm-cli stamp list ``` Copy stamp ID. + ```bash Stamp ID: daa8c5b36e1cf481b10118a8b02430a6f22618deaa6ba5aa4ea660de66aa62db Usage: 13% @@ -356,6 +207,7 @@ swarm-cli stamp topup --amount 10000000 --stamp daa8c5b36e1cf481b10118a8b02430a ``` Wait for topup transaction to complete. + ```bash ⬡ ⬡ ⬢ Topup in progress. This may take a while. Stamp ID: daa8c5b36e1cf481b10118a8b02430a6f22618deaa6ba5aa4ea660de66aa62db @@ -363,100 +215,10 @@ Depth: 20 Amount: 100000001000 ``` - - - - ## Dilute your batch In order to store more data with a batch of stamps, you must "dilute" the batch. Dilution simply refers to increasing the depth of the batch, thereby allowing it to store a greater number of chunks. As dilution only increases the the depth of a batch and does not automatically top up the batch with more xBZZ, dilution will decrease the TTL of the batch. Therefore if you wish to store more with your batch but don't want to decrease its TTL, you will need to both dilute and top up your batch with more xBZZ. - - - - -#### API - - -Here we call the `/stamps` endpoint and find a batch with `depth` 24 and a `batchTTL` of 2083223 which we wish to dilute: - -```bash -curl http://localhost:1633/stamps -``` - -```json -{ - "stamps": [ - { - "batchID": "0e4dd16cc435730a25ba662eb3da46e28d260c61c31713b6f4abf8f8c2548ae5", - "utilization": 0, - "usable": true, - "label": "", - "depth": 24, - "amount": "10000000000", - "bucketDepth": 16, - "blockNumber": 29717348, - "immutableFlag": false, - "exists": true, - "batchTTL": 2083223, - "expired": false - } - ] -} -``` - -Next we call the [`dilute`](/api/#tag/Postage-Stamps/paths/~1stamps~1dilute~1{batch_id}~1{depth}/patch) endpoint to increase the `depth` of the batch using the `batchID` and our new `depth` of 26: - -```bash -curl -s -XPATCH http://localhost:1633/stamps/dilute/0e4dd16cc435730a25ba662eb3da46e28d260c61c31713b6f4abf8f8c2548ae5/26 -``` -And a `txHash` of our successful transaction: - -```bash -{ - "batchID": "0e4dd16cc435730a25ba662eb3da46e28d260c61c31713b6f4abf8f8c2548ae5", - "txHash": "0x298e80358b3257292752edb2535a1cd84440c074451b61f78fab349aea4962b7" -} -``` - -And finally we use the `/stamps` endpoint again to confirm the new `depth` and decreased `batchTTL`: - -```bash -curl http://localhost:1633/stamps -``` - -We can see the new `depth` of 26 and a decreased `batchTTL` of 519265. - -```json -{ - "stamps": [ - { - "batchID": "0e4dd16cc435730a25ba662eb3da46e28d260c61c31713b6f4abf8f8c2548ae5", - "utilization": 0, - "usable": true, - "label": "", - "depth": 26, - "amount": "10000000000", - "bucketDepth": 16, - "blockNumber": 29717348, - "immutableFlag": false, - "exists": true, - "batchTTL": 519265, - "expired": false - } - ] -} -``` - - - - - #### Swarm CLI List available stamps, make sure to use the `--verbose` flag so that we can see the batch depth. @@ -496,9 +258,6 @@ Depth: 20 Amount: 100010002000 ``` - - - ## Stewardship The stewardship endpoint in combination with [pinning](/docs/develop/access-the-swarm/pinning) can be used to guarantee that important content is always available. It is used for checking whether the content for a Swarm reference is retrievable and for re-uploading the content if it is not. @@ -513,9 +272,10 @@ An HTTP GET request to the `stewardship` endpoint checks to see whether the cont curl "http://localhost:1633/stewardship/c0c2b70b01db8cdfaf114cde176a1e30972b556c7e72d5403bea32e c0207136f" ``` + ```json { - "isRetrievable": true + "isRetrievable": true } ``` @@ -525,4 +285,4 @@ If the content is not retrievable, an HTTP PUT request can be used to re-upload curl -X PUT "http://localhost:1633/stewardship/c0c2b70b01db8cdfaf114cde176a1e30972b556c7e72d5403bea32ec0207136f" ``` -Note that for the re-upload to succeed, the associated content must be available locally, either pinned or cached. Since it isn't easy to predict if the content will be cached, for important content pinning is recommended. \ No newline at end of file +Note that for the re-upload to succeed, the associated content must be available locally, either pinned or cached. Since it isn't easy to predict if the content will be cached, for important content pinning is recommended. From fc9173ddf74709abe3135b340408cf5764018be6 Mon Sep 17 00:00:00 2001 From: tamas6 <81620050+tamas6@users.noreply.github.com> Date: Wed, 26 Mar 2025 14:55:11 +0100 Subject: [PATCH 16/16] swarm-cli commands --- .../access-the-swarm/buy-a-stamp-batch.md | 2 +- .../access-the-swarm/store-with-encryption.md | 10 +- .../access-the-swarm/upload-and-download.md | 170 +++--------------- 3 files changed, 34 insertions(+), 148 deletions(-) diff --git a/docs/develop/access-the-swarm/buy-a-stamp-batch.md b/docs/develop/access-the-swarm/buy-a-stamp-batch.md index e74b9385a..fa1ebf39c 100644 --- a/docs/develop/access-the-swarm/buy-a-stamp-batch.md +++ b/docs/develop/access-the-swarm/buy-a-stamp-batch.md @@ -179,7 +179,7 @@ Expires: 2023-10-26 Don't let your batch run out! If it does, you will need to restamp and resync your content. ::: -If your batch is starting to run out, or you would like to extend the life of your batch to protect against storage price rises, you can increase the batch TTL by topping up your batch using the stamps endpoint, passing in the relevant batchID into the HTTP PATCH request. +If your batch is starting to run out, or you would like to extend the life of your batch to protect against storage price rises, you can increase the batch TTL by topping up your batch using swarm-cli's stamp topup command, passing in the relevant batchID. #### Swarm CLI diff --git a/docs/develop/access-the-swarm/store-with-encryption.md b/docs/develop/access-the-swarm/store-with-encryption.md index 7c1c3685e..2ca39f464 100644 --- a/docs/develop/access-the-swarm/store-with-encryption.md +++ b/docs/develop/access-the-swarm/store-with-encryption.md @@ -9,10 +9,10 @@ The Bee client provides a facility to encrypt files and directories while upload # Encrypt and Upload a File -To encrypt a file simply include the `Swarm-Encrypt: true` header with your HTTP request. +To encrypt a file simply include the `--encrypt` flag to your `swarm-cli` upload command. ```bash -curl -F file=@bee.jpg -H "Swarm-Postage-Batch-Id: 78a26be9b42317fe6f0cbea3e47cbd0cf34f533db4e9c91cf92be40eb2968264" -H "Swarm-Encrypt: true" http://localhost:1633/bzz +swarm-cli upload bee.jpg --stamp 78a26be9b42317fe6f0cbea3e47cbd0cf34f533db4e9c91cf92be40eb2968264 --encrypt ``` When successful, the Bee client will return a 64 byte reference, instead of the usual 32 bytes. @@ -21,7 +21,7 @@ More information on how to buy a postage stamp batch and get its batch id can be ```json { - "reference": "f7b1a45b70ee91d3dbfd98a2a692387f24db7279a9c96c447409e9205cf265baef29bf6aa294264762e33f6a18318562c86383dd8bfea2cec14fae08a8039bf3" + "reference": "f7b1a45b70ee91d3dbfd98a2a692387f24db7279a9c96c447409e9205cf265baef29bf6aa294264762e33f6a18318562c86383dd8bfea2cec14fae08a8039bf3" } ``` @@ -37,10 +37,10 @@ Encryption is disabled by default on all Swarm Gateways to keep your data safe. # Download and Decrypt a File -To retrieve your file, simply supply the full 64 byte string to the files endpoint, and the Bee client will download and decrypt all the relevant chunks and restore them to their original format. +To retrieve your file, simply enter the full 64-byte string to swarm-cli's download command, and the Bee client will download and decrypt all the relevant chunks and restore them to their original format. ```bash -curl -OJ http://localhost:1633/bzz/f7b1a45b70ee91d3dbfd98a2a692387f24db7279a9c96c447409e9205cf265baef29bf6aa294264762e33f6a18318562c86383dd8bfea2cec14fae08a8039bf3 +swarm-cli download f7b1a45b70ee91d3dbfd98a2a692387f24db7279a9c96c447409e9205cf265baef29bf6aa294264762e33f6a18318562c86383dd8bfea2cec14fae08a8039bf3 ``` :::danger diff --git a/docs/develop/access-the-swarm/upload-and-download.md b/docs/develop/access-the-swarm/upload-and-download.md index b8dd91f1d..803d61308 100644 --- a/docs/develop/access-the-swarm/upload-and-download.md +++ b/docs/develop/access-the-swarm/upload-and-download.md @@ -3,29 +3,20 @@ title: Upload and Download id: upload-and-download --- +When you upload your files to the Swarm, they are split into 4kb _chunks_ and then distributed to nodes in the network that are responsible for storing and serving these parts of your content. +To learn more about how Swarm's decentralized storage solution works, check out the ["Concepts" section](/docs/concepts/what-is-swarm). -import Tabs from '@theme/Tabs'; -import TabItem from '@theme/TabItem'; - -When you upload your files to the Swarm, they are split into 4kb -_chunks_ and then distributed to nodes in the network that are -responsible for storing and serving these parts of your content. -To learn more about how Swarm's decentralized storage solution works, -check out the ["Concepts" section](/docs/concepts/what-is-swarm). - -In order for you to be able to upload any data to the network, -you must first purchase [postage stamps](/docs/concepts/incentives/postage-stamps) -and then use those stamps to upload your data. Keep on reading below to learn how. +In order for you to be able to upload any data to the network, you must first purchase [postage stamps](/docs/concepts/incentives/postage-stamps) and then use those stamps to upload your data. Keep on reading below to learn how. ## Uploads and Download Endpoints Overview -There are three endpoints which can be used for uploading and downloading data from Swarm, and each endpoint has different usage. +There are three endpoints which can be used for uploading and downloading data from Swarm, and each endpoint has different usage. 1. [`/bytes`](/api/#tag/Bytes) - Used for uploading raw data, lacks convenience features present in the `/bzz` endpoint but allows for greater customization for advanced use cases. -1. [`/bzz`](/api/#tag/BZZ) - Used for general download and uploads of files or collections of files. -1. [`/chunks`](/api/#tag/Chunk) - Used for downloading and uploading individual chunks, and also for uploading streams of chunks. +2. [`/bzz`](/api/#tag/BZZ) - Used for general download and uploads of files or collections of files. +3. [`/chunks`](/api/#tag/Chunk) - Used for downloading and uploading individual chunks, and also for uploading streams of chunks. -Generally speaking, the `/bzz` endpoint is appropriate for general common use cases such as uploading websites, sharing files, etc., while the `/chunks` and `bytes` endpoints allow for more complex uses cases. In this guide, we focus on the usage of the `/bzz` endpoint. +Generally speaking, the `/bzz` endpoint is appropriate for general common use cases such as uploading websites, sharing files, etc., while the `/chunks` and `/bytes` endpoints allow for more complex use cases. In this guide, we focus on the usage of the `/bzz` endpoint. ## Upload a File @@ -39,78 +30,25 @@ To upload data to the swarm, you must perform the following steps: ## Purchasing Your Batch of Stamps -In order to upload your data to swarm, you must agree to burn (spend) -some of your xBZZ to signify to storer and fowarder nodes that this -content is valued. Before you proceed to the next step, you must buy -stamps! See this guide on how to [purchase an appropriate batch of stamps](/docs/develop/access-the-swarm/buy-a-stamp-batch). +In order to upload your data to Swarm, you must agree to burn (spend) some of your xBZZ to signify to storer and forwarder nodes that this content is valued. +Before you proceed to the next step, you must buy stamps! See this guide on how to [purchase an appropriate batch of stamps](/docs/develop/access-the-swarm/buy-a-stamp-batch). ## Using Stamps to Upload a File -Once your Bee node is running, a HTTP API is enabled for you to interact with. The command line utility [curl](https://ec.haxx.se/http/http-multipart) is a great way to interact with a Bee node's API. Swarm CLI alternative commands are also included as a more user-friendly way of interacting with your Bee node's API. - +Once your Bee node is running, you can use the `swarm-cli` to interact with the network. - - +### Swarm CLI -#### API - -First, let's check to see if the API is running as expected... - -```bash -curl http://localhost:1633 -``` - -``` -Ethereum Swarm Bee -``` - -Once running, a file can be uploaded by making an HTTP POST request to the `bzz` endpoint of the Bee API. - -Here, you must specify your _Batch ID_ in the `Swarm-Postage-Batch-Id` header, the file name in the `name` query parameter, and also pass the appropriate mime type in the `Content-Type` header. - -You may also wish to employ the erasure coding feature to add greater protection for your data, see [erasure coding page](/docs/develop/access-the-swarm/erasure-coding) for more details on its usage. - -```bash - curl -X POST -H "Swarm-Postage-Batch-Id: 54ba8e39a4f74ccfc7f903121e4d5d0fc40732b19efef5c8894d1f03bdd0f4c5" -H "Content-Type: text/plain" -H "Swarm-Encrypt: false" -v --data-binary "@test.txt" localhost:1633/bzz -``` - -:::danger -Data uploaded to Swarm is always public. In Swarm, sensitive files -must be [encrypted](/docs/develop/access-the-swarm/store-with-encryption) -before uploading to ensure their contents always remains private. -::: - -When succesful, a JSON formatted response will be returned, containing -a **swarm reference** or **hash** which is the _address_ of the -uploaded file, for example: - -```json -{ - "reference": "22cbb9cedca08ca8d50b0319a32016174ceb8fbaa452ca5f0a77b804109baa00" -} -``` - -Keep this _address_ safe, as we'll use it to retrieve our content later on. - - - - - -#### Swarm CLI -We have a `test.txt` file we wish to upload, let's check its contents. +We have a `test.txt` file we wish to upload, let's check its contents: ```bash cat test.txt This is a test file It will be used to test uploading and downloading from Swarm + ``` -Check that our node is operating normally. +Check that our node is operating normally. ```bash swarm-cli status @@ -120,7 +58,7 @@ swarm-cli status Bee API: http://localhost:1633 [OK] -Version: 2.0.0-50fcec7b +Version: 2.5.0 Mode: full Topology @@ -165,6 +103,7 @@ Remaining Capacity: 7.50 GB TTL: 91 days 1 hour 45 minutes 28 seconds Expires: 2024-02-01 ``` + Use the stamp ID to upload our file. ```bash @@ -178,7 +117,7 @@ Swarm hash: 1ffd2b67c8f34596a0b8375be29423c2d47e7995fcac8dd83fbd34e3d839b5a2 URL: http://localhost:1633/bzz/1ffd2b67c8f34596a0b8375be29423c2d47e7995fcac8dd83fbd34e3d839b5a2/ Stamp ID: daa8c5b3 Usage: 7% -Remaining Capacity: 7.50 GB +Remaining Capacity: 7.50 GB ``` Let's check that the file is downloadable. @@ -195,9 +134,6 @@ cat test.txt This is a test file It will be used to test uploading and downloading from Swarm ``` - - - In Swarm, every piece of data has a unique _address_ which is a unique and reproducible cryptographic hash digest. If you upload the same file twice, you will always receive the same hash. This makes working with data in Swarm super secure! @@ -209,47 +145,17 @@ Once your file has been **completely synced with the network**, you will be able ## Download a File -Once your file is uploaded to Swarm it can be easily downloaded. - - - - - -#### API - -Uploaded files can be retrieved with a simple HTTP GET request. - -Substitute the _hash_ in the last part of the URL with the reference -to your own data. - -:::tip -Make sure to include the trailing slash after the hash. -::: -```bash -curl -OJL http://localhost:1633/bzz/c02e7d943fbc0e753540f377853b7181227a83e773870847765143681511c97d/ -``` - -You may even simply navigate to the URL in your browser: - -[http://localhost:1633/bzz/22cb...aa00](http://localhost:1633/bzz/22cbb9cedca08ca8d50b0319a32016174ceb8fbaa452ca5f0a77b804109baa00) - - - - - +Once your file is uploaded to Swarm it can be easily downloaded. #### Swarm CLI -Simply use the `swarm-cli download` command followed by the hash of the file you wish to download. + +Simply use the `swarm-cli download` command followed by the hash of the file you wish to download. ```bash swarm-cli download 1ffd2b67c8f34596a0b8375be29423c2d47e7995fcac8dd83fbd34e3d839b5a2 test.txt OK ``` + And let's print out the file contents to confirm it was downloaded properly. ```bash @@ -257,11 +163,8 @@ cat test.txt This is a test file It will be used to test uploading and downloading from Swarm ``` - - - -## Upload a Directory +## Upload a Directory It is possible to use Bee to upload directories of files all at once. @@ -301,30 +204,17 @@ tar -cf ../my_website.tar . cd .. ``` -Next, simply POST the `tar` file as binary data to Bee's `dir` endpoint, taking care to include the header `Content Type: application/x-tar`. - :::info -In order to upload your data to swarm, you must agree to burn some of your xBZZ to signify to storer and fowarder nodes that the content is important. Before you progress to the next step, you must buy stamps! See this guide on how to [purchase an appropriate batch of stamps](/docs/develop/access-the-swarm/buy-a-stamp-batch). +For instances where a single page app has a JavaScript router that handles url queries itself, simply pass `index.html` as the error document. Bee will pass over control to the JavaScript served by the `index.html` file in the circumstance that a path does not yield a file from the manifest. ::: +Upload the tar file using swarm-cli: + ```bash -curl \ - -X POST \ - -H "Content-Type: application/x-tar" \ - -H "Swarm-Index-Document: index.html" \ - -H "Swarm-Error-Document: error.html" \ - -H "Swarm-Collection: true" \ - -H "Swarm-Postage-Batch-Id: 78a26be9b42317fe6f0cbea3e47cbd0cf34f533db4e9c91cf92be40eb2968264" \ - --data-binary @my_website.tar http://localhost:1633/bzz +swarm-cli upload my_website.tar --stamp daa8c5b36e1cf481b10118a8b02430a6f22618deaa6ba5aa4ea660de66aa62db ``` -:::info -For instances where a single page app has a JavaScript router that handles url queries itself, simply pass `index.html` as the error document. Bee will pass over control to the JavaScript served by the `index.html` file in the circumstance that a path does not yield a file from the manifest. -::: - -When the upload is successful, Bee will return a JSON document containing the Swarm Reference. - -```json +``` { "reference": "b25c89a401d9f26811680476619a1eb4a4e189e614bc6161cbfd8b343214917b" } @@ -344,8 +234,6 @@ Once your data has been [fully processed into the network](/docs/develop/access- If you are not able to download your file from a different Bee node, you may be experiencing connection issues, see [troubleshooting connectivity](/docs/bee/installation/connectivity) for assistance. - - ## Public Gateways To share files with someone who isn't running a Bee node yet, simply change the host in the link to be one of our public gateways. Send the link to your friends, and they will be able to download the file too! @@ -354,10 +242,9 @@ To share files with someone who isn't running a Bee node yet, simply change the - ## Deferred and Direct Uploads -By default your bee instance will handle uploads in a _deferred_ manner, meaning that the data will be completely uploaded to your node locally before being then being uploaded to the Swarm network. +By default your bee instance will handle uploads in a _deferred_ manner, meaning that the data will be completely uploaded to your node locally before being then being uploaded to the Swarm network. In contrast, for a direct upload, the data will be completely uploaded to the Swarm network directly. @@ -371,4 +258,3 @@ curl \ -H "swarm-postage-batch-id: 78a26be9b42317fe6f0cbea3e47cbd0cf34f533db4e9c91cf92be40eb2968264" \ --data-binary @my_data.tar http://localhost:1633/bzz ``` -