# Getting Started

Setup and run your first Arweave miner

This guide walks you through planning, installing, and bringing an Arweave miner online for the first time.

{% hint style="info" %}
For any questions and support queries regarding mining on Arweave, we strongly recommend that you join our [**Discord server**](https://discord.gg/GHB4fxVv8B) and visit our [Discussions Board](https://github.com/ArweaveTeam/arweave/discussions) as these are the hubs of our mining and developer communities. There you will find plenty of community members and Arweave team members available to help you out 🤖
{% endhint %}

{% hint style="warning" %}
Miners are responsible for their own compliance with data protection laws (such as GDPR) and other applicable laws in their jurisdiction. Data storage laws vary country to country. Failure to adhere to these laws may entail substantial legal risks for the miner. Please only participate in mining Arweave data if you have understood the legal implications of doing so and consider seeking legal advice.
{% endhint %}

## 1. [Choose Your Node Type](/developers/mining/overview/node-types)

Decide whether you are running a solo miner, coordinated miner, pool miner, VDF server, or validator.

## 2. [Plan Your Hardware](/developers/mining/getting-started/hardware)

Size CPU, memory, storage, and network based on your chosen role.

## 3. [Configure the Operating System](/developers/mining/getting-started/os)

Configure your operating system for Arweave workloads.

## 4. [Install the Arweave Node](/developers/mining/getting-started/install)

Install the node software either from pre-built binaries or by building from source, and verify the installation.

## 5. [Setup Your Directory Structure](/developers/mining/getting-started/directory-structure)

Create the directories and links for your `data_dir` and storage modules.

## 6. [Create Your Node Wallet](/developers/mining/getting-started/wallet)

All nodes need a configured wallet (aka mining key), if you don't specify one it will be created for you. If you're not mining, this default wallet is probably fine. For miners:

## 7. [Configure and Run Your Node](/developers/mining/getting-started/configuration)

Depending on your node type, operating phase, and different elements of your hardware and system configuration you will want to run your node with a different set of configuration options. We've provided a few examples in the [Node Configuration Guide](/developers/mining/getting-started/configuration) to get you started.

## 8. Learn, Iterate, and Optimize

After you get your node running, we recommend familiarizing yourself with the rest of the Mining Guide, joining the [Discord Server](https://discord.gg/GHB4fxVv8B), and reviewing the [Discussions Board](https://github.com/ArweaveTeam/arweave/discussions). There is a lot to learn and you will likely hit issues as you ramp up and tune your Arweave node - hopefully these resources will help you through it.

Thank you for supporting the Permaweb!


# Hardware Guide

Planning your miner's hardware configuration

## 1. Overview

This guide will outline the main considerations when building your miner and provide an example configuration.

{% hint style="warning" %}
Mining configurations vary tremendously from miner to miner, and we're not yet able to certify specific component compatibility. As you build your miner you will need to verify compatibility between components.
{% endhint %}

The Arweave dataset (called the "weave") is broken up into 3.6TB partitions (3,600,000,000,000 bytes). There are 103 partitions as of November, 2025, although that will grow over time as users upload more data. **The Arweave protocol provides a strong incentive to mine against the complete dataset or multiple copies of the complete dataset (called "full replicas").** For more details on how hashrate is calculated and why it's important to mine as close to a full replica as possible see [Overview - Hashrate](/developers/mining/overview/hashrate).

There are 3 operating phases with different resource bottlenecks:

### 1.1 Syncing and Packing

In this phase a miner is syncing weave data and preparing it to be mined. Data is ready to be mined only after entropy has been generated and the data has been packed to that entropy. See [Overview - Syncing and Packing](/developers/mining/overview/syncing-and-packing) for more information about this process.

During this phase the main resource bottlenecks are (roughly in order):

1. [Network bandwidth](#32-network-bandwidth)
2. [CPU](#341-cpu-while-packing)
3. [Storage bandwidth](#31-storage-bandwidth)
4. [RAM](#33-ram)

### 1.2 Mining

In this phase a miner has all of their data packed and stored and is now mining it. See [Overview - Hashrate](/developers/mining/overview/hashrate) for more information about the mining process.

During this phase the main resource bottlenecks are (roughly in order):

1. Storage space
2. [Storage bandwidth](#31-storage-bandwidth)
3. [RAM](#33-ram)
4. [CPU](#342-cpu-while-mining)

### 1.3 VDF Computation

VDF computation isn't a distinct phase, it happens all the time and is an input to both mining and block validation. Since VDF speed has a strong impact on mining hashrate, most miners opt to use a dedicated VDF server optimized for the task. This is not required, though. As of November 2025 the fastest observed VDF computation is on Apple Silicon (e.g. M4).

The main resource bottleneck whe computing VDF:

1. [CPU](#343-cpu-while-computing-vdf) (specifically single-threaded SHA256 compute speed)

## 2. Mining Platform

Although the resource requirements differ materially between the Syncing & Packing and Mining phases, most miners opt to use the same hardware configuration throughout. So whilke it is possible to have dedicated Syncing & Packing servers and dedicated Mining server, we will focus on the single-platform approach for this guide.

There are 2 possible mining configurations:

1. [Solo Miner](/developers/mining/overview/node-types#1-solo-miner): A single node mining a full replica
2. [Coordinated Miner](/developers/mining/overview/node-types#2-coordinated-miner): Multiple nodes each mining a partial replica and coordinating together to assemble a full replica

**To date the dominant strategy has been to adopt a multi-node / coordinated mining approach.** As the weave continues to grow we believe this strategy will only increase in popularity.

{% hint style="warning" %}
This sample node was configured before the `replica.2.9` packing format was introduced. Prior to `replica.2.9` it was important for miners to be able to sustain an average read rate of **200 MB/s** from each **4TB** HDD. Storage bandwidth is still important, but the optimal read rate has dropped to **20 MB/s** per **16TB** HDD. With these improvements it's possible that miners with lower read bandwidth can still mine optimally. However until we have examples of those configurations working well, we are leaving in place the recommendation for highly optimized storage bandwidth.
{% endhint %}

{% hint style="success" %}

### An example 64-partition (256TB) node could include:

1. 1x mid-tier Ryzen CPU (e.g. Ryzen 5/7/9)
2. 1x motherboard with at least one PCIe 3.0 8x slot
3. 1x 16-port Host Bus Adapter (HBA)
   * SAS2 or SAS3, LSI or Broadcom HBA, 16i or 16e
   * For example:
     * LSI SAS 9201-16i (SAS2)
     * Broadcom 9305-16e (SAS3)
4. 4x Mini SAS to SATA breakout cables
   * Mini SAS ports can be either SFF-8087 or SFF-8643
5. 16x 16TB 7200rpm SATA HDDs (for 64 partitions of mineable weave data)
6. 1x 1TB SSD or NVMe (for `data_dir`)
7. 1x PSU with at least 16 SATA ports
   {% endhint %}

You would then coordinate 2 or more of these nodes to cover the full weave.

It is also possible to configure a single node that mines against more than 64 partitions. We outline the main considerations below to provide guidance should you wish to move away from the example configuration above.

Note: it is also possible to mine efficiently as a partial replica miner. In that case you will want to join a [Mining Pool](/developers/mining/overview/node-types#3-pool-miner) that is able to coordinate your partitions with other miners in the pool so that you are still able to get the full replica hashrate bonus.

## 3. Resource bottlenecks

This section attempts to break down the different hardware bottlenecks and provide some guidance in designing your system. We also suggest you review the [Operations - Benchmarking](/developers/mining/operations/benchmarking) guide for some direction on benchmarking your system to estimate its mining, packing, and VDF performance.

## 3.1 Storage Bandwidth

An efficient miner needs to maintain at last an average of 5MB/s read throughput per 3.6TB partition while mining. In our example configuration we used 16TB HDDs that can each fit 4 partitions. So the miner will need to maintain read throughput of 20MB/s. Read throughput is measured from the disk to the CPU. The main components involved are:

1. Hard Disk Drive (HDD)
2. Host Bus Adapter (HBA) (optionally with SAS expander)
3. PCIe slots on the motherboard

We'll now cover each component in a bit more depth.

### 3.1.1 Solid State Drive (SSD) for `data_dir`

Most of this section is focused on bandwidth requirements for mining weave data. In addition to weave data, every Arweave node (miner or othwerwise) needs to allocate space for the `data_dir`. You can read more about the `data_dir` in [Setup - Directory Structure](/developers/mining/getting-started/directory-structure). The data in `data_dir` is read and written frequently by all node services. Because of this we recommend that it be stored on an NVMe or SSD. Storing your `data_dir` on an HDD can negatively impact the peformance of all node operations. The minimum recommended size for the `data_dir` is 256GB - a larger size will provide you some buffer as datasets grow as well as allow you to store more of the blockchain history. A larger `data_dir` isn't required for efficient mining, but it allows your node to participate more fully with the network and can limit the frequency of configuration changes and data cleanup tasks. Many miners opt for a 500GB or 1TB `data_dir`.

### 3.1.2 Hard Disk Drive (HDD)

**The main requirement is that your HDDs are able to provide an average read throughput of 5MB/s per 3.6TB partition.** For example, a 16TB HDD storing 4 partitions would need to sustain an average read rate of 20MB/s. The extra 0.4TB is used for metadata stored adjacent to the weave data.

However, each miner's situation is different and miners may find it more profitable to mine different configurations, for example:

1. Use smaller disks with fewer partitions (e.g. 1x 4TB HDD with 1 partition, 1x 8TB HDD with 2 partitions, etc..)
2. Distribute 3 partitions across 4x 3TB HDDs
3. Use even larger disks (e.g. 1x 24TB HDD with 6 partitions that can sustain 30MB/s read rate)

Similarly, both SATA and SAS HDDs will work fine, you will just need to ensure compatibility between the HDDs, cabling, and other components.

### 3.1.3 Host Bus Adapter (HBA)

Most motherboards don't integrate enough SATA connectors to support 16+ disks, so you will likely need at least one HBA. There are many, many different HBAs to choose from. The first question is: how many disks will you connect to the HBA? Once you have that number you can work through the following attributes to select your HBA:

1. SAS version
2. Number of SAS lanes
3. Optional SAS expander
4. Number of PCIe lanes and PCIe version
5. Internal or external SAS ports
6. Miscellaneous

Let's work through them assuming our sample configuration of 16x 16TB SATA disks per node.

16x 16TB SATA disks will require a total of 16 x 160Mbps = 2.56 Gbps of sustained, average read throughput. (Note: 20MB/s = 160Mbps)

{% hint style="info" %}
Note: we don't recommend using RAID. In general neither software nor hardware RAID provide enough benefits to offset the cost and complexity - and under some configurations can hurt performance. As always: each miner's situation is different. Some miners with expertise or access to hardware may find RAID configurations that are beneficial.
{% endhint %}

#### SAS Version

SAS (stands for Serial-Attached SCSI) is a data transfer protocol. There are 3 different speed standards for SAS

* SAS-1: 3 Gbps per lane
* SAS-2: 6 Gbps per lane
* SAS-3: 12 Gbps per lane

All the standards are interoperable, however when combining cables and peripherals at different SAS standards, the data transfer throughput is determined by the slowest component. e.g. if you attach a SAS-1 expander to a SAS-3 HBA, your throughput will be 3 Gbps per lane, not 12 Gbps per lane.

Because of this we recommend deciding on a standard early and selecting all components at that standard or higher.

{% hint style="info" %}
We recommend sticking with SAS-2 or SAS-3 as it will help ensure the SAS speed does not become a bottleneck if you decide to add more disks in the future.
{% endhint %}

#### Number of SAS Lanes

HBA product names end in a number and a letter, like 8i, 16i, 16e. The number refers to the number of SAS lanes supported by the HBA. There are 4 lanes per HBA connector (typically a Mini-SAS connector, but there are other ports too). So a "SAS-2 LSI HBA 16i" has 4 connectors, each with 4 SAS lanes, for a total of 16 lanes. 16 lanes x 6 Gbps = 96 Gbps of aggregate throughput.

Without using a SAS expander (discussed below) each HBA lane can connect directly to a single HDD. So if you want to support 16 disks, you need a 16-lane (sometimes called 16-port) HBA. Each 16TB disk requires 160 Mbps of read bandwidth, which is well below the SAS bandwidth (all versions).

{% hint style="info" %}
We recommend using a 16i or 16e HBA to connect 16 disks.
{% endhint %}

As you may have noticed each HBA lane has enough bandwidth to theoretically support multiple disks. A 6Gbps SAS-2 lane, for example, could theoretically support 37x 16TB disks at 160 Mbps per disk. To achieve this, you would need to add a SAS Expander.

#### SAS Expander

Using a SAS Expander you can connect multiple disks to each SAS lane on your HBA. Aligning SAS versions is particularly important when using a SAS Expander. For example if you use a SAS-1 Expander with a SAS-2 HBA and try to attach 30x 16TB disks to each SAS lane, the lower SAS-1 throughput of 3 Gbps will throttle your read rate.

{% hint style="info" %}
Using a SAS Expander also requires an extra PCIe slot (discussed below), and is one more component to troubleshoot and replace. For these reasons we don't recommend using a SAS expander unless you are prepared for the additional complexity.
{% endhint %}

#### Number of PCIe lanes and PCIe version

The final connection is from the HBA to the motherboard via the PCIe slot.

{% hint style="info" %}
To ensure the PCIe bandwidth itself does not become a bottleneck we recommend sticking with adapters that use PCIe version 3.0 with 8 PCIe lanes adapters. PCIe 3.0 8x provides 62.4 Gbps of bandwidth which is enough to handle up to 390x 16TB disks.
{% endhint %}

#### Internal vs. External

One more note on the HBA: the letter at the end of the product number (i.e. 16i vs. 16e) refers to "internal" vs. "external" connectors. A 16i HBA will expose the Mini-SAS connectors to the interior of the case, a 16e will expose the MIni-SAS connectors to the exterior of the case. We have no recommendation here as it depends on where you plan to mount your disks.

#### Miscellaneous

Since computer systems are complex and the components incredibly varied, it's possible that there may be other bandwidth limitations in your system separate from the HBA and disks. You may want to review the specifications of any other components in your system to ensure they don't restrict your available read bandwidth.

### 3.1.4 PCIe Slots on the Motherboard

As mentioned above in the HBA section, we recommend using 8-lane PCIe 3.0 or better for connecting your HBA and any SAS expanders. You'll want to keep this in mind when buying a motherboard to ensure it has enough slots of the right type to accommodate your HBA(s) and any SAS expanders.

### 3.1.5 Storage Bandwidth while Packing

Depending on how you're packing data as well other resource constraints (e.g. network bandwidth, CPU), it's possible for storage read or write bandwidth to become a bottleneck while packing. Some examples:

* It's often possible to generate 1 GB per second of packing entropy. In this case you may want to ensure you're always packing entropy for several disks at once to avoid hitting a write bandwidth bottleneck.
* When syncing and packing you'll need to read the previously written entropy from disk, pack a chunk, and then write the packed chunk back to disk. Storage bandwidth can be noticeably impacted here due to need to read and write, as well as seek to different locations.
* A similar read, write, and seek bottleneck can also surface while repacking in place.

As noted [below](#351-cpu-while-packing) a saving grace for packing is the fact that you only have to do it once data range. Once complete you can mine that packed data forever without repacking.

See [Overview - Syncing and Packing](/developers/mining/overview/syncing-and-packing) for more information on the packing process.

## 3.2 Network Bandwidth

### 3.2.1 Bandwidth While Mining

While mining the network bandwidth requirements are low. The main network activities are:

1. Receive new blocks and transactions to be validated
2. Share validated blocks and transactions with peers
3. Share mined blocks with peers
4. Continue to share chunk data in order to maintain your node reputation. See [Overview - Node Reputation](/developers/mining/overview/node-reputation) for more information.

In general 100 Mbps is more than enough network bandwidth while mining.

### 3.2.2 Bandwidth While Syncing and Packing

Before you can start mining you need to download a full replica (373 TB as of November, 2025). This phase is heavily bottlenecked by available download bandwidth and CPU capacity. For example if your download bandwidth is 1 Gbps it will take over 34 days to download the full data set. The faster your download speed, the faster you can sync the dataset. CPU capacity is covered below.

The saving grace to all this is that you only need to download and pack the data once per replica. Some miners will rent CPU time and access to bandwidth to reduce the time of this phase.

## 3.3 RAM

The current recommendation is to have 1GB of RAM per partition being mined - with a minimum of 8GB. Anecdotally many miners don't exceed 500-700MB of resident memory per partition being mined.

## 3.4 CPU

The CPU requirements while mining, packing, or computing VDF differ substantially. While it's possible and common to use the same CPU while packing and mining, the optimal CPU for computing VDF is not well-suited to mining or packing. More details below.

### 3.4.1 CPU While Packing

Packing is a parallelizable, CPU-intensive encryption process (the weave data is symmetrically encrypted using your mining address). Generally miners will sync and pack at the same time - packing data as they download it. As of November, 2025, most miners run AMD Ryzens or EPYC processors - although Intel variants are also common.

When selecting a CPU to use for packing your main metric will be how many chunks per second you can pack. Each chunk is 256KiB which means that a 373 TB full replica (as of November, 2025) contains about 1,492,000,000 chunks. You can use these values, as well as the guidance in [Benchmarking](/developers/mining/operations/benchmarking) to estimate how long your chosen CPU will take to pack a full replica. Of note: under some configurations [storage bandwidth](#314-storage-bandwidth-while-packing) and [network bandwidth](#332-bandwidth-while-syncing-and-packing) may replace the CPU as the main packing bottleneck.

### 3.4.2 CPU While Mining

CPU utilization while mining is much lower than packing. [Hashrate](/developers/mining/overview/hashrate) and [Benchmarking](/developers/mining/operations/benchmarking) provide detailed information about estimating hashrate and CPU capacity. As a rough guide you can expect 1 RandomX hash and 1,600 SHA256 hashes per partition per second. So a 100-partition miner needs to compute roughly 100 RandomX hashes (aka H0 hashes), and 160,000 SHA256 hashes (aka H1 and H2 hashes) per second. These hashing computations can be parallelized across cores.

### 3.4.3 CPU While Computing VDF

Computing VDF is a non-parallelizable, CPU-intensive process. At its core VDF is just a large number of recursive/serial SHA256 calculations. Because they are recursive (the output of one hash is used as the input to the next hash) they can **not** be parallelized across cores. VDF speed is determined by the SHA256 hashing speed of a single core.

To date the fastest VDF speed has been observed on Apple's M-class chips (e.g. M4). In order to maximize mining hashrate it's recommended that miners either run their own Mac-based VDF server, or rent access to a 3rd party Mac-based VDF server.

When packing or simply validating the block chain, a slower VDF speed is fine. Your non-Mac CPU is likely fast enough. The Digital History Associate (DHA) team also operates a few public VDF servers running on M2 processors that are free to use.

For more information about VDF please see [VDF](/developers/mining/overview/vdf) and [Benchmarking](/developers/mining/operations/benchmarking).

### 3.4.4 Dual-CPU Motherboards

There are several documented performance issues when trying to pack or mine on a dual-CPU motherboard. The current recommendation is to pin each node to a single CPU. You can also experiment with running multiple nodes on a single server (each one pinned to a different CPU) in order to maximize utilization. See [Multiple Nodes, One Server](/developers/mining/operations/multiple-nodes) for more information.


# System Configuration

How to configure your operating system to run Arweave

In order to run an Arweave miner efficiently, several operating system defaults should be updated.

## 0. Recommonded OS: Ubuntu Linux

We recommend running Arweave on Ubuntu Linux 22.04 or 24.04.

## 1. File Descriptors Limit

The number of available file descriptors affects the rate at which your node can process data. Most operating systems default to assigning a low limit for user processes, we recommend increasing it.

{% hint style="info" %}
These File Descriptors Limit instructions apply to Linux. When running a VDF Server on MacOS, please refer to the VDF guide.
{% endhint %}

You can check the current limit by executing `ulimit -n`.

On Linux, to set a bigger global limit, open `/etc/sysctl.conf` and add the following line:

```
fs.file-max=10000000
```

Execute `sysctl -p` to make the changes take effect.

You may also need to set a proper limit for the particular user. To set a user-level limit, open `/etc/security/limits.conf` and add the following line:

```
<your OS user>         soft    nofile  1000000
```

Open a new terminal session. To make sure the changes took effect, and the limit was increased, type `ulimit -n`. You can also change the limit for the current session via `ulimit -n 10000000`

If the above does not work, set

```
DefaultLimitNOFILE=1000000
```

in both `/etc/systemd/user.conf`and `/etc/systemd/system.conf`

## 2. Configuring Large Memory Pages

Mining involves computing 1 RandomX hash and several SHA2 hashes every second for every 3.6 TB mining partition. It is not a lot, but your CPU may nevertheless become a bottleneck when you configure a lot of mining partitions. To maximize your hashing performance, consider configuring huge memory pages in your OS.

On Ubuntu, to see the current values, execute:`cat /proc/meminfo | grep HugePages`. To set a value, run `sudo sysctl -w vm.nr_hugepages=5000`. To make the configuration survive reboots, create `/etc/sysctl.d/local.conf` and put `vm.nr_hugepages=5000` there.

The output of `cat /proc/meminfo | grep HugePages` should then look like this:\
`AnonHugePages: 0 kB`\
`ShmemHugePages: 0 kB HugePages_Total: 5000 HugePages_Free: 5000 HugePages_Rsvd: 0 HugePages_Surp: 0`

If it does not or if there is a "erl\_drv\_rwlock\_destroy" error on startup, reboot the machine.

Finally, tell the miner it can use large pages by specifying `enable randomx_large_pages` on startup (you can find a complete startup example further in the guide).


# Installing Arweave

Download the `.tar.gz` archive for your OS from the [releases page](https://github.com/ArweaveTeam/arweave/releases). Extract the contents of the archive - `tar -xzf [release_file]`.

{% hint style="info" %}
When upgrading Arweave make sure to extract the new archive to a new location. If you extract a new archive ontop of an existing install Arweave may not launch correctly.
{% endhint %}

For instructions on building Arweave from source see [Development - Building Arweave](/developers/development/build),


# Directory Structure

How to setup your node's directory structure

## 1. Overview

There are 3 main directories to plan for:

* Arweave install directory
* `data_dir`
* Storage modules

## 2. Arweave Install Directory

Most of the information can be found in [Installing Arweave](/developers/mining/getting-started/install). Main caveats:

* When upgrading Arweave make sure to extract the new archive to a new location. If you extract a new archive ontop of an existing install Arweave may not launch correctly.
* There should be no overlap between the install directory and your `data_dir`. i.e. `data_dir` should not be within the install directory, nor vice versa.

## 3. `data_dir`

All Arweave [node types](/developers/mining/overview/node-types) require a `data_dir` configured at launch - this can be any location on your system. The `data_dir` will store all the indices, data files, and metadata that an Arweave node needs while running.

Most of these files will be created or recreated by Arweave automatically and so are safe to delete. With 2 important exceptions. You should be very careful before deleting:

* `[data_dir]/wallets`: this directory stores your mining key and unless you have it backed up (recommended) if you delete it you will not be able to sign new blocks or access your mining rewards. See [Mining Key](https://github.com/ArweaveTeam/docs.arweave.org-info/blob/master/mining/setup/mining-key.md) for more information.
* `[data_dir]/storage_modules`: this directory is the root directory under which all of your packed chunk data is stored. This data drives your mining hashrate and preparing it is often the most expensive and time consuming part of miner setup. You can review the topics in the **Overview** section for information on syncing, packing, and mining. And see below for more information on the `storage_modules` directory.

{% hint style="danger" %}
Be **very** careful before deleting `[data_dir]/wallets` or `[data_dir]/storage_modules`
{% endhint %}

### 3.1 `data_dir` Recommendations:

* At least 200GB of of available space, 500GB is recommended - even more if you want to store the full blockchain.
* Stored on an SSD or NVMe. The data in `data_dir` is frequently read and written by all node services and can become a performance bottleneck if it resides on an HDD. See [Hardware Guide](/developers/mining/getting-started/hardware#311-solid-state-drive-ssd-for-data_dir) for more information.

Note: You will need a lot more than 200GB when mining, but typically your mined data (stored in `storage_modules`) is mounted on separate disks from your `data_dir` and symlinked in. So your `data_dir` disk itself only needs to have 200GB+ available capacity. More about this below.

## 4. Storage Modules

The Arweave dataset is logically partitioned into collections of 3.6 TB "mining partitions". You will store some or all of those mining partitions on your miner in "storage modules". Storage modules can be any size (smaller or larger than the default 3.6TB mining partition size), but many miners opt to align their storage modules with the Arweave partitions.

To setup your storage modules, the first step is to create a folder inside `[data_dir]/storage_modules/` for each of the storage modules that you intend to mine with. Storage module folder names should use the following pattern: `storage_module[_storage_module_size]_[storage_module_index]_[packing]` where `packing` is either `replica.2.9`, or `unpacked`. The default storage module size is 3.6TB - in that case specifying `storage_module_size` is optional.

For any given `storage_module_size`, you should allow for an additional 10% metadata overhead (such as merkle proofs). This is why, for the default 3.6 TB `storage_module_size`, we recommend reserving 4 TB of space. The storage modules are indexed sequentially starting from 0, with 0 being the very first 3.6 TB (or `storage_module_size`) worth of data stored on Arweave, and ranging up to or beyond the current Arweave dataset size (`weave_size`). You can choose which mining partitions you store by indicating their `storage_module_index` in the folder name.

For example, to set up a storage module with the very first mining partition in the weave with the default 3.6 TB `storage_module_size` (packed with your mining address), create the folder such as `[data_dir]/storage_modules/storage_module_0_[your_mining_address].replica.2.9`. If you were to store 2 TB storage modules, create the folder such as: `[data_dir]/storage_modules/storage_module_2000000000000_0_[your_mining_address].replica.2.9`.

After creating the relevant folders for your chosen partitions, mount your drives onto them. E.g.,

```
sudo mount /dev/sda [data_dir]/storage_modules/storage_module_0_[your_mining_address].replica.2.9
sudo mount /dev/sda [data_dir]/storage_modules/storage_module_2000000000000_0_[your_mining_address].replica.2.9
```

Make sure you replace `/dev/sda` with the name of your drive (`lsblk`), `[data_dir]` - with the absolute path to your data folder, and `[your_mining_address]` - with your mining address.

If you have a drive already mounted elsewhere, you may create a symbolic link instead:

```
ln -s [path/to/disk/mountpoint] [data_dir]/storage_modules/storage_module_0_[your_mining_address].replica.2.9
```

### 4.1 Storage Module Recommendations

* Having two or more storage modules that store the same mining partition (say, the partition at index 0 more than once) with the same mining address does not increase your mining performance. Also, it is more profitable mine a complete replica (all mining partitions) of the weave packed with a single address than mine off an equal amount of data packed with different mining addresses. Currently, we only support one mining address per node.
* If you want to copy the contents of a storage module elsewhere, restart the node without the corresponding `storage_module` command line parameter, copy the data, and restart the node with the `storage_module` parameter again. You can attach the copied data as a storage module to another node. Just make sure to not copy while the node is interacting with this storage module. Do NOT mine on several nodes with the same mining address simultaneously (see the warning below.)
* Make sure the disks with the storage modules have sufficient available space for both the data itself and metadata (10% of the size of the data). Note that `disk_space` command line parameter does NOT apply to the storage modules.
* If you created storage modules with custom `storage_module_size` as mentioned above, make sure to specify the `storage_module_size` in your command line invocation as follows: `storage_module [storage_module_index],[storage_module_size],[your_mining_address].replica.2.9`\
  The module will sync data with the weave offsets between `storage_module_index * storage_module_size` (in bytes) and `(storage_module_index + 1) * storage_module_size` at folder `[data_dir]/storage_modules/storage_module[_storage_module_size]_[storage_module_index]_[your_mining_address].replica.2.9`.
* The specified mining partition index does not have to be under the current weave size. This makes it possible to configure storage modules in advance. Once the weave data grows sufficiently large to start filling the mining partition at the specified index, the node will begin placing the new data in the already configured storage module.

{% hint style="danger" %}
It is very dangerous to have two or more nodes mine independently using the same mining address. If they find and publish blocks simultaneously, the network will slash your rewards and revoke the mining permission of the mining address! In order to have multiple nodes use the same mining address they must be configured to use coordinated mining. See the [Coordinated Mining Guide](/developers/mining/overview/coordinated-mining) for more information.
{% endhint %}

## 5. Additional Directories and Files

### 5.1 Logs

You can find your node's log files in the `[Install Dir]/logs` directory. You will always have `info` logs, and if you've run your node with the `debug` option you'll also have `debug` logs. The file name format is:

Info logs:

```
arweave-arweave@127.0.0.1-info.log
arweave-arweave@127.0.0.1-info.log.0
arweave-arweave@127.0.0.1-info.log.1
...
arweave-arweave@127.0.0.1-info.log.9
```

Debug logs

```
arweave-arweave@127.0.0.1-debug.log
arweave-arweave@127.0.0.1-debug.log.0
arweave-arweave@127.0.0.1-debug.log.1
...
arweave-arweave@127.0.0.1-debug.log.19
```

Higher numbers are older, and the log files rotate.


# Node Wallet

Creating your node's wallet

The node wallet (aka mining key) provides a miner with their:

* **mining address**: where mining rewards are sent
* **packing address**: used to prepare data for mining (same as mining address)
* **signing key**: private key used to sign blocks when a mining solution is found

For more information on how mining works see: [How Mining Works](/developers/mining/overview/mining)

{% hint style="danger" %}
If you lose your node wallet you will not be able to access your mining rewards or sign new blocks. We strongly recommend you backup your node wallet.
{% endhint %}

The node wallet is stored in `[data_dir]/wallets` and is required for all [node types](/developers/mining/overview/node-types). If one is not present when the node first launches, it will be automatically created. If you're not running a miner it is probably fine to rely on this automatically created wallet. For miners, however, we recommend creating or importing your wallet explicitly.

You can create a wallet with the provided `wallet` tool:

```sh
./bin/arweave wallet create rsa [data_dir]
```

This script will create the wallet and place it in the `[data_dir]/wallets` directory. See [Directory Structure](/developers/mining/getting-started/directory-structure) for more information on setting your `data_dir`.

Reward keys may also be `secp256k1` (ECDSA) since the 2.9 hard fork — substitute `ecdsa` for `rsa` above. See [ECDSA Keys](/developers/development/overview/ecdsa-keys) for details.

If you want to use an existing wallet, place it in `[data_dir]/wallets`. Imported wallets must bin in `.json` format and be named `arweave_keyfile_ADDRESS.json` where `ADDRESS` is the address associated with the wallet.

Note: when using [coordinated mining](/developers/mining/overview/coordinated-mining), the wallet only needs to be present on the exit node.

{% hint style="danger" %}
Make sure to never share you wallet with anyone.
{% endhint %}


# Running Your Node

A guide to configuring and running your node for different purposes

## 0. Overview

Arweave provides a number of configuration options to control, customize, and tune its operation. This guide will describe the main operating phases for different [node types](/developers/mining/overview/node-types) and provide example configurations you can adapt as needed.

## 0.1 Run-script

We recommend using the `./bin/start` wrapper script to run your node. This script wraps the core [Arweave entrypoint](/developers/mining/operations/entrypoint) with naive auto-restart functionality. If your node crashes, `./bin/start` will wait 15 seconds and then restart it with the same configuration.

{% hint style="warning" %}
Avoid killing the arweave process if at all possible. I.e. **don't** do `kill -9 arweave` or `kill -9 beam` or `kill -9 erl`. To stop the arweave process, use `./bin/stop` and then wait for as long as you can for the node to shutdown gracefully. Sometimes if can take a while for the node to shutdown, which we realize is frustrating, but if you kill the node abruptly it can cause `rocksdb` corruption that can be difficult to recover from. In the worst case you may need to resync and repack a partition. If you can't wait, we recommend using `kill -1` rather thank `kill -9`.
{% endhint %}

## 0.2 Keeping the Miner Running

Linux provides many way to run an application in the background or as a daemon so that it will keep running even after you've exited your shell or closed your remote connection. You can likely use any approach your comfortable with. Many miners use the `screen` session manager, e.g.:

```sh
screen -dmSL arweave ./bin/start config_file config.json
```

This will start your node in the background, piping console output to a file named `screenlog.0` and keep your node running after you exit your shell.

In order to bring your node to the foreground:

```sh
screen -r
```

You can read more about `screen` [here](https://www.gnu.org/software/screen/manual/screen.html).

## 0.3 Command-line vs. Configuration File

When running your node you can configure it via command-line arguments as well as via a json file. To load configuration from a json file you specify the `config_file YOURFILE.json` command-line argument. You can use both command-line arguments and a config.json but in general we recommend against mixing as it can be confusing if there are conflicts between the two.

## 0.4 Required Options

All node types and operating phases require at least the following options

* `data_dir`: indicates where the node should store indices and metadata. See [Directory Structure](/developers/mining/getting-started/directory-structure)
* `peer`: specifies the node's [Trusted Peers](/developers/mining/overview/trusted-peers). Your node will use these peers when it initially joins the network so it is important that you trust them to behave honestly.

## 1. Mining

There are 3 main phases when running a miner that apply to Solo Miners, Coordinated Miners, and Pool Miners:

1. Entropy Generation
2. Syncing & Packing
3. Mining

Refer to the [Syncing & Packing](/developers/mining/overview/syncing-and-packing) and [How Mining Works](/developers/mining/overview/mining) guides for more information on the 3 phases. This guide will focus on the configuration options required for each.

As you complete each phase you'll want to shutdown your node, update its configuration, and restart it.

**Note:** It is possible to run all 3 phasees concurrently (e.g. generate entropy while you sync and pack new data and mine any packed data). Prior to Arweave 2.9.5 this was discouraged as it reduced performance and often caused out-of-memory issues. However since the release of 2.9.5 many of the memory issues have been addressed so you **may** have more luck running the different phases concurrently. We still recommend generating entropy first as it should allow everything to complete more quickly, but you may be able to mine efficiently while syncing & packing. As with many things, it will likely depend on your specific node, system, and hardware configuration.

### 1.1 Entropy Generation

While it is possible to generate entropy while you sync and pack, the current guidance is that separating the two phases provides better performance. During entropy generation you node will generate and write to disk the entropy needed to pack all of your configured storage modules.

As noted in the [Syncing & Packing](/developers/mining/overview/syncing-and-packing) guide some partitions are smaller than others due to unseeded data. This is **not** the case for entropy: all partitions will generate 3.6TB of entropy. If you've budgeted enough storage capacity to [allow 4TB per partition](/developers/mining/getting-started/directory-structure#4-storage-modules) this will generally be fine 0 3.6TB of entropy plus \~10% extra for needed metadata. However some of the earlier partitions (notably partitions 0 and 1) sometimes need more than 400GB of space for their metadata. For those partitions you may find yourself exceeded 4TB during the entropy generation phase. If you have opted for a configuration with larger disks (e.g. 8, 12, 16TB) each containing multiple partitions, you should be fine as most partitions will use less than 4TB providing a buffer.

When the node has finished generating entropy for a partition it will print a message like this

to the console: `The storage module storage_module_26_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 is prepared for 2.9 replication.`

and in your logs: `event: storage_module_entropy_preparation_complete, store_id: 6_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`

Entropy generation is complete when you see that message printed for **each** configured storage module.

[**Example Entropy Generation Configuration**](/developers/mining/sample-node-configurations/entropy-generation)

### 1.2 Syncing & Packing

Syncing & Packing is often the most expensive and time consuming part of miner setup. We provide a sample configuration file below, but you may want to tweak the options to optimize your performance. For guidance on this refer to [Syncing & Packing](/developers/mining/overview/syncing-and-packing).

[**Example Syncing & Packing Configuration**](/developers/mining/sample-node-configurations/sync-pack)

### 1.3 Mining

Once you have your data packed, you can start mining it. See [How Mining Works](/developers/mining/overview/mining) for more information about the mining process.

There are 3 different mining node configurations (described in [Node Types](/developers/mining/overview/node-types)):

* Solo Mining
* Coordinated Mining
* Pool Mining

[Coordinated Mining](/developers/mining/overview/coordinated-mining) and [Pool Mining](/developers/mining/overview/pool-mining) involve some additional setup. For more information please refer to their dedicated guides.

[**Example Solo Mining Configuration**](/developers/mining/sample-node-configurations/solo-mining)

## 2. Repacking

When first starting out most miners will need to sync their data from peers and pack it. However if you already have some data locally that you want to repack to a new packing address or format (e.g. `unpacked` to `replica.2.9`), there are 2 other options (described below). For more information on the packing and repacking process see [Syncing & Packing](/developers/mining/overview/syncing-and-packing)

### 2.1 Cross-module Repack

You can use cross-module repacking if you have a set of data packed to one format or address, and want to **copy** the data while repacking it to a new format or address. In this case your node needs access to both the source and destination storage modules.

**Note:** it's a good idea to first generate entropy for the data you'll be repacking too. See [Entropy Generation](#11-entropy-generation) above.

[**Example Cross-module Repack Configuration**](/developers/mining/sample-node-configurations/cross-module-repack)

### 2.2 Repack-in-Place

You can use repack-in-place if you have a set of data packed to one format or address, and want to repack it to a new address or format without using any more storage space. In this case the node will replace the source data with the repacked data.

[**Example Repack-in-Place Configuration**](/developers/mining/sample-node-configurations/repack-in-place)

## 3. VDF Server

VDF Servers are typically run on MacOS hardware and are configured to run without mining and without any storage modules. See [VDF](/developers/mining/overview/vdf) for more information.

[**Example VDF Server Configuration**](/developers/mining/sample-node-configurations/vdf)


# Overview


# Node Types

Understanding the different Arweave node types

This pages describes the different roles your node can play. Each role can be launched from the same `arweave` application found on the main [github repository](https://github.com/ArweaveTeam/arweave).

See the [Hardware Guide](/developers/mining/getting-started/hardware) for guidance on the hardware requirements for each node type, and [Getting Started](/developers) for next steps in getting your miner setup.

## 1. Solo Miner

A solo miner is a single node that stores and mines all the data associated with a single mining address. It is in contrast to a [Coordinated Miner](#2-coordinated-miner) which involves multiple nodes coordinating to mine all the data associated with a single mining address.

### When it’s a good fit

* You are able to direct attach all your minable storage to a single server
* Your server has enough hardware resources to mine all the data itself
* You want full control over keys and payouts (no pool/coordinator in the middle) (see [Pool Miner](#23-pool-miner) for more information)
* You can run or rent access to a VDF server (see [VDF Server](#24-vdf-server) for more information)

## 2. Coordinated Miner

A coordinated miner is collection of 2 or more nodes that coordinate to mine all the data associated with a single mining address. Every coordinated mining cluster has one exit node and then 1 or more mining nodes. All mining nodes share the same mining address and are configured to mine non-overlapping storage modules.

### When it’s a good fit

* You don't have a single server that is capable of mining all of your data itself
* You do have a collection of servers that altogether are capable of mining all of your data
* You are comfortable with the increased complexity of configuring, operating, and optimizing a cluster of servers (in contrast to running a single Solo Miner)
* You want full control over keys and payouts (no pool/coordinator in the middle) (see [Pool Miner](#23-pool-miner) for more information)
* You can run or rent access to a VDF server (see [VDF Server](#24-vdf-server) for more information)

For more information see [Coordinated Mining](/developers/mining/overview/coordinated-mining).

## 3. Pool Miner

A pool miner can either be a solo miner or a coordinated miner. They mine some or all of the data associated with a mining address, and delegate reward accounting, VDF, coordination, and support to a third‑party pool.

### When it’s a good fit

* You are still comfortable running your own Solo Miner or Coordinated miner
* You want the extra setup and operations support provided by the pool operator
* You don't have enough storage to mine the full weave and want the pool to help you coordinated with another miner to cover the full weave
* You can't run and don't want to rent access to a VDF server and would like to use the one provided by the pool
* You’re happy to share rewards according to pool rules in exchange for smoother payouts
* You’re happy to delegate control of the mining keys to pool operator

For more information see [=Pool Mining](/developers/mining/overview/pool-mining).

## 4. VDF Server

VDF servers are specialized nodes that focus on computing and distributing VDF steps. They typically do not store data or mine.

### When it's a good fit

* You are also planning to run a miner and want to maximize your mining hashrate without joining a pool or renting access to a 3rd party VDF server
* You have access to a Mac running on Apple Silicon (e.g. an M4) - to date the fastest VDF calculations observed are on Apple processors

For more information see [VDF](/developers/mining/overview/vdf).

### 5. Validator

Validators validate and share blocks and transactions with other nodes in the network. They may also, but do not have to, share unpacked data. They typically do not not mine or may mine only incidentally. All Arweave nodes are also validators so if you are running a miner or VDF server you do not also need to run a dedicated validator.

### When it's a good fit

* You want to interact with the Arweave network without relying on a 3rd-party gateway (e.g. to support your own applications)
* You're not already running a miner or VDF servers


# Coordinated Mining

A guide to operating a coordinated mining cluster

**Adapted from a guide originally written by @Thaseus**

## 1. What is coordinated mining?

Coordinated mining involves multiple nodes using the same mining address to discover solutions and mine blocks. In the earlier days of Arweave, mining operations were typically conducted by a single node per address. However, the weave has grown enough some server configurations are unable to handle the full dataset alone. In these cases multiple nodes can collaborate to mine the full weave. While powerful high-core Epyc processor-based systems may still operate effectively as a single node, most consumer-level hardware requires a coordinated mining (CM) cluster.

A CM cluster consists of multiple mining nodes and a single exit node. The exit node serves as the gateway through which mined blocks are published to the network and potentially acts as a VDF forwarder. Each CM cluster can include as many regular nodes as needed, but it has only one exit node. This exit node may also participate in mining storage modules.

It is important that *only* the exit node publish the blocks from your CM cluster. If the same mining address publishes 2 blocks at the same height, the protocol will ban that mining address and slash its rewards (this is known as "double signing"). Having a single exit node through which all of your cluster's solutions are published avoids this problem. Additionally, as an extra safeguard, we recommend that the exit node be the only node with your wallet file in the `<data_dir>/wallets` directory. As it is the only node that is able to sign and publish blocks, this can avoid having one of the CM miners accidentally publish a block due to a configuration error.

## 2. CM Basics

All nodes in the cluster share the same mining address. Each Miner generates H1 hashes for the partitions they store. Occasionally they will need an H2 for a packed partition they don't store. In this case, they can find another miner in the coordinated mining cluster who does store the required partition packed with the required address, send them the H1 and ask them to calculate the H2. When a valid solution is found (either from the H1 or H2) the solution is sent to the Exit Node. Since the Exit Node is the sole node in the coordinated mining cluster which publishes blocks, there's no risk of "double signing" causing you address to be banned and your pending rewards slashed. Every node in the coordinated mining cluster will still peer with any other nodes on the network as normal.

## 3. VDF Forwarding

When using Coordinated Mining (CM), it is beneficial to keep your VDF steps relatively synchronized. To achieve this, there is an optional VDF forwarder function that can be used. On the CM exit node, you should set the flag `vdf_server_trusted_peer IP:Port` to designate the [VDF Server](/developers/mining/overview/vdf) to use for your cluster.

In addition to this flag, you must specify each peer to which you wish to send VDF steps by using the `vdf_client_peer IP:Port` flag for each client server. While employing this feature is not strictly required, it significantly enhances the stability of your systems.

On the client servers, you would use the `vdf_server_trusted_peer <Exit Node IP>:<port>` flag to specify the IP:Port of your VDF forwarder.

## 4. Coordinated Mining Start Flags

* `coordinated_mining`: Enables coordinated mining mode
* `local_peer IP:Port`: Registers a node as a local peer which disables rate limiting
  * While this is not specifically a CM command, it corrects an edge case which may cause rate limiting between CM cluster members. This is useful for all nodes you operate
* `cm_peer IP:Port`: Registers a node as a CM peer and allow sharing H1 and H2 hashes between them
  * Each peer will have to include this flag for each other node in the cluster
* `cm_api_secret your_secret_12_char_string`: This is the password for your CM cluster, each node must have the same password
* `cm_exit_peer IP:Port`: This flag must be included on all nodes except for the exit peer
  * When this flag is included, it directs all solutions to be sent to this exit node
  * When this flag is not included, that single node will be responsible for publishing blocks
* `cm_out_batch_timeout 10`: This is the only optional cm flag
  * Frequency in ms that a node will send out H1 hashes to the CM peers
  * Default is 20ms
  * A higher value will result in less network usage, but higher hash latency
  * A lower value will result in more network usage, but lower hash latency
* `mining_addr <your_mining_address>`: All nodes in the CM cluster must have the same mining address
* `vdf_server_trusted_peer IP:Port`: This flag can be used in two ways
  * On the exit node to connect to an external VDF server, such as the Arweave team VDF servers
  * On the CM client nodes to connect to either the VDF forwarder, or a dedicated internal VDF server
  * This flag is used to connect to external VDF servers to receive their VDF steps
* `vdf_client_peer IP:Port`:
  * This flag must only be included on the exit node or a designated internal VDF server
  * This flag tells the exit node / VDF forwarder to send the VDF steps that it received (or generated) to the clients listed by IP:Port

## 5. Example Configuration

See [Example Coordinated Mining Configuration](/developers/mining/sample-node-configurations/coordinated-mining)

## 6. Coordinated Mining (CM) Cluster Stats:

See [Mining Performance Report](/developers/mining/operations/mining-report)

## 7. Troubleshooting

Coordinated mining operates effectively when all suggested flags above are used. This ensures your nodes remain synchronized and operational. Typically, the only reported errors are connectivity issues and discrepancies in the "Hash (Ideal)" values on the mining screens.

The output screen below displays your CM statistics. The values will scale with the number of partitions each node is mining. If you observe zeros in any column (other than H2 in/out), it indicates an improper connection between your nodes. This could be due to a network issue or a misconfiguration in the start command.

Ensure that you use a single source for your network connection, either WiFi or wired. Using both may result in receiving data on a different IP than configured, leading to communication errors. Ensure that all ports are forwarded as required to ensure external arweave nodes can connect to your cluster nodes.

For more information see:

* [Arweave 2.7.2 Coordinated Mining Details](https://github.com/ArweaveTeam/arweave/releases/tag/N.2.7.2)
* [Arweave 2.7.3 Coordinated Mining Details](https://github.com/ArweaveTeam/arweave/releases/tag/N.2.7.3)


# Pool Mining

A guide mining as part of a pool

Currently there is one main mining pool: [VirdPool](https://ar.virdpool.com/) (you can contact them via the `#🐳pool-vird` channel on the [Arweave Miners discord](http://discord.gg/hTCmhGWPEp))


# Trusted Peers

Understanding Trusted Peers

When your node first connects to the network it does so through a set of "trusted peers". These are nodes that you specify using the `peer` flag. Your node queries its trusted peers for the recent blockchain data. It's important to only specify nodes you trust, but since your node will validate the data it receives from these peers the potential for abuse is minimal.

If you operate multiple nodes yourself you can (and should) have your own nodes specify each other as trusted peers. Although it's important to also include some external nodes as well in case all of your nodes go offline at once.

The Digital History Association operates a set of nodes that can be used as trusted peers:

| **type** | **region**             | **hostname**                              | **notes**                                    |
| -------- | ---------------------- | ----------------------------------------- | -------------------------------------------- |
| dns pool | worldwide              | `peers.arweave.xyz`                       | global dns pool containing all trusted peers |
| dns pool | asia                   | `asia.peers.arweave.xyz`                  | -                                            |
| dns pool | europe                 | `europe.peers.arweave.xyz`                | -                                            |
| dns pool | india                  | `india.peers.arweave.xyz`                 | -                                            |
| dns pool | north-america          | `north-america.peers.arweave.xyz`         | -                                            |
| dns pool | oceania                | `oceania.peers.arweave.xyz`               | -                                            |
| hostname | europe (netherlands)   | `ams-1.nl.europe.arweave.xyz`             | -                                            |
| hostname | north-america (usa)    | `bhs-1.ca.north-america.arweave.xyz`      | -                                            |
| hostname | north-america (usa)    | `dal-1.east.us.north-america.arweave.xyz` | -                                            |
| hostname | north-america (usa)    | `den-1.west.us.north-america.arweave.xyz` | -                                            |
| hostname | europe (uk)            | `eri-1.uk.europe.arweave.xyz`             | aka `ams-1.eu-central-1.arweave.xyz`         |
| hostname | europe (germany)       | `fsn-1.de.europe.arweave.xyz`             | aka `fsn-1.de.europe.arweave.xyz`            |
| hostname | north-america (usa)    | `hil-1.west.us.north-america.arweave.xyz` | aka `sfo-1.na-west-1.arweave.xyz`            |
| hostname | europe (germany)       | `lim-1.de.europe.arweave.xyz`             | -                                            |
| hostname | europe (spain)         | `mad-1.es.europe.arweave.xyz`             | -                                            |
| hostname | india (india)          | `mum-1.in.india.arweave.xyz`              | aka `blr-1.ap-central-1.arweave.xyz`         |
| hostname | india (india)          | `mum-2.in.india.arweave.xyz`              | -                                            |
| hostname | north-america (usa)    | `pho-1.east.us.north-america.arweave.xyz` | -                                            |
| hostname | asia (singapore)       | `sin-1.sg.asia.arweave.xyz`               | -                                            |
| hostname | asia (singapore)       | `sin-2.sg.asia.arweave.xyz`               | aka `sgp-1.ap-central-2.arweave.xyz`         |
| hostname | asia (singapore)       | `sin-3.sg.asia.arweave.xyz`               | -                                            |
| hostname | oceania (australia)    | `syd-1.au.oceania.arweave.xyz`            | -                                            |
| hostname | oceania (australia)    | `syd-2.au.oceania.arweave.xyz`            | -                                            |
| hostname | north-america (canada) | `van-1.ca.north-america.arweave.xyz`      | -                                            |
| hostname | north-america (usa)    | `vin-1.east.us.north-america.arweave.xyz` | -                                            |
| hostname | europe (switzerland)   | `zur-1.ch.europe.arweave.xyz`             | -                                            |

Status of dns pools and individual peers can be checked at [status.arweave.xyz](https://status.arweave.xyz/).


# Syncing and Packing

A guide to syncing and packing

One of the first things you'll do when mining is sync and pack some or all of the weave data.

## 1. Syncing

"Syncing" refers to the process of downloading data from network peers. When you launch your miner you'll configure a set of storage modules that cover some or all of the weave. Your node will continuously check for any gaps in your configured data and then search out peers from which to download the missing data.

## 2. Packing

Storage modules can be either "unpacked" (e.g. `storage_module 16,unpacked`) or "packed" (e.g. `storage_module 16,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`). Before you can mine data it must be packed to your mining address. There are two symmetric operations that fall under the "packing" umbrella:

1. `pack` - Symmetrically encrypt a chunk of data with your mining address.
2. `unpack` - Decrypt a packed chunk of data.

Both operations consume roughly the same amount of computational power. See the [Benchmarking Guide](/developers/mining/operations/benchmarking) for more details.

As of Arweave 2.9 there is one main packing format: `replica.2.9`. You can read the full [Arweave 2.9 Whitepaper here](https://github.com/ArweaveTeam/arweave/blob/master/papers/arweave2_9_2024.pdf). Put simply: the intent is for packing to be an expensive operation - expensive enough that the most profitable strategy is to pack data once and store it to disk rather than store the data unpacked and pack it "on demand". The Arweave packing format relies heavily on [RandomX](https://xmrig.com/benchmark) to implement this cost/benefit tradeoff.

**Note:** You will almost always have to **unpack** data when syncing it. Whichever peer you sync the data from will likely return it to you packed to its own address. Before you can do anything with it you will first need to unpack. You may then have to pack it to your own address. i.e. each chunk of data synced will usually need 1-2 packing operations.

### 2.1 Packing Processes

There are 3 ways to get packed data:

1. **Sync and Pack**: Used when you don't have any data locally. Your node will query chunk data from peers, unpack it from the peer's address, pack it to your address, and then store it in your storage module.
2. **Cross Module Repack**: Used when you have data locally but want to repack it to a different format or address. Your node will read data from one storage module, repack it, and then write it to a different storage module.
3. **Repack In Place**: Used when you have data locally and want to repack it to a different format or address and then store it back in the same storage module. Your node will iterate through your storage module, read chunks, repack them, and then write them back to the same storage module.

See [Running Your Node](/developers/mining/getting-started/configuration) for a sample configurations of each packing type.

### 2.2 Replica 2.9 Entropy Generation

Starting with the `replica.2.9` format introduced in Arweave 2.9, the packing process is broken into 2 steps:

1. **Entropy Generation**: Generate a random entropy value for each chunk.
2. **Packing**: Encrypt the chunk data using the entropy value.

Currently the recommended approach when using "Sync and Pack" or "Cross Module Repack" is to first generate entropy for an entire partition, and then pack data for it. This is not possible with "Repack In Place" so no special handling is needed for it. See [Running Your Node](/developers/mining/getting-started/configuration) for for guidance on how to do this.

## 3. Storage Module Data Format

Each storage module has 2 directories `chunk_storage` and `rocksdb`.

### 3.1 `chunk_storage`

This directory stores the actual weave data in a series of roughly 2GB sparse files. Each file contains 8000 chunks stored as `<< Offset, ChunkData >>`.

* `Offset` is a 3-byte integer used to handle partial chunks (i.e. chunks less than 256KiB). This is only relevant for unpacked data as packed chunks are always 256 KiB.
* `ChunkData` is the 256 KiB (262,144 bytes) chunk data.

The maximum file size is 2,097,176,000 bytes. Each file is named with the starting offset of the chunks it contains (e.g. `chunk_storage` file `75702992896000` stores the 8000 chunks starting at weave offset 75,702,992,896,000).

A full partition will contain 3.6 TB (3,600,000,000,000 bytes) of chunk data. Depending on how you've configured your storage modules, your `chunk_storage` directory may only store a subset of a partition.

The data stored may be packed or unpacked - and the two formats will often take up **different** amount of space. For this reason we suggest you rely on the `v2_index_data_size_by_packing` metric in order to track the amount of data that you have synced. Diskspace measuring tools (e.g. `du`, `ls -l`) will not be able to give an accurate measurement of the amount of weave data synced.

For reasons [explained below](#42-partitions-are-rarely-full) you will rarely be able to sync a full 3.6TB partition. However, your node will continue to search the network for missing chunks so while unlikely it is possible that a previously "dormant" `chunk_storage` directory to see some activity if previously missing chunk data comes online. In general, though, once you have "fully" synced a storage\_module you would expect there to be no further writes to the `chunk_storage` directory. [Below](#4-partition-sizes) we provide an estimate of each partition's "full synced" size.

### 3.2 `rocksdb`

The `rocksdb` directory contains several [RocksDB](https://rocksdb.org/) databases used to store metadata related to chunk data (e.g. record keeping, indexing, proofs, etc..).

The exact size of the `rocksdb` directory will vary over time - unlike `chunk_storage` you should expect the `rocksdb` directory to continue to be written to as long as your node is running. The current rough size of a `rocksdb` directory is \~100 GB (although it will vary from partition to partition and node to node).

## 4. Partition Sizes

### 4.1 Measuring

As mentioned [above](#31-chunk_storage) the amount of space your data takes up on disk may not exactly match the amount of weave data that you have synced. This is due to several factors:

1. `chunk_storage` files are sparse
2. Users can upload partial chunk data (data that is not exactly a multiple of 256 KiB in size)
3. Unpacked data will be stored as it was uploaded with partial chunks stored sparsely at 256 KiB boundaries
4. Packed data will always be packed to multiples of 256 KiB in size
5. The handling of partial chunks has changed a couple times during Arweave's history

For these reasons we recommend you don't rely on diskspace measuring tools (e.g. `du`, `ls -l`) to measure the amount of weave data synced. Instead we suggest you rely on the `v2_index_data_size_by_packing` metric, or the "Performance Mining Report" that is printed to your console.

Sample metric data:

```
v2_index_data_size_by_packing{store_id="storage_module_19_1",packing="spora_2_6_1",partition_number="19",storage_module_size="3600000000000",storage_module_index="19"} 3110370541568
v2_index_data_size_by_packing{store_id="storage_module_1200000000000_115_1",packing="spora_2_6_1",partition_number="38",storage_module_size="1200000000000",storage_module_index="115"} 1025578106880
v2_index_data_size_by_packing{store_id="storage_module_1200000000000_114_1",packing="spora_2_6_1",partition_number="38",storage_module_size="1200000000000",storage_module_index="114"} 1195550703616
v2_index_data_size_by_packing{store_id="storage_module_1200000000000_116_1",packing="spora_2_6_1",partition_number="38",storage_module_size="1200000000000",storage_module_index="116"} 1195550703616
v2_index_data_size_by_packing{store_id="storage_module_8_unpacked",packing="unpacked",partition_number="8",storage_module_size="3600000000000",storage_module_index="8"} 2571878652607
v2_index_data_size_by_packing{store_id="default",packing="unpacked",partition_number="undefined",storage_module_size="undefined",storage_module_index="undefined"} 262144
```

This indicates that the node has:

* **3,110,370,541,568 bytes (3.1TB, 2.8TiB)** of weave synced for partition 19
  * it is stored **packed** on disk and may take up **more** than 3.1TB of disk space
* **3,416,679,514,112 bytes (3.4TB, 3.1TiB)** synced for partition 38
  * 3,416,679,514,112 = **102,557,810,6880 + 119,555,070,3616 + 119,555,070,3616**
  * it is stored **packed** on disk and may take up **more** than 3.1TB of disk space
* **2,571,878,652,607 bytes (2.6TB, 2.3TiB)** of weave synced for partition 8
  * it is stored **unpacked** on disk and may take up **more or less** than 2.5TB of disk space
* The `default` partition is a temporary staging partition and can be ignored

### 4.2 Partitions are rarely full

You will find as you sync data that you're never able to download a full 3.6TB partition - and in fact some partitions seem to stop syncing well short of the 3.6TB. There are 2 steps when adding data to the Arweave network:

1. Submit a transaction with a hash of the data and a fee to reserve space in the weave.
2. Upload the data to the weave (aka seeding).

The data that is missing from a "fully synced" partition is either data that has been filtered out by your [content policies](https://arwiki.wiki/#/en/content-policies) (or the content policies of your peers), or it is data that was never seeded by the uploader.

Typically there are 2 reasons why a user might not seed data after they've paid for it:

1. They're just testing / exploring the protocol
2. They're a miner experimenting with sacrifice mining

## 5. Sacrifice Mining

Sacrifice Mining is a mining strategy where a miner will pay to upload data to the weave but then never actually seed it. Instead they will keep and mine the data themselves, only sharing the chunks required for any blocks they mine. The premise is that all of this "sacrificed data" gives them a hashrate boost that other miners don't have (since the other miners are unable to mine the unseeded data).

Sam has a good [thread](https://twitter.com/samecwilliams/status/1374062282817290247) describing this.

The important bits:

1. Both in practice and based on economic models: sacrifice mining is not profitable. The cost to reserve space on the weave exceeds the incremental revenue a miner can hope to get from the additional hashrate. The payback period for the initial investment is long and gets longer as the weave grows - in practice it is likely that a miner is never able to recoup their initial investment.
2. Putting aside the profitability of sacrifice mining, it is ultimately good for the network as a whole. Sam breaks down why this is in his [thread](https://twitter.com/samecwilliams/status/1374062282817290247).

That said if you look through the partition size data below you'll notice 2 periods where partition sizes are materially smaller than the expected 3.6TB (partitions 0-8, and 30-32). We believe these correspond to periods when miners were experimenting with the strategy, ultimately abandoning it as they realized it was unprofitable.

## 6. Latest Estimated Partition Sizes

[See tables here](/developers/mining/overview/syncing-and-packing/estimated-partition-sizes)

You'll see a table for unpacked as well as packed data. Technically these sizes should match exactly however

1. The data is pulled from public network nodes so we expect some slight discrepancies based on which specific data each node has synced
2. Due to changes in partial chunk handling over time, you may see some partitions with materially different sizes.

For example the estimated data size for partition 0 varies by about 400GB depending on whether it is stored unpacked vs. packed.

{% hint style="warning" %}
These numbers are *mostly* reliable, but there is always a chance that a previously "fully synced" partition grows in size (though never greater than 3.6TB). This can happen any time the original uploader decides to finally seed their previously unseeded data. In practice this gets less and less likely the older a partition is.
{% endhint %}


# Estimated Partition Sizes

Table of the latest estimate on partition sizes

This is the current estimated size of each partition (*last updated December 1, 2025*).

Refer to the [Syncing and Packing guide](/developers/mining/overview/syncing-and-packing) for more information.

## Packed Data

| Partition | Size (TB) | Size (TiB) | Size (bytes)      |
| --------- | --------- | ---------- | ----------------- |
| 0         | 2.08      | 1.89       | 2,081,981,988,864 |
| 1         | 1.91      | 1.73       | 1,905,301,913,600 |
| 2         | 2.22      | 2.02       | 2,218,313,121,792 |
| 3         | 2.93      | 2.66       | 2,927,743,729,664 |
| 4         | 2.82      | 2.57       | 2,822,858,866,688 |
| 5         | 3.02      | 2.75       | 3,024,196,468,736 |
| 6         | 3.09      | 2.81       | 3,092,391,919,616 |
| 7         | 3.46      | 3.15       | 3,460,717,871,104 |
| 8         | 2.55      | 2.32       | 2,550,132,113,408 |
| 9         | 2.85      | 2.59       | 2,851,870,605,312 |
| 10        | 3.31      | 3.01       | 3,310,991,179,776 |
| 11        | 3.50      | 3.18       | 3,496,812,216,320 |
| 12        | 3.55      | 3.23       | 3,549,009,281,024 |
| 13        | 3.59      | 3.26       | 3,588,012,113,920 |
| 14        | 3.57      | 3.25       | 3,568,946,642,944 |
| 15        | 3.58      | 3.26       | 3,582,538,022,912 |
| 16        | 3.56      | 3.24       | 3,560,872,083,456 |
| 17        | 3.57      | 3.25       | 3,568,904,962,048 |
| 18        | 3.57      | 3.25       | 3,570,602,344,448 |
| 19        | 3.13      | 2.84       | 3,127,030,579,200 |
| 20        | 3.52      | 3.20       | 3,515,082,604,544 |
| 21        | 3.58      | 3.26       | 3,579,100,004,352 |
| 22        | 3.55      | 3.23       | 3,548,541,616,128 |
| 23        | 3.50      | 3.18       | 3,500,144,590,848 |
| 24        | 3.53      | 3.21       | 3,534,197,096,448 |
| 25        | 3.52      | 3.20       | 3,522,969,468,928 |
| 26        | 3.55      | 3.23       | 3,553,407,270,912 |
| 27        | 3.55      | 3.23       | 3,548,674,260,992 |
| 28        | 3.57      | 3.24       | 3,566,525,218,816 |
| 29        | 3.54      | 3.22       | 3,535,693,938,688 |
| 30        | 3.46      | 3.15       | 3,462,831,276,032 |
| 31        | 3.20      | 2.91       | 3,203,679,649,792 |
| 32        | 2.34      | 2.13       | 2,341,440,585,728 |
| 33        | 3.06      | 2.79       | 3,063,537,467,392 |
| 34        | 3.48      | 3.16       | 3,475,104,858,112 |
| 35        | 3.47      | 3.16       | 3,473,030,512,640 |
| 36        | 3.55      | 3.23       | 3,551,502,270,464 |
| 37        | 3.55      | 3.22       | 3,545,321,963,520 |
| 38        | 3.41      | 3.10       | 3,412,431,994,880 |
| 39        | 3.59      | 3.27       | 3,591,798,784,000 |
| 40        | 3.58      | 3.26       | 3,579,732,557,824 |
| 41        | 3.57      | 3.24       | 3,567,672,360,960 |
| 42        | 3.57      | 3.25       | 3,569,194,893,312 |
| 43        | 3.59      | 3.27       | 3,594,903,879,680 |
| 44        | 3.56      | 3.24       | 3,560,972,484,608 |
| 45        | 3.58      | 3.26       | 3,581,806,903,296 |
| 46        | 3.41      | 3.10       | 3,408,547,282,944 |
| 47        | 3.45      | 3.14       | 3,452,200,288,256 |
| 48        | 3.58      | 3.25       | 3,575,475,601,408 |
| 49        | 3.54      | 3.22       | 3,542,680,338,432 |
| 50        | 3.56      | 3.24       | 3,557,189,746,688 |
| 51        | 3.47      | 3.16       | 3,473,083,727,872 |
| 52        | 3.56      | 3.23       | 3,556,755,111,936 |
| 53        | 3.51      | 3.20       | 3,514,169,294,848 |
| 54        | 3.58      | 3.26       | 3,584,168,558,592 |
| 55        | 3.46      | 3.15       | 3,463,087,915,008 |
| 56        | 3.12      | 2.84       | 3,122,720,407,552 |
| 57        | 3.56      | 3.24       | 3,562,040,983,552 |
| 58        | 3.58      | 3.25       | 3,575,902,109,696 |
| 59        | 3.58      | 3.26       | 3,584,394,264,576 |
| 60        | 3.60      | 3.27       | 3,596,489,064,448 |
| 61        | 3.60      | 3.27       | 3,598,349,762,560 |
| 62        | 3.55      | 3.23       | 3,554,325,561,344 |
| 63        | 3.53      | 3.21       | 3,531,652,464,640 |
| 64        | 3.60      | 3.27       | 3,599,511,322,624 |
| 65        | 3.43      | 3.12       | 3,425,698,578,432 |
| 66        | 3.54      | 3.22       | 3,537,121,837,056 |
| 67        | 3.60      | 3.27       | 3,599,468,593,152 |
| 68        | 3.58      | 3.26       | 3,583,583,715,328 |
| 69        | 3.60      | 3.27       | 3,599,532,032,000 |
| 70        | 3.60      | 3.27       | 3,598,697,627,648 |
| 71        | 3.59      | 3.27       | 3,591,661,682,688 |
| 72        | 3.60      | 3.27       | 3,597,990,100,992 |
| 73        | 3.60      | 3.27       | 3,597,831,503,872 |
| 74        | 3.60      | 3.27       | 3,599,774,777,344 |
| 75        | 3.60      | 3.27       | 3,599,964,831,744 |
| 76        | 3.60      | 3.27       | 3,596,078,809,088 |
| 77        | 3.59      | 3.26       | 3,588,547,411,968 |
| 78        | 3.59      | 3.26       | 3,585,553,465,344 |
| 79        | 3.60      | 3.27       | 3,595,451,236,352 |
| 80        | 3.58      | 3.26       | 3,581,588,537,344 |
| 81        | 3.59      | 3.27       | 3,591,937,982,464 |
| 82        | 3.59      | 3.27       | 3,593,655,812,096 |
| 83        | 3.60      | 3.27       | 3,597,261,340,672 |
| 84        | 3.60      | 3.27       | 3,599,645,540,352 |
| 85        | 3.59      | 3.27       | 3,592,734,113,792 |
| 86        | 3.59      | 3.27       | 3,593,188,933,632 |
| 87        | 3.31      | 3.01       | 3,313,395,302,400 |
| 88        | 3.43      | 3.12       | 3,432,306,704,384 |
| 89        | 3.39      | 3.08       | 3,391,763,513,344 |
| 90        | 3.60      | 3.27       | 3,598,684,782,592 |
| 91        | 3.60      | 3.27       | 3,599,995,764,736 |
| 92        | 3.58      | 3.25       | 3,576,239,751,168 |
| 93        | 3.59      | 3.27       | 3,593,200,467,968 |
| 94        | 3.59      | 3.27       | 3,592,693,743,616 |
| 95        | 3.59      | 3.26       | 3,585,157,103,616 |
| 96        | 3.59      | 3.27       | 3,594,077,077,504 |
| 97        | 3.49      | 3.17       | 3,485,191,634,944 |
| 98        | 2.77      | 2.52       | 2,767,139,110,912 |
| 99        | 3.60      | 3.27       | 3,596,046,041,088 |
| 100       | 3.59      | 3.27       | 3,593,655,549,952 |
| 101       | 3.59      | 3.27       | 3,591,767,851,008 |
| 102       | 3.60      | 3.27       | 3,596,456,558,592 |

## Unpacked Data

| Partition | Size (TB) | Size (TiB) | Size (bytes)      |
| --------- | --------- | ---------- | ----------------- |
| 0         | 2.47      | 2.25       | 2,468,681,763,254 |
| 1         | 2.14      | 1.95       | 2,141,565,474,213 |
| 2         | 2.35      | 2.14       | 2,354,730,559,665 |
| 3         | 3.04      | 2.77       | 3,040,888,609,156 |
| 4         | 2.87      | 2.61       | 2,866,116,423,748 |
| 5         | 3.06      | 2.78       | 3,061,989,129,004 |
| 6         | 3.16      | 2.87       | 3,160,976,045,927 |
| 7         | 2.69      | 2.45       | 2,688,793,689,779 |
| 8         | 2.57      | 2.34       | 2,571,878,652,607 |
| 9         | 2.85      | 2.59       | 2,851,870,605,312 |
| 10        | 3.31      | 3.01       | 3,310,991,179,776 |
| 11        | 3.50      | 3.18       | 3,496,812,216,320 |
| 12        | 3.55      | 3.23       | 3,549,009,281,024 |
| 13        | 3.59      | 3.26       | 3,588,012,113,920 |
| 14        | 3.57      | 3.25       | 3,568,946,642,944 |
| 15        | 3.58      | 3.26       | 3,582,537,760,768 |
| 16        | 3.56      | 3.24       | 3,560,872,083,456 |
| 17        | 3.57      | 3.25       | 3,568,904,962,048 |
| 18        | 3.57      | 3.25       | 3,570,588,450,816 |
| 19        | 3.13      | 2.84       | 3,127,026,122,752 |
| 20        | 3.52      | 3.20       | 3,515,079,196,672 |
| 21        | 3.58      | 3.26       | 3,579,100,004,352 |
| 22        | 3.55      | 3.23       | 3,548,541,616,128 |
| 23        | 3.50      | 3.18       | 3,500,143,017,984 |
| 24        | 3.53      | 3.21       | 3,534,197,096,448 |
| 25        | 3.52      | 3.20       | 3,522,969,468,928 |
| 26        | 3.55      | 3.23       | 3,553,670,201,344 |
| 27        | 3.55      | 3.23       | 3,548,673,998,848 |
| 28        | 3.57      | 3.24       | 3,566,525,218,816 |
| 29        | 3.54      | 3.22       | 3,535,688,171,520 |
| 30        | 2.10      | 1.91       | 2,104,285,200,384 |
| 31        | 2.22      | 2.02       | 2,221,009,534,976 |
| 32        | 2.34      | 2.13       | 2,341,428,527,104 |
| 33        | 3.06      | 2.79       | 3,063,528,554,496 |
| 34        | 3.48      | 3.16       | 3,475,104,333,824 |
| 35        | 3.47      | 3.16       | 3,473,030,512,640 |
| 36        | 3.55      | 3.23       | 3,551,502,270,464 |
| 37        | 3.55      | 3.22       | 3,545,321,963,520 |
| 38        | 3.41      | 3.10       | 3,412,431,994,880 |
| 39        | 3.59      | 3.27       | 3,591,798,784,000 |
| 40        | 3.58      | 3.26       | 3,579,732,295,680 |
| 41        | 3.57      | 3.24       | 3,567,672,360,960 |
| 42        | 3.57      | 3.25       | 3,569,194,893,312 |
| 43        | 3.59      | 3.27       | 3,594,903,879,680 |
| 44        | 3.56      | 3.24       | 3,560,972,484,608 |
| 45        | 3.46      | 3.14       | 3,457,301,348,352 |
| 46        | 3.07      | 2.79       | 3,072,400,556,032 |
| 47        | 3.40      | 3.09       | 3,397,853,118,464 |
| 48        | 3.58      | 3.25       | 3,575,475,601,408 |
| 49        | 3.54      | 3.22       | 3,542,680,338,432 |
| 50        | 3.56      | 3.24       | 3,557,189,746,688 |
| 51        | 3.47      | 3.16       | 3,473,185,964,032 |
| 52        | 3.56      | 3.23       | 3,556,857,085,952 |
| 53        | 3.51      | 3.20       | 3,514,271,531,008 |
| 54        | 3.58      | 3.26       | 3,584,270,794,752 |
| 55        | 3.46      | 3.15       | 3,463,190,151,168 |
| 56        | 3.12      | 2.84       | 3,122,822,643,712 |
| 57        | 3.56      | 3.24       | 3,562,143,219,712 |
| 58        | 3.58      | 3.25       | 3,576,004,345,856 |
| 59        | 3.59      | 3.26       | 3,589,500,305,408 |
| 60        | 3.60      | 3.27       | 3,596,591,300,608 |
| 61        | 3.60      | 3.27       | 3,598,451,998,720 |
| 62        | 3.55      | 3.23       | 3,554,420,457,472 |
| 63        | 3.53      | 3.21       | 3,531,754,700,800 |
| 64        | 3.60      | 3.27       | 3,599,613,558,784 |
| 65        | 3.43      | 3.12       | 3,425,800,814,592 |
| 66        | 3.54      | 3.22       | 3,537,224,073,216 |
| 67        | 3.60      | 3.27       | 3,599,570,567,168 |
| 68        | 3.58      | 3.26       | 3,584,962,068,480 |
| 69        | 3.60      | 3.27       | 3,599,592,849,408 |
| 70        | 3.60      | 3.27       | 3,599,419,572,224 |
| 71        | 3.59      | 3.27       | 3,591,942,438,912 |
| 72        | 3.60      | 3.27       | 3,598,092,337,152 |
| 73        | 3.60      | 3.27       | 3,597,933,477,888 |
| 74        | 3.60      | 3.27       | 3,599,788,146,688 |
| 75        | 3.60      | 3.27       | 3,599,964,831,744 |
| 76        | 3.60      | 3.27       | 3,596,079,071,232 |
| 77        | 3.59      | 3.26       | 3,588,883,742,720 |
| 78        | 3.59      | 3.26       | 3,585,641,807,872 |
| 79        | 3.60      | 3.27       | 3,595,549,540,352 |
| 80        | 3.58      | 3.26       | 3,581,306,470,400 |
| 81        | 3.60      | 3.27       | 3,598,359,461,888 |
| 82        | 3.59      | 3.27       | 3,592,176,795,648 |
| 83        | 3.59      | 3.27       | 3,591,524,581,376 |
| 84        | 3.60      | 3.27       | 3,599,853,420,544 |
| 85        | 3.59      | 3.26       | 3,588,436,000,768 |
| 86        | 3.59      | 3.27       | 3,593,188,933,632 |
| 87        | 3.29      | 2.99       | 3,292,990,275,584 |
| 88        | 3.41      | 3.10       | 3,411,987,922,944 |
| 89        | 3.38      | 3.07       | 3,378,962,235,392 |
| 90        | 3.60      | 3.27       | 3,598,684,782,592 |
| 91        | 3.60      | 3.27       | 3,599,527,313,408 |
| 92        | 3.58      | 3.25       | 3,576,260,198,400 |
| 93        | 3.59      | 3.27       | 3,593,297,985,536 |
| 94        | 3.59      | 3.27       | 3,592,782,348,288 |
| 95        | 3.59      | 3.26       | 3,585,138,491,392 |
| 96        | 3.59      | 3.27       | 3,593,216,196,608 |
| 97        | 2.75      | 2.51       | 2,754,901,966,848 |
| 98        | 1.93      | 1.75       | 1,925,633,277,952 |
| 99        | 3.60      | 3.27       | 3,596,075,139,072 |
| 100       | 3.59      | 3.27       | 3,593,729,998,848 |
| 101       | 3.59      | 3.27       | 3,591,858,552,832 |
| 102       | 3.60      | 3.27       | 3,596,558,270,464 |


# How Mining Works

Understanding Arweave mining

## 0. Overview

After you have finished [syncing and packing](/developers/mining/overview/syncing-and-packing) your data, the basic mining process is:

1. Join the network
2. Hash your data
3. Find a solution
4. Build a block
5. Share the block
6. Receive mining rewards

## 1. Join the Network

The first thing your node will do on startup is to join the Arweave network:

1. Node reaches out to its [Trusted Peers](/developers/mining/overview/trusted-peers) to request the latest blockchain data
2. Validate that data
3. Join and participate in the network by validating the blockchain

Once your node joins the network it will print a message like the following:

{% code overflow="wrap" %}

```
Joined the Arweave network successfully at the block 9oLuJnrq7SwAlodPE1WoZyhCgdqPTL-6AJBKfA7LQeIuDwaE5Z2QMCFmS8Kn-XnO, height 1804183.
```

{% endcode %}

### 1.1 Participating in the Network

All [node types](/developers/mining/overview/node-types) participate in the network whether they are mining or not. Participating nodes:

1. Receive new blocks, transactions, and chunks from peers and users
2. Validate and either accept or reject those blocks, transactions, and chunks
3. Share valid blocks, transactions, and chunks with peers
4. If there is a fork in the chain, select and advertise the "heaviest" fork

The most important step for miners is #1 as you always want to be mining ontop of the latest block. If your node falls behind its peers and is unaware of the latest valid blocks, your miner runs the risk of mining valid solutions that don't make it into the main blockchain. These solutions are called "orphans" and they will not provide you with any mining rewards.

### 1.2 Receiving Blocks, Transactions, and Chunks

Your node can receive new blocks and transactions from peers in two ways:

1. Gossip - where a peer pushes a block or transaction to your node
2. Polling - where your node requests the latest blocks, transactions, or chunks from peers

To ensure your node learns about new blocks as soon as possible it is important that both methods are working correctly.

Note: chunk data is generally only shared via polling.

### 1.2.1 Block and Transaction Gossip

Gossip is a form of communication used in peer-to-peer networks (like Arweave and many blockchains). It works by having each node randomly share information (e.g. blocks and transactions) with a small group of its peers, who then pass it on to their peers.

In order for your node to participate it needs to be accessible to the internet so that peers can connect with your node and share their blocks.

To check if your node is publicly accessible, browse to `http://[Your Internet IP]:1984`. You can [obtain your public IP here](https://ifconfig.me/), or by running `curl ifconfig.me/ip`. If you specified a different port when starting the miner, replace "1984" anywhere in these instructions with your port. If you can not access the node, you need to set up TCP port forwarding for incoming HTTP requests to your Internet IP address on port 1984 to the selected port on your mining machine. For more details on how to set up port forwarding, consult your ISP or cloud provider.

If the node is not accessible on the Internet, the miner functions but is significantly less efficient.

### 1.2.2 Block and Transaction Polling

As a fallback and to increase the chance that your node receives new blocks and transactions as soon as possible, all nodes will also poll (i.e. make an outbound HTTP request) a random subset of their peers to ask for new blocks.

### 1.2.3 Falling Behind

If you see the following warnings in your console it indicates that your node may have fallen behind and may not have received or validated the latest blocks:

{% code overflow="wrap" %}

```
WARNING: Peer 138.197.232.192 is 5 or more blocks ahead of us. Please, double-check if you are in sync with the network and make sure your CPU computes VDF fast enough or you are connected to a VDF server.
```

{% endcode %}

If you see them shortly after joining the network, see if they disappear in a few minutes - everything might be fine then. Otherwise, it is possible that either your processor can't keep up with node validation or there are network connection issues. Confirm that your network is healthy, that you have a properly configured VDF Server, and that you have spare CPU capacity. Sometimes the issue is short lived and a node restart can help.

## 2. Hash Your Data

Once your miner joins the network it will begin hashing any of its packed data looking for a solution. The Arweave network data (referred to as "the weave") is divided into 3.6TB partitions.

Note: "storage modules" and "partitions" are often used interchangeably but they are slightly different. Please see [Directory Structure](/developers/mining/getting-started/directory-structure) for the distinction.

The mining loop:

1. Compute a VDF step or receive one from a VDF server
2. Use that VDF step to compute an `H0` value for full or partial partition being mined
3. For each partition, use the `H0` to compute a random byte offset within that partition (i.e. an offset from 0 to 3.6TB)
4. Read the 2.5 MiB of data at each partition's offset to compute a series of `H1` hashes (32 hashes per 256KiB chunk of data read)
5. For each partition, use the `H0` to compute a random byte offset across the entire weave (e.g. an offset from 0 to 373TB as off November 28, 2025)
6. Read the 2.5 MiB of data at each weave offset and use it as well as the corresponding `H1` hashes to compute a series of `H2` hashes (32 hashes per 256KiB chunk of data read)

Each `H1` and `H2` hash is compared against the network difficulty to determine whether it is a "solution". The `H1` and `H2` hashes are weighted differently and most metrics and logs will report an "effective hashrate" that accounts for this weighting rather than simply reporting the number of SHA256 hashes computed. Please see the [Hashrate Guide](/developers/mining/overview/hashrate) for more information.

Of note, the `H1` and `H2` hashes computed are all SHA256 and therefore are not compute intensive. The `H0` hashes use RandomX and are more compute intensive, but since there is only one `H0` per partition, generally the load is minimal.

## 3. Find a Solution

A solution is any valid mining hash that exceeds the network difficulty. The network difficulty adjusts every 10 blocks in order to target an average block time of 2 minutes. You can find the current network difficulty by querying the current block from any node - e.g. `http://NODEIP:PORT/block/current` or <https://arweave.net/block/current> - and grabbing the `diff` field from the returned JSON (it's a *very* large number). The logic for comparing a hash against the network difficulty is nuanced - please see the [Hashrate Guide](/developers/mining/overview/hashrate) for more information.

Once your miner finds a valid solution it will build and publish a block.

## 4. Build a Block

There's a lot of information that goes into an Arweave block - you can see the full set of fields by inspecting the JSON returned by any node's `/block/current` endpoint. Many of those fields are determined by the protocol and not configurable by the miner. However a miner does have some flexibility in setting these values:

* The block height (via selecting which previous block to build ontop of)
* The block transactions

### 4.1 Determining Block Height

Every valid solution is tied to a specific VDF step, and every valid block is tied to a specific "previous block". However the same solution could be used to build valid blocks at different heights or with different "previous blocks" so long as the previous block's VDF step is **lower** than the solution step. This is discussed more below under [Orphans and Rebasing](#61-orphans-and-rebasing).

{% hint style="danger" %}
Your should never publish two blocks with the same solution at the same height as this violates the Arweave protocol and will result in the network slashing your rewards and revoking the mining permission of the mining address.

The only way this can happen when mining with an unmodified node is if you have multiple nodes mining against the same mining address at the same time. In order to have multiple nodes use the same mining address they must be configured to use coordinated mining. See the [Coordinated Mining Guide](/developers/mining/overview/coordinated-mining) for more information.
{% endhint %}

### 4.2 Determining Transactions

The biggest decision a miner has when building a block is which transactions to include. In general miners will simply include as many unconfirmed transactions as they are aware of at that moment. A portion of the block rewards come from the transaction fees paid by users when they post transactions - the more fees that are included in a block, the higher the block reward collected by the miner.

#### 4.2.1 0-transaction Blocks

Occasionally a block will be published that contains no transactions. Generally this indicates a network connectivity issue with the miner that mined the block. If you see your miner publishing 0-transaction blocks you should:

1. Confirm that your miner is reachable from the internet (e.g. `http://NODEIP:PORT/info` is reachable from a remote server)
2. Confirm that your miner can reach remote peers (e.g. you can issue a `GET http://PEERIP:PORT/info` request from your node's server)
3. Confirm that you have not explicity disabled transaction polling or blocked transaction gossip in your node or network configuration.

## 5. Share the Block

Once your miner has mined a solution and built a block, it will publish that block by sharing it with its peers. This begins the "race" portion of mining. All miners are mining solutions concurrently and there will often be multiple blocks mined ontop of given block (i.e. multiple blocks at the same height and with the same previous block). In those cases only one of those blocks (at most) will provide mining rewards. In order to increase the chance that your block is the "winner" you want it to be shared and accepted by as many peers as possible, as quickly as possible. The 3 main factors in this race:

1. The time that block was first published. The earlier you publish a block the higher the chance it will "win"
2. How quickly your miner can share the block with its peers. The more peers you're connected with and the faster your network connection to them, the higher the chance your block will "win"
3. Your node's reputation. Nodes will prioritize their relationship with peers based on their reputation. They will share new block and transactions with high reputation peers first, and they will validate and gossip blocks from high reputation peers first. Both of these factors can be the difference between your block "winning" or being orphaned. For more on reputation see [Node Reputation](/developers/mining/overview/node-reputation)

### 5.1 Logs

When you mine a block, you'll get the following logs:

* console: `Produced candidate block HASH ...`
* logs: `{event, mined_block}, {block, HASH} ...`

At this point the race discussed above begins. If your block is accepted by the network and included in the main chain you should see the following message about 20 minutes later:

* console: `Your block HASH was accepted by the network!`
* logs: `{event, block_got_10_confirmations}, {block, HASH}`

However, those messages aren't completely reliable. You may also want to search your logs for these messages:

Indicating your block HASH has been orphaned:

* console: `Your block HASH was orphaned.`
* logs: `{event, mined_block_orphaned}, {block, HASH}` Indicating your previously orphaned block has been rebased:
* console: `Rebasing block HASH ...`
* logs: `{event, rebasing_block}, {h, HASH}`

### 5.2 Orphans and Rebasing

When a block ends up on a chain fork that is not the heaviest, it is considered orphaned. Orphaned blocks do not receive mining rewards.

When your node detects that one of the blocks it has mined has become orphaned it will try to rebase it. Rebasing a block involves reusing a solution to build a new block on top of the current chain tip. A solution can only be rebased if it uses a VDF step that is higher than the VDF step included in the tip block. A rebased block is the same as any mined block and, if it is accepted and remains part of the heaviest fork, it will generate mining rewards for the mining address that mined it.

## 6. Receive Mining Rewards

You do not immediately receive the block reward after mining a block. There is a delay in the release of block rewards for miners by approximately thirty days or 30 \* 24 \* 30 blocks. Your node does **not** need to stay online in order to receive your reserved mining rewards. This mechanism is designed to discourage signing the same block several times and several competitive forks in general - the network detects these cases and may slash the reserved rewards and revoke the mining permission from the corresponding mining address. Also, the mechanism incentivizes miners to be aligned with the network for at least the medium-term.

To see the total number of Winston (divide by 1000\_000\_000\_000 to get the AR value) reserved for you address, browse to <https://arweave.net/wallet/\\[your-mining-address]/reserved\\_rewards\\_total>.


# Hashrate

Understanding your miner's hashrate

**Adapted from a guide originally written by @Thaseus**

A guide to understanding the fundamentals of AR hashrate and its many variables

## 1. Overview

This guide provides general information regarding hashrate estimations and discusses the various factors that influence these hashrates. As AR mining evolves, fundamentals may change; every effort will be made to keep this document current.

It is important to note that this document does not guarantee specific hashrates. Each system and its underlying hardware are unique, resulting in different potential hashrates for every miner. Therefore, variances in the values and details provided throughout this document should be expected.

## 2. Hashrate Variables Under Your Control

Several variables contribute to your final hashrate. The key variables you can control are hard drive read speed and the number of fully packed storage modules. The ultimate goal is to achieve the best possible read speed and ensure all storage modules are fully packed, thereby maximizing your hashrate. For the purposes of this section, assume the values discussed are intended to provide optimal hashrate. Lower values may still be acceptable depending on your specific requirements.

### 2.1 Number of fully packed storage modules

The number one priority is to pack the entire weave into storage modules. This can be accomplished either individually (solo or through [Vird’s Pool](https://ar.virdpool.com/) | [Discord](https://discord.gg/hTCmhGWPEp)) or by sharing a weave with others (e.g. on [Vird’s Pool](https://ar.virdpool.com/) | [Discord](https://discord.gg/hTCmhGWPEp)).

Consider the following example to understand the importance of having all partitions packed. If the weave has 100 partitions and you have 50% of them fully packed (50 partitions), you will only generate up to 25% of the maximum possible hashrate. At 75% of the weave (75 partitions), your hashrate will be closer to 50% of the maximum. We'll break down the math below, but it's important to highlight the underlying principle: without most or all partitions packed, your hashrate will be significantly lower than those who have them fully packed.

### 2.2 Read speed of your hard drive

The next critical metric is the read speed of your hard drive. If you have the weave fully packed, you will need to sustain on average 5 MiB/s read speed per partition. This data is read from 2 different 2.5 MiB ranges and will typically involve a disk seek. If you are mining on 16 TB disks each storing 4 partitions, you will need to sustain a 20 MiB/s read rate across 8 seeks. Dropping below this read rate is fine, it will just mead a lower hashrate - but there are no other penalties.

Note: In earlier versions of Arweave the required read rate was 200 MiB/s per partition (40x higher than it is now). At that time the disk read rate was far more critical and difficult to achieve.

### 2.3 Note on Terminology and Units

KB and KiB, MB and MiB, TB and TiB are all, confusingly, different metrics. The world (including the Arweave documentation) does not use the consistently.

* 1 KB = 1,000 bytes
* 1 KiB = 1,024 bytes
* 1 MB = 1,000,000 bytes
* 1 MiB = 1,048,576 bytes
* 1 TB = 1,000,000,000 bytes
* 1 TiB = 1,073,741,824 bytes

You will note that many drives report their capacity and read rate in MB and TB whereas the target read rates listed above are in MiB/s. You can do the math as needed, ignore the difference, or use this rough guide:

**1 MB/s ≈ 0.95 MiB/s**

## 3. Hashrate Formula

There is a formula you can use to estimate your hashrate. It is based on several factors:

1. Amount of data packed
2. VDF speed
3. Disk Read Rate

The number that comes out is then normalized.

### 3.1 The Normalization Factor

As described in the [Understanding Mining](/developers/mining/overview/mining#2-hash-your-data) guide a miner will generate 320 raw hashes for each 2.5 MiB of data it reads (e.g. 320 raw H1 hashes and 320 raw H2 hashes). For historical reasons when reporting the hashrate we normalize that number to 400. This is due to earlier versions of the protocol that yielded a different number of raw hashes for each range of data read - normalizing to 400 was necessary to ensure all packing formats yielded the same chance of finding a valid solution.

After normalizing to 400 we discount the H1 hashes by 100x. This has to do with how a hash is compared with the network difficulty to determine whether it is a valid solution.

1. Network difficulty is pulled from the latest valid block
2. Each hash is converted to a decimal number
3. The H1 hash is compared with 100x the difficulty, the H2 hash is compared with difficulty as it is.

This has the effect of making it 100x harder for each H1 hash to yield a valid solution. Another way to represent this is just to say each H1 hash is worth 1/100 of an H2 hash.

The end result is that, in an ideal scenario with a fully packed weave, each partition yields 404 normalized hashes (4 normalized or effective H1 hashes, 400 normalized or effective H2 hashes).

#### 3.1.2 Why discount H1?

The H1 hash is discounted to provide a strong financial incentive for miners to pack the full weave - or to collaborate with other miners to pack the full weave. Since the H2 hash is selected across the full weave a miner who packs the same partition multiple times will have a lower effective hashrate than a miner who packs different partitions. This helps ensure that all weave data is replicated equally and is the underlygin principle mentioned [above](#21-number-of-fully-packed-storage-modules).

### 3.2 Ideal Hashrate

If the full weave is 100 partitions, an ideal miner will have these characteristics:

* 360TB of packed data (3.6TB per partition)
* VDF Speed: 1s
* Sustained disk read speed fo 5 MiB/s per partition

This ideal miner will have an effective hashrate of 40,400:

| H1         | H2           | VDF  | Hashrate |
| ---------- | ------------ | ---- | -------- |
| (4 x 100 + | 400 x 100) / | 1s = | 40,400   |

That means they have 40,400 chances every second to find a valid solution.

### 3.3 Real Hashrate

In practice the ideal never exists, this ideal scenario is unattainable as the weave currently has gaps where storage space has been purchased but not yet filled (for more information on this see the [Syncing and Packing Guide](/developers/mining/overview/syncing-and-packing#42-partitions-are-rarely-full)). The impact of these gaps varies, as of August, 2024 the weave was about 86% full. As newpartitions are filled, this percentage will likely increase, gradually raising the overall maximum hashrate possible per partition.

We'll now walk through n example for a miner with sub-optimal characteristics:

* 240 TB of packed data
  * for simplicity we'll represnt this as having 66% of the weave
* VDF Speed: 1.05s
* Sustained disk read speed of 2 MiB/s per partition
  * for simplicity we'll represent this as being to read 40% of each data range

| H1                     | H2                             | VDF     | Hashrate |
| ---------------------- | ------------------------------ | ------- | -------- |
| (4 x 40% x 100 x 66% + | 400 x 40% x 100 x 66% x 66%) / | 1.05s = | 6,738    |

Breaking that down a bit:

* The 40% multiplier indicate that for each range the miner is allowed to read, it can only read 40% of it in time, reducing the hashes it can generate
* The 66% term under H1 indicates that there is only a 66% change that the randomly selected partition offset falls in data that the miner has packed
* The (66% x 66%) term under H2 indicates that unpacked/missing data has a quadratic impact on H2 hashes. For each missing H1 hash the miner loses the opportunity to even select an H2 offset (the first 66% term). And even when the miner is able to gnerate an H1 hash, there is only a 66% change that the full-weave H2 offset falls in data that the miner has packed.
* Finally the 1.05s VDF indicates that because the miner's VDF is slow it only gets a chance at generating hashes every 1.05 seconds and not every second (a loss of 5% hashrate)


# VDF

A guide to running a VDF Server

## What is VDF?

The VDF (Verifiable Delay Function) controls the speed of mining with new mining "seeds" available at roughly 1 second intervals. To keep up with the network your CPU must be able to maintain this 1 second cadence while calculating the VDF. For that the CPU needs to support [hardware SHA2 acceleration](https://en.wikipedia.org/wiki/Intel_SHA_extensions). Additional cores will not improve VDF performance as VDF hash calculations are sequential and therefore limited to a single thread on a single core.

The node will report its VDF performance on startup, warning you if it is too low. You can also run `./bin/benchmark-vdf` to print your system's VDF performance.

{% hint style="info" %}
As of May 2024 the fastest VDF calculations observed are on the Apple M2 processor. Packing and mining are not supported on MacOS, but running a node as a VDF server is possible if you build from source. For instructions on building from source see [Building from source](https://github.com/ArweaveTeam/arweave#building-from-source).
{% endhint %}

### VDF Difficulty

The network VDF difficulty adjusts daily to target an average VDF time of 1 second across all mined blocks. For ease of comparison the VDF performance printed on startup and from the `./bin/benchmark-vdf` assumes a fixed difficulty of `600,000`. You can expect your actual VDF performance when connected to the network to be lower than the benchmark.

For context the current VDF difficulty is `685,976` *(May 2024, block height 1417119)*. So with a benchmark VDF of 1 second you can expect a network performance of 1.14 seconds (`1 second * (685,976 / 600,000)`).

## VDF Servers

Since VDF is so important to mining performance you may have another machine compute VDF for you. For instance, you may set up a dedicated VDF node broadcasting VDF outputs to all your mining nodes.

Running a node fetching VDF states from a peer (aka a "VDF client"):

```
./bin/start vdf_server_trusted_peer IP-ADDRESS ...
```

Running a node pushing its VDF outputs to other peers (aka a "VDF server"):

```
./bin/start vdf_client_peer IP-ADDRESS-1 vdf_client_peer IP-ADDRESS-2 ...
```

Make sure to specify \[IP-ADDRESS]:\[PORT] if your node is configured to listen on a TCP port other than 1984.

In all cases `IP-ADDRESS` can also be a resolvable domain name.

For an example invocation see [Examples](https://docs.arweave.org/developers/mining/examples#running-a-vdf-server).

{% hint style="warning" %}
Do not connect to an external peer you do not trust.
{% endhint %}

{% hint style="info" %}
Make sure every client node is reachable from its VDF servers - they are in the same network or the node has a public IP and the port (the default is 1984) is forwarded if there are firewalls. If the node is launched with the mine flag and showing no mining performance reports, it is likely no input comes from the VDF server(s).
{% endhint %}

{% hint style="info" %}
The team operates 2 VDF servers that can be used by any miner that wants to:

* `vdf-server-3.arweave.xyz`
* `vdf-server-4.arweave.xyz`

To configure your miner to use the team VDF servers:

1. Add this to your launch config: `enable vdf_server_pull`
2. Add the team VDF servers to your list of `vdf_server_trusted_peer`s
   {% endhint %}

The number of SHA256 iterations (aka VDF difficulty) required to compute a single VDF step is continually adjusted by the Arweave network in order to target a 1-second step time. You can query the current VDF difficulty by looking at the `nonce_limiter_info.vdf_difficuly` field of the latest Arweave block (i.e. <https://arweave.net/block/current>). As of block height 1798684 the `vdf_difficulty` is 1,107,523 - meaning each VDF step requires 1,107,523 recursive SHA256 hashes.


# Transaction Blacklist

Understanding Shepherd and the transaction blacklist

In order to protect your machine from material that may be illegal in your country, you should use a content policy when mining Arweave. Content policies can be generated using the [Shepherd tool](https://shepherd.arweave.net). Shepherd allows you to create your own content policies for the content that you would like to store on your Arweave node, abiding by your moral and legal requirements.

In order to help you get started quickly, @ArweaveTeam provides an NSFW content filter which you can load by adding the following to your Arweave start command:

`transaction_blacklist_url https://public_shepherd.arweave.net`


# Node Reputation

Understanding node reputation

Each node maintains a reputation score for all of its peers. This score is based on how much valid dat each peer has shared with it. The more valid data (blocks, transactions, chunks) that a peer shares with a node, that higher that peer's reputation. A node will gossip to and process data from highly rated peers first. Having a high reputation can help get your mined blocks processed and shared across the network more quickly and so can help you "win the race" when you have mined a new block.


# Operations


# Arweave Entrypoint

How to use the Arweave entrypoint script

## 0. `./bin/start` vs. `./bin/arweave`

This guide covers the core Arweave entrypoint: `./bin/arweave`. That entrypoint provides a lot of useful functionality. However when launching your node it is recommended that you use `./bin/start`.

`./bin/start` wraps `./bin/arweave foreground` and includes a naive auto-restart functionality. If your node crashes, `./bin/start` will wait 15 seconds and then start it again.

## 1. Arweave Entrypoint

The Arweave entry-point located in `bin/arweave` integrates all required subcommands in one place. To print the help page, execute the script:

```sh
./bin/arweave
```

It is also possible to have a more detailed help of one particular subcommand by passing it after the `help` one.

```sh
./bin/arweave help ${subcommand}
```

## 2. Start Arweave

Arweave can be started in many different ways depending of the needs and all these methods can be used with `./bin/arweave` entry-point. Most of the users are using `./bin/start` to start an arweave node, this script is equivalent to:

```sh
./bin/arweave foreground ${parameters}
```

To have access to Arweave output directly from the terminal (without the Erlang console) the following command can be used. It could be used with any process manager like `systemd`, because the VM will not fork.

```sh
./bin/arweave foreground ${parameters}
```

To have access to Arweave output directly from the terminal with an Erlang console:

```sh
./bin/arweave console ${parameters}
```

Arweave can also be started as an Unix daemon (in background) by executing the following command:

```sh
./bin/arweave daemon ${parameters}
```

To reattach a daemon (and having access to the Erlang console), one can execute the subcommand `daemon_attach`.

```sh
./bin/arweave daemon_attach
```

## 3. Arweave Status

To ensure a node is correctly running, one can ping it using `./bin/arweave` entry-point. The script will return the string `pong` if the node is up.

```sh
./bin/arweave ping
```

The same information can be available by using the subcommand `status`, except nothing will be printed. The command will return `0` if the node is up and `1` if the node is down. Useful for monitoring scripts.

```sh
./bin/arweave status
```

Finally, to see if the node is reachable, it is also possible to use external software like `curl`:

```sh
curl http://localhost:1984/
```

## 4. Remote Console

An Erlang shell can be invoked to control the Erlang VM where Arweave is running. The `./bin/console` script can be used and it is equivalent to execute this command:

```sh
./bin/arweave remote_console
```

The shell can be ended by pressing `Ctrl` + `C`.

## 5. Stop Arweave

An Arweave node can be stopped by using the script `./bin/stop` or by executing the following command:

```
./bin/arweave stop
```

It can take some time for the node to shutdown. If you can, it is best to wait for the node to complete its shutdown process. However if you can't wait, you can kill the `arweave` and `beam.smp` processes using `kill -1`.

{% hint style="warning" %}
Sending a SIGKILL (`kill -9`) is **not** recommended as it can cause data corruption.
{% endhint %}

## 6. Custom Erlang VM Arguments

The first - and easiest - method is to pass the new argument directly from the command line, all arguments before `--` will be used to overwrite the default VM parameters of the Erlang VM. All arguments after `--` will be used for Arweave.

Example:

```sh
./bin/start +MMscs 131072 +S 16:16 -- config_file config.json
```

The second method is to modify the `rel/arweave/releases/${arweave_release}/vm.args.src` file. This file contains all default parameters used by Arweave with some links to the official documentation to help anyone wanting to optimize the Erlang VM.


# Mining Performance Report

Understanding the Mining performance Report

## 1. The Mining Performance Report

Every 10 seconds a miner will print a report like the following to the console:

```
================================================= Mining Performance Report =================================================

VDF Speed:        1.00 s
H1 Solutions:     0
H2 Solutions:     0
Confirmed Blocks: 0

Local mining stats:
+-----------+-----------+----------+---------------+---------------+---------------+------------+------------+--------------+
| Partition | Data Size | % of Max |   Read (Cur)  |   Read (Avg)  |  Read (Ideal) | Hash (Cur) | Hash (Avg) | Hash (Ideal) |
+-----------+-----------+----------+---------------+---------------+---------------+------------+------------+--------------+
|     Total |  21.5 TiB |      6 % |    17.5 MiB/s |    17.7 MiB/s |    17.5 MiB/s |    146 h/s |    200 h/s |      192 h/s |
|        28 |   3.2 TiB |     98 % |     2.2 MiB/s |     2.6 MiB/s |     2.6 MiB/s |      3 h/s |     32 h/s |       28 h/s |
|        29 |   3.2 TiB |     97 % |     2.7 MiB/s |     2.6 MiB/s |     2.6 MiB/s |     43 h/s |     21 h/s |       28 h/s |
|        30 |   1.9 TiB |     58 % |     1.4 MiB/s |     1.7 MiB/s |     1.5 MiB/s |      2 h/s |     17 h/s |       17 h/s |
|        31 |   2.0 TiB |     61 % |     1.3 MiB/s |     1.7 MiB/s |     1.6 MiB/s |      2 h/s |     29 h/s |       18 h/s |
|        32 |   2.1 TiB |     64 % |     2.3 MiB/s |     1.6 MiB/s |     1.7 MiB/s |      3 h/s |     11 h/s |       18 h/s |
|        33 |   2.8 TiB |     84 % |     2.4 MiB/s |     2.2 MiB/s |     2.2 MiB/s |     43 h/s |     21 h/s |       24 h/s |
|        34 |   3.2 TiB |     96 % |     2.7 MiB/s |     2.7 MiB/s |     2.6 MiB/s |     43 h/s |     37 h/s |       28 h/s |
|        35 |   3.2 TiB |     96 % |     2.3 MiB/s |     2.6 MiB/s |     2.6 MiB/s |      3 h/s |     29 h/s |       28 h/s |
+-----------+-----------+----------+---------------+---------------+---------------+------------+------------+--------------+
```

Both [Solo Miners and Coordinated Miners](/developers/mining/overview/node-types) print this report, however Coordinated Miners inclues some extra information discussed below.

### 1.1 VDF Speed and Solution Stats

* **VDF Speed**: the averge VDF speed that your miner has realized since the last time the report was generated (i.e. typically 10 seconds).
* **H1 and H2 Solutions**: the number of H1 or H2 solutions your miner has found. Most, but not all, solutions will become blocks. However do to orphan rate and occasional race conditions, many blocks are not confirmed.
* **Confirmed Blocks**: the number of blocks that your miner believes have been accepted by the network. Each confirmed block **should** generate miner rewards for you. However, there are some limitations in the the miner which cause it to miss some orphans. Some tips on how to account for these limitations are discussed in [Understanding Mining](/developers/mining/overview/mining)

{% hint style="warning" %}
**Pool Mining:** When mining against a pool, the H1 and H2 solutions will report **partial** solutions. Pool miners maintain 2 difficulties: the normal network difficulty, and a lower difficulty set by the pool operator. Partial solutions just satisfy the lower difficulty and usually will not result in a valid block. Partial Solutions are used by the pool operator to track how much work each pool client is performing in order to calculate their share of rewards.
{% endhint %}

### 1.2 Local mining stats

The mining performance stats are broken down by partition with the total across all partitions listed at the top.

* **Data Size** and **% of Max**: the amount of data you have packed for a given partition (as well as the total) and what percent that is of the total possible. The amount of data you have packed is the main determinant of your hashrate.
* **Read (xxx)**: the mining read throughput per partition and in aggregate.
* **Hash (xxx)**\*: mining hashrate per partition and in aggregate.

You can read more about how hashrate is calculated in the [Hashrate](/developers/mining/overview/hashrate) guide.

#### 1.2.1 `Cur` vs. `Avg` vs. `Ideal`

You'll see 3 values for the `Read` and `Hash` stats.

* **Cur**: The average `Read` or `Hash` rate since the last time the Performance Report was shown. i.e. the average over the last 10 seconds
* **Avg**: The average `Read` or `Hash` rate since the node started.
* **Ideal**: The ideal `Read` or `Hash` rate given the amount of data you have synced and your VDF Speed. This value is also an average over the last 10 seconds.

You can use the `Ideal` values to determine whether you're getting your exepected `Read` or `Hash` rates.

{% hint style="warning" %}
**Coordinated Mining:** The `Ideal` rates are incorrect and too low for coordinated miners. They currently track the `Ideal` `Read` or `Hash` rate for the miner assuming that it is solo mining and does not have access to any of the partitions mined by a peer. The `Cur` and `Avg` values, however, are correct. The result is that it will seems as if your coordinated miner is mining far better than `Ideal`.
{% endhint %}

## 2. Coordined mining cluster stats

Coordinated miners will have an additional table printed blow the **Local mining stats**:

```
Coordinated mining cluster stats:
+-----------------+--------------+--------------+--------------+-------------+--------+-------+
|      Peer       | H1 Out (Cur) | H1 Out (Avg) |  H1 In (Cur) | H1 In (Avg) | H2 Out | H2 In | 
+-----------------+--------------+--------------+--------------+-------------+--------+-------+
|             All | 	3714 h/s | 	   3733 h/s |	  3419 h/s |    3390 h/s |      0 |  	0 |
| 10.0.0.100:1984 |      602 h/s |  	611 h/s | 	   559 h/s |     489 h/s |      0 |  	0 |
| 10.0.0.102:1986 | 	1736 h/s | 	   1606 h/s |	  1523 h/s |    1503 h/s |      0 |  	0 |
+-----------------+--------------+--------------+--------------+-------------+--------+-------+
```

This table tracks the H1 and H2 solutions that each miner in the cluster exchanges with each other.

* **Peer**: Local CM peer IP:Port#
* **H1 Out (Cur)**: \*\*The average H1 hashes per second sent to Peer since the last screen refresh
* **H1 Out (Avg)**: This average H1 hashes per second sent to Peer since the miner was started
* **H1 In (Cur)**: The average H1 hashes per second received from Peer since the last screen refresh
* **H1 In (Cur)**: The average H1 hashes per second received from Peer since the miner was started
* **H2 Out**: When a node in your CM cluster generates a Solution, it is sent out to the cluster and the exit node will submit it to the network in the hopes of mining that block
* **H2 In**: Same as above, except incoming


# Benchmarking Guide

A guide to benchmarking your miner's performance

The arweave node ships with 2 tools you can use to benchmark different elements of your miner's performance.

* Hashing: `./bin/arweave benchmark hash`
* VDF: `./bin/arweave benchmark vdf`

{% hint style="warning" %}
There are 3 other benchmarking tools (`2.9`, `packing`, and `./data-doctor bench`) that need to be rewritten and can't be relied on to benchmark packing speed.
{% endhint %}

## 1. Hashing

The `hash` benchmark will report the speed in milliseconds to compute an H0 hash as well as an H1 or H2 hash. These metrics are primarily used while mining.

The times reported are for a single thread (i.e. single core) of execution. The number of H0 or H1/H2 hashes your system can compute every second of wallclock time can be scaled up by the number of cores in your CPU. We don't yet have guidance on the impact of hyperthreading/SMT, so for now best to only count the number of physical cores on your CPU rather than virtual cores.

Some points to keep in mind. For each VDF step your miner will compute:

* 1 H0 hash for every partition
* 400 H1 hashes for every partition
* 0-400 H2 hashes for every partition
  * *The specific number of H2 hashes is determined by how much of the weave you're mining.*

For the following examples, please keep in mind that with all the benchmarks, these computations should be taken as guides. In practice your hashing speed will be impacted by a number of factors not captured by the benchmark (e.g. contention with other processes running, impact of hyperthreading/SMT, etc...). Also you should budget your CPU capacity to exceed these calculations in order to accommodate all the other work your miner is doing (both within the Arweave node and at the system level).

For more information about how hashrate is calculated, please see [Overview - Hashrate](/developers/mining/overview/hashrate).

### 1.1 Examples

#### 1.1.1 Example 1

* The full weave is 50 partitions
* You are mining all 50 partitions
* Each VDF step you will compute
  * 50 H0 hashes
  * 20,000 H1 hashes *(50 \* 400)*
  * 20,000 H2 hashes *(50 \* 400)*
* The `hash` benchmark reports
  * H0: **1.5 ms**
  * H1/H2: **0.2 ms**
* Each VDF step you will need **8,075 ms** of compute time (40,000 \* 0.2 + 50 \* 1.5)
* Implication is that you will need **more than 8-cores** to mine a 1 second VDF.

#### 1.1.2 Example 2

* The full weave is 50 partitions
* You are mining 20 partitions
* Each VDF step you will compute
  * 20 H0 hashes
  * 8,000 H1 hashes *(20 \* 400)*
  * 3,200 H2 hashes *(20 \* (20/50) \* 400)*
* The `hash` benchmark reports
  * H0: **1 ms**
  * H1/H2: **0.1 ms**
* Each VDF step you will need **1,140 ms** of compute time (11,200 \* 0.1 + 20 \* 1)
* Implication is that you will need **more than 1 core** to mine a 1 second VDF.

### 1.2 Options

Usage: `./bin/arweave benchmark hash [options]` Options:

* `randomx <512|4096>` (default: 512)
* `jit <0|1>` (default: 1)
* `large_pages <0|1>` (default: 1)
* `hw_aes <0|1>` (default: 1)

In general the defaults are fine unless you have a really old CPU. If the benchmark runs without crashing, then you can stick to the defaults.

## 2. VDF Speed

The `vdf` benchmar will report the speed in seconds to compute a VDF.

**Note:** By default the benchmark tool assumes a fixed **VDF difficulty of 600,000**. The Arweave network VDF difficulty is updated daily in order to target a network average VDF speed of 1 second.

As of November26, 2025, block height 1803283, the Arweave network VDF difficulty is **1,106,177**. As VDF difficulty rises, VDF time increases (gets slower), as VDF difficulty drops, VDF time decreases (gets faster). So today if you use the default options on the `vdf` benchmark and it reports a 1 second VDF for your CPU, you can expect to achieve 1.14 seconds once connected to the network. `(1,106,177 / 600,000) * 1 second = 1.84 seconds`

To make this less confusing we recommend specifying the current network difficulty rate when running the benchmark. See below for options.

### 2.1 Options

Usage: `./bin/arweave benchmark vdf [options]` Options:

* `mode <default|openssl|fused|hiopt_m4>` (default: default)
* `difficulty <vdf_difficulty>` (default: 600,000)
* `verify <true|false> (default: false)`

#### 2.1.1 `mode`

This mimics the `vdf` option when running your node and instructs the benchmark tool to use the specifid VDF algorithm.

#### 2.1.2 `difficulty`

Specify the VDF difficulty to use when running the tool. You can check the current network VDF difficulty at <https://arweave.net/block/current> - search for `vdf_difficulty`

#### 2.1.3 `verify`

If `true` then the benchmark tool will verify the VDF output against a slower "debug" VDF algorithm. This is primarily only useful when you're modifying one of the included VDF algorithms.

## 3. Deprecated Tools

There are 3 other benchmarking tools (`2.9`, `packing`, `./data-doctor bench`) that need to be rewritten and can't be relied on to benchmark packing speed.


# Multiple Nodes, One Server

A guide to running more than one Arweave node on the same server

**Adapted from a guide originally written by @Thaseus**

## 1. Why would you need to run more than one node on a server?

In most cases miners will run a single node per server. However it is possible, and sometimes beneficial, to run multiple nodes on a single server. Some examples:

* mine storage modules while also syncing/packing the tip partition that isn't yet minable
* run both your exit node and a miner on the same server
* use both CPUs in a dual-CPU server without getting hit by [known performance issues](/developers/mining/getting-started/hardware#344-dual-cpu-motherboards)

## 2. How to run more than one node on n server

Each node on a server needs a unique:

* `data_dir`
* `port`
* [Erlang node name](https://www.erlang.org/doc/system/distributed.html#nodes)
  * Can be set via the `ARNODE` environment variable
* [Erlang cookie](https://www.erlang.org/doc/system/distributed.html#security)
  * Can be set via the `ARCOOKIE` environment

You can set the environment variables for the session, but easiest is probably set them just for each node invocation. Here is an example launching 2 nodes (each one running in the background):

```sh
ARNODE=node1@127.0.0.1 \
ARCOOKIE=node1 \
./bin/start port 1984 data_dir /opt/data/node1 &

ARNODE=node2@127.0.0.1 \
ARCOOKIE=node2 \
./bin/start port 1985 data_dir /opt/data/node2 &
```

{% hint style="info" %}
In practice you will need to provide more launch options if you want the node to do something useful. See [Running Your Node](/developers/mining/getting-started/configuration) for more information.
{% endhint %}

{% hint style="info" %}
Running a node in the background using the linux `&` isn't recommended (and just shown here for simplicity). [We recommend](/developers/mining/getting-started/configuration#02-keeping-the-miner-running) using `screen` or some other more sophisticated process manager.
{% endhint %}

## 3. Pinning your node to certain cores

When running multiple nodes on single server we recommend pinning each node to a distinct set of CPU cores. This is useful for working around the dual-CPU performance issue mentioned above, but is also useful in single-CPU systems to keep the node workloads separate and avoid bottlenecking.

You can use any pinning utility you're comfortable with (e.g. `taskset`, `numactl`, etc...).

An example extending the above example to use `screen` and `numactl`, to both run the nodes in the background and pin them to a different set of cores (0-31 vs. 32-63 on a 64-core CPU):

```sh
ARNODE=node1@127.0.0.1 \
ARCOOKIE=node1 \
screen -dmSL arweave.node1 -Logfile ./screenlog.node1 \
    numactl --physcpubind=0-31 \
    ./bin/start port 1984 data_dir /opt/data/node1;
ARNODE=node2@127.0.0.1 \
ARCOOKIE=node2 \
creen -dmSL arweave.node2 -Logfile ./screenlog.node2 \
    numactl --physcpubind=32-63 \
    ./bin/start port 1985 data_dir /opt/data/node2;
```


# Optimizing Sync & Pack

Tips for optimizing the sync and pack process

## 1. Overview

**Most important performance tip:** Do not mine while you pack. The two processes are both resource intensive and will slow each other down. (i.e. omit the `mine` flag from your configuration) If you've already removed the `mine` flag, continue on below for more optimization tips.

There are 3 primary bottlenecks when syncing and packing:

1. Your network bandwidth *(used to download chunks from peers)*
2. Your CPU *(used to pack and unpack chunks)*
3. Your disk write speed *(used to write chunks to disk)*

And to a lesser degree:

4. RAM *(more heavily used in mining than in syncing/packing, but can become a bottleneck under certain situations)*

If any of the 3 primary resources are maxed out: congratulations! Your configuration is syncing and packing as fast as it can!

## 2. Increasing Bandwidth

Not much to do here other than negotiate a faster internet connection, or find a second one.

## 3. Increasing CPU

Packing and unpacking can be parallelized across chunks, so you can add more cores or increase the clock speed to increase your packing speed. See the [Benchmarking](/developers/mining/operations/benchmarking) guide for guidance on evaluating CPU pack speed.

## 4. Increasing Disk Write Speed

During the syncing and packing phase you will typically hit a network bandwidth or CPU bottleneck before you hit a disk IO bottleneck (the reverse is true once you start mining).

If you believe you've hit a disk IO bottleneck you have a few options.

First, confirm that you're getting your expected disk write speed. You can use tools like `fio` or `dd` to measure your disks write speed. If it is below your expected speed, you'll want to check your system configuration (software and hardware) for issues.

Second, you can add more disks to your node. This is really only relevant if you have partitions that you intend to sync and pack but which you haven't added to your node configuration. As a general rule you should add all your storage modules to your node while syncing and packing as this will increase your disk IO bandwidth as well as help fully use your network and CPU bandwidth.

Third, you can buy faster disks. This is generally not recommended to unblock a syncing and packing bottleneck as there's a good chance that extra IO speed will go unused once you start mining. Including it here for completeness.

## 5. Increasing RAM

The RAM guidelines mentioned in the [Guide](https://github.com/ArweaveTeam/docs.arweave.org-info/blob/master/mining/operations/mining-guide.md#preparation-ram) are focused on mining. Often RAM is not a primary bottleneck during syncing and packing. If you are maxing out your RAM: review the guidelines below. It's possible you can optimize your node configuration.

## 6. Increasing Utilization

Okay, so you've reviewed your bottlenecks and determined that **none** of them are at capacity. Here are some tips to increase syncing and packing speed.

### 6.1 sync\_jobs

The `sync_jobs` flag controls the number of concurrent requests your node will make to peers to download data. The default is `100`. Increasing this number should increase your utilization of all resources: the amount of data you pull from peers (network bandwidth), the number of chunks you're packing (CPU), and the volume of data written to disk (disk IO).

However, it is possible to increase this number **too much**. This can:

1. Cause your node to be rate-limited / throttled by peers and ultimately decrease your bandwidth utilization.
2. Increase your RAM utilization due to backed up sync jobs. This is particularly common if your miner has a poor network connection (e.g. high latency or data loss). Increasing the volume of slow/hanging requests can cause a backup which eventually leads to an out of memory error.

Setting `sync_jobs` to `200` or even `400` is unlikely to cause any issues. But before you increase it even further our recommendation is to first confirm:

1. Your CPU and network bandwidths are below capacity
2. Your network connectivity is good (e.g. using tools like `mtr` to track packet loss)

### 6.2 storage\_module

As mentioned above under [Increasing Disk Write Speed](#4-increasing-disk-write-speed) syncing to all your storage modules at once will maximize your available disk write bandwidth. The same applied to network bandwidth. Adding more storage modules when syncing increases the set of peers you can pull data from (as different peers share different parts of the weave data). This will help your node maximize its network bandwidth by pulling from the "best" set of peers available at a given time.

### 6.3 Repacking

If you configure your node to repack from one local storage module to another the node will prioritize that over pulling data from peers. This can cause you to max out your CPU capacity while your network bandwidth stays low.

This is not a problem. It simply means your node will max out its CPU doing local repacks before it begins searching for peers to download more data from. If you'd rather focus on syncing, just make sure to configure your node without any repacking. Two examples of configurations that will cause local repacking:

1. `storage_module 9,unpacked storage_module 9,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
2. `storage_module 16,Q5EfKawrRazp11HEDf_NJpxjYMV385j21nlQNjR8_pY.replica.2.9 storage_module 16,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`

**Note:** As mentioned in [Syncing & Packing](/developers/mining/overview/syncing-and-packing#2-packing), whenever you sync data - even if you are syncing to `unpacked` - you will likely have to perform at least one packing operation.

### 6.4 Multiple Full Replicas

If you intend to build more than 1 packed full replica, the following approach should get you there fastest:

1. Download all the data to `unpacked` storage modules
2. Build each packed replica using [Cross-Module Repacking](/developers/mining/getting-started/configuration#21-cross-module-repack) from your `unpacked` storage modules
3. You can either keep the `unpacked` data around for later, or, you can do a [Repack-in-Place](/developers/mining/getting-started/configuration#22-repack-in-place) when building your final packed replica.

This approach will reduce your download time (since you only have to download the data once) and reduce the number of packing operations (since you only have to unpack peer data once).

**Note:** This approach is not recommended if your goal is to have 1 or fewer packed replicas. It will work, but won't be any faster than just syncing straight to packed storage modules.


# Optimizing with Metrics

A guide to monitoring your miner.

## 1. Metrics

The arweave node publishes a set of [Prometheus](https://prometheus.io/docs/introduction/overview/) metrics at the `/metrics` endpoint (i.e. `<IP>:<PORT>/metrics`) - you can see an example at <https://arweave.net/metrics>. The `/metrics` endpoint also includes descriptions of each metric.

You can integrate Prometheus with a number of monitoring and visualization tools. Below we'll share some sample dashboards in [Grafana](https://grafana.com/) and some guidance.

### 1.1 Setup

1. [Setup Prometheus](https://prometheus.io/docs/prometheus/latest/getting_started/) to scrape the `/metrics` endpoint of your arweave node.
2. When you get to the point of defining Prometheus targets to monitor, add an `instance` label for each target that provides a name for your node (can just be your IP if you want). This isn't required in general, but it will make using the sample dashboard easier. e.g.

```
  - job_name: arweave

    static_configs:
      - targets: ['111.222.333.444:1984']
      labels:
        instance: 'my-miner'
```

Note: If you have previously set up your job\_name with a value other than the default 'arweave', you will get a chance to override that default during the dashboard import in step 4 below.

3. [Setup Grafana](https://grafana.com/docs/grafana/latest/datasources/prometheus/configure-prometheus-data-source/) to visualize the Prometheus data.
4. Download the sample dashboards (.json files) linked in each section and...
5. [Import the sample dashboards](https://grafana.com/docs/grafana/latest/dashboards/build-dashboards/import-dashboards/).

## 2. Mining Metrics

[Sample dashboard in Grafana](https://github.com/ArweaveTeam/docs.arweave.org-info/blob/master/mining/operations/grafana/mining.json)

![Sample Dashboard](/files/E3yErfigQ6KSEwMlsNW3)

### 2.1 Read Rate

**Metric**: `mining_rate{type="read"}`

This metric tracks the number of chunks read per second (reported in MiB/s). 1 chunk is 256KiB.

The protocol allows for up to 20 chunks per partition per VDF step to be read. That equates to roughly 5MiB/s per partition.

**Alerting**: We recommend setting an alert at 0 MiB/s as that indicates the miner is no longer mining. You may also want to establish a baseline and set an alert if read rate falls some amount below that baseline

### 2.2 Read Rate vs. Ideal

**Metrics**: `mining_rate{type="read"}` and `mining_rate{type="ideal_read"}`

This metric combines two values:

1. Your miner's actual read rate
2. The ideal read rate for an optimal miner with the same set of data synced and the same VDF speed.

The result is a percentage where 100% indicates you are mining at the ideal rate. The rate can exceed 100% for two reasons:

1. The ideal and actual metrics are calculated on slightly different periods and so there might be some oscillation in the percentage.
2. If your miner is mining as part of a coordinated mining set, the ideal rate is currently calculated assuming your miner is solo mining and doesn't take into account the hashes that your miner will perform for coordinated mining peers.

**Alerting**: You may want to establish a baseline and set an alert if read rate falls some amount below that baseline

### 2.3 Hash Rate

**Metric**: `mining_rate{type="hash"}`

This metric tracks the miner hashrate. The protocol allows for up to 400 H1 hashes and 400 H2 hashes per partition per VDF step. The metric also consider that an H1 hash is 100x less likely to result in a solution and scales the H1 hash count down accordingly. You can roughly interpret that as the protocol allowing 404 solution attempts (combination of H1 and H2 hashes) per partition per VDF step. Please see the [Hashrate](/developers/mining/overview/hashrate) guide for more information.

Note: hashes are generated after chunks are read, so if your Read Rate chart shows a low read rate, your Hash Rate chart will also be lower.

**Alerting**: Re recommend setting an alert on 0 as that indicates your miner is no longer mining. You may also want to establish a baseline and set an alert if hashrate falls some amount below that baseline

### 2.4 Hash Rate vs. Ideal

**Metrics**: `mining_rate{type="hash"}` and `mining_rate{type="ideal_hash"}`

This metric combines two values:

1. Your miner's actual hash rate
2. The ideal hash rate for an optimal miner with the same set of data sync and the same VDF speed.

The result is a percentage where 100% indicates you are mining at the ideal rate. The rate can exceed 100% for two reasons:

1. The ideal and actual metrics are calculated on slightly different periods and so there might be some oscillation in the percentage.
2. If your miner is mining as part of a coordinated mining set, the ideal rate is currently calculated assuming your miner is solo mining and doesn't take into account the hashes that your miner will perform for coordinated mining peers.

**Alerting**: You may want to establish a baseline and set an alert if hashrate falls some amount below that baseline

## 3. Mining Debug Metrics

These metrics, found in the "Debugging" row on the Mining Dashboard, provide additional information to help investigate mining performance issues. If you are seeing \~100% of the ideal hashrate, you can ignore these metrics.

Note: The mining debug metrics are always available and don't require that you set the `debug` launch flag.

### 3.1 Raw Read Rate

**Metric**: `mining_rate{type="raw_read"}`

This panel tracks the time it takes to read a 2.5MiB recall range per partition (reported in MiB/s). This differs from the [Read Rate](#21-read-rate) which tracks the number of chunks read per second. In particular the Raw Read Rate is not impacted by other bottlenecks in the mining pipeline and should give you a good indication of the disk speed actually observed by the node.

For example if your disk is capable of reading at 200MiB/s the Raw Read Rate should reflect this. However if, for example, you have a slow VDF speed, your Read Rate might show a much lower number.

**Debugging**: If you're not getting the hashrate you expect from your miner, this chart can help you pinpoint the bottleneck. If this chart is showing lower read rates than you'd expect you might want to check your hardware or system-level configuration. If this chart is showing expected read rates, then you'll have to look elsewhere in the pipeline (e.g. VDF Speed, CPU utilization, RAM utilization, etc.)

### 3.2 Chunk Cache Size

**Metric**: `mining_server_chunk_cache_size`

This panel tracks the size of your mining chunk cache (in MiB chks). While mining your node will need to temporarily cache chunks of data after reading them, this metric tracks how many of those chunks are currently cached. The cache has a size limit which is printed periodically by your node (to the console and to the logs), and can be set using the `mining_server_chunk_cache_size_limit` launch parameter.

**Debugging**: An optimal miner would expect the per-partition chunk cache size to stay beteen 0 and 5 MiB. Occasional spikes above 5 MiB are also fine as they can occur when there is temporary system-level resource contention or when your node validates a block that is ahead of it in the VDF chain and it can process a number of VDF steps at once.

However if you see that some partitions are regularly using more thann 5MiB it can indicate a performance issue somewhere in the mining pipeline (e.g. low read rate, CPU capacity, low VDF, memory contention, etc...)

### 3.3 Mining Task Queue

**Metric**: `mining_server_task_queue_len`

There are several steps in the [Mining Process](/developers/mining/overview/mining). Those steps are tracked and managed via a mining task queue. This chart shows the number of each task type that is queued up waiting to be processed.

**Debugging**: An optimal miner would expect each task queue to grow and be emptied regularly. If you notice that one task type queue is growing and rarely being emptied it indicates a bottleneck somewhere in the mining process.

## 4. Syncing Metrics

[Sample dashboard in Grafana](https://github.com/ArweaveTeam/docs.arweave.org-info/blob/master/mining/operations/grafana/syncing.json)

![Sample Dashboard](/files/vbR0XqLECSGctU3UoPsq)

### 4.1 Sync Requests

**Metric**: `http_client_get_chunk_duration_seconds_count`

This metric tracks the the number of `GET /chunk2` requests that your node makes to peers. This is the primary method through which a node syncs chunks during the Syncing and Packing phase.

**Debugging**: If you believe your sync rate is too slow, consulting this graph might explain why. Your node should pull data from several peers at once - if this isn't the case, your node could be in the process of searching for healthier peers.

### 4.2 Average Sync Latency

**Metrics**: `http_client_get_chunk_duration_seconds_sum` and `http_client_get_chunk_duration_seconds_count`

These metrics track the average latency of `GET /chunk2` requests to peers.

**Debugging**: If you believe your sync rate is too slow, consulting this graph might explain why. The node should detect and adjust to high latencies by selecting different peers. But it can take some time to find new peers - during this period syncing/packing rate may dip.

### 4.3 Chunks Received and Written

**Metrics**: `ar_http_request_duration_seconds_count` and `chunks_stored`

This panel tracks both the number of chunks received from peers and the number of chunks written (in bytes per second). Each chunk that is received is validated, unpacked, and then repacked to your miner's address and packing format. While we expect the chumks received and the chunks written to be very close, it is possible for some chunks to be discarded in this process which can result in the chunks written being lower than chunks received. Each chunk written is assumed to be 256 KiB. This may differ from your packing rate as each chunk written may need a different number of packing operations (0 to 2 depending on the format the chunk is received and the format it is written)

**Debugging**: If Chunks Received is lower than you'd expect you may want to look at the Sync Requests and Average Sync Latency charts. If there is a wide and sustained gap between Chunks Received and Chunks Written it could indicate an error somewhere in the validation or packing processes.

### 4.4 Sync Request Status

**Metric**: `ar_http_request_duration_seconds_count`

This panel breaks down the response codes from all `GET /chunk2` requests. A `client-error` response indicates a 4xx status and is usually a 404, meaning that your node requested a chunk from a peer that did not have it. Given how chunk requests are batched you should expect a lot of 404s.

**Debugging**: If your Chunks Received is not as high as you'd expect this chart can provide some insight as to the cause. As noted above `client-error`s are generally expected and it's hard to know what is an "appropriate amount". However if you're seeing al ot of `timeout`, or shutdown responses it may indicate that your node has poort network connectivity with a set of peers.

### 4.5 Device Lock Status

**Metric**: `device_lock_status`

When syncing, packing, and preparing entropy the node will manage which operations can be active on a given storage module at a time. This is to prevent the disk thrash that can occur when different operations try to read or write to different locations of a disk at the same time. The `device_lock_status` metric tracks what state a storge module is in.

The metric reports both the operation name and what state it is in:

| Operation | Description         |
| --------- | ------------------- |
| prepare   | Generating entropy  |
| sync      | Syncing and packing |
| repack    | Repacking in place  |

| State    | Metric Value |
| -------- | ------------ |
| paused   | 0            |
| active   | 1            |
| complete | 2            |

This can help explain some syncing or packing behaviors. For example if you're expecting a storage module to be syncing data but it's not, it might be that the node has `paused` the syncing temporarily or has swtiched that storage module to `prepare`.

## 5. Packing Metrics

[Sample dashboard in Grafana](https://github.com/ArweaveTeam/docs.arweave.org-info/blob/master/mining/operations/grafana/packing.json)

![Sample Dashboard](/files/LryVMkyEpoHjxD7fkjR9)

### 5.1 Chunks Written

**Metrics**: `chunks_stored`

This panel is similar to [Chunks Received and Written](#43-chunks-received-and-written) from the Syncing dashboard, but it excludes "Chunks Received". The `chunks_stored` metric tracks the number of chunks written to disk for a given packing type (represented as MiB/s). Each chunk written is assumed to be 256 KiB. This may differ from your packing rate as each chunk written may need a different number of packing operations (0 to 2 depending on the format the chunk is received and the format it is written)

**Debugging**: This chart can highlight which storage modules are packing at slower or faster rates, and will also tease out an intermediate steps (E.g. a chunk might first be written as `unpacked_padded` and then packed and rewritten as `replcia_2_9_1`)

### 5.2 Partition Sizes

**Metric**: `v2_index_data_size_by_packing`

This metric tracks the size of the data synced for each partition and packing format. The packing format is indicated by the `packing` label, and the partition number is indicated by the `partition_number` label.

### 5.3 Packing Requests

**Metric**: `packing_requests`

This panel tracks the number of packing operations performed per second.

### 5.4 Entropy

**Metrics**: `replica_2_9_entropy_stored` and `replica_2_9_entropy_generated`

This metric tracks the total amount of entropy generated and the amount written to each storage module. "Generate Total" and "Write Total" should match almost exactly.

### 5.5 Packing Buffer

**Metric**: `packing_buffer_size`

Before being packed or unpacked a chunk is added to the packing buffer. We expect this buffer to be empited out frequently and never to get too large. If you see the packing buffer steadily growing or rarely being emptied to 0, it might indicate a performance bottleneck somewhere.

### 5.6 Device Lock Status

**Metric**: `device_lock_status`

When syncing, packing, and preparing entropy the node will manage which operations can be active on a given storage module at a time. This is to prevent the disk thrash that can occur when different operations try to read or write to different locations of a disk at the same time. The `device_lock_status` metric tracks what state a storge module is in.

The metric reports both the operation name and what state it is in:

| Operation | Description         |
| --------- | ------------------- |
| prepare   | Generating entropy  |
| sync      | Syncing and packing |
| repack    | Repacking in place  |

| Metric Value | State    |
| ------------ | -------- |
| 0            | paused   |
| 1            | active   |
| 2            | complete |

This can help explain some syncing or packing behaviors. For example if you're expecting a storage module to be syncing data but it's not, it might be that the node has `paused` the syncing temporarily or has swtiched that storage module to `prepare`.

## 6. Debugging Metrics

The Debugging Dashboard provides some more detail information that can help with debugging performance issues. Some of the metrics are only populated when the `debug` option is set.

[Sample dashboard in Grafana](https://github.com/ArweaveTeam/docs.arweave.org-info/blob/master/mining/operations/grafana/debug.json)

![Sample Dashboard](/files/bQD1RLli9R5lmer1qNRD)

### 6.1 Block Height

**Metric**: `arweave_block_height`

This metric tracks the height of the node's current tip block. We expect this number to increase roughly every 2 minutes, but there can be substantial variation in the block time.

### 6.2 VDF Steps Behind

**Metric**: `block_vdf_advance`

This metric tracks how many VDF steps the node is behind the last block it processed. A negative number means the node is *ahead* of the VDF step in the latest block. We expect this number to be usually negative on a well-functioning node, with occasionally short-lived positive spikes.

If this number grows too large or is consistently positivve it can indicate that the node's VDF or VDF server is too slow or has fallen behind.

**Alerting**: We recommend setting an alert at 200, and adjusting as needed.

### 6.3 Message Queue

**Metric**: `process_info{type="message_queue"}`

**Note**: this metric is only populated when the `debug` node option is set

This panel tracks the number of messages stored in each erlang process's message queue. Erlang processes can be thought of as threads without shared memory. They send messages to communicate with each other. Before being processed a message is stored in a message queue. If a process's message queue is growing it means that process is receiving more messages than it can process.

### 6.4 CPU Load / # Cores

**Metric**: `process_cpu_seconds_total`

**Note**: this metric is only populated when the `debug` node option is set

Total CPU across all *virtual* cores. If you have a 16-core CPU with Hyperthreading/SMT enabled, you will likely have 32 virtual cores. Set the dashboard variable appropriately to get a sense of your overall CPU load.

### 6.5 Memory

**Metric**: `process_info{type=~"memory}`

**Note**: this metric is only populated when the `debug` node option is set

This panel tracks the memory used per Erlang process.

### 6.6 Reductions

**Metric**: `process_info{type="reductions"}`

**Note**: this metric is only populated when the `debug` node option is set

This panel tracks Erlang reductions. Reductions are a measure of Eerlang process activity. the more reductions performed by a process, the more CPU cycles it has consumed.

### 6.7 Inbound Requests

**Metrics**: `cowboy_requests_total`, `cowboy_request_duration_seconds_sum`, and `cowboy_request_duration_seconds_count`

These panels track the requests that your node is receiving from peers on the network. They track number of requests per second, total latency by request type, and average latency per request per type.

**Debugging**: These charts can help you identify activity that could be impacting your performance (e.g. mining, syncing, packing). For example a spike in `POST /tx2` or `GET /tx` might correspond to a period of high Arweave network activity. Or a high total latency servicing `GET /chunk2` might indicate that your node is serving a lot of chunks to peers. Depending on the type of activity and how strongly it is impacting your node performance, you can take different actions.

For example if you believe your node is serving too much chunk data and it is negatively impacting performance you can set the `get_chunk` `semaphore` (see the help for a brief description of how to set it - it's only usable via config.json). This will control how many concurrent `get_chunk` requests your node will handle. Default is 100.

Note: restricting `get_chunk` too much may negatively impact your node's reputation, which can in turn negatively impact sync rate or block orphan rate.

### 6.8 Outbound Requests

**Metrics**: `cowboy_requests_total`, `cowboy_request_duration_seconds_sum`, and `cowboy_request_duration_seconds_count`

These panels track the requests that your node is making to peers on the network. They track number of requests per second, total latency by request type, and average latency per request per type.

**Debugging**: Similar to the [Total Inbound Requests](#67-inbound-requests) chart, you can use these charts to identify activity that could be impacting your node's performance.


# Advanced: TLS Guide

Using TLS/HTTPS protocol is not necessary to have when operating a node, in fact most nodes don't use it. If you are considering to enable TLS support for your node you are most likely concerned with end-to-end encryption of HTTP requests. This makes sense if your node is publicly accessible and you are expecting to communicate with it using private secrets (example: you have metrics enabled for mining statistics protected by an Authentication).

This article handles the limited (but usable) support that arweaev has for TLS via the erlang library cowboy. But we do encourage node operators to consider more stable approaches, like nginx proxy with certbot, or cloud provided solutions like AWS's ELB load-balancer or Cloudfront. Operating TLS certificates on top of the Erlang runtime, is rather "bare-metal" and can be difficult, but if that's the only solution for your infrastructure, then read on.

## Generating TLS certificates using certbot

Using the certbot command line tool to generate certificates is a nice free way to get browser compatible certificates. Self-signed TLS certificates via `openssl` or `mkcert` are also viable options.

Seen in the screenshot below, it's not necessary to use nginx as certbot can start a python http server to perform the verification procedure. But whatever works for you, please use.

The cerbot on ubuntu systems (your operating system may vary) will generate a folder with pem file extensions in `/etc/letsencrypt/live/{your-domain-name}/`, two files will be important for us, `cert.pem` and `privkey.pem`.

By default these files are going to be symlinks to files stored under `/etc/letsencrypt/archive/...` it's important to be aware of, that the user that is going to run arweave is allowed read-access to these files. If you run arweave under root user (not-recommended!) then this isn't going to be a problem, otherwise you must perform the appropriate chmod operations on these symlink files as well as their target files to allow your current user to read these files and use them. Erlang doesn't provide good enough error messages if this isn't the case.

## Starting arweave with TLS certs

Here's an example of starting arweave with tls support.

```sh
./bin/start port 8443 tls_key_file /etc/letsencrypt/live/{your-domain-name}/privkey.pem tls_cert_file /etc/letsencrypt/live/{your-domain-name}/cert.pem # rest of your arweave cli arguments
```

the key here is to pass the arg tls\_key\_file with the value of the filepath to privkey.pem as well as passing tls\_cert\_file to the path of cert.pem.


# Advanced: Rate-Limiting

A guide to server-side rate-limiting

> This page documents a change introduced in version **2.9.6-alpha1**

## 1. Rate limiter

To regulate resource use, the arweave node implements rate limiting groups on HTTP endpoints. Endpoints are freely mapped to different groups.

Each group can be independently configured to fit different load profiles.

A list of local nodes in exempt from the rate limiting logic. This list with the peers addresses can be provided in the configuration.

### 1.1 Purpose

The arweave node aims to handle uneven load with mitigate possible starvation.

### 1.2 Hybrid rate limiting

The arweave node implements a hybrid rate-limiting algorithm; a composition of concurrency-monitoring, sliding windows, and leaky bucket limiting.

By configuration, sliding windows, or leak bucket limiting can be disabled, or be used in combination, but their order of precendence can't be changed.

#### 1.2.1 Concurrency

Each pool has an arbitrary limit for the allowed concurrent requests being handled. Once the limit is reached further requests will be rejected.

Please note, that the webservice has a global concurrency limit as well.

#### 1.2.2 Sliding Windows

If the concurrency limit is not breached, requests are validated against a Sliding Windows limiter. If the load is within the configured rate for the configured interval, the request will be processed. However, if the load is over the configured profile, the validation falls back to the Leaky Bucket Tokens algorithm

#### 1.2.3 Leaky Bucket Tokens

A leaky bucket token rate limiter is a traffic-shaping algorithm that enforces a steady request rate by adding tokens to a bucket at a fixed rate and allowing requests only when a token is available, effectively smoothing bursts and preventing overload.

Once the leaky bucket tokens are exhausted (limit is reached) the request will be rejected, there is no further option to fall back to.

## 2. Configuration

### 2.1 List of rate limiting groups

* general
* chunk
* data\_sync\_record
* recent\_hash\_list\_diff
* block\_index
* wallet\_list
* get\_vdf
* get\_vdf\_session
* get\_previous\_vdf\_session
* metrics

### 2.2 Config parameters

| Name                                                                         | Type    | Default Value                                                                                                                                                                                                                   | Description                                                                           |
| ---------------------------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| http\_api.limiter.\<group\_id>.sliding\_window\_limit                        | Number  | 0                                                                                                                                                                                                                               | Amount of requests allowed in Sliding Window limiter                                  |
| http\_api.limiter.\<group\_id>.sliding\_window\_duration                     | Number  | 1000                                                                                                                                                                                                                            | Sliding Window interval length in milliseconds                                        |
| http\_api.limiter.\<group\_id>.sliding\_window\_timestamp\_cleanup\_interval | Number  | 120000                                                                                                                                                                                                                          | How often sliding window cleanup routine runs (milliseconds)                          |
| http\_api.limiter.\<group\_id>.sliding\_window\_timestamp\_cleanup\_expiry   | Number  | 120000                                                                                                                                                                                                                          | Interval of inactivity after which cleanup routine removes peer from the registry     |
| http\_api.limiter.\<group\_id>.leaky\_limit                                  | Number  | <p>general: 450<br>chunk: 6000<br>data\_sync\_record: 20<br>recent\_hash\_list\_diff: 120<br>block\_index: 10<br>wallet\_list: 10<br>get\_vdf: 90<br>get\_vdf\_session: 30<br>get\_previous\_vdf\_session: 30<br>metrics: 2</p> | Leaky bucket token limit; requests beyond this start to be rejected                   |
| http\_api.limiter.\<group\_id>.leaky\_tick\_interval                         | Number  | 30000                                                                                                                                                                                                                           | Leaky bucket token reduction interval (how often tokens are reduced), in milliseconds |
| http\_api.limiter.\<group\_id>.leaky\_tick\_reduction                        | Number  | same as leaky\_limit                                                                                                                                                                                                            | Number of leaky bucket tokens removed in one run                                      |
| http\_api.limiter.\<group\_id>.concurrency\_limit                            | Number  | same as leaky\_limit                                                                                                                                                                                                            | Number of concurrent requests allowed per peer                                        |
| http\_api.limiter.\<group\_id>.is\_manual\_reduction\_disabled               | Boolean | False                                                                                                                                                                                                                           | Whether external requests can reduce leaky tokens                                     |

### 2.3 Example

```
{
    "enable": [ "randomx_large_pages" ],
    "peers": [
        "chain-1.arweave.xyz",
        "data-2.arweave.xyz",
        "data-3.arweave.xyz",
        "data-4.arweave.xyz",
        "vdf-server-3.arweave.xyz"
    ],
    "data_dir": "/opt/data_dir",
    "vdf_server_trusted_peers": ["vdf-server-3.arweave.xyz"	],
    "transaction_blacklist_urls": ["https://public_shepherd.arweave.net"],

    "storage_modules": [
        "0,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9"
    ],
    "mining_addr": "En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI",

    "max_connections": 250,

    "http_api.limiter.general.sliding_window_limit": 0,
    "http_api.limiter.general.leaky_limit": 450,
    "http_api.limiter.general.leaky_tick_interval": 30000,
    "http_api.limiter.general.leaky_tick_reduction": 450,

    "sync_jobs": 0
}
```

## 3. Metrics

Following metrics are provided per rate-limiting group.

| Name                                                                                            | Type      | Description                                                                                                                  |
| ----------------------------------------------------------------------------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------- |
| ar\_limiter\_response\_time\_microseconds                                                       | Histogram | Time it took for the limiter to respond to requests                                                                          |
| ar\_limiter\_requests\_total                                                                    | Counter   | The number of requests the limiter has processed                                                                             |
| ar\_limiter\_rejected\_total                                                                    | Counter   | The number of request were rejected by the limiter                                                                           |
| ar\_limiter\_reduce\_requests\_total                                                            | Counter   | The number of reduce request by peer in total. (This reduction is requested by the handler when a transaction is successful) |
| ar\_limiter\_peers                                                                              | Gauge     | The number of peers the limiter is monitoring currently (Connection, Memory)                                                 |
| ar\_limiter\_tracked\_items\_total                                                              | Gauge     | The number of timestamps, leaky tokens, concurrent processes are tracked (Memory leaks, process memory use)                  |
| ar\_limiter\_leaky\_ticks                                                                       | Counter   | The number of leaky bucket ticks the limiter has processed                                                                   |
| (Perhaps, overkill, should confirm correctness of behaviour, when there is no peer to drop etc) |           |                                                                                                                              |
| ar\_limiter\_leaky\_tick\_delete\_peer\_total                                                   | Counter   | The number of times a peer has been dropped from the leaky bucket token register                                             |
| ar\_limiter\_cleanup\_tick\_expired\_sliding\_peers\_deleted\_total                             | Counter   | The number of times a peer has been dropped from the sliding window timestamp register - how many peers have been deleted    |
| ar\_limiter\_leaky\_tick\_token\_reductions\_total                                              | Counter   | All the consumed leaky bucket tokens that were reduced for all peers in total (How much of the burst is being used)          |
| ar\_limiter\_leaky\_tick\_reductions\_peer                                                      | Counter   | The times a leaky bucket token reduction had have to be performed for a peer - how many peers have burned tokens             |


# Sample Node Configurations


# Entropy Generation

Example arweave configurations for entropy generation.

{% hint style="info" %}

* For the following examples we will alway use `En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI` or `Q5EfKawrRazp11HEDf_NJpxjYMV385j21nlQNjR8_pY` as mining addresses. **Replace them with your own address(es) before running the sample commands.**
  {% endhint %}

## 1. Overview

* You're just getting started and want to generate entropy before you sync and pack your data
* You'll pack the data to 16TB disks using the mining address `En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI`
* You'll use one of the DHA-provided public VDF servers
* You'll use the publicly available NSFW filter provided by Shepherd
* Run your miner with:
  * `sync_jobs 0`
  * `replica.2.9_workers` greater than 0 (default is fine)
* Wait until you see a message like the following for each storage module:
  * Console: `The storage module X is prepared for 2.9 replication.`
  * Log: `event: storage_module_entropy_preparation_complete, store_id: X`
* See [Running Your Node](/developers/mining/getting-started/configuration) for more information

## 2. Sample Directory Structure

* Mount points for 16TB disks that will store the packed data:
  * `/mnt/a`
  * `/mnt/b`
* `data_dir`: `/opt/data`
* Storage module symlinks:
  * `/opt/data/storage_modules/storage_module_0_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/a/storage_module_0_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_1_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/a/storage_module_1_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_2_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/a/storage_module_2_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_3_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/a/storage_module_3_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_4_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/b/storage_module_4_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_5_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/b/storage_module_5_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_6_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/b/storage_module_6_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_7_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/b/storage_module_7_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`

## 3.Sample Command-line Configuration

```
./bin/start \
    enable randomx_large_pages \
    peer peers.arweave.xyz \
    data_dir /opt/data \
    sync_jobs 0 \
    vdf_server_trusted_peer vdf-server-3.arweave.xyz \
    transaction_blacklist_url https://public_shepherd.arweave.net \
    mining_addr En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI \
    storage_module 0,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 1,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 2,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 3,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 4,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 5,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 6,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 7,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 
```

## 4. Sample Configuration File (config.json)

```
{
    "enable": [ "randomx_large_pages" ],
    "peers": [ "peers.arweave.xyz" ],
    "data_dir": "/opt/data",
    "vdf_server_trusted_peers": [ "vdf-server-3.arweave.xyz" ],
    "transaction_blacklist_urls": [ "https://public_shepherd.arweave.net" ],

    "storage_modules": [
        "0,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "1,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "2,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "3,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "4,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "5,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "6,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "7,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9"
    ],
     
    "mining_addr": "En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI",

    "sync_jobs": 0
}
```


# Syncing & Packing

Example arweave configurations for syncing and packing

{% hint style="info" %}

* When syncing & packing you do not need a private key - you will only need a mining address (aka packing address)
* Your mining address is **not** a private key - it is a public address
* For the following examples we will alway use `En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI` and `Q5EfKawrRazp11HEDf_NJpxjYMV385j21nlQNjR8_pY` as mining addresses. **Replace them with your own address(es) before running the sample commands.**
  {% endhint %}

## 1. Overview

* You're just getting started and need to download and pack data
* You'll sync the data from network peers and pack it as you store it to disk
* You'll pack the data to 16TB disks using the mining address `En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI`
* You'll use the `replica.2.9` packing format and will pack 4 partitions per disk
* You'll use one of the DHA-provided public VDF servers
* You'll use the publicly available NSFW filter provided by Shepherd
* Run your miner with:
  * `sync_jobs` greater than 0 (default is fine)
* See [Running Your Node](/developers/mining/getting-started/configuration) for more information

## 2. Sample Directory Structure

* Mount points for 16TB disks that will store the packed data:
  * `/mnt/a`
  * `/mnt/b`
* `data_dir`: `/opt/data`
* Storage module symlinks:
  * `/opt/data/storage_modules/storage_module_0_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/a/storage_module_0_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_1_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/a/storage_module_1_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_2_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/a/storage_module_2_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_3_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/a/storage_module_3_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_4_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/b/storage_module_4_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_5_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/b/storage_module_5_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_6_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/b/storage_module_6_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_7_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/b/storage_module_7_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`

## 3.Sample Command-line Configuration

```
./bin/start \
    enable randomx_large_pages \
    peer peers.arweave.xyz \
    data_dir /opt/data \
    sync_jobs 200 \
    vdf_server_trusted_peer vdf-server-3.arweave.xyz \
    transaction_blacklist_url https://public_shepherd.arweave.net \
    mining_addr En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI \
    storage_module 0,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 1,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 2,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 3,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 4,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 5,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 6,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 7,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 
```

4. Sample Configuration File (config.json)

```
{
    "enable": [ "randomx_large_pages" ],
    "peers": [ "peers.arweave.xyz" ],
    "data_dir": "/opt/data",
    "vdf_server_trusted_peers": [ "vdf-server-3.arweave.xyz" ],
    "transaction_blacklist_urls": [ "https://public_shepherd.arweave.net" ],

    "storage_modules": [
        "0,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "1,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "2,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "3,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "4,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "5,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "6,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "7,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9"
    ],
     
    "mining_addr": "En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI",

    "sync_jobs": 200
}
```


# Solo Mining

Example arweave configuration for solo mining

{% hint style="info" %}

* When mining your node needs to have a valid wallet installed - see [Node Wallet](https://github.com/ArweaveTeam/docs.arweave.org-info/blob/master/mining/setup/node-wallet.md)
* For the following examples we will alway use `En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI` or `Q5EfKawrRazp11HEDf_NJpxjYMV385j21nlQNjR8_pY` as mining addresses. **Replace them with your own address(es) before running the sample commands.**
  {% endhint %}

## 1. Overview

* You've downloaded and packed all your data to 16TB disks using the mining address `En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI`
* You'll use one of the DHA-provided public VDF servers
* You'll use the publicly available NSFW filter provided by Shepherd
* Run your miner with:
  * `mine`
  * `vdf_server_trusted_peer vdf-server-3.arweave.xyz` to use the DHA-provided VDF server
* See [Running Your Node](/developers/mining/getting-started/configuration) for more information

## 2. Sample Directory Structure

* Mount points for 16TB disks that will store the packed data:
  * `/mnt/a`
  * `/mnt/b`
* `data_dir`: `/opt/data`
* Storage module symlinks:
  * `/opt/data/storage_modules/storage_module_0_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/a/storage_module_0_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_1_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/a/storage_module_1_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_2_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/a/storage_module_2_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_3_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/a/storage_module_3_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_4_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/b/storage_module_4_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_5_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/b/storage_module_5_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_6_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/b/storage_module_6_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_7_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/b/storage_module_7_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`

## 3.Sample Command-line Configuration

```
./bin/start \
    enable randomx_large_pages \
    peer peers.arweave.xyz \
    data_dir /opt/data \
    mine \
    vdf_server_trusted_peer vdf-server-3.arweave.xyz \
    transaction_blacklist_url https://public_shepherd.arweave.net \
    mining_addr En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI \
    storage_module 0,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 1,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 2,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 3,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 4,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 5,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 6,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 7,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 
```

## 4. Sample Configuration File (config.json)

```
{
    "enable": [ "randomx_large_pages" ],
    "peers": [ "peers.arweave.xyz" ],
    "data_dir": "/opt/data",
    "vdf_server_trusted_peers": [ "vdf-server-3.arweave.xyz" ],
    "transaction_blacklist_urls": [ "https://public_shepherd.arweave.net" ],

    "storage_modules": [
        "0,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "1,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "2,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "3,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "4,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "5,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "6,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "7,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9"
    ],
     
    "mining_addr": "En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI",

    "mine": true
}
```


# Cross-Module Repacking

Example arweave configuration for cross-module repacking

{% hint style="info" %}

* When repacking you do not need a private key - you will only need a mining address (aka packing address)
* Your mining address is **not** a private key - it is a public address
* For the following examples we will alway use `En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI` and `Q5EfKawrRazp11HEDf_NJpxjYMV385j21nlQNjR8_pY` as mining addresses. **Replace them with your own address(es) before running the sample commands.**
  {% endhint %}

## 1. Overview

* You've downloaded 4 partitions of unpacked data
* You want to pack it so you can mine against it
* You've downloaded the unpacked partitions to an 16TB disk
* You'll pack the data to 4TB disks using the mining address `En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI`
* You'll use the `replica.2.9` packing format
* You'll use one of the DHA-provided public VDF servers
* You'll use the publicly available NSFW filter provided by Shepherd
* Run your miner with:
  * `sync_jobs 0` to prevent it from trying to sync while you repack
  * each `storage_module` defined twice, once as `unpacked` and once as `En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
* See [Running Your Node](/developers/mining/getting-started/configuration) for more information

## 2. Sample Directory Structure

* Unpacked data mount point: `/mnt/unpacked`
* Mount points for 4TB disks that will store the packed data:
  * `/mnt/a`
  * `/mnt/b`
  * `/mnt/c`
  * `/mnt/d`
* `data_dir`: `/opt/data`
* Storage module symlinks:
  * `/opt/data/storage_modules/storage_module_0_unpacked` -> `/mnt/unpacked/storage_module_0_unpacked`
  * `/opt/data/storage_modules/storage_module_1_unpacked` -> `/mnt/unpacked/storage_module_1_unpacked`
  * `/opt/data/storage_modules/storage_module_2_unpacked` -> `/mnt/unpacked/storage_module_2_unpacked`
  * `/opt/data/storage_modules/storage_module_3_unpacked` -> `/mnt/unpacked/storage_module_3_unpacked`
  * `/opt/data/storage_modules/storage_module_0_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/a/storage_module_0_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_1_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/b/storage_module_1_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_2_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/c/storage_module_2_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_3_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/d/storage_module_3_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`

## 3.Sample Command-line Configuration

```
./bin/start \
    enable randomx_large_pages \
    peer peers.arweave.xyz \
    data_dir /opt/data \
    sync_jobs 0 \
    vdf_server_trusted_peer vdf-server-3.arweave.xyz \
    transaction_blacklist_url https://public_shepherd.arweave.net \
    mining_addr En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI \
    storage_module 0,unpacked \
    storage_module 0,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 1,unpacked \
    storage_module 1,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 2,unpacked \
    storage_module 2,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 \
    storage_module 3,unpacked \
    storage_module 3,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9 
```

4. Sample Configuration File (config.json)

```
{
    "enable": [ "randomx_large_pages" ],
    "peers": [ "peers.arweave.xyz" ],
    "data_dir": "/opt/data",
    "vdf_server_trusted_peers": [ "vdf-server-3.arweave.xyz" ],
    "transaction_blacklist_urls": [ "https://public_shepherd.arweave.net" ],

    "storage_modules": [
        "0,unpacked",
        "0,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "1,unpacked",
        "1,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "2,unpacked",
        "2,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9",
        "3,unpacked",
        "3,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9"
    ],
     
    "mining_addr": "En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI",

    "sync_jobs": 0
}
```


# Repack-in-Place

Example arweave configuration for repacking-in-place

{% hint style="info" %}

* When repacking you do not need a private key - you will only need a mining address (aka packing address)
* Your mining address is **not** a private key - it is a public address
* For the following examples we will alway use `En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI` and `Q5EfKawrRazp11HEDf_NJpxjYMV385j21nlQNjR8_pY` as mining addresses. **Replace them with your own address(es) before running the sample commands.**
  {% endhint %}

## 1. Overview

* You've been solo mining against 4 partitions of packed data
* You want to repack it so you can join a mining pool
* You want to repack in place so you don't need any extra storage capacity
* Your packed data is stored on 4TB disks and is packed using the mining address `En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI`
* You want to repack your data to the mining address `Q5EfKawrRazp11HEDf_NJpxjYMV385j21nlQNjR8_pY`
* You'll use one of the DHA-provided public VDF servers
* You'll use the publicly available NSFW filter provided by Shepherd
* **NOTE** Unlike with the other two repacking processes ("Sync and Pack" and "Cross-Module Repack"), you will **not** need to split up the "Repacking in Place" process into two steps. Entropy generation and repacking will happen in a single step.
* Run your miner with:
  * the special `repack_in_place` syntax for your storage modules
* After the repack in place completes you'll need to rename all your storage module directories
* See [Running Your Node](/developers/mining/getting-started/configuration) for more information

2. Sample Directory Structure

* Mount points for 4TB disks that store your packed data:
  * `/mnt/a`
  * `/mnt/b`
  * `/mnt/c`
  * `/mnt/d`
* `data_dir`: `/opt/data`
* Storage module symlinks:
  * `/opt/data/storage_modules/storage_module_0_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/a`
  * `/opt/data/storage_modules/storage_module_1_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/b`
  * `/opt/data/storage_modules/storage_module_2_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/c`
  * `/opt/data/storage_modules/storage_module_3_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/d`
* Wallets: no wallet.json needed since you are only packing

3. Sample Command-line Configuration

```
./bin/start \
    enable randomx_large_pages \
    peer peers.arweave.xyz \
    data_dir /opt/data \
    sync_jobs 200 \
    vdf_server_trusted_peer vdf-server-3.arweave.xyz \
    transaction_blacklist_url https://public_shepherd.arweave.net \
    mining_addr Q5EfKawrRazp11HEDf_NJpxjYMV385j21nlQNjR8_pY \
    storage_module 0,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9,repack_in_place,Q5EfKawrRazp11HEDf_NJpxjYMV385j21nlQNjR8_pY.replica.2.9 \
    storage_module 1,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9,repack_in_place,Q5EfKawrRazp11HEDf_NJpxjYMV385j21nlQNjR8_pY.replica.2.9 \
    storage_module 2,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9,repack_in_place,Q5EfKawrRazp11HEDf_NJpxjYMV385j21nlQNjR8_pY.replica.2.9 \
    storage_module 3,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9,repack_in_place,Q5EfKawrRazp11HEDf_NJpxjYMV385j21nlQNjR8_pY.replica.2.9 
```

4. Sample Configuration File (config.json)

```
{
    "enable": [ "randomx_large_pages" ],
    "peers": [ "peers.arweave.xyz" ],
    "data_dir": "/opt/data",
    "vdf_server_trusted_peers": [ "vdf-server-3.arweave.xyz" ],
    "transaction_blacklist_urls": [ "https://public_shepherd.arweave.net" ],

    "storage_modules": [
        "0,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9,repack_in_place,Q5EfKawrRazp11HEDf_NJpxjYMV385j21nlQNjR8_pY.replica.2.9",
        "1,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9,repack_in_place,Q5EfKawrRazp11HEDf_NJpxjYMV385j21nlQNjR8_pY.replica.2.9",
        "2,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9,repack_in_place,Q5EfKawrRazp11HEDf_NJpxjYMV385j21nlQNjR8_pY.replica.2.9",
        "3,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9,repack_in_place,Q5EfKawrRazp11HEDf_NJpxjYMV385j21nlQNjR8_pY.replica.2.9"
    ],
     
    "mining_addr": "Q5EfKawrRazp11HEDf_NJpxjYMV385j21nlQNjR8_pY",

    "sync_jobs": 200
  }

```

{% hint style="warning" %}
After repacking in place has completed, stop your node and rename your directories, eg.

```
mv /opt/data/storage_modules/storage_module_0_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZR.replica.2.9 /opt/data/storage_modules/storage_module_0_Q5EfKawrRazp11HEDf_NJpxjYMV385j21nlQNjR8_pY.replica.2.9

mv /opt/data/storage_modules/storage_module_1_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZR.replica.2.9 /opt/data/storage_modules/storage_module_1_Q5EfKawrRazp11HEDf_NJpxjYMV385j21nlQNjR8_pY.replica.2.9

mv /opt/data/storage_modules/storage_module_2_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZR.replica.2.9 /opt/data/storage_modules/storage_module_2_Q5EfKawrRazp11HEDf_NJpxjYMV385j21nlQNjR8_pY.replica.2.9

mv /opt/data/storage_modules/storage_module_3_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZR.replica.2.9 /opt/data/storage_modules/storage_module_3_Q5EfKawrRazp11HEDf_NJpxjYMV385j21nlQNjR8_pY.replica.2.9
```

{% endhint %}


# VDF Server

Example arweave configuration for a VDF server

{% hint style="info" %}

* Since VDF server will not mine or sign any blocks, they do not need access to your wallet.json
  {% endhint %}

## 1. Overview

* You'd like to run a dedicated node to compute and publish VDF
* You are running on an Apple M4 processor (the fastest benchmarked processor as of September, 2025)
* You've decided not to configure any storge modules no have your VDF server mine (this is the most common setup)
* You'll use the publicly available NSFW filter provided by Shepherd
* You only want to provide VDF for the following nodes:
  * `1.2.3.4`
  * `5.6.7.8`
  * `5.6.7.8:1985`
  * `node.example.com`
* Run your miner with:
  * `vdf_client_peer` flags to restrict which nodes can query your server's VDF
  * `vdf hiopt_m4` to enable a VDF algorithm optimized for the M4 processor

## 2. Sample Directory Structure

* `data_dir`: `/opt/data`
* Storage module symlinks: None

## 3. Sample Command-line Configuration

```
./bin/start \
    enable randomx_large_pages \
    peer peers.arweave.xyz \
    data_dir /opt/data \
    transaction_blacklist_url https://public_shepherd.arweave.net \
    vdf hiopt_m4 \
    vdf_client_peer 1.2.3.4 \
    vdf_client_peer 5.6.7.8 \
    vdf_client_peer 5.6.7.8:1985 \
    vdf_client_peer node.example.com
```

## 4. Sample Configuration File (config.json)

```
{
    "enable": [ "randomx_large_pages" ],
    "peers": [ "peers.arweave.xyz" ],
    "data_dir": "/opt/data",
    "transaction_blacklist_urls": [ "https://public_shepherd.arweave.net" ],

    "vdf": "hiopt_m4",

    "vdf_client_peers": [
        "1.2.3.4",
        "5.6.7.8",
        "5.6.7.8:1985",
        "node.example.com"
    ]
}
```


# Coordinated Mining

Example arweave configuration for coordinated mining

{% hint style="info" %}

* When mining your Exit Node needs to have a valid wallet installed - see [Node Wallet](https://github.com/ArweaveTeam/docs.arweave.org-info/blob/master/mining/setup/node-wallet.md)
* For the following examples we will alway use `En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI` or `Q5EfKawrRazp11HEDf_NJpxjYMV385j21nlQNjR8_pY` as mining addresses. **Replace them with your own address(es) before running the sample commands.**
  {% endhint %}

## 1. Overview

* Please review the [Coordinated Mining](/developers/mining/overview/coordinated-mining) guide for more information
* You are running a coordinated mining cluster with the following nodes:
  * Exit Node at IP:PORT 10.0.0.100:1984
  * Worker 1 at IP:PORT 10.0.0.101:1985
  * Worker 2 at IP:PORT 10.0.0.102:1986
* You've downloaded and packed all your data to 16TB disks using the mining address `En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI`
* Each miner has 4 partitions
* You'll use one of the DHA-provided public VDF servers forwarded through your Exit Node
* You'll use the publicly available NSFW filter provided by Shepherd
* See the [Coordinated Mining](/developers/mining/overview/coordinated-mining) guiide and [Running Your Node](/developers/mining/getting-started/configuration) for more information

## 2. Sample Directory Structure

### 2.1 Exit Node Directory Structure

* `data_dir`: `/opt/data`

### 2.2 Worker 1 Directory Strcuture

* Mount point for 16TB disk that will store the packed data:
  * `/mnt/a`
* `data_dir`: `/opt/data`
* Storage module symlinks:
  * `/opt/data/storage_modules/storage_module_0_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/a/storage_module_0_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_1_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/a/storage_module_1_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_2_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/a/storage_module_2_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_3_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/a/storage_module_3_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`

### 2.2 Worker 2 Directory Strcuture

* Mount point for 16TB disk that will store the packed data:
  * `/mnt/b`
* `data_dir`: `/opt/data`
* Storage module symlinks:
  * `/opt/data/storage_modules/storage_module_4_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/b/storage_module_4_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_5_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/b/storage_module_5_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_6_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/b/storage_module_6_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`
  * `/opt/data/storage_modules/storage_module_7_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9` -> `/mnt/b/storage_module_7_En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI.replica.2.9`

## 3.Sample Command-line Configuration

### 3.1 Exit Node Command-line Configuration

```
./bin/start \
    enable randomx_large_pages \
    peer peers.arweave.xyz \
    data_dir /opt/data \
    transaction_blacklist_url https://public_shepherd.arweave.net \
    mining_addr En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE_ZRI \
    coordinated_mining \
    local_peer 10.0.0.101:1985 \
    local_peer 10.0.0.102:1986 \
    cm_peer 10.0.0.101:1985 \
    cm_peer 10.0.0.102:1986 \
    cm_api_secret arweave_is_great_right \
    vdf_server_trusted_peer vdf-server-3.arweave.xyz \
    vdf_server_trusted_peer vdf-server-4.arweave.xyz \
    vdf_client_peer 10.0.0.101:1985 \
    vdf_client_peer 10.0.0.102:1986
```

### 3.2 Worker 1 Command-line Configuration

./bin/start\
enable randomx\_large\_pages\
peer peers.arweave.xyz\
data\_dir /opt/data\
transaction\_blacklist\_url <https://public\\_shepherd.arweave.net\\>
mining\_addr En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE\_ZRI\
port 1985\
coordinated\_mining\
local\_peer 10.0.0.100:1984\
local\_peer 10.0.0.102:1986\
cm\_peer 10.0.0.100:1984\
cm\_peer 10.0.0.102:1986\
cm\_api\_secret arweave\_is\_great\_right\
cm\_exit\_peer 10.0.0.100:1984\
vdf\_server\_trusted\_peer 10.0.0.100:1984\
storage\_module 0,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE\_ZRI.replica.2.9\
storage\_module 1,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE\_ZRI.replica.2.9\
storage\_module 2,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE\_ZRI.replica.2.9\
storage\_module 3,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE\_ZRI.replica.2.9

### 3.3 Worker 2 Command-line Configuration

./bin/start\
enable randomx\_large\_pages\
peer peers.arweave.xyz\
data\_dir /opt/data\
transaction\_blacklist\_url <https://public\\_shepherd.arweave.net\\>
mining\_addr En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE\_ZRI\
port 1986\
coordinated\_mining\
local\_peer 10.0.0.100:1984\
local\_peer 10.0.0.102:1985\
cm\_peer 10.0.0.100:1984\
cm\_peer 10.0.0.102:1985\
cm\_api\_secret arweave\_is\_great\_right\
cm\_exit\_peer 10.0.0.100:1984\
vdf\_server\_trusted\_peer 10.0.0.100:1984\
storage\_module 4,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE\_ZRI.replica.2.9\
storage\_module 5,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE\_ZRI.replica.2.9\
storage\_module 6,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE\_ZRI.replica.2.9\
storage\_module 7,En2eqsVJARnTVOSh723PBXAKGmKgrGSjQ2YIGwE\_ZRI.replica.2.9


# Motivation

## The Vision

Imagine a world where information cannot be lost, censored, or controlled by any single entity. Where creators truly own their content, developers build on a shared data commons, and human knowledge is preserved for generations to come. This is the mission of Arweave — permanent, decentralized data storage that can serve as the foundation for an open internet.

The Arweave promise: pay once, store forever, own it permanently.

## The Ecosystem

The Arweave ecosystem is broader than the base network — it includes gateways (that offer indexing, search, seeding, caching), bundlers (scale uploads), and compute layers like [AO](https://ao.arweave.net/). The Arweave node is a fundamental building block that provides permanence and consensus, while adjacent services provide distribution, discovery, and higher-level UX.

Responsibilities of an Arweave node:

* Cold storage of the ever-growing dataset: persist the blockweave data and indexes; verify and prove access to data over time; prioritize durability and verifiability over raw throughput.
* Estimation of fair upload prices, mining rewards, and endowment contributions: compute a price per GiB-minute, quote upload fees via the HTTP API, split fees between miners and the endowment, and account for storage burden relative to base rewards.
* Accepting and distributing transactions: validate, gossip, and include transactions that transfer tokens and/or upload data; maintain a mempool and participate in block production.
* Optional content policies: operators may subscribe to policy lists or enforce local rules to filter what their node serves in order to meet local regulations. These choices affect serving behavior but do not alter global permanence or consensus.

Responsibilities the Arweave node does **not** take on:

* Data sharing at CDN scale: miners are rewarded for storage, not bandwidth. High-bandwidth distribution is provided by gateways and third-party services.
* Data seeding: the initial spreading of newly uploaded data is the client/uploader’s responsibility. Clients may choose to use a gateway or seed to multiple miners until they believe data is durably replicated.
* Bundling large volumes of data together: packaging many small items into shared on-chain transactions to amortize base costs is performed by external bundling services/tooling, not by the core node.


# Protocol

This document outlines the core architectural components of the Arweave protocol. It is intended for developers and engineers seeking a high-level understanding of how Arweave achieves permanent, decentralized data storage.

## 1. Protocol Design

Arweave is a global network of computers that collectively store multiple copies of all data uploaded to the system.

One of the core tasks of the protocol is to define incentives for storage providers (miners) such that the emergent network behavior meets the following objectives:

* miners allocate the majority of their budget to storage mediums with read throughput of about 5 MB/s and reasonable latency; beyond that, the price should matter more than the drive specs. This also implies it is not beneficial to exchange some of that storage for extra computation;
* miners fill up their allocated drive space with Arweave data evenly (contrasted with replicating the same subset over and over again);
* miners do not accept new data into the Arweave dataset unless the fees cover storage of a sufficient number of replicas so that incidental data loss is extremely improbable over time.

The protocol is designed around two core principles: minimalism (using well-tested cryptographic primitives) and optimization through incentives (incentivizing participants to achieve desirable outcomes rather than prescribing behavior).

To achieve that, the system uses a decentralized consensus mechanism inspired by Proof of Work but adapted for permanent storage. Nodes periodically reach consensus on new data to be added to the ever-growing Arweave dataset (or simply, weave).

Arweave is a blockchain - every state transition is defined by a block (often called a confirmation). Every block serves the dual purpose of accepting new data (in addition to account updates, like in any other cryptocurrency) and validating the storage of previously uploaded data.

## 2. Cryptographic Proofs of Storage

Arweave uses a succinct cryptographic proof system to verify the even replication and accessibility of data. This system is known as Succinct Proofs of Random Access (SPoRA).

To mine a block, a node must prove it has access to historical data. A naive approach would be to require every miner to include all of their data in the block and distribute it across the network to prove it to everyone they actually store this data. The obvious downside of this naive approach is the requirement for huge communication bandwidth.

To address this, we rely on a certain generation-verification asymmetry where we require every block to include only one or two 256 KiB chunks (called "Recall Chunks"). These, however, are picked up randomly (pseudorandomly, to be precise, as the protocol has to be deterministic) from all historical data (every miner always works with whatever data they have synced, but benefits from replicating as much data as possible, evenly).

The miner iterates over the Recall Chunks picked out by the protocol, combines them with some metadata, computes the cryptographic hash of the combined data, and compares the hash with the current network difficulty. If the hash is greater than the network difficulty, the solution is considered valid. See [Understanding Mining](/developers/mining/overview/mining) for more information about the mining process.

## 3. Verifiable Delay Function

Crucially, SPoRA is designed to work in conjunction with the Verifiable Delay Function (VDF). The VDF is a form of cryptographic "speed limit" that limits the number of Recall Chunks that can be considered per second. This limit ensures that mining is bottlenecked by storage volumes rather than pure data retrieval speed. This shift removes the incentive for expensive, high-speed storage (e.g., NVMe SSDs), allowing miners to use cost-effective commodity hard drives while still mining efficiently.

## 4. Replica Uniqueness

To ensure the network is resilient against data loss, Arweave incentivizes the creation of distinct physical copies of data.

The weave is broken down into 3.6 TB segments called "partitions." Every partition is packed using the miner's unique mining address as a seed. This packing process creates a unique representation of the data for that specific miner, and only that specific miner receives a reward from mining with recall chunks from this packed partition.

## 5. The Storage Endowment

Arweave's incentive model requires uploaders of data to pay a small transaction placement fee and provide an upfront contribution, denominated in AR, to the network's storage endowment. This endowment serves as a faucet through which miners are paid out over time, as they collectively provide proofs of replication of the dataset. The necessary payout from the endowment to maintain a piece of data decreases as the cost of storage declines.

## 6. Pricing

The Arweave protocol determines the minimum required fee every transaction should pay at any given time.

Even if a transaction does not upload data (i.e., it only transfers tokens), it is considered a small burden to the network and has to pay a small fee to cover that.

When a transfer is made to an account that does not yet exist in the state, a "new account fee" is charged, as every new account increases the block processing overhead.

If a transaction does upload data, the required upload fee scales with the uploaded volume.

A part of the fee goes directly to the miner including this transaction into a block. Its purpose is to incentivize miners to enlarge the Arweave dataset.

The rest of the fee goes to the endowment.

The Arweave network's endowment removes tokens from circulation every time data is uploaded, creating a reserve to pay for data storage over time. The storage purchasing power of the endowment is elastic, changing with the volume of data committed, the cost of data storage, and token value over time. One of the main drivers of change in the value of the endowment is that a decreasing cost of storage creates a corresponding proportional increase in storage purchasing power, leading to fewer tokens needing to be released from the endowment in the future. We call the rate of decline in overall costs for storing a unit of data for a fixed period of time the Kryder+ rate. This rate incorporates the change in price of hardware, electricity, and operational costs surrounding data storage.

Users pay for 200 years' worth of replicated storage at present prices, such that only a 0.5% Kryder+ rate is sufficient to sustain the endowment for an indefinite term, in the absence of token price changes. Under these conditions, the storage purchasing power of the endowment at the end of each year would be equal to that at the beginning. The actual declining cost of storage over the last 50 years has been, on average, ≈38.5% per year.

To determine how much a single byte costs in AR at any given time, the protocol uses the current network difficulty (as an oracle of the total amount of mining resources currently maintaining the network) and the recent history of operations.

## 7. Decentralized Content Policies

By not enforcing individual miners to store specific data, the Arweave protocol allows the network to support diverse content policies without centralization.

The Arweave network thus employs a disintermediated, layered system of content policies without centralized points of control or moderation. The underlying principle of this system is voluntarism: every participant is able to choose what data they would like to store and serve, without any mandates from the protocol. This system allows each participant in the network to create and operate their own content policy without requiring consensus from others.

The Arweave node software provides a blacklisting system. Each node accepts an optional blacklist containing the identifiers of transactions with unwanted data. The node operator may either maintain a list themselves or subscribe to a service where the node will periodically fetch updates from remote servers.


# Denomination

## When Does Redenomination Occur?

Redenomination is triggered when the available supply (total supply + debt supply - endowment pool) drops below a protocol-defined threshold. This happens as the endowment pool grows to cover long-term storage costs.

Redenomination is not imminent and may never happen. It is a safety mechanism to keep the base unit practical if the endowment pool absorbs a large share of the supply.

When triggered, the redenomination is scheduled 100 blocks (\~200 minutes) in the future. At the scheduled height, each unit becomes 1,000 units in the new denomination and the block `denomination` field increments by 1.

## Use Explicit Denomination in Transactions

Transactions have a single `denomination` field that applies to both the `reward` and `quantity` amounts. We recommend always setting it explicitly rather than leaving it at 0 (implicit/legacy).

* `denomination = 0` — uses the current block's denomination implicitly.
* `denomination >= 1` — explicitly declares the denomination.

When `denomination >= 1`, the value is included in the transaction's signed payload, so a transaction signed with an explicit denomination cannot be reinterpreted at a different denomination after a redenomination event.

To determine the current denomination, read the `denomination` field from the latest block via `GET /block/current`.

In the blocks leading up to a redenomination event (when `height` <= `redenomination_height`), transactions with `denomination = 0` are rejected (see Transition Period below). Services that always set explicit denomination will be unaffected.

## Fee Estimation

Use `/price2/` or `/optimistic_price/` endpoints for fee estimation. They return the denomination alongside the fee:

* `GET /price2/{bytes}` — estimated fee, no new wallet fee
* `GET /price2/{bytes}/{address}` — estimated fee, includes new wallet fee if the address is not in the account tree
* `GET /optimistic_price/{bytes}` — optimistic (lower) fee estimate
* `GET /optimistic_price/{bytes}/{address}` — optimistic fee with new wallet fee check

Response format:

```json
{
  "fee": "5000000",
  "denomination": 1
}
```

Note that `fee` is a JSON string (to preserve precision for large integers) while `denomination` is a JSON number. By contrast, the `denomination` field inside block JSON is a string (e.g. `"1"`).

Use the returned `fee` for the transaction `reward` field and the returned `denomination` for the transaction `denomination` field. The `quantity` field on the same transaction is interpreted in that same denomination.

The legacy `GET /price/{bytes}` endpoints return a plain integer without denomination. Migrate to `/price2/` or `/optimistic_price/`.

## Account Balances

* `GET /wallet/{address}/balance` — current balance as a plain integer, in the current denomination
* `GET /block/height/{height}/wallet/{address}/balance` — balance at a specific height, in that block's denomination

These endpoints do not include denomination in the response. Read the `denomination` field from the corresponding block to interpret the value.

When comparing balances across different block heights, normalize using each block's `denomination` field.

## Transition Period

When redenomination is scheduled, there is a transition window of up to 100 blocks (\~200 minutes) during which transactions with `denomination = 0` are rejected. This prevents ambiguity about which denomination a transaction intends.

* While the current block height is at or below `redenomination_height`, transactions with `denomination = 0` are rejected. The rejection is lifted in the block immediately after `redenomination_height`.
* Transactions with explicit denomination (`1 <= denomination <= current block denomination`) pass the denomination check throughout.

Services that always set explicit denomination experience no disruption.

## Monitoring

Monitor the `redenomination_height` field in block headers via `GET /block/current`, comparing it to the current block's `height`:

* `redenomination_height = 0` — no redenomination has ever been scheduled.
* `redenomination_height > height` — a redenomination is scheduled at that height; \~100 blocks to prepare.
* `redenomination_height > 0` and `redenomination_height <= height` — the redenomination at that height has already taken effect. In theory, multiple redenominations may occur over very long time horizons; each adds 1 to denomination and multiplies amounts by 1,000.


# ECDSA Keys

Arweave supports ECDSA secp256k1 signing keys for blocks and transactions.

ECDSA support was activated at [the 2.9 hard fork](https://github.com/ArweaveTeam/arweave/releases/tag/N.2.9.1).

The key differences between RSA and ECDSA transactions are:

* An ECDSA account can only sign a format=2 transaction.
* The `owner` field must be empty for ECDSA txs.
* The signature preimage is constructed slightly differently - the `owner` is omitted from the recursively hashed list.
* The signature must be a 65-byte **compact recoverable signature** (64 bytes of `r || s` followed by a 1-byte recovery id). The protocol recovers the public key from the signature before validating it.

{% hint style="warning" %}
**Arweave ECDSA addresses are not compatible with Ethereum addresses.** Although Ethereum uses secp256k1 too, its public-key-to-address scheme is different (Keccak-256 of the uncompressed public key, truncated to 20 bytes). Arweave uses the same encoding for RSA and ECDSA accounts: every address is the SHA-256 hash of the public key.

**If you transfer AR to an Ethereum address on Arweave, you will lose the funds.**
{% endhint %}

ECDSA transactions can be used for transferring tokens and uploading data, just like RSA txs.

There is no account delegation mechanism in Arweave.

## Signing and verifying with arweave-js

Native ECDSA support is currently available in `arweave-js` in [a dedicated branch](https://github.com/ArweaveTeam/arweave-js/tree/master-ec).

It is published under the `ec` npm tag:

```bash
npm install arweave@ec
```

You can see how to create and use ECDSA wallets [in the library docs](https://github.com/ArweaveTeam/arweave-js/tree/master-ec#create-wallets-200).

## Mining with ECDSA

Miners can use either RSA or ECDSA keys. ECDSA reward keys produce 65-byte block signatures, much shorter than RSA's 512-byte signatures.

To create a new ECDSA mining wallet, use the `wallet create` subcommand of the Arweave node:

```bash
./bin/arweave wallet create ecdsa [data-dir]
```

Use `rsa` instead of `ecdsa` to create an RSA wallet.

The new keyfile is written to the `wallets/` subdirectory of the node's data directory (`data_dir`), as a standard JWK JSON file named after the resulting Arweave address. On startup, the node automatically picks up keyfiles from `wallets/` and detects the key type from the JWK; no extra configuration is needed to mine with ECDSA.


# Getting Started

For any questions not answered in these documents please visit our [Github Discussions](https://github.com/ArweaveTeam/arweave/discussions)

1. [Clone and Build arweave](/developers/development/build)
2. [Configure your system](/developers/mining/getting-started/os)
3. [Run the automated tests](/developers/development/automated-tests)
4. [Run your node](/developers)


# Building Arweave

## 1. Clone the Repo

```sh
git clone --recursive https://github.com/ArweaveTeam/arweave.git
cd arweave
```

## 2. Install Dependencies

### 2.1 Linux Dependencies

* Ubuntu 22 or 24 is recommended
* OpenSSL development headers
* GCC or Clang (GCC 8+ recommended)
* Erlang OTP v26, with OpenSSL support
* GNU Make
* CMake (CMake version > 3.10.0)
* SQLite3 header
* GNU MP
* On some systems you might need to install `libncurses-dev`.

Erlang R26 is now required. Unfortunately, Ubuntu 22.04 and 24.04 do not natively support Erlang R26 and a PPA repository is required. The RabbitMQ Team is maintaining this release for all Ubuntu version:

```sh
# add rabbitmq ppa repository
sudo add-apt-repository ppa:rabbitmq/rabbitmq-erlang-26
sudo apt update

# install required packages
sudo apt install erlang libssl-dev libgmp-dev libsqlite3-dev make cmake gcc g++
```

### 2.2 MacOS Dependencies

{% hint style="warning" %}
Syncing, packing, and mining is not supported on MacOS. MacOS has only been validated to run a VDF Server. Refer to the [mining VDF guide](https://github.com/ArweaveTeam/docs.arweave.org-info/blob/master/mining/vdf.md) for more information on running your own VDF server.
{% endhint %}

1. Install [Homebrew](https://brew.sh/)
2. Install dependencies

```sh
brew install gmp erlang@26 cmake pkg-config
```

3. Homebrew may ask you to update your `LDFLAGS` for erlang: don't. You should however update your `PATH` as requested.

## 2. Build

The Arweave repo supports several build types, each configured for a different used case. The build types are defined in the [rebar.config](https://github.com/ArweaveTeam/arweave/blob/master/rebar.config)

* `default` / `prod`: configured to run against mainnet. This is the normal build type. `default` and `prod` are aliases for each other.
* `testnet`: configured to run against a separate testnet. Search for `testenet` in the [rebar.config](https://github.com/ArweaveTeam/arweave/blob/master/rebar.config) for more instructions.
* `test`: configured for automated tests. See [Automated Tests](/developers/development/automated-tests) for more information.
* `e2e`: configured for the end-to-end tests. See [Automated Tests](/developers/development/automated-tests) for more information.
* `localnet`: configurd to launch a new chain from genesis. See [Localnet](/developers/development/localnet) for more information.

To build a runnable Arweave binary for given build type:

```sh
./ar-rebar3 BUILDTYPE release
```

e.g.

```sh
./ar-rebar3 default release
./ar-rebar3 prod release
./ar-rebar3 testnet release
```

## 3. Run

For instructions on running arweave see [Running Arweave](/developers).

## 4. Developer Mode

If you set the environment variable `ARWEAVE_DEV` to any value then Arweave will be automatically recompiled whenever you launch. The built type is `release` and only changed artifacts will be rebuilt. You will get the same behavior if you launch Arweave via `./bin/arweave-dev`.


# Automated Tests

### First, a bit of terminology confusion

The bulk of the Arweave tests are written using the [eunit testing framework](https://www.erlang.org/doc/apps/eunit/chapter.html). However **most** of the tests are not true Unit Tests - in fact most are closer to full integration tests (they launch and interact with fully running Arweave nodes). This terminology issue regularly causes frustration and confusion when engineers first encounter the codebse. It is probably best to just consider them integration tests that run within the eunit framework.

### Next, a bit of test methodology debate

Broadly speaking there are 4 types of automated tests:

1. **Unit Tests**: tests which attempt to limit the scope of the code under test as much as possible. These tests often use mocking and dependency injection to limit the amount of dependent code that is invoked while running the test. In their purest form a unit test might test the inputs and outputs of a single function - but larger “units” (e.g. all the functions in a specific module or process) are common.
2. **Integration Tests**: tests which expand the scope of code under test to include multiple interacting units. These tests might also use mocking and dependency injection to restrict which dependent modules are pulled in, but they are explicitly looking to test the behavior of an integrated set of units. The scope of an integration test can include the fully loaded application.
3. **End-to-end Tests:** like integration tests, the scope of end-to-end tests includes the full application stack. What differentiates end-to-end tests from integration tests is often the configuration used: end-to-end tests aim to replicate a real-world or production configuration as much as is possible, while integration tests might limit certain parameters in the interest of improving test performance.
4. **Production Tests**: tests run against the live, Arweave mainnet. These tests make and post real transactions, mine real blocks, and query real data.

Each type of test has its own benefits and shortcomings. The arweave repo has tests of all types and generally it is left to individual engineers to decide what type of test is most helpful for their work.

It is helpful for all engineers to be familiar with the existing test suite - in particular the set of integration test utilities defined in [`ar_test_node`](https://github.com/ArweaveTeam/arweave/blob/master/apps/arweave/test/ar_test_node.erl). There have been attempts in the past to move the test suite off of `eunit`. Either to replace the integration tests with smaller-scoped unit test equivalents or to simply move the integration tests out of the `eunit` framework into a more integration-friendly framework. However to date all of those attempts have eventually fizzled when it came to reproducing the valuable functionality provided by [`ar_test_node`](https://github.com/ArweaveTeam/arweave/blob/master/apps/arweave/test/ar_test_node.erl). Arweave is a complex beast and testing it deterministically can be hard - [`ar_test_node`](https://github.com/ArweaveTeam/arweave/blob/master/apps/arweave/test/ar_test_node.erl) provides a lot of very helpful utilities (e.g. run a node and have it mine a single block, have 2 nodes gossip a single transection, etc…).

Currently @humaite has taken a new, promising approach: he has introduced [Common Test](https://www.erlang.org/doc/apps/common_test/introduction.html) not as a replacement for our existing tests, but as a framework for testing a new erlang app he is adding (the [`arweave_config`](https://github.com/ArweaveTeam/arweave/tree/master/apps/arweave_config) app). As this is a modular entity separate from the core [`arweave`](https://github.com/ArweaveTeam/arweave/tree/master/apps/arweave) app, it is provides a great opportunity for applying a new testing paradigm without having to replicate the functionality of the existing test suite.

As you familiarize yourself with the `eunit` test suite we expect you will have great ideas on how to improve it. This is welcomed and encouraged! We ask only that you spend some time to understand the strengths and weaknesses of the existing suite first as this will help avoid another aborted rewrite.

### Finally, the tests

To run the unit/integration test suite: `./bin/start test`

Of note: the full test run will take a while and, unfortunately, there are several flaky tests, so you may need to run it a few times to get everything to pass. The flakiness and long-runtime of integration tests are two of their biggest shortcomings - however the coverage we get from some of those flaky tests is important for preventing regressions in some critical and hard to manually tests code paths. Addressing the flakiness is a constant priority.

In general engineers will rely on the Github actions that run on PRs to confirm a code change passes the full body of tests. Locally engineers often run a subset of the testsuite as part of their iterative development cycle.

You can run also run a single module of tests: `./bin/start test MODULE_NAME`


# Debugging

### Test Environment

The test environment is set up when running tests (locally via `./bin/test` or `./bin/shell`).

To see some of the macros configured for the test environment see the `test` profile in `rebar.config`.

The majority of macros overridden for the test environment are defined throughout the header files using `-ifdef(AR_TEST).` directives.

Some notable constants overridden for tests:

1. RandomX operations

See `STUB_RANDOMX` set in `rebar.config`, used for defining `ar_mine_randomx.erl` functions.

RandomX is a relatively slow hashing algorithm, which would substantially increase the test runtime unless mocked.

2. VDF computation

See `INITIAL_VDF_DIFFICULTY` set in `rebar.config`, used in `ar.hrl` to define the default values for VDF difficulty fields of the `#nonce_limiter_info` record (`nonce limiter` is another name for `VDF` used in some parts of the codebase).

Computing every VDF step takes approximately one second on the mainnet which is too long for tests.

VDF computation controls the mining pace, which we do not want to be too fast either so we add a simple test implementation of `ar_vdf:compute2/3` where we introduce explicit short sleeps to define the mining pace.

3. VDF difficulty retarget

See `VDF_DIFFICULTY_RETARGET` in `rebar.config`, used in `ar_block:compute_next_vdf_difficulty/1`.

VDF difficulty update happens every 1200 steps on mainnet (approx 1200 seconds) that is too long for tests so we make it much lower.

4. Block Trail

See `STORE_BLOCKS_BEHIND_CURRENT` in `ar.hrl`.

This constant defines the number of blocks downloaded when joining the network (`ar_join.erl` downloads `2 * ar_block:get_max_tx_anchor_depth()` blocks, and the anchor depth is determined by this constant). In production, it is set to 50 blocks, but in tests, it is overridden to 10 blocks.

### Debugging Tests

Execute `./bin/shell` to launch test nodes and open an Erlang shell with a test environment.

The script launches 5 test nodes including the one the shell is attached to - this is the "main" node. The other 4 nodes are named `peer1`, `peer2`, `peer3`, and `peer4`.

You can run individual tests:

```sh
eunit:test(ar_fork_recovery_tests:height_plus_one_fork_recovery_test_()).
```

If they fail, all the nodes stay up and you can inspect them to troubleshoot.

Below we walk you through a number of common scenarios and interfaces.

**Launching Arweave**

Note that at launch, test nodes do not have a fully initialized Arweave state. The simplest way to start an Arweave node is to run `ar_test_node:start/0`.

```sh
(main-localtest@127.0.0.1)1> ar_test_node:start().
ok
```

Under the hood, it creates a new account and a genesis block with a single transaction uploading 3 256 KiB chunks of data and initializes the Arweave node with it.

**Managing Nodes**

The shell is attached to the main node. To execute code on other nodes, we need to make Erlang RPC calls - `ar_test_node:remote_call/4` is a convenient wrapper for this. Let's launch Arweave on `peer1`:

```sh
(main-localtest@127.0.0.1)4> ar_test_node:remote_call(peer1, ar_test_node, start, []).
ok
```

**Health Check**

Note that we have initialized two nodes on two different genesis blocks. This is not a very interesting setup.

The node is configured with a new TCP port every time, use `ar_test_node:peer_port/1` to learn it.

```sh
(main-localtest@127.0.0.1)5> ar_test_node:peer_port(main).
65494
(main-localtest@127.0.0.1)6> ar_test_node:peer_port(peer1).
65498
```

```sh
$ curl localhost:65494
{"version":5,"release":89,"queue_length":0,"peers":0,"node_state_latency":2,"network":"arweave.localtest","height":0,"current":"DE2MpboqbBWRiRH4wj2_afFE71YHToXeVJzs40ONzUwLX4Pkp0Uhdlo2WyXe08h7","blocks":1}

$ curl localhost:65498
{"version":5,"release":89,"queue_length":0,"peers":0,"node_state_latency":5,"network":"arweave.localtest","height":0,"current":"7djulC-ju_6fFTywjAJoiwCGwpBhbbnmbpTxQrAhnkL1f0mNzByFxeI4tx-BiIDB","blocks":1}
```

The `"current"` field stores the hash of the tip block - we can see the nodes are initialized with different blocks.

**Joining the Network**

Instead, we want them to be in the same network. We can use `ar_test_node:join_on/1` to make one node join the network from the other. This is what usually happens on mainnet when we run `./bin/start peer ...`

```sh
(main-localtest@127.0.0.1)10> ar_test_node:join_on(#{ node => peer1, join_on => main }).
<32196.12327.0>
```

We can use `ar_node:get_current_block()` to fetch the tip now.

```sh
(main-localtest@127.0.0.1)8> B0_main = ar_node:get_current_block().
#block{nonce = 0,previous_block = <<>>,
       ...}
(main-localtest@127.0.0.1)9> B0_peer1 = ar_test_node:remote_call(peer1, ar_node, get_current_block, []).
#block{nonce = 0,previous_block = <<>>,
       ...}
(main-localtest@127.0.0.1)10> rr(ar).
[block,block_announcement,block_announcement_response,
 chunk_metadata,chunk_offsets,config,config_webhook,
 nonce_limiter_info,nonce_limiter_update,
 nonce_limiter_update_response,p3_account,p3_config,
 p3_payment,p3_service,p3_transaction,poa,sample_report,tx,
 vdf_session,verify_report]
(main-localtest@127.0.0.1)11> B0_main#block.indep_hash == B0_peer1#block.indep_hash.
true
```

**Using Records in Shell**

Note we called `rr(ar).` to be able to use records defined in `ar.hrl` in the shell - in this case, the `#block` record.

**Mining**

Test nodes do not start mining when launched. To mine a block, run:

```sh
(main-localtest@127.0.0.1)3> ar_test_node:mine().
ok
```

It may be convenient to use the `ar_http_iface_client` module to query the HTTP API from the shell. Usually its methods accept a `Peer` argument which is a `{IP0, IP1, IP2, IP3, Port}` tuple - you can learn via `ar_test_node:peer_ip/1`:

```sh
(main-localtest@127.0.0.1)13> Peer = ar_test_node:peer_ip(main).
{127,0,0,1,65494}
(main-localtest@127.0.0.1)14> ar_http_iface_client:get_info(Peer).
#{<<"blocks">> => 2,
  <<"current">> =>
      <<"z9353ReVppPAWplYmoZyQNaPbdbVcpgBp9CO2nBKpk3HYv3HtuZJUrdpXKeDk0k0">>,
  <<"height">> => 1,<<"network">> => <<"arweave.localtest">>,
  <<"node_state_latency">> => 6,<<"peers">> => 1,
  <<"queue_length">> => 0,<<"release">> => 89,
  <<"version">> => 5}
```

We can see the height has advanced by one because the node has mined a block.

**Downloading Blocks by Hash**

Let's take the current tip and download the block:

```sh
H = ar_util:decode(<<"z9353ReVppPAWplYmoZyQNaPbdbVcpgBp9CO2nBKpk3HYv3HtuZJUrdpXKeDk0k0">>).
<<207,221,249,221,23,149,166,147,192,90,153,88,154,134,
  114,64,214,143,109,214,213,114,152,1,167,208,142,218,
  112,...>>
```

`ar_util:decode` converts Base64Url to the raw binary representation Arweave uses internally.

Now let's retrieve the block:

```sh
(main-localtest@127.0.0.1)18> {Peer, B, _, _} = ar_http_iface_client:get_block_shadow([Peer], H).
{{127,0,0,1,65494},
 #block{nonce = 3,
        ...},
 11207,673236}
```

It is called `get_block_shadow` because it only downloads the block header and `#block.txs` contains a list of transaction identifiers instead of `#tx` records.

The function may search several peers. It returns the peer it downloaded the block from as the first element of the returned tuple.

**Inspecting Node Configuration**

Let's get the node's configuration.

```sh
(main-localtest@127.0.0.1)27> {ok, Config} = arweave_config:get_env().
{ok,#config{...}}
```

**Storage Modules**

Let's see which storage modules are configured:

```sh
(main-localtest@127.0.0.1)28> Config#config.storage_modules.
[{20000000,0,
  {replica_2_9,<<117,193,95,178,157,29,21,233,22,64,184,
                 84,91,31,60,250,232,5,154,148,129,115,
                 110,...>>}},
  ...
```

Each storage module stores a particular range of the Arweave dataset. The structure has the format `{Size, Number, Packing}` where `Size` denotes the size in bytes of the stored range, `Number` tells which block of size `Size` inside the weave is stored, counting from 0, and `Packing` signifies how the data will be packed before being stored in this storage module.

For example, the first storage module we see in the snippet above is responsible for storing the first 20 MB of the weave and uses replica 2.9 packing - the go-to packing for miners since Arweave 2.9.

Each storage module is assigned a dedicated folder. For every configured storage module, the node runs an `ar_data_sync` process (that manages various data pipelines) and an `ar_sync_record` process (that maintains in-memory records of currently synced data intervals and persists them on disk).

Storage module identifiers (`StoreID`s) are used to refer to a particular storage module:

```sh
(main-localtest@127.0.0.1)29> StoreID = ar_storage_module:id(hd(Config#config.storage_modules)).
"storage_module_20000000_0_dcFfsp0dFekWQLhUWx88-ugFmpSBc27uYPzr-NM014w.replica.2.9"
```

**Sync Record**

For example, we can query the data intervals stored by the module. We call these intervals "sync records".

```sh
(main-localtest@127.0.0.1)32> ar_sync_record:get(ar_data_sync, StoreID).
{1,{{786432,0},nil,nil}}
```

The `{786432, 0}` interval contains the first three 256 KiB chunks of the weave. The module is configured to store the first 20 MB of the weave, but our dataset only contains 3 chunks initialized in `ar_test_node:start/0`.

The structure returned by `ar_sync_record:get/2` is defined in the `ar_intervals.erl` module. It manages a sorted list of non-intersecting and non-contiguous intervals. Each interval is encoded as an `{EndOffset, StartOffset}` tuple where `EndOffset` is strictly greater than StartOffset.

**Accessing Metrics**

Another way to get an insight into the data stored on the node is to look at the metrics reported by the node - simply call the `GET /metrics` endpoint. Metrics are defined in `ar_metrics.erl`.

One of the most informative metrics is `v2_index_data_size_by_packing`:

```sh
v2_index_data_size_by_packing{store_id="storage_module_0_replica_2_9_1",packing="replica_2_9_1",partition_number="0",storage_module_size="2000000",storage_module_index="0",packing_difficulty="2"} 786432
```

`partition_number` is the 0-based number of the 3.6 TB partition of the dataset. `store_id` and `packing` are anonymised because node operators may not want to expose their account addresses.

**Setting up a Custom Genesis Block**

Instead of using the default genesis block, let's create our own with a custom wallet and storage configuration.

**Creating Wallets**

First, create an ECDSA wallet:

```sh
(main-localtest@127.0.0.1)33> {Priv, Pub} = ar_wallet:new_newkeyfile({ecdsa, secp256k1}).
{{{ecdsa,secp256k1},
  <<216,42,124,81,110,157,100,144,194,61,212,34,181,250,119,
    16,67,143,52,157,9,246,163,177,150,152,...>>,
  <<2,178,161,147,183,230,107,24,250,201,149,17,249,103,15,
    30,120,106,42,8,113,118,16,44,78,...>>},
 {{ecdsa,secp256k1},
  <<2,178,161,147,183,230,107,24,250,201,149,17,249,103,
    15,30,120,106,42,8,113,118,16,44,78,...>>}}
```

Note that we use `ar_wallet:new_keyfile/1` and not `ar_wallet:new/1` because the former does not only generate a new key, but also stores it on disk - the node loads it when it signs mined blocks.

Get the wallet address:

```sh
(main-localtest@127.0.0.1)34> Addr = ar_wallet:to_address(Pub).
<<168,91,62,65,253,161,125,236,107,245,195,213,227,180,
  107,100,182,59,242,8,138,225,96,222,22,23,102,188,231,
  ...>>
(main-localtest@127.0.0.1)35> ar_util:encode(Addr).
<<"qFs-Qf2hfexr9cPV47RrZLY78giK4WDeFhdmvOcg4bk">>
```

**Providing Initial Balance**

Now initialize a genesis block with our wallet funded with 1 million AR:

```sh
(main-localtest@127.0.0.1)36>[B0] = ar_weave:init([{Addr, 100_000_000_000_000_000_000, <<>>}]).
[#block{nonce = 0,previous_block = <<>>, ...]
```

1 AR equals `1_000_000_000_000` (10^12) Winston.

Note: in the test environment, transaction fees are typically very large. This is because the network is small, so the pricing algorithm considers the token to be very cheap and sets high fees accordingly. When testing scenarios that involve uploading data, it makes sense to start the weave with a large balance so that tests can afford to post transactions.

Now let's configure a storage module for bytes 0 to `4_000_000` with `replica_2_9` packing:

```sh
(main-localtest@127.0.0.1)38> StorageModule = {4_000_000, 0, {replica_2_9, Addr}}.
{4000000,0,
 {replica_2_9,<<168,91,62,65,253,161,125,236,107,245,195,
                213,227,180,107,100,182,59,242,8,138,225,
                96,222,...>>}}
```

Start the node with our custom genesis block and storage module:

```sh
(main-localtest@127.0.0.1)26> ar_test_node:start(#{ b0 => B0, addr => Addr, storage_modules => [StorageModule] }).
ok
```

```sh
(main-localtest@127.0.0.1)52> f(Config), {ok, Config} = arweave_config:get_env().
...
(main-localtest@127.0.0.1)53> Config#config.storage_modules.
[{4000000,0,
  {replica_2_9,<<168,91,62,65,253,161,125,236,107,245,
                 195,213,227,180,107,100,182,59,242,8,
                 138,225,96,...>>}}]
```

```sh
(main-localtest@127.0.0.1)54> Config#config.mining_addr == Addr.
true
```

Let's also bring `peer1` into this new network:

```sh
(main-localtest@127.0.0.1)72> ar_test_node:join_on(#{ node => peer1, join_on => main }).
<32196.405860.0>
```

**Checking Account Balance**

```sh
(main-localtest@127.0.0.1)55> ar_node:get_balance(Addr).
100000000000000000
```

Via HTTP API:

```sh
$ curl localhost:65494/wallet/qFs-Qf2hfexr9cPV47RrZLY78giK4WDeFhdmvOcg4bk/balance
```

**Sending Transactions**

Let's use our account now. We'll send 1 Winston to a random address:

```sh
(main-localtest@127.0.0.1)27> RandomAddr = crypto:strong_rand_bytes(32).
<<...>>
(main-localtest@127.0.0.1)28> TX = ar_test_node:sign_tx({Priv, Pub}, #{ target => RandomAddr, quantity => 1 }).
#tx{...}
```

The `ar_test_node:sign_tx/2` function is a convenient helper that:

1. Fetches a block hash to use as an anchor (via `ar_test_node:get_tx_anchor/1`, which queries `GET /tx_anchor`)
2. Estimates the transaction fee (via `GET /price/{data_size}` or `GET /price/{data_size}/{target}` if a target is specified)
3. Signs the transaction

Now let's post the transaction:

```sh
(main-localtest@127.0.0.1)74> ar_test_node:assert_post_tx_to_peer(main, TX).
{ok,{{<<"200">>,<<"OK">>},
     [{<<"access-control-allow-origin">>,<<"*">>},
      {<<"content-length">>,<<"2">>},
      {<<"date">>,<<"Thu, 20 Nov 2025 16:08:44 GMT">>},
      {<<"server">>,<<"Cowboy">>}],
     <<"OK">>,1763654925536197,1763654925542633}}
```

**Accessing Mempool**

Check the mempool:

```sh
(main-localtest@127.0.0.1)79> {{ok, TXIDs}, Peer} = ar_http_iface_client:get_mempool(Peer).
{{ok,[<<5,101,215,33,72,80,41,200,124,225,226,92,152,
        189,41,77,92,128,24,125,234,8,120,146,134,...>>]},
 {127,0,0,1,65494}}
```

`peer1` has learned about the transaction as well:

```sh
(main-localtest@127.0.0.1)85> Peer1 = ar_test_node:peer_ip(peer1).
{127,0,0,1,65498}
(main-localtest@127.0.0.1)86> {{ok, TXIDs}, Peer1} = ar_http_iface_client:get_mempool(Peer1).
{{ok,[<<5,101,215,33,72,80,41,200,124,225,226,92,152,
        189,41,77,92,128,24,125,234,8,120,146,134,...>>]},
 {127,0,0,1,65498}}
```

In the API:

```sh
$ curl localhost:65494/tx/pending
["BWXXIUhQKch84eJcmL0pTVyAGH3qCHiShmCj-XmKiXg"]
```

```sh
$ curl localhost:65494/tx/BWXXIUhQKch84eJcmL0pTVyAGH3qCHiShmCj-XmKiXg
Pending
```

Check the balances before mining:

```sh
(main-localtest@127.0.0.1)88> ar_node:get_balance(Addr).
100000000000000000
(main-localtest@127.0.0.1)89> ar_node:get_balance(RandomAddr).
0
```

Mine a block:

```sh
(main-localtest@127.0.0.1)34> ar_test_node:mine().
ok
```

Check the mempool again - it should be empty:

```sh
(main-localtest@127.0.0.1)35> ar_http_iface_client:get_pending_txs(Peer).
{{ok,[]},...}
```

Check the balances after mining:

```sh
(main-localtest@127.0.0.1)36> ar_node:get_balance(Addr).
99999999984017435209
(main-localtest@127.0.0.1)37> ar_node:get_balance(RandomAddr).
1
```

The sending address balance decreased by 1 Winston plus the transaction fee, and the receiving address now has 1 Winston.

```sh
(main-localtest@127.0.0.1)15> TX#tx.reward + 1 + 99999999984017435209 == 100_000_000_000_000_000_000.
true
```

**Fetching Chunks**

Before we upload some data, let's look at the chunks already stored in the weave with the genesis block.

```sh
(main-localtest@127.0.0.1)20> ar_data_sync:get_chunk(1, #{ packing => {replica_2_9, Addr}, pack => false }).
{ok,#{chunk_size => 262144,
      chunk =>
          <<168,206,204,22,200,228,55,147,83,129,156,249,149,203,
            143,232,174,186,53,78,14,246,86,144,82,183,...>>,
      tx_path =>
          <<178,38,127,31,158,128,18,154,171,176,133,55,132,229,12,
            114,191,30,110,149,22,208,26,54,115,217,...>>,
      data_path =>
          <<176,23,135,208,212,216,170,39,43,114,112,84,231,252,128,
            75,81,177,146,250,114,67,110,148,94,5,...>>,
      tx_root =>
          <<226,165,118,182,96,174,176,60,3,148,166,87,181,193,186,
            235,27,177,52,205,226,225,234,6,85,243,...>>,
      absolute_end_offset => 262144}}
```

The first argument `ar_data_sync:get_chunk/2` accepts is an offset. This offset is strictly greater than the chunk's start offset (where it begins in the weave) and less than or equal to the chunk's end offset. Therefore, the following call fetches the same chunk:

```sh
(main-localtest@127.0.0.1)20> ar_data_sync:get_chunk(262144, #{ packing => {replica_2_9, Addr}, pack => false }).
{ok,#{chunk_size => 262144,
      chunk =>
          <<168,206,204,22,200,228,55,147,83,129,156,249,149,203,
            143,232,174,186,53,78,14,246,86,144,82,183,...>>,
      tx_path =>
          <<178,38,127,31,158,128,18,154,171,176,133,55,132,229,12,
            114,191,30,110,149,22,208,26,54,115,217,...>>,
      data_path =>
          <<176,23,135,208,212,216,170,39,43,114,112,84,231,252,128,
            75,81,177,146,250,114,67,110,148,94,5,...>>,
      tx_root =>
          <<226,165,118,182,96,174,176,60,3,148,166,87,181,193,186,
            235,27,177,52,205,226,225,234,6,85,243,...>>,
      absolute_end_offset => 262144}}
```

Add 1 to the offset, and we get a new chunk:

```sh
(main-localtest@127.0.0.1)22> ar_data_sync:get_chunk(262144 + 1, #{ packing => {replica_2_9, Addr}, pack => false }).
{ok,#{chunk_size => 262144,
      chunk =>
          <<133,232,24,98,34,222,100,193,62,117,143,4,5,220,35,94,
            64,221,26,181,83,99,238,190,89,136,...>>,
      tx_path =>
          <<178,38,127,31,158,128,18,154,171,176,133,55,132,229,12,
            114,191,30,110,149,22,208,26,54,115,217,...>>,
      data_path =>
          <<176,23,135,208,212,216,170,39,43,114,112,84,231,252,128,
            75,81,177,146,250,114,67,110,148,94,5,...>>,
      tx_root =>
          <<226,165,118,182,96,174,176,60,3,148,166,87,181,193,186,
            235,27,177,52,205,226,225,234,6,85,243,...>>,
      absolute_end_offset => 524288}}
```

`pack => false` tells the function not to repack the chunk in case it is not stored in the desired packing.

```sh
(main-localtest@127.0.0.1)23> ar_data_sync:get_chunk(262144 + 1, #{ packing => unpacked, pack => false }).
{error,chunk_not_found}
```

However, we can ask to pack it for us:

```sh
(main-localtest@127.0.0.1)24> ar_data_sync:get_chunk(262144 + 1, #{ packing => unpacked, pack => true }).
{ok,#{chunk_size => 262144,
      chunk =>
          <<0,1,0,0,0,1,0,1,0,1,0,2,0,1,0,3,0,1,0,4,0,1,0,5,0,1,...>>,
      tx_path =>
          <<178,38,127,31,158,128,18,154,171,176,133,55,132,229,12,
            114,191,30,110,149,22,208,26,54,115,217,...>>,
      data_path =>
          <<176,23,135,208,212,216,170,39,43,114,112,84,231,252,128,
            75,81,177,146,250,114,67,110,148,94,5,...>>,
      unpacked_chunk =>
          <<0,1,0,0,0,1,0,1,0,1,0,2,0,1,0,3,0,1,0,4,0,1,0,5,0,1,...>>,
      tx_root =>
          <<226,165,118,182,96,174,176,60,3,148,166,87,181,193,186,
            235,27,177,52,205,226,225,234,6,85,243,...>>,
      absolute_end_offset => 524288}}
```

**Uploading Data**

Let's create a transaction to upload 2 MiB of data:

```sh
(main-localtest@127.0.0.1)45> Data = crypto:strong_rand_bytes(2 * 1024 * 1024).
<<...>>
(main-localtest@127.0.0.1)46> DataTX = ar_test_node:sign_tx({Priv, Pub}, #{ data => Data }).
#tx{...}
```

Post the transaction:

```sh
(main-localtest@127.0.0.1)28> ar_test_node:assert_post_tx_to_peer(main, DataTX).
{ok,{{<<"200">>,<<"OK">>},
     [{<<"access-control-allow-origin">>,<<"*">>},
      {<<"content-length">>,<<"2">>},
      {<<"date">>,<<"Thu, 20 Nov 2025 16:41:06 GMT">>},
      {<<"server">>,<<"Cowboy">>}],
     <<"OK">>,1763656867804420,1763656867833993}}
```

Mine a block to include the transaction:

```sh
(main-localtest@127.0.0.1)48> ar_test_node:mine().
ok
```

**Disk Pool**

Let's take a look at the metrics:

```sh
v2_index_data_size_by_packing{store_id="storage_module_4000000_0_replica_2_9_1",packing="replica_2_9_1",partition_number="0",storage_module_size="4000000",storage_module_index="0",packing_difficulty="2"} 786432
v2_index_data_size_by_packing{store_id="default",packing="unpacked",partition_number="undefined",storage_module_size="undefined",storage_module_index="undefined",packing_difficulty="0"} 2097152
```

The data has been uploaded to the "default" storage module. The default storage module runs even when no storage modules are configured, its main purpose is to cache and distribute data uploaded by clients via `POST /chunk` or attached to transactions using the "data" field. Once some data receives a sufficient number of confirmations (blocks on top), it is either moved to the storage modules covering the corresponding range, if any, or deleted.

Let's mine two more blocks and watch the new data moved to the configured storage module.

```sh
(main-localtest@127.0.0.1)40> ar_test_node:mine().
ok
```

Make sure a new block has been mined and applied:

```sh
(main-localtest@127.0.0.1)44> ar_test_node:assert_wait_until_height(main, 3).
[{<<162,161,197,227,251,60,20,83,168,182,229,45,44,222,
```

```sh
(main-localtest@127.0.0.1)40> ar_test_node:mine().
ok
```

```sh
(main-localtest@127.0.0.1)44> ar_test_node:assert_wait_until_height(main, 4).
[{<<162,161,197,227,251,60,20,83,168,182,229,45,44,222,
```

Now query metrics:

```sh
v2_index_data_size_by_packing{store_id="storage_module_4000000_0_replica_2_9_1",packing="replica_2_9_1",partition_number="0",storage_module_size="4000000",storage_module_index="0",packing_difficulty="2"} 2883584
v2_index_data_size_by_packing{store_id="default",packing="unpacked",partition_number="undefined",storage_module_size="undefined",storage_module_index="undefined",packing_difficulty="0"} 0
```

**Disk Pool Threshold**

There is a special function for getting the current byte threshold separating the disk pool from confirmed data:

```sh
(main-localtest@127.0.0.1)45> ar_data_sync:get_disk_pool_threshold().
2883584
```

The disk pool threshold is the weave size at the `?SEARCH_SPACE_UPPER_BOUND_DEPTH`s block counting from the tip. It is defined in `ar_consensus.hrl` and is set to 3 in the test environment and 50 on mainnet.

**Inspecting Sync Records After Upload**

Fetch the updated sync records:

```sh
(main-localtest@127.0.0.1)15> ar_sync_record:get(ar_data_sync, StoreID).
{1,{{2883584,0},nil,nil}}
```

The sync record now shows bytes 1 through 2883584 are synced (the original 768 KiB plus the 2 MiB we just uploaded).

Note that the `GET /data_sync_record` endpoint (the one `ar_http_iface_client:get_sync_record/1` queries) does not serve these intervals anymore.

```sh
(main-localtest@127.0.0.1)56> ar_http_iface_client:get_sync_record(Peer).
{ok,{0,nil}}
```

This is because the so-called "global" sync record, which aggregates sync records from all storage modules, excludes 2.9 data. Our node is configured only with `replica_2_9` data now.

See `ar_global_sync_record.erl` for the implementation details.

2.9 data is excluded to make syncing more efficient. When a node syncs data, it queries its peers for synced intervals calling `GET /data_sync_record/{Start}/{End}/{Limit}` and then syncs the missing ranges chunk by chunk. Syncing 2.9 data this way is not efficient because 2.9 packing generates entropy (what takes substantial amount of time/computing resources) which is by design shared across chunks spread out across the entire 3.6 TB partition (2 MB partition in tests). That's why syncing it chunk by chunk will cause redundant entropy generation and waste resources. Instead, to look for 2.9 data, the nodes query the `GET /footprint/{partition}/{footprint}` endpoint to query data "footprint" by "footprint" where each footprint is a collection of chunks sharing the entropy as defined by the protocol.

**Footprint Records**

To fetch footprint records, use `ar_footprint_record:get_intervals/3`:

```sh
(main-localtest@127.0.0.1)59> FootprintIntervals = ar_footprint_record:get_intervals(0, 0, StoreID).
...
```

Footprint intervals have the same form as normal intervals but different semantics. Adjacent chunks in the footprint record are not adjacent in the weave. Also, the footprint record stores 256 KiB-bucket numbers instead of byte offsets.

To convert footprint intervals to normal byte-range intervals:

```sh
(main-localtest@127.0.0.1)60> ar_footprint_record:get_intervals_from_footprint_intervals(FootprintIntervals).
...
```

### End-to-end tests

End-to-end (e2e) tests are heavy tests run in an environment close to production. They do not mock RandomX and VDF functions. We do not run them as part of the CI.

Run `./bin/e2e` to execute all e2e tests. You can run individual modules via `./bin/e2e ar_sync_pack_mine_tests`, `./bin/e2e ar_repack_in_place_mine_tests`, and `./bin/e2e ar_repack_mine_tests.erl`.

To run a debug shell in the e2e environment, run `./bin/e2e_shell` and wait until the console reports that `peer2` has started (it will take some time).


# Running You Own Localnet

To start a new weave, create a new data directory

```sh
mkdir -p localnet_data_dir
```

, create a wallet:

```sh
./bin/create-wallet localnet_data_dir
```

, and run:

```sh
$ ./bin/start-localnet init data_dir <your-data-dir> mining_addr <your-mining-addr>
storage_module 0,<your-mining-addr> mine
```

The given address (if none is specified, one will be generated for you) will be assigned `1_000_000_000_000` AR in the new weave.

The network name will be `arweave.localnet`. You can not start the same node again with the init option unless you clean the data directory - you need to either restart with the `start_from_block_index` option or specify a peer from the same Arweave network via `peer <peer>`. Note that the state is only persisted every 50 blocks so if you restart the node without peers via `start_from_block_index` before reaching the height 50, it will go back to the genesis block.

As with mainnet peers, each peer must be run in its own physical or virtual environment (e.g. on its own machine or in its own container or virtual machine). If you try to run two nodes within the same environment you will get an error like `Protocol 'inet_tcp': the name arweave@127.0.0.1 seems to be in use by another Erlang node`

When POST'ing transactions to your localnet make sure to include the `X-Network: arweave.localnet` header. If the header is omitted, the mainnet network will be assumed and the request will fail.

## Configuring localnet

See the `localnet` section in [rebar.config](https://github.com/ArweaveTeam/arweave/blob/master/rebar.config) for instructions on changing network constants for your localnet.


# HTTP API

An overview of the Arweave HTTP API.

The Arweave protocol is based on HTTP, so any existing http clients/libraries can be used to interface with the network, for example Axios or Fetch for JavaScript, Guzzle for PHP, etc.

The default port is **1984**.

Requests and queries can be sent to any Arweave node directly using their IP address, for example <http://159.65.213.43:1984/info>. Hostnames can also be used if configured with DNS, for example <https://arweave.net/info>.

## Sample Request

{% tabs %}
{% tab title="cURL" %}

```bash
curl --request GET \
  --url 'https://arweave.net/info'
```

{% endtab %}

{% tab title="JavaScript (Fetch)" %}

```js
fetch("https://arweave.net/info")
  .then((response) => response.json())
  .then((data) => {
    console.log("Arweave network height is: " + data.height);
  })
  .catch((error) => {
    console.error(error);
  });
```

{% endtab %}

{% tab title="NodeJS" %}

```js
let request = require("request");

let options = {
  method: "GET",
  url: "https://arweave.net/info",
};

request(options, function (error, response, body) {
  if (error) {
    console.error(error);
  }
  console.log("Arweave network height is: " + JSON.parse(body).height);
});
```

{% endtab %}
{% endtabs %}

## Integrations

Arweave specific wrappers and clients are currently in development to simplify common operations and API interactions, there are currently integrations for [Go](https://github.com/everFinance/goar), [PHP](https://github.com/ArweaveTeam/arweave-php), [Scala](https://github.com/toknapp/arweave4s) (which can also be used with Java and C#) and [JavaScript/TypeScript/NodeJS](https://github.com/ArweaveTeam/arweave-js).

## Schema

Common data structures, formats, and processes explained.

## Block Format

{% tabs %}
{% tab title="block height < 269510" %}

```json
{
  "nonce": "AAEBAAABAQAAAQAAAQEBAAEAAAABAQABAQABAAEAAAEBAAAAAQAAAAAAAQAAAQEBAAEBAAEBAQEBAQEAAQEBAAABAQEAAQAAAQABAAABAAAAAAEBAQEBAAABAQEAAAAAAAABAQAAAQAAAQEAAQABAQABAQEAAAABAAABAQABAQEAAAEBAQABAQEBAQEBAAABAQEAAAABAQABAAABAAEAAQEBAQAAAAABAQABAQAAAAAAAAABAQABAAEBAAEAAQABAQABAAEBAQEBAAEAAQABAAABAQEBAQAAAQABAQEBAAEBAQAAAQEBAQABAAEBAQEBAAAAAAABAAEAAAEAAAEAAAEBAAAAAAEAAQABAAAAAAABAQABAQAAAAEBAQAAAAABAAABAAEBAQEAAAAAAQAAAQABAQABAAEAAQABAQAAAAEBAQAAAQAAAAEBAAEBAAEBAQEAAAEBAQAAAQAAAAABAAEAAQEAAQ",
  "previous_block": "V6YjG8G3he0JIIwRtzTccX39rS0jH-jOqUJy6rxrVAHY0RT0AVhG8K22wCDxy1A0",
  "timestamp": 1528500720,
  "last_retarget": 1528500720,
  "diff": 31,
  "height": 100,
  "hash": "AAAAANsEvzGbICpfAj3NN41_ox--2cNxkEhAo0aggpDPkY7zru29g24uMWUP9hTa",
  "indep_hash": "",
  "txs": ["7BoxcxiJIjTwUp3JXp0xRJQXf6hZtyJj1kjGNiEl5A8"],
  "wallet_list": "ph2FDDuQjNbca34tz7vP9X5Xve2EGJi2ZgFqhMITAdw",
  "reward_addr": "em8MfGRInwWEAQnE6b50ENaFOf-0to4Pbygng1ilWGQ",
  "tags": [],
  "reward_pool": 60770606104,
  "weave_size": 599058,
  "block_size": 0
}
```

{% endtab %}

{% tab title="block height >= 269510, < 422250" %}

```json
{
  "nonce": "O3IQWXYmxLN_b0w7QyT2GTruaVIGsl-Ybhc6Pl2V20U",
  "previous_block": "VRVYubqppWUVAeCWlzHR-38dQoWcFAKbGculkVZThfj-hNMX4QVZjqkC6-PkiNGE",
  "timestamp": 1567052949,
  "last_retarget": 1567052114,
  "diff": "115792088374597902074750511579343425068641803109251942518159264612597601665024",
  "height": 269512,
  "hash": "____47liyh_OZdYUP4EzBoLl7JOPge9VsWPQ3b5kiU8",
  "indep_hash": "5H-hJycMS_PnPOpobXu2CNobRlgqmw4yEMQSc5LeBfS7We63l8HjS-Ek3QaxK8ug",
  "txs": [
    "tqDWYT-qdoCeSWGpV2Ig48lpswOxccbBpyxf0GQjs2U",
    "y0bIjxLaXu1gEjpRlyPUh0Uz0c5XrhIOs6z4lerXo8w"
  ],
  "wallet_list": "6haahtRP5WVchxPbqtLCqDsFWidhebYJpU5PVB4zQhE",
  "reward_addr": "aE1AjkBoXBfF-PRP2dzRrbYY8cY2OYzeH551nSPRU5M",
  "tags": [],
  "reward_pool": 0,
  "weave_size": 21080508475,
  "block_size": 991723,
  "cumulative_diff": "616416144",
  "hash_list_merkle": "1QVbbLwZHpNMJd8ZghRb13HZfrRu-aIIfzY29r64_yBJAcYv-Kfblv_c2pfKbQBP"
}
```

{% endtab %}

{% tab title="block height >= 422250, < 812970" %}

```json
{
  "nonce": "W3Jy4wp2LVbDFhGX_hUjRQZCkTdEbKxz45E5OVe52Lo",
  "previous_block": "YuTyalVBTNB9t5KhuRezcIgxVz9PbQsbrcY4Tpkiu8XBPgglGM_Yql5qZd0c9PVG",
  "timestamp": 1586440919,
  "last_retarget": 1586440919,
  "diff": "115792089039110416381168389782714091630053560834545856346499935466490404274176",
  "height": 422250,
  "hash": "_____8422fLZnBsEsxtwEdpi8GZDHVT-aFlqroQDG44",
  "indep_hash": "5VTARz7bwDO4GqviCSI9JXm8_JOtoQwF-QCZm0Gt2gVgwdzSY3brOtOD46bjMz09",
  "txs": ["IRPCjc_ws7aS5GWp4mwR2k-HuQy-zT_GWrgR6kRdbmI"],
  "tx_root": "lsoo-p3Tj7oblZ-54WVPHoVguqgw5rA9Jf3lLH6H8zY",
  "tx_tree": [],
  "wallet_list": "N5NJtXhgH9bPmXoSopehcr_zqwyPjjg3igel0V8G1DdLk_BYdoRVIBsqjVA9JmFc",
  "reward_addr": "Oox7m4HIcVhUtMd6AUuGtlaOoSCmREUNPyyKQCbz4d4",
  "tags": [],
  "reward_pool": 3026104059201252,
  "weave_size": 407672420044,
  "block_size": 937455,
  "cumulative_diff": "99416580392277",
  "hash_list_merkle": "akSjDrBKPuepJMOhO_S9C-iFp5zn9Glv57HGdN_WPqEToWC0Ukb37Gzs4PDA7oLU",
  "poa": {
    "option": "1",
    "tx_path": "xZ6vhVXw_0BlD-Xkv3KtfnJeLXykjkjUrwcPsXw2JUnie021At7I-fMZkt5EF_xOHtcdq4RIqXto1gwFAM5eZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfDSbuKpWzKZ9HP_N2I4gX6cUujNsJtelJULjHmbZp0XzmkBljlK4S1PMlSrTePIjfJdRfqvFNE8idpnj69X1P0zAfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAn4ybxD6lgdArqnPJzs7t8bU-7KfEb1YqpAOvbr6q3vmP-MWnCTWZJKTL90azeYZmHrTMx-iutuT6bP6CUC7zgHAfGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmTpFIGvz18gKl5rZ6p2Ve4yVeRzWNwibyVTKz80HSBYprfIpVJk9oRG3E5q1xRn5wErqyH2vFLbsLxDqKcR0vLunBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfDwBRWXT_vDxcaBxGmihJwlU_n_PFBCOsP-Lx3hSG6H6UGesIMAEYMmd2c5QixR-fCimhm_9S582cLzSUffsrAHliQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmP-RTrBhY9xCC1yywyehB7X6EmlBjyQBqm0y1L9Ex_dkswkf50rG-LE29UJP4st0bzFthHukfHvvWZY3bgIiog3L7gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfD3YxQguhfH8daMBAQrveQq3MMp4iKB3khk5mbU34Ckl1q8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJj_kQ",
    "data_path": "bTVpffiN3SSDeqBEJpKiXegQGKKnprS_AFMh6zz4QRIU-8dJuvFzyKxqjkDHQvtKl0Eajfm18yZsjaAJkNhbAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAOH0cuoLq1CTbSelF9C59C-fcO3a3ywoceaNxRl4nQQH1BuwcpiNdDdZvEz6Pfk5wKbnsF_VwVIgrfcLZgsxoKwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAefOoaNyW7ORmrzbZ5O7midzLByHooxjM5oEMJfZbQsY9mKS14G9fUEFmFaCPPJX6EXVGrUwROzDIWfHf8oHErAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAktmxYyC7BSV-MULrjzgdJJYfJY7lDFcKe3mo_EX19xoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA",
    "chunk": "aHQ6OTBweH1AbWVkaWEgKG1pbi13aWR0aDo3NjhweCkgYW5kIChtYXgtd2lkdGg6MTA..."
  }
}
```

{% endtab %}

{% tab title="block height >= 812970, < 1132210" %}

```json
{
  "usd_to_ar_rate": ["1", "65"],
  "scheduled_usd_to_ar_rate": ["1", "65"],
  "packing_2_5_threshold": "30581055168778",
  "strict_data_split_threshold": "30607159107830",
  "nonce": "byirx1oc0-_7YhQn-ALGBgAAVKmh8Bgmp7OyLtvgruk",
  "previous_block": "R58RTTzEKmSyaqhRik4fvl9AkN3g98QEntvZuoly02uwm8J4fZbcvgv9wEEgN5Ne",
  "timestamp": 1637154761,
  "last_retarget": 1637154761,
  "diff": "115792089200990798889969750100406950138692751005015780350441187278229868977849",
  "height": 812970,
  "hash": "_____6737DxIc6c3tMtRsYRgDfdgOODK83odB3ziOTg",
  "indep_hash": "nIq5881hbLMH5vPsv0mwrP6Je-4-0fp0AOSf2UbsQ1jnoA3SfSOYZm4dd6X3g2lu",
  "txs": [
    "4EsvhIGP6u6GR-kEHdUVhHYYJJyKkV-AGJGHKsVlrGI",
    "ruaiUHWfCs7T4JibsThWfEcPyS5GeUqPBp5IihIGutY",
    "waN_Hd2VvkgF0sV05RbwetZn4WelCKkxO4TMrMRmGIQ",
    "TkM3YodeJmCBqUQ5l05KP_EakVugtLmYNa3L_01qdL4",
    "NIKhWyDeSxgnwz0NU6YdbeuImxKNN0LHRPaCaMI_hyU",
    "oFEv3Us4Xlou8Y2BFshni1HhtVa3yz7Dq2BhSPvaFX0",
    "wDVpAsaXFTxHLHJYN10oLDc8eDu-affzU7hBD42HinQ",
    "f1tWS-CQQGS1hgJbg8lHkeUuLcW95JiMwV9DCq8R93w",
    "cx2_2A-SYqOy3H4xheL6Sw4BYpkHeaejT8CBX-VWmxI",
    "alDLqHTWniFYNQZEQG12dfGzCwoTpQq1OOHxjgauQNI",
    "Gs96AeOjTDw0MCd0ODAdde94hG20VyG6XeztElvFTbQ",
    "M0BceHPA8oJcZHhqBrJCgPzQjLicOUQDa9N5lwATIeQ"
  ],
  "tx_root": "AQP-SjJY8MtBMMFBBbJU1Eoxn6CD5Bh0Z4B6tW1V1IY",
  "wallet_list": "UO7vrGy8Utyw1dwquK4l3Rs066EJ0i7ajoFNC7L20h-9VXWbjl56TmPT_yWnWakF",
  "reward_addr": "-GMnn4oswztJB548o6o9ctdTLHg8Mpusn943kZXhaJM",
  "tags": [],
  "reward_pool": "27384655909087787",
  "weave_size": "30607610781942",
  "block_size": "451674112",
  "cumulative_diff": "2951089982733595",
  "hash_list_merkle": "GgXDIzoQ41V3ZM-VQotjH3IpzwJy_DAh2mfk_yyXPBkNgZ5anApDmsIOr7H43_ZG",
  "poa": {
    "option": "1",
    "tx_path": "e2ipAYDKa-YunBFWV99cSIzGV9FO1aTxaXCtKmPtai5PpzADXBf1BLtDBp2ciPIZFHl0oS-KjDWWgxhv-Bda8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABa58fJUKs6QMpg1ptwBNt6nc_aVlMd4Kd628A4-Fxcr1bqwsOSkM8mXNQpjQHMz1xMwe0n2YOtSBKPx5X883DKBB59mQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACblBWHSGPnCrYdXQRjCE3XO40tV-KTB2kvRpiB3GqgGoNYmzCMAOyrJDHkEmhtjLTJ7-yg3S7iEL6mR-hMqgyXz7gPrQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACxLb2JvCYIx4ERkyJoOYcpCjNC1z4GdgWh0ISsD-1PlAlRODfZ55zP0IhperbkeocXdpoZ6OBaUiajv2cFkq4-BrFz_wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACqxhpNH06zea_uKgSVub9j6hPmGoIy12sw3nZ87PfwJhwyJEbnnKGrMfZdF0g0VZCiR14Fwd_vxoeepCU4NZbDtZ6MuwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACicbyeYZNImtaELodhb4pBZ-rM_fLdPFCdhwq9HHxKnAtwz9Uy-3maQzT3TWJHubIGj2n6rM6RwB7IIZt3rcf9UnK8OwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACbrleQWgcbj3MYv_i1gFnYZOrcmtTMbltaEgXMz3zKPz9L0Vv41n7JqyS4407e-BGIvkY2pTG_3VzYiKwLw0qdH_G8pwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACe7TTteiSQXwoQioyuO-RMXDjMVQxW89RxJwawXaCzpAh2obAhCUYpjchknyeaURQk6l0azfwjqvzuN73IF8iDThJSrQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACicDjyNmTKPrVLWIg_vH8SlkLopb-APUbG32yw82HZQFJooQMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAonA48g",
    "data_path": "lbOSqGDAcekqm0ULAHcSIQQrWR3p22Z9K6i4Tr02mEPs5bthSxAWERDrkAXYUpaN8emeQOaZELzH74xQTH6-4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAADqoN2m3hCFmZRKKhGJFTQuHnZCMHY5W4ugplcETycOg-Ed0URmCG2BZlhkWdHebonivetWOYlAtw_0BX2NZqIwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAhi2cKXN0lzUhaJgGyjUbFnMGjTcJWgymS_hjWtP5RYUQxqYLp28rLzUvkeUhYpMIrIYBXtnmKtW4ZbsFYXG55QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAyEFZMrEuMkhTz2T_WvyJ0JUP6wt8fX0O-nRk4oUCe1R-Po0t34LWpF9PHyHdIoAum8XWs91IAmzjgXu7XQyCjgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAWnL8BlqlQjjTgVxVKlNPZODxBZVZa5RnsUSInsxLHk7RSXzC6Y7BlOoX067N8ZqAiAJyh2SzdnA9j0-iwr548wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAALyUauaExQ60Oej6spAZOlwss00m7vU-cHj3gFYZwoOWC0d8YnVhDEsxhyrDVMu-Pu49vRcoo7XXUrgMWeVKd1QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAe7pHYSp1vPYKvaIy1wSf9zerD8Tmud1_2DJJSFQZaJf0FdFONJ1jSsxhGiN-YTfQ0C1gZBkmByCiYLG-RwaUvgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAHvQ0I2O9LenILtrkV1kSuwqs98roAKpdsSjta7gXOKKzpdUKDTUWeqi4uHNEn4fjniB7MOfVWVb6CI_-xfPZhgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAn_DFXGpaRfj2znizeXtph7PQoXhQEPM0yqgRmRwUe_UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAA",
    "chunk": "4FY69JenKk-loETCL7wTv3DGzCkVjTV8x8Mo5w2vxz_mKs4YX8PsB-m..."
  }
}
```

{% endtab %}

{% tab title="block height >= 1132210" %}

```json
{
  "hash_preimage": "zxjxIc7BEGfCZOvhA599qRjuVfnTjnTPP4r2SVnn44I",
  "recall_byte": "20038419977588",
  "reward": "1465707980036",
  "previous_solution_hash": "______DyF1XD_nHsnEh6pdyYJ-0oHn0DCUyqN4Akkx8",
  "partition_number": 5,
  "nonce_limiter_info": {
    "output": "s2a28R-wRiQ-iM53XsYcgydB6sxj1QvDT4SYdBWcW1M",
    "global_step_number": 80,
    "seed": "AM7rbYBtYzJMmX9D5A6LEPAAE02yN-4LzsSKAk459Lpao_M0JUhUK_53Yp6_7bNb",
    "next_seed": "gMsCnK2EimYg8wvEt7BvOFvyFLZGsu5HSJ48cpTklxyzYsMB2E3NDRRAv4mTD1jb",
    "zone_upper_bound": 134783121793270,
    "next_zone_upper_bound": 134792922570998,
    "prev_output": "oJJOt_1wU0qGKC23r95R-OuL5ei_Z4XJrGGG2NPl9qk",
    "last_step_checkpoints": [
      "s2a28R-wRiQ-iM53XsYcgydB6sxj1QvDT4SYdBWcW1M",
      "n8jGN9BxH-_63bDGekTZCVQyigsYhVN2VFfxcTmtWLQ",
      "ZMbGYkazClEaZgQQeeLN0pzTmzvOT6TDFwc4ClLYnfs",
      "FgG2VW4m-gnWwUEsytFWZFa3n0A_cRpXr5tGjaT7iT8",
      "vrOEpUDmPdEtU1rVat9ddRaQFILyXZgPd-VrzvBsi2s",
      "vvdrlyeNLcpUrjpGYzYfGVKWRGQMYLCDXpmDEYO74Hw",
      "r9XhO0mPBImvlNfzWxuxkBz0KHuOrwyGCoX4ugFu09Y",
      "i7CSZDVzuEMaf1zamSr-YcdzFDUBly_WuXdtJdCn7Wk",
      "nJx3ORNUhrc7aXBIBZS5jzMVj0JoyKdn1_H0fUVUWgw",
      "VS_M6lvFUuEAb0XGUb43Zcy5mWj4OqvMDlF7pqgVd_0",
      "1-QEzyO_bjFiGnq59fujRA9dXdRNbzPKIrSHwLs7bOY",
      "JAiHlkIl2KO_oLB3Wmd3Z3mG1pVB7TnObZkjVLa3tQ4",
      "H0vGq1vw54qyyZ8cUJDORzKsP6Ka4fZtEHF2RDbjhtk",
      "D2EMFw_MywM2prEtC9VBY7ABJXYmKklZH3h_7U-QTKE",
      "frqJdF717fyV4fHmlCFQMbnGAnf1ue--0DhCuTwM5iY",
      "y10LgNaDO3_v1-mCrkWm_AcosrLu72_CqlmXqcTVRoQ",
      "na6qGtR67t2ild7LHqtrDiIiLjwSaR4NtXdR9tbGeuU",
      "7k04qTS4utzamCEtiavGdybZGDOXncGUbL7cz-EbUHo",
      "A_8B316ZJ2ynQPKZ4sQsou43-4RTYdhEw8AgqfPENy4",
      "v4_bsH7A7RzrKHf_yXmOGusnwxCX0TqKvN8y-43Thus",
      "9oc9zPu-yBNRIygEuuN1NpylTnhAEVAl7LDQIex4TrA",
      "sUGDC7p_EEa-crTDuLZpfiKmpgp3aGK-Kbo7mLDR_BU",
      "cEo95Mvy5NZAiboJTWa7uW0SUYjqgdaaSYWIcpHv99g",
      "JfQuVzhCZOlFslAwOxO5dT4WCGUb1x-N_a_1DV-KOs4",
      "bCjdytXpTamI8Dn5LHmQHIS86PB5aTG6UxGFvGSUbls"
    ],
    "checkpoints": [
      "s2a28R-wRiQ-iM53XsYcgydB6sxj1QvDT4SYdBWcW1M",
      "8w2UXIcPI-4TMzlLokT6PlLXEt8CvwuUyAh2kvT4l9Q",
      "o3mHmozBtKAW_vs96ANIxaOoul3Td1g6eoR6rvKLV4Y",
      "7M-lVdz0C8JHo3Tx9ZlXG6mlpzlSQyGiMYo4s1LADi0",
      "46ZaCstUm1fVlvgin8b6Md082ydUs2EqhNgx6k3r1ig",
      "uJwPMNNFP_asFzQ24M1nM4LCuL64c3VruVOkUKr2JMc",
      "8ozNKZXisTwwQ2jmcMWQjUm83yVmrTsEkfCZX1dlNBg",
      "ONf3U_542veOtgXykDM5ozxDhl5WtDB7EiTYoPJAgcI",
      "rqyIn_morrYURnbImUx7VieAT1BWiD71jLYWXugBI3o",
      "zfsTWFt7KjjQMfewrrqv8jg5U2N7KiVisG27qsDUSR0",
      "4IQaX7HFRnXFAbtBvUI6YOAWkglVoqVrjZeG4XUVcOg",
      "g5LdQ0EfshaCxrl1ZgyR7E4chksc63l314UanvGfaKA",
      "eeRu4FNtC-xLFW9xC97KEtt6hP0yW0WWOHxQ-xhAScw",
      "1cbBFvlBFey9BbPP3_kf34QijkAxBQQSPM5fDMlKdBM",
      "hbpoPfCNS_hokiOwJOjLV2ktUb4vtRIH-zYAZEi1S1Y",
      "104eeVItYcoebsopnNt-pLnQd86Yw9ewZoTT9TfWXO0",
      "SJv6_zA3lbQbDlstObuKaHGTMc63ov2s3D1TFUgPi54",
      "RQ5-kHJ7duWSto17HJa6pxfAasKVsfU_ZKzo7KQEi9M",
      "IexQqVNJSoTIF3qH9nqZnpfFrKzuPGUK2mutdEuq_jk",
      "V6ikLEujYS4UqDiGrodE6_Cm76FLggWVXNaGNqMpCNs",
      "SO6O36Cxb6MqXOSrpaxRnRkTVohySppVdGJxuvmwLuo",
      "2GSiFs37Qam-sC-qHOODNmDk971JBPi3XVvGRTH6CAk",
      "8FLS2KaDOBvFmdxfbQeVHhxzxNPi5qkIrZTrNbJvX00",
      "Kbp3hCAZXUeztkhkU9tVuhBzHBEXsbKPc4rdhDVaCeI",
      "7wv3TtAizWk0g4BCnlK235aPAaVrz_aIMTT36yknGkw",
      "_Ztkvdyiln7-wdjcpACVruCdvy4UwG93y9Cam73iqGg",
      "x2Xv9GjYeKC0_wqa3DjKX-CB17uZp9IJdHrl8dRFoew",
      "wnOLZndTnQ7Myp77hon0DPoe-PR9HiQKlAuQEdPbof4",
      "q7bP0sGua5zMpHgI_e0-XRb9PHNn_bsNjg1KN1XVmYw",
      "PBtm8ftDalbk5OpcKQfTnFwcmeTm9kg2wOUH0gbgo1g",
      "VEvjbgAIQFxEIAGmhNO6QUsyMKmSVNFN2OHbRXXHrh0",
      "AZUB8jjMwtxrYkguPob0n4PCf3P1yYQgr4pK2CbKQy0",
      "SE7pHN0fiAsFjEFS84MmERhUuAi0ld3M7Ip2tjElDWY",
      "ukCdukTb9LxDlcPdKNElcBaXHsIavK2cChMJUw3Uz1g",
      "FWnsPp-Mb1nMjxU-esQRRzHoSHnsR260ie6FiLPDXSY",
      "AJhvOqQpK_DyGyfaw21fMPPKB0tNRWFGNpg7RX6g4NM",
      "DrUySBtauxDqj9OmdgxArcrKSuNmKKPXohBKZJoUDU8",
      "5t7ah6zqLfq4T1_mF2xGrcXabMdWIaVA9PH-ff9Fk8E",
      "wXM0ihQIvXx9k-FMRhOM172ePwuu0qCBx1YSmYIFvPg",
      "YDtMxHFZg2dSBNVstInQNbzAGf2f_s_DG92DMzEsklI",
      "y_l2J3rryKkoK8OvcJm_zk6nL3VM35rbS6DrdF0bne4",
      "C4z3A-aPvWPsKYZK23mFyXsJ_wfXOivwX4eQzW8L4AU",
      "NATIlXDQq-l9-H0qbQCD5hx1ZYJ2AZHImNIQibLECic",
      "zK_IvJRs4YzGaeLoR_k5_dGgfnUAUe3ZXi6V0GiEJtU",
      "PujjTCaLIyYdXyo82soGz2l4Tf89vCJZX99V8ljw3Pg",
      "WonkHtnh91sJ_94YiH77ZyQIk6iD8NnLNxoVG4A-Tvc",
      "I-ur7MGpI7MdRjdr4ITJs9LhoZaDrbaO-ZyT6bkvGL8",
      "wKc0p7VybSEGU7rHuXJTb1QxlrjF3uvKwYsclvEtl1w",
      "vaCrMtHQ_VHw2oQY0mphbCl-GxMsA_bltHnN3U5v3mw",
      "5Oo-syJG_4i2uqqJQd7LepKVwzunC9GDRDDZ9eLi4CA",
      "qArgC_F6QvYX7RYPojK-oaIWLQ0RyAAlApbFDWfuuy4",
      "Z1jlbha1kGt03MY8rRq7LM41fEjt1XFnqfKKHrLrdAw",
      "m0FXlq5qokRMxtG8WseIE7C8SWaqCNZRRl2r-SwD4zo",
      "PHvWj-3dseMmABYamSy0G2uOeBijC-S8QPuKkR5mkAU",
      "PJaADkiBfNHHD-PBBvslCYd78sgb75vttCRyqbQGjpo",
      "RPuIij4-rRtpUgDQYk51LBtrxJBcHyrEcQXfcileWfM",
      "2mqvvdBZeHabiz4Gmk3JDF2EVj96AnOACj3eS5uFTcw",
      "5po52oX5qd7QVb_C8hhqR6ngU2oPtniq3J9whalzgNs",
      "jgMX-1tbA0TbiR4UzpCAf31Aj7WJg5eFRwM5215qjZM",
      "JTqXNfFsuwjzx2X7vs_cjb_waPtvR-s-KDtxgLUIAXo",
      "bRG0LDix39KujHgpPQ3bb9xfiZDdK0iqYP8lfkb-IS4",
      "YB_gur8BUk39ed-cSVB7agdx2cHJuOkP2dYdHITTwV8",
      "dzAuPGtmp4XaYh-we4fHqisGKgJMIlB7Dr2Mds1_-yM",
      "nG3_3G773uPGoAdTGT1-xCmCaRJrIJNxD-GcQ9rF5Nw",
      "BCIYXrDyabiA5TzmrkmXuN7VO2TtTm2dll5-tPlUtOI",
      "-oZ2BVhhD4pRa2XiYjbLaQ8cZ3cByeqouhaexcdZ0vo",
      "XZ4RV-ZW03ppM2OT6jHd-Vw6F5tTIAOl-xhHdYF4CXg",
      "EoODt3Y-A_6uUjyO7SIWv7dmvvm_R92d5T1ioxD5kZ4",
      "swF9_kdEQ9xHANHvrfS8_002SL1YKBB56LrRJJLf5dw",
      "WMn8p3N35Nsr-9NCIT3Jm2Wy9gwlqh4Yza8f_dibxxM",
      "yZNXdl7xWN5QiXc5aDqZ4828QS8eDEhkBtd7Zu_wqO4",
      "-esBMMucA2ihMvh0Plsa9xAkrCZtKx0WeWaKT8JSfwc",
      "ViA8mtBrUqGrvOxsKKN3VqKV8Y2WHKJNZgZMnX55S9w",
      "wM7YGSJPX2PLa8yiaib9gv9d6tbU30kBzRF287yALHw",
      "dRJm9u7N7Ea3JiXd9c1eOYVYV4FTgSDz5Wj7PF6bwrU",
      "crkNSGwg1XC5Pn_f9jC4y-6930TqAd58eoSyu16E2nE",
      "9rzjzw1ezmMxJbd-vOZslE-e__HOAMYTivqGIzcTd6A",
      "vv-AS6Rd-kokfP8wsGAlz2FpnBoM3j6auH-MuzpCq5Q",
      "jKVMzwIEtFxXJtoUUALDuJV5ki8urWX2I_0g5pXZHLk"
    ]
  },
  "poa2": { "option": "1", "tx_path": "", "data_path": "", "chunk": "" },
  "signature": "Ygl9YMlJMrD_lphxulN_n1Y0FJI8OcjvoPcScgZWvhGtg5zTj9Y9LZYREwZrF4PgUq0ktVeYlG4i-Qv1z1QJYgSn7FMX-8SWvjBzgGERdmyxWSeF-DtAwU3JiiInrtilZDZmw3y0QzXKwyzysUeWXQoL1B2Kj0N9swvuENJmiqfY7yWmvUlTFQO-AHr5FHrHRadH3dMrpbNJ4GlithNmNACjBYiqGnrwxH62d_gdc13G4MG3frITkX8lPf5KPAwenUNE2UZ9kv3Yyihog2PXH7x1lx5dfDBCb8uVsNsNxgHAud1krNpNO8ycq2L6-fmEEvAUvsf-YBqeCXjtMYPacOwzWsmPF--6Ed9VT_Om6mGGf0_XZjzuoDl7vQiafdpgW8dtW9qJD8cCmgf_63pltEDRxSkEp_COho293NR84ggN8sJGbXKH0EBFTIAa_ce-hgUy9wP4e18hoLHVLHK737HpJsaxBLoA-JrOUpWoCGT2T910NrIqMo9G-Wsy7xEiSVPaJGfmU4sRJJcjGAj84U4TPp4XJGYps8n-DdW3C2ZA5xCf7fw8Ic7H1JXqYiGUo3isKYkUD7w-7V_FezcnJ7D_znTH5rfkuEvdp3w3f-ZHyKNCdVIC9m2qC-rVOtOOfwAQtRKBK6T8PYpiQLvg3soOVAqIDoGWRVLe8kIqMl8",
  "reward_key": "2LWWYCT6WKJ_AJoxGqicO5gyLg_joq6kHEU_4K-nPcA3dMCZWs7hDkyQcsFrk5sCtSmjJ2C4Rf1M54jLb21-kSE6rxMYZeWtJDldsFuUyEJ8y99p8MWLQohno9t1BDM9cBVIQh4sbV6A8_P4ICv-rTnVfG2YIfGzsz044vUm3kqKXFJW44kBksoktuXOGVPR0ak03TfKu1PgzHm23Ms4u4Ug3-yyDGoNWrHkCkDf3BIxG8lGHc_UrkjN16oG8UgJviyKzZMg59HBgcUeSrgAnSW36zCtFC03_fpfvA0VQpKPFmVFXNts1bMoyUkW2oCvQMhE-iNQkUwv79BO3_NxZZpqLk7HlfB6gQ_0fxHoEIpUnjM8-PRVNFQCHNZ8zdyCHmEZtA2SLlxocLmA5VNyjNChAThT-xYnNijbLLfs1FHjEV4Q_2PYcvV4w8R9hYcveexgRvEc69dEwM3i9Op9QPVX53u0Wi0bqfnHoVZnrNbIJWbpWrLxwHN2j097QaPl-83Pzg63kF6bkyLlpKNMW6sjGSGOOR1yrnUUUnRrM_t_7BD5ZpKoobcQDcwjuUSzIf_ypz51SytPSEL0Kh8-oK5BPEEpvcAuEoZh-X0EXInIKW0eTRn5G9JiuCydHXy4SKwZBhGvTHHY_ZdynOlKPMNYyt05V9DIqno5DlxCLNk",
  "price_per_gib_minute": "6986",
  "scheduled_price_per_gib_minute": "6986",
  "reward_history_hash": "I190QrZCm05s9aIbt9j6bjFJn1BkNvZVMPEXJ7QFTtI",
  "debt_supply": "0",
  "kryder_plus_rate_multiplier": "1",
  "kryder_plus_rate_multiplier_latch": "0",
  "denomination": "1",
  "redenomination_height": 0,
  "double_signing_proof": {},
  "previous_cumulative_diff": "4369104305356760",
  "usd_to_ar_rate": ["8855", "524288"],
  "scheduled_usd_to_ar_rate": ["1", "10"],
  "packing_2_5_threshold": "0",
  "strict_data_split_threshold": "30607159107830",
  "nonce": "AQ8",
  "previous_block": "gMsCnK2EimYg8wvEt7BvOFvyFLZGsu5HSJ48cpTklxyzYsMB2E3NDRRAv4mTD1jb",
  "timestamp": 1678092233,
  "last_retarget": 1678092233,
  "diff": "115792084401224566807772651152730092358388734887252574358647557874619658061534",
  "height": 1132210,
  "hash": "____09aYjKvcwjKp_Qb444oIiJVpbSxJF3o21jBOwFU",
  "indep_hash": "7OkBVCwRpf-w5B-yKClukNEzDbyV4Cs1Jlc65WmL-uR4gu6ZisocC2gHufg0wHVe",
  "txs": [
    "fzuqZGVS5FvX_EsSxAB670ZLYT4cWGI8Ais-CeF7Sc4",
    "x2jV0Y_g67VCTJxI-BxP9VtHkWbzfKdvRtRUieYCAeo",
    "Kr95NEJ_lhWm_k0iw13G5d0j7-96a03SEAI4BSPTUus",
    "zzaw9uCdk_Ic679oFMzDLKKcnzngROU1GYHSqEBrTN4",
    "6VuOwldWcQKi6DaIIs5zCf5MMLUxKhCY0bf6eZXvYew",
    "2IPzj7-LShrohdJdOttYQJDrL-AQTZ82Xy2ECv829-w",
    "Tw5WQjRhm5JKpzSIefX8OU47eMqG6YdBx7Hy7kwq45o",
    "JJcSEzZU3wOqJNDTTA0bSGO_akvkm6DECLQc78jdKAs",
    "PFfKmEk6q7HNjEzrirrjLMZfVD6vvnNUIvTa12VqIb8",
    "2N9aoBB21Sq7X3e7sn9oK4aRwjQJj-0RZQsdtSPT0_E",
    "WdwA5PGd6Ah5l2BGY0l0pHd7n1q_mzipydhwSqCXvzI",
    "ikTT02RSNwJtD5jHEScfjTkxMa-5tGmvyAPjzWdenL8",
    "oxubxfn5AK3fCQCO-3sKQS1i14AH-iPhswyBWo8rCCw",
    "uNdOaUP70uioo15K2wAlPkJ1H4MkOhhYRTKy81Wzj_U",
    "NsIOyrSB2o3RSMcb2WrfV7xRUfwCEkpnnCvez5FozuM",
    "pyxDgRreB52B-sYv5lS_6EOJhY5EzYaJVp29d1YDB9A",
    "unahGYmRyN8pahTiij9aS1T4Ind0HtpU92lltprIoqg",
    "vG1WlB2y8t_1ePuOt2oRudUoUjjDuQ1HlIeMNH7Nc6Q",
    "UbHFan5Tqwnau4CyiVxEO3DoxzGctr9udIUcqsYAUYM"
  ],
  "tx_root": "jHMSGnQUPqGM21zwVi2EFpJrHmjrLDqyavxodjC61mw",
  "wallet_list": "Y17X1la5YZWup2Q0tn7YQVizb8fs2R8OY1KUmqLayeU_SBEEDTHp9PgtR_90kWS3",
  "reward_addr": "SOtIrcaiJwVs4h3yqXKjOs0P9bNJG5F77y0-TilnQ2U",
  "tags": [],
  "reward_pool": "46030523196756537",
  "weave_size": "134792975261942",
  "block_size": "52690944",
  "cumulative_diff": "4369104329300079",
  "hash_list_merkle": "iMx_IwEe6lEGXGBqFr0NXl5AtQYPb9HILU8FD3nNqXvoqgqvoriXTiSeW7PmtCtF",
  "poa": {
    "option": "1",
    "tx_path": "mTA_E-nj8VL4XjyQp0PX8wmQYHqTTBQ-TQR9p8ySBK9WNjzAci0Wh9FgYIjVgSNhtNz-G8dJfPz-1L1DOoiDIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAuuY4QTEhLRfqmYdRvKQ0Ln1c5Fz3zlhqKUBRfpnFPUs1WhbuFCYjZjjZgjv1kILQDY9HQJa6GT1qKdYhPnAHukOIKDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbhl1-TXlZj7Sm7u5ZXWQfd4pUdYeoEMLhe0Nm6YqDrHt6uudfzVBHQ-qnHZtwXYZoTD65f_IYLwN-gO6ygJCwzU566QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASL4xgq6YQAokrDGhdVpXVw1oIwDNvuNOVnxgLeK02xsFp4elqLw2vEwR6uZ4YixqDFunCOSz68pkB-q6Dt3T2r-fRJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWnvsAuuGc3Ra9YSnuHmXpv_Tca7IYW2O3Qb12ojYIbWggC5fUJzChVVm_01A57dvpI3KSBxrofHRWsc9BZU6ecpulBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbf7IdSwQ66LRKwxoIMIQFMI5-fNZJE4ZzQH5r2MEE3zhV1fwZXBxJLfaavp2TI7F9c6gFLdIHxNKGjyye1tq3ucC4vgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWoJCnFnlRI-1gWVLTT6oNSfHB8JehHhdRza0LedElmr9K6wmQQd4guZNFdOUYt-2LRA4HAWCavdRr6eIl28NPJQkiKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWoJ16-86ZLi5VeUTqYq3lCWI-KYwYbJ-TzugMbY7Z5gT3DdIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAG3-yHQ",
    "data_path": "TuqqNP9Hk2K6cDU8PDSp_BC5cHvjYJk2KrMM-uP_fOiWOBeOg1n1qdP3k-zDFDZ4YAhylENe6zjR_BA5EvufCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAArDlTG5drIK1C9IeuYvLqv6NmJYbJvxFNoCMeoIZZasMwMUA4MxR3sLjRYwcKtq8L1PQC7-T6GWo3-hcnH958MwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAhKyWpTMsE_StjgwW1PNFdH7xN_SBY14weoeonM_wXsYNJT8IpMkfAXfFiKSn6T55OKeT2Pw2QgEcJMMSW8R1AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAR3a4pdzYsSjFYGc3KC9ZFYxe-lksRbGzoUQGkz9jdeEQtx0uFuPGUGPycoWo-RXyCFJH_Zf4x9880NcG5Y6R0QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAlcA-Z6ojqsWBwqJsMk-nibjOtOcKURTzWOd3awrhVRIPeYosVskIql7V-_ix188TrLm-AIjzWtMH7Q44WCzTSgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADwAAAET9zJFpjrYti3st1dvhztjDsoV1rnc-JdO2HQLsOdIbe8mTHJ8sn-EzKR4WHt-pdW4SdaTeBvTnbaP47ttwI8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAb01i3lbiGlAds8x1ywEBzeb0lUMzGpV8t6AfIm2zLaDVFJIGy4oI4ouX8FXhq5mbXAs8_faexv8cVAUKGADQIQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD0AAA9EZm_6-QghTZb3NV2kQZcQJR50VcQPXIdrLXDKveFNWvD4MgV-RVn4_k4gqiRr5QbrxvbjwbS0m-7oStNrAh5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD2AAAs6AhgIw3KFviltC_gBcRfDt_BxxMUlOMDbZcoO_tHsSAaTbg8kiOAXI7ZddFpYlbn3m85-UTIFiSHSzhwuSmsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD3AAA7_heFX0YS58BmcACzOdu8u7AjUnht-8OJkpVIm7VwOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA-AAAA",
    "chunk": "vsLWa3iv1i8VxoQN6coorkRAWveASY6brn..."
  }
}
```

{% endtab %}
{% endtabs %}

## Transaction Format

Nodes and gateways accept transactions through the `POST /tx` endpoint. The body must be a JSON encoding of a transaction. Amounts are specified in *winstons*.

Transaction and block identifiers and wallet addresses, among some other fields, are encoded as Base64URL strings when sent over HTTP or put in the URLs or displayed in the block explorers.

{% hint style="info" %}
**Base64URL is case-sensitive.**

For example, `T414mkfW-EQWEwPtk__LMJAgawNdxZfdjxhGPQKMwDQ`, `t414mkfW-EQWEwPtk__LMJAgawNdxZfdjxhGPQKMwDQ`, and `t414mkfw-eqwewptk__lmjagawndxzfdjxhgpqkmwdq` are three different addresses. It is impossible to recover tokens sent to a different case of the same address.
{% endhint %}

A transaction may be used for uploading data, transferring tokens, or both.

See the [sample transactions](#sample-transactions) below for full examples.

### Field Definitions

| Name        | Required | Serialization Format        | Value                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| ----------- | -------- | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `format`    | Yes      | integer                     | Currently supported formats are \`1\` and \`2\` (often referred to as v1 and v2 respectively). The v1 format is deprecated. ECDSA (secp256k1) accounts only support `format=2`.                                                                                                                                                                                                                                                                                        |
| `id`        | Yes      | Base64URL string            | A SHA-256 hash of the transaction signature.                                                                                                                                                                                                                                                                                                                                                                                                                           |
| `last_tx`   | Yes      | Base64URL string            | An anchor - a protection against replay attacks. It may be either a hash of one of the last 50 blocks or the last outgoing transaction ID from the sending wallet. If this is the first transaction from the wallet then an empty string may be used. The recommended way is to use the value returned by `GET /tx_anchor`. Two different transactions can have the same last\_tx if a block hash is used.                                                             |
| `owner`     | Yes      | Base64URL string            | The full RSA modulus value of the sending wallet. The modulus is the n value from the JWK. The RSA public key. For ECDSA (secp256k1) accounts, this field must be an empty string — the public key is recovered from the signature. See [ECDSA Keys](/developers/development/overview/ecdsa-keys).                                                                                                                                                                     |
| `tags`      | No       | array of objects            | A list of name-value pairs, each pair is serialized as `{"name": "a BaseURL string", "value":" a Base64URL string"}`. If no tags are being used then use an empty array \[]. The total size of the names and values may not exceed 2048 bytes. Tags might be useful for attaching a message to a transaction sent to another wallet, for example a reference number or identifier to help account for the transaction.                                                 |
| `target`    | No       | Base64URL string            | The target address to send tokens to (if required). If no tokens are being transferred to another wallet then use an empty string. Note that sending tokens to the owner address is not supported. The address is the SHA-256 hash of the RSA public key.                                                                                                                                                                                                              |
| `quantity`  | No       | Numerical string (winstons) | The amount to transfer from the owner wallet to the target wallet address (if required).                                                                                                                                                                                                                                                                                                                                                                               |
| `data_root` | No       | Base64URL string            | Only use with `v2` transactions. The merkle root of the transaction data. If there is no data then use an empty string.                                                                                                                                                                                                                                                                                                                                                |
| `data_size` | No       | Numerical string (bytes)    | Only use with `v2` transactions. The size in bytes of the transactin data. Use "0" if there is no data. The string representation of the number must not exceed 21 bytes.                                                                                                                                                                                                                                                                                              |
| `data`      | No       | Base64URL string            | The data to be submitted. If no data is being submitted then use an empty string. For `v2` transactions there is no need, although it is possible, to use this field even if there is data (means, `data_size` > 0 and `data_root` is not empty). In `v1` transactions, data cannot be bigger than 10 MiB. In `v2` transactions, the limit is decided by the nodes. At the time this was written, all nodes in the network accept up to 12 MiB of data via this field. |
| `reward`    | Yes      | Numerical string (winstons) | The transaction fee. See the price endpoint docs for more info.                                                                                                                                                                                                                                                                                                                                                                                                        |
| `signature` | Yes      | Base64URL string            | An RSA signature of a merkle root of the SHA-384 hashes of transaction fields (except for id, which is the hash of the signature). See Transaction Signing for more. For ECDSA (secp256k1) accounts, this is a 65-byte compact recoverable signature (`r \|\| s \|\| v`) instead; see [ECDSA Keys](/developers/development/overview/ecdsa-keys).                                                                                                                       |

## Sample Transactions

{% tabs %}
{% tab title="Data transaction" %}

```json
{
  "format": 2,
  "id": "BNttzDav3jHVnNiV7nYbQv-GY0HQ-4XXsdkE5K9ylHQ",
  "last_tx": "jUcuEDZQy2fC6T3fHnGfYsw0D0Zl4NfuaXfwBOLiQtA",
  "owner": "posmE...psEok",
  "tags": [],
  "target": "",
  "quantity": "0",
  "data_root": "PGh0b...RtbD4",
  "data": "",
  "data_size": "1234235",
  "reward": "124145681682",
  "signature": "HZRG_...jRGB-M"
}
```

{% endtab %}

{% tab title="Wallet to wallet AR Transfer" %}

```json
{
  "format": 2,
  "id": "UEVFNJVXSu7GodYbZoldRHGi_tjzNtNcYjeSkxKCpiE",
  "last_tx": "knQ5gf4Z_3i-NQ6_jFT2a9zShUOHh4lDZoAUzsWMxMQ",
  "owner": "1nPKv...LjJMc",
  "tags": [{ "name": "BBBB", "value": "AAAA" }],
  "target": "WxLW1MWiSWcuwxmvzokahENCbWurzvwcsukFTGrqwdw",
  "quantity": "46598403314697200",
  "data": "",
  "data_root": "",
  "data_size": "0",
  "reward": "321179212",
  "signature": "OYIJU...j9Mxc"
}
```

{% endtab %}

{% tab title="Wallet to wallet AR transfer with data" %}

```json
{
  "format": 2,
  "id": "3pXpj43Tk8QzDAoERjHE3ED7oEKLKephjnVakvkiHF8",
  "last_tx": "NpeIbi93igKhE5lKUMhH5dFmyEsNGC0fb2Qysggd-kM",
  "owner": "posmE...psEok",
  "tags": [],
  "target": "pEbU_SLfRzEseum0_hMB1Ie-hqvpeHWypRhZiPoioDI",
  "quantity": "10000000000",
  "data_root": "PGh0b...RtbD4",
  "data_size": "234234",
  "data": "VGVzdA",
  "reward": "321579659",
  "signature": "fjL0N...f2UMk"
}
```

{% endtab %}
{% endtabs %}

## Transaction Signing

Transaction signatures are generated by computing a merkle root of the SHA-384 hashes of transaction fields: `format`, `owner` , `target` , `data_root`, `data_size`, `quantity`, `reward`, `last_tx`, `tags`, then signing the hash. Signatures are **RSA-PSS** with **SHA-256** as the hashing function.

For ECDSA (secp256k1) accounts, `owner` is omitted from the hashed list (the public key is recovered from the signature) and the signature is a 65-byte compact recoverable signature instead of RSA-PSS. See [ECDSA Keys](/developers/development/overview/ecdsa-keys).

## Key Format

Arweave uses the JSON Web Key (JWK) format ([RFC 7517](https://tools.ietf.org/html/rfc7517)) with 4096 length RSA-PSS keys. This JWK format allows for cryptographic keys to be represented as a JSON object where each property represents a property of the underlying cryptographic key. It's widely supported with libraries for most popular languages. It's possible to convert a JWK to a PEM file or other crypto key file format, support for this this will vary from language to language. If you're generating your own keys manually the **public exponent (e) must be 65537**. If any other value is used the transactions signed by these keys will be invalid and rejected.

### Addressing

The `n` value is the public modulus and is used as the transaction owner field, and the address of a wallet is a Base64URL encoded SHA-256 hash of the `n` value from the JWK.

### Sample JWK

The address for this wallet is `GRQ7swQO1AMyFgnuAPI7AvGQlW3lzuQuwlJbIpWV7xk`.

```json
{
  "kty": "RSA",
  "e": "AQAB",
  "n": "ovFF6EbOtXeg7VnojIgtChgxfU6GZ16JjVj5JFHh6NGHJnq4p059BnMphcDx1mqb3yxM73FxhEszSFLcJiPzway6eIDiXuYiT-Sf_0Wl6_wDLvEmlz43psp7WYJumwpaSyiI_1FWmOVQnTnoAIKaOYKVqzUlteiECQj7XjJl0MZH16RlEfVqVpJ_8Ier4_QXIJ8Y3pe2KF3Lg9UANFU97nuvEM94CSzX-0WIju6Lykt3DBb2YtFFg4bJjOFv3T38nCZmDh8lYjm25_1qILalsB0XRoDxQy9FLxWb4zd09JsDhL0EYAQ_hNfOnQFVOBtYEHVYMCHYH6GoTcNgxmUkZPk4AfpAqZmjDzKfVJrw4Fr68pPTEQOQEzBcIWp61P21BSkhqO4QuFinkQsSH6NdTB_3FpbhYf34Hjf-iH7hdpdWo4aoRLb8eZeZcqBRZoRmlhQnOD-PVxQR_vb9rjXSjGkCWwRbsurVLWdBh_FQn0S9Q6EHqiV8nbW-R0Rk2E76JwgMFkqGUtZj8DeEqXJ2jlAvuzp56fXeAViPEtvUj1HheO8O3LxdVYCiapWWKq4qQVoRzdiyvydYSmbztgFUhekvmjNkxLNKOh71i3hFtoXycegqZ6izrUGoF2oD24lsTKsV5lV5pwfmUjVvxtHZm54bJIMfUDYbOV6yeDjYBb8",
  "d": "EePSrJeFn4f0a8rozPEwnMCeQmdKO3Q2PwYrSJES8Ch9IbzspDXqZThksTJHeya2WXD4O3vlnkRRa5npYOimnTeVO6DO-eNjlgkAhhsEBh5jzRYeChIDMzVdCK1Y7n3a_xCCxiGMk_nteW2_qrqsKy9KtoL90nSmdoV9b9CxvBPhFGyQykF7POkV0fdbaIpGtcayCNJ4ZgMyUpWi0ZwgUhxTUtGsmLlLN2Phg-vt_jZ96h5lS-E1NCUq4ORpj018fDp9DwTdamTyz5LTwaa8F1OCWDPVCW7Ztjs1o-NVXHvejYbhQZeFz9SP804PqLrb1ubDWXmFzKdHns4aRH4bWivh9L8HwSJUl5UEXprJUpYilT0tb3VauI7Cih2LBfhU3fUIDJFYm_j9etgNcPlqt64T7_TI8elgj7-sciXa1XEqIje9Mn8spxT6lpn4nhxJ9qelERCJwiWbuPnW2VsJHeqXZTly52KQEP_UBC4z8a0tDm7HIQw7WQ-OAuNUOu8ongOHaOexkqKYIcF3f812sOIVEJufoBXUUTIvJk-buH0ytgtTjkrO64zZeIvFHa1MFU-6UXh8jipSZ617znNR2Pc1-l3s7pACdbXvy2-5VWE3psRr1L5HM4KNwm6Rs5BXXqBSifzfiJ5qNGqKabfXvPXI8wYyl3mhUQtHW6sUUl0",
  "p": "0q_DP_FzSi8JEd-NNXoIaeL5MOxmNiXmDHGNxP3noKPyr-N6h3CrK5G59Rj2vWAJMhKToz1eSQ1p0-X0Ku2DvdT5LQOGIXVPtojw0OcOI8G8SoqMGAGehaLsnV3vexwtwjLfIM99XccKAxWMA1SMuL48nuBpMUhO0MlagbrL5vfpKB9kL7XCQqspAnN_vBmQZGWYczQmBgfC6v6xGQV3xHJmL--dn-qF2XU9pKuqd0J-cKYcdLPrccdJtGLid4nrSOTDfEbr77IUI5VGWV8CFJ-n8Vki-GwUxUkJpIoRyp5DxnYtSJb7cV-xOf7kBTCEUFn5B8fb2q-d8011cgnp5Q",
  "q": "xfzB-Yf4fa2y2q4ubJCJA5H-IG9-mr7fVRTUbj-gTqVL-I7MCDIImdAPbA-3EoIR5H70GVbAFGQJyYDq6eDeTbNs1zfnU0JPurASE3fKbOpoRdLwXwaSdRJRP9qnqUe-BzuloIzWc-dI-6TJxmHUSA1X9CtHvIdfNdKPCVFKUMrb1bv5arAI8tRbNRfy3tnbiw4wfKhYEQ1e6RPpxAR5F4We9RJ81-sIlfAy7WfliwmcGmgcPNdUinGR299CiVYKf5ktoqGFQ9n6K-v4gNZV23f33-tuD8pMVxyc3xG34j4frH57bsbm7v8Qz-92ZxHWzOUgxIVhGgSaa4E51d9m0w",
  "dp": "yArepo4I230BbZkHKKlv56n81PkAq5UccuA2rb4u-ZXxThP9OTA_NiUtnYxQassOsB53U91m8pHr06hZR5ExL0NSO-1Go-oQ_83SaWeZQ1YmA9i83-ZZr6VcaKbSReAhimxm825PKIVd-kOxJ1BWNOtb_7Yv6v0u6IrmhproE6t8E_6KT8qSYl7Fl3A27lCPiuPz9h6jo8Imzp15ZbqNV1cPs6Ad18MDx8_L8diVCJt4FlmCV0Sl3uhMERx6zumDHzkma4-jYXmCKa8Ilr7g6NgWy8_Ipnto1VFd-H6oGexficaXhH7my2UCj4B23H6OgwSKsVqQY3mvzV3Uj6zeCQ",
  "dq": "a0_ey6OZWnWFleYHH60PtrGw7l_AXZvLbVBG_CLcfwQ1M1oi2OZVpxkQ4t95uTxq-lCdegZ9QhAfBessaOwLUk5IVjbk2Un98RByG784JuS-8-mrg7YKOA5fn56idax_IWiBE46Cxnu8ITlmbHKmHw-sdpnm3hb50jB4evJmt3fcw_KI8_zKPORBM3vxljy7NJnSSh7s7QE0Sl0Svb427Drut6L3rAimtK5mzCseTcg9pkp707ZbClcYWfafF9VdB2A9TgMCOo6xfJEANsT18GkMH4B6PXDHBAhsNrRh2O0XOeWsfZStoyj5Mdt3b9JJfPFMW3h38yQ_lrmKYZQfJQ",
  "qi": "aDsPYxE-JBYsYhCYXSU7WsCrnFxNsRpFMcYXdmdryYIdQUpeemChDGzVJXLnJhE4cAS9TtLcNg82xZSKZvHrnkbFpRfSJxzEnvIXW4V0LHkxkxbmM0e9B7UrpYm6LKtvEY6I7L8wHFpHdOwV6NjY925oULEV156X0r55V7N0XF-jy3rbm71DCWRh6IDRghhCZQ3aNgJxE-OtnABqasaY6CQnTDRXLkGE0kq9GCx85-92fQLHMzvrMhr9m_2MHYJ_gZehL4j95CQzhD3Zh602D0YYYwRSsU4h5HGjlmN52pe-rfTLgwCJq5295s7qUP8TTMzbZAOM_hehksHpAaFghA"
}
```

## AR and Winston

Winston is the smallest possible unit of AR, similar to a [satoshi](https://en.bitcoin.it/wiki/Satoshi_\(unit\)) in Bitcoin, or [wei](http://ethdocs.org/en/latest/ether.html#denominations) in Ethereum.

**1 AR** = 1000000000000 Winston (12 zeros) and **1 Winston** = 0.000000000001 AR.

The HTTP API will return all amounts as winston strings, this is to allow for easy interoperability between environments that do not accommodate arbitrary-precision arithmetic.

JavaScript for example stores all numbers as double precision floating point values and as such cannot natively express the integer number of winston. Providing these values as strings allows them to be directly loaded into most 'bignum' libraries.

## Transactions

Endpoints for interacting with transactions and related resources.

## Get Transaction by ID

<mark style="color:blue;">`GET`</mark> `https://arweave.net/tx/{id}`

Get a transaction by its ID.

#### Path Parameters

| Name                                 | Type   | Description    |
| ------------------------------------ | ------ | -------------- |
| id<mark style="color:red;">\*</mark> | String | Transaction ID |

#### Headers

| Name   | Type   | Description      |
| ------ | ------ | ---------------- |
| Accept | String | application/json |

{% tabs %}
{% tab title="200 " %}

```javascript
{
  "format": 2,
  "id": "BNttzDav3jHVnNiV7nYbQv-GY0HQ-4XXsdkE5K9ylHQ",
  "last_tx": "jUcuEDZQy2fC6T3fHnGfYsw0D0Zl4NfuaXfwBOLiQtA",
  "owner": "posmE...psEok",
  "tags": [],
  "target": "",
  "quantity": "0",
  "data_root": "PGh0b...RtbD4",
  "data_size": "123",
  "reward": "124145681682",
  "signature": "HZRG_...jRGB-M"
}
```

{% endtab %}

{% tab title="202 " %}

```bash
pending
```

{% endtab %}

{% tab title="400 " %}

```bash
Invalid hash.
```

{% endtab %}

{% tab title="404 " %}

```bash
Not Found.
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
The **quantity** and **reward** values are always represented as winston strings.
{% endhint %}

See the [Transaction Format](#transaction-format) section for details about transaction structure and contents, with examples.

## Get Transaction Status

<mark style="color:blue;">`GET`</mark> `https://arweave.net/tx/{id}/status`

Gets the status of a transaction

#### Path Parameters

| Name                                 | Type   | Description    |
| ------------------------------------ | ------ | -------------- |
| id<mark style="color:red;">\*</mark> | String | Transaction ID |

#### Headers

| Name   | Type   | Description      |
| ------ | ------ | ---------------- |
| Accept | String | application/json |

{% tabs %}
{% tab title="200 " %}

```json
{
  "block_height": 641606,
  "block_indep_hash": "akLaom7XAKYvIW7HPCtCqSCgYTGAa0zjer6FXvF8lX0pAPzcHMZj4XnQq0jaedT6",
  "number_of_confirmations": 12
}
```

{% endtab %}
{% endtabs %}

## Get Transaction Field

<mark style="color:blue;">`GET`</mark> `https://arweave.net/tx/{id}/{field}`

Get a single field from a transaction.

#### Path Parameters

| Name                                 | Type   | Description                                                                                                                  |
| ------------------------------------ | ------ | ---------------------------------------------------------------------------------------------------------------------------- |
| id<mark style="color:red;">\*</mark> | String | Transaction ID                                                                                                               |
| id<mark style="color:red;">\*</mark> | String | Field name, acceptable values: id, last\_tx, owner, tags, target, quantity, data, data\_root, data\_size, reward, signature. |

#### Headers

| Name   | Type   | Description      |
| ------ | ------ | ---------------- |
| Accept | String | application/json |

{% tabs %}
{% tab title="200 " %}

```bash
jUcuEDZQy2fC6T3fHnGfYsw0D0Zl4NfuaXfwBOLiQtA
```

{% endtab %}

{% tab title="202 " %}

```bash
pending
```

{% endtab %}

{% tab title="400 " %}

```bash
Invalid hash.
```

{% endtab %}

{% tab title="404 " %}

```bash
Not Found.
```

{% endtab %}
{% endtabs %}

## Get Transaction Data

<mark style="color:blue;">`GET`</mark> `https://arweave.net/{id}`

Get the decoded data from a transaction.

The `Content-Type` will default to the one specified in a tag with tag-name `Content-Type`.

You can also get the data with a different `Content-Type` response, by doing:

## Get Transaction Data with extension

<mark style="color:blue;">`GET`</mark> `https://arweave.net/tx/{id}/data.{extension}`

Get the decoded data from a transaction with specific mime extension.

#### Path Parameters

| Name                                        | Type   | Description                                       |
| ------------------------------------------- | ------ | ------------------------------------------------- |
| id<mark style="color:red;">\*</mark>        | String | Transaction ID                                    |
| extension<mark style="color:red;">\*</mark> | String | Mime extension (example: ".html", ".txt", ".jpg") |

{% tabs %}
{% tab title="200 " %}
Any extension can be specified depending on the clients use case. Web pages can be requested with data.html

```html
<html
  lang="en-GB"
  class="b-pw-1280 no-touch orb-js id-svg bbcdotcom ads-enabled bbcdotcom-init bbcdotcom-responsive bbcdotcom-async bbcdotcom-ads-enabled orb-more-loaded  bbcdotcom-group-5"
  id="responsive-news"
>
  <meta charset="utf-8" />
  <meta
    name="viewport"
    content="width=device-width, initial-scale=1, user-scalable=1"
  />
  ...
</html>
```

{% endtab %}

{% tab title="202 " %}

```bash
pending
```

{% endtab %}

{% tab title="400 " %}

```bash
Invalid hash.
```

{% endtab %}

{% tab title="404 " %}

```bash
Not Found.
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
A `Content-Type` tag-name can be submitted with a transaction, the tag-value will then be used as the `Content-Type` header when serving the data response, this allows you to submit binary files like images and have them served with correct content type headers over HTTP.

The default Content-Type is **application/octet-stream**.
{% endhint %}

## Get Transaction Price

<mark style="color:blue;">`GET`</mark> `https://arweave.net/price/{bytes}/{target}`

This endpoint is used to calculate the minimum fee (reward) for a transaction of a specific size, and possibly to a specific address.This endpoint should always be used to calculate transaction fees as closely to the submission time as possible. Pricing is dynamic and determined by the network, so it's not always possible to accurately calculate prices offline or ahead of time. **Transactions with a fee that's too low will simply be rejected**.

#### Path Parameters

| Name                                    | Type   | Description                                                                                                                                                         |
| --------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| bytes<mark style="color:red;">\*</mark> | String | <p>The number of bytes to go into the transaction data field.<br><strong>If sending AR to another wallet with no data attached, then 0 should be used</strong>.</p> |
| target                                  | String | The target wallet address if sending AR to another wallet.                                                                                                          |

#### Headers

| Name   | Type   | Description      |
| ------ | ------ | ---------------- |
| Accept | String | application/json |

{% tabs %}
{% tab title="200 " %}

```html
10000
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
**An extra fee is taken for the first transaction sent to a new wallet address.** This is intentional and to discourage wallet spam.
{% endhint %}

### Examples

To get a fee for sending 10 AR to a wallet with address `abc` consult `/price/0/abc`.

To upload 123 bytes without transferring tokens consult `/price/123`.

To send some AR to the "abc" wallet and upload 123 bytes of data query `/price/123/abc`.

## Submit a transaction

<mark style="color:green;">`POST`</mark> `https://arweave.net/tx`

Submit a new transaction to the network.The request body should be a JSON object with the attributes described in Transaction Format.

#### Headers

| Name         | Type   | Description      |
| ------------ | ------ | ---------------- |
| Accept       | String | application/json |
| Content-Type | String | application/json |

{% tabs %}
{% tab title="200 " %}

```html
OK
```

{% endtab %}

{% tab title="208 " %}

```html
Transaction already processed.
```

{% endtab %}

{% tab title="400 " %}

```html
Transaction verification failed.
```

{% endtab %}

{% tab title="429 " %}

```html
Too Many Requests
```

{% endtab %}

{% tab title="503 " %}

```html
Transaction verification failed.
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
**Find more information** about these fields and examples in the [Transaction Format](#transaction-format) section.
{% endhint %}

## Wallets

Endpoints for getting information about a wallet.

## Get a Wallet Balance

<mark style="color:blue;">`GET`</mark> `https://arweave.net/wallet/{address}/balance`

Get the balance for a given wallet. Unknown wallet addresses will simply return 0.

#### Path Parameters

| Name    | Type   | Description    |
| ------- | ------ | -------------- |
| address | String | Wallet address |

{% tabs %}
{% tab title="200 " %}

```html
9554799572505
```

{% endtab %}

{% tab title="400 " %}

```html
Invalid address.
```

{% endtab %}
{% endtabs %}

## Get Last Transaction ID

<mark style="color:blue;">`GET`</mark> `https://arweave.net/wallet/{address}/last_tx`

Get the last outgoing transaction for the given wallet address.

#### Path Parameters

| Name    | Type   | Description    |
| ------- | ------ | -------------- |
| address | String | Wallet address |

{% tabs %}
{% tab title="200 " %}

```html
7SRpf0dWDqN4hbnCMPkdg02u_tzyMBtqwjDBy3EU9dg
```

{% endtab %}

{% tab title="400 " %}

```html
Invalid address.
```

{% endtab %}
{% endtabs %}

## Blocks

Endpoints for getting blocks and block data.

## Get Block by (hash) ID

<mark style="color:blue;">`GET`</mark> `https://arweave.net/block/hash/{id}`

Get a block by its id/hash (idep\_hash).

#### Path Parameters

| Name | Type   | Description                   |
| ---- | ------ | ----------------------------- |
| id   | String | The block hash (indep\_hash). |

#### Headers

| Name           | Type   | Description      |
| -------------- | ------ | ---------------- |
| Accept         | String | application/json |
| X-Block-Format | String | 2                |

{% tabs %}
{% tab title="200 " %}

```json
{
  "nonce": "W3Jy4wp2LVbDFhGX_hUjRQZCkTdEbKxz45E5OVe52Lo",
  "previous_block": "YuTyalVBTNB9t5KhuRezcIgxVz9PbQsbrcY4Tpkiu8XBPgglGM_Yql5qZd0c9PVG",
  "timestamp": 1586440919,
  "last_retarget": 1586440919,
  "diff": "115792089039110416381168389782714091630053560834545856346499935466490404274176",
  "height": 422250,
  "hash": "_____8422fLZnBsEsxtwEdpi8GZDHVT-aFlqroQDG44",
  "indep_hash": "5VTARz7bwDO4GqviCSI9JXm8_JOtoQwF-QCZm0Gt2gVgwdzSY3brOtOD46bjMz09",
  "txs": ["IRPCjc_ws7aS5GWp4mwR2k-HuQy-zT_GWrgR6kRdbmI"],
  "tx_root": "lsoo-p3Tj7oblZ-54WVPHoVguqgw5rA9Jf3lLH6H8zY",
  "tx_tree": [],
  "wallet_list": "N5NJtXhgH9bPmXoSopehcr_zqwyPjjg3igel0V8G1DdLk_BYdoRVIBsqjVA9JmFc",
  "reward_addr": "Oox7m4HIcVhUtMd6AUuGtlaOoSCmREUNPyyKQCbz4d4",
  "tags": [],
  "reward_pool": 3026104059201252,
  "weave_size": 407672420044,
  "block_size": 937455,
  "cumulative_diff": "99416580392277",
  "hash_list_merkle": "akSjDrBKPuepJMOhO_S9C-iFp5zn9Glv57HGdN_WPqEToWC0Ukb37Gzs4PDA7oLU",
  "poa": {
    "option": "1",
    "tx_path": "xZ6vhVXw_0BlD-Xkv3KtfnJeLXykjkjUrwcPsXw2JUnie021At7I-fMZkt5EF_xOHtcdq4RIqXto1gwFAM5eZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfDSbuKpWzKZ9HP_N2I4gX6cUujNsJtelJULjHmbZp0XzmkBljlK4S1PMlSrTePIjfJdRfqvFNE8idpnj69X1P0zAfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAn4ybxD6lgdArqnPJzs7t8bU-7KfEb1YqpAOvbr6q3vmP-MWnCTWZJKTL90azeYZmHrTMx-iutuT6bP6CUC7zgHAfGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmTpFIGvz18gKl5rZ6p2Ve4yVeRzWNwibyVTKz80HSBYprfIpVJk9oRG3E5q1xRn5wErqyH2vFLbsLxDqKcR0vLunBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfDwBRWXT_vDxcaBxGmihJwlU_n_PFBCOsP-Lx3hSG6H6UGesIMAEYMmd2c5QixR-fCimhm_9S582cLzSUffsrAHliQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmP-RTrBhY9xCC1yywyehB7X6EmlBjyQBqm0y1L9Ex_dkswkf50rG-LE29UJP4st0bzFthHukfHvvWZY3bgIiog3L7gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfD3YxQguhfH8daMBAQrveQq3MMp4iKB3khk5mbU34Ckl1q8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJj_kQ",
    "data_path": "bTVpffiN3SSDeqBEJpKiXegQGKKnprS_AFMh6zz4QRIU-8dJuvFzyKxqjkDHQvtKl0Eajfm18yZsjaAJkNhbAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAOH0cuoLq1CTbSelF9C59C-fcO3a3ywoceaNxRl4nQQH1BuwcpiNdDdZvEz6Pfk5wKbnsF_VwVIgrfcLZgsxoKwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAefOoaNyW7ORmrzbZ5O7midzLByHooxjM5oEMJfZbQsY9mKS14G9fUEFmFaCPPJX6EXVGrUwROzDIWfHf8oHErAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAktmxYyC7BSV-MULrjzgdJJYfJY7lDFcKe3mo_EX19xoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA",
    "chunk": "aHQ6OTBweH1..."
  }
}
```

{% endtab %}

{% tab title="404 " %}

```html
Block not found.
```

{% endtab %}
{% endtabs %}

## Get Block by Height

<mark style="color:blue;">`GET`</mark> `https://arweave.net/block/height/{height}`

Get a block by its height.

#### Path Parameters

| Name                                     | Type   | Description       |
| ---------------------------------------- | ------ | ----------------- |
| height<mark style="color:red;">\*</mark> | String | The block height. |

#### Headers

| Name           | Type   | Description      |
| -------------- | ------ | ---------------- |
| Accept         | String | application/json |
| X-Block-Format | String | 2                |

{% tabs %}
{% tab title="200 " %}

```json
{
  "nonce": "W3Jy4wp2LVbDFhGX_hUjRQZCkTdEbKxz45E5OVe52Lo",
  "previous_block": "YuTyalVBTNB9t5KhuRezcIgxVz9PbQsbrcY4Tpkiu8XBPgglGM_Yql5qZd0c9PVG",
  "timestamp": 1586440919,
  "last_retarget": 1586440919,
  "diff": "115792089039110416381168389782714091630053560834545856346499935466490404274176",
  "height": 422250,
  "hash": "_____8422fLZnBsEsxtwEdpi8GZDHVT-aFlqroQDG44",
  "indep_hash": "5VTARz7bwDO4GqviCSI9JXm8_JOtoQwF-QCZm0Gt2gVgwdzSY3brOtOD46bjMz09",
  "txs": ["IRPCjc_ws7aS5GWp4mwR2k-HuQy-zT_GWrgR6kRdbmI"],
  "tx_root": "lsoo-p3Tj7oblZ-54WVPHoVguqgw5rA9Jf3lLH6H8zY",
  "tx_tree": [],
  "wallet_list": "N5NJtXhgH9bPmXoSopehcr_zqwyPjjg3igel0V8G1DdLk_BYdoRVIBsqjVA9JmFc",
  "reward_addr": "Oox7m4HIcVhUtMd6AUuGtlaOoSCmREUNPyyKQCbz4d4",
  "tags": [],
  "reward_pool": 3026104059201252,
  "weave_size": 407672420044,
  "block_size": 937455,
  "cumulative_diff": "99416580392277",
  "hash_list_merkle": "akSjDrBKPuepJMOhO_S9C-iFp5zn9Glv57HGdN_WPqEToWC0Ukb37Gzs4PDA7oLU",
  "poa": {
    "option": "1",
    "tx_path": "xZ6vhVXw_0BlD-Xkv3KtfnJeLXykjkjUrwcPsXw2JUnie021At7I-fMZkt5EF_xOHtcdq4RIqXto1gwFAM5eZgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfDSbuKpWzKZ9HP_N2I4gX6cUujNsJtelJULjHmbZp0XzmkBljlK4S1PMlSrTePIjfJdRfqvFNE8idpnj69X1P0zAfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAn4ybxD6lgdArqnPJzs7t8bU-7KfEb1YqpAOvbr6q3vmP-MWnCTWZJKTL90azeYZmHrTMx-iutuT6bP6CUC7zgHAfGgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmTpFIGvz18gKl5rZ6p2Ve4yVeRzWNwibyVTKz80HSBYprfIpVJk9oRG3E5q1xRn5wErqyH2vFLbsLxDqKcR0vLunBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfDwBRWXT_vDxcaBxGmihJwlU_n_PFBCOsP-Lx3hSG6H6UGesIMAEYMmd2c5QixR-fCimhm_9S582cLzSUffsrAHliQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmP-RTrBhY9xCC1yywyehB7X6EmlBjyQBqm0y1L9Ex_dkswkf50rG-LE29UJP4st0bzFthHukfHvvWZY3bgIiog3L7gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfD3YxQguhfH8daMBAQrveQq3MMp4iKB3khk5mbU34Ckl1q8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJj_kQ",
    "data_path": "bTVpffiN3SSDeqBEJpKiXegQGKKnprS_AFMh6zz4QRIU-8dJuvFzyKxqjkDHQvtKl0Eajfm18yZsjaAJkNhbAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAOH0cuoLq1CTbSelF9C59C-fcO3a3ywoceaNxRl4nQQH1BuwcpiNdDdZvEz6Pfk5wKbnsF_VwVIgrfcLZgsxoKwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAefOoaNyW7ORmrzbZ5O7midzLByHooxjM5oEMJfZbQsY9mKS14G9fUEFmFaCPPJX6EXVGrUwROzDIWfHf8oHErAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAktmxYyC7BSV-MULrjzgdJJYfJY7lDFcKe3mo_EX19xoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAA",
    "chunk": "aHQ6OTB..."
  }
}
```

{% endtab %}

{% tab title="404 " %}

```html
Block not found.
```

{% endtab %}
{% endtabs %}

## Network and Node State

Endpoints for getting information about the current network and node state.

## Network Info

<mark style="color:blue;">`GET`</mark> `https://arweave.net/info`

Get the current network information including height, current block, and other properties.

#### Headers

| Name   | Type   | Description      |
| ------ | ------ | ---------------- |
| Accept | String | application/json |

{% tabs %}
{% tab title="200 " %}

```json
{
  "network": "arweave.N.1",
  "version": 5,
  "release": 43,
  "height": 551511,
  "current": "XIDpYbc3b5iuiqclSl_Hrx263Sd4zzmrNja1cvFlqNWUGuyymhhGZYI4WMsID1K3",
  "blocks": 97375,
  "peers": 64,
  "queue_length": 0,
  "node_state_latency": 18
}
```

{% endtab %}
{% endtabs %}

## Peer list

<mark style="color:blue;">`GET`</mark> `https://arweave.net/peers`

Get the list of peers from the node. Nodes can only respond with peers they currently know about, so this will not be an exhaustive or complete list of nodes on the network.

#### Headers

| Name   | Type   | Description      |
| ------ | ------ | ---------------- |
| Accept | String | application/json |

{% tabs %}
{% tab title="200 " %}

```json
["127.0.0.1:1984", "0.0.0.0:1984"]
```

{% endtab %}
{% endtabs %}

## Chunks

## Upload Chunks

<mark style="color:green;">`POST`</mark> `https://arweave.net/chunk`

Upload Data Chunks.

Example json-data payload:

```json
{
  "data_root": "<Base64URL encoded data merkle root>",
  "data_size": "a number, the size of transaction in bytes",
  "data_path": "<Base64URL encoded inclusion proof>",
  "chunk": "<Base64URL encoded data chunk>",
  "offset": "<a number from [start_offset, start_offset + chunk size), relative to other chunks>"
}
```

#### Headers

| Name         | Type   | Description      |
| ------------ | ------ | ---------------- |
| Accept       | String | application/json |
| Content-Type | String | application/json |

{% tabs %}
{% tab title="200 " %}

```html
OK
```

{% endtab %}

{% tab title="400 " %}
When chunk is bigger than 256 KiB.

```json
{ "error": "chunk_too_big" }
```

or

When the proof is bigger than 256 KiB.

```json
{ "error": "data_path_too_big" }
```

or

When the offset is bigger than 2 ^ 256.

```json
{ "error": "offset_too_big" }
```

or

When the data size is bigger than 2 ^ 256.

```json
{ "error": "data_size_too_big" }
```

or

When `data_path` is bigger than the chunk. **NOTE:** If the original data is too small, it should not be uploaded in chunks. Also, this does not apply to chunks which are the only chunks of their transaction and to the last chunk of every transaction.

```json
{ "error": "chunk_proof_ratio_not_attractive" }
```

or

When the node hasn’t seen the header of the corresponding transaction yet.

```json
{ "error": "data_root_not_found" }
```

or

The corresponding transaction is pending and it is either of:

* 50 MiB worth of chunks have been already accepted by this node for this (data root, data size);
* 2 GiB worth of all pending chunks have been accepted by this node.

Note: The values above are default values, any node may configure bigger limits.

```json
{ "error": "exceeds_disk_pool_size_limit" }
```

or

```json
{ "error": "invalid_proof" }
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
Note that `data_size` is requested in addition to data root, because one may submit the same data root with different transaction sizes. To avoid chunks overlap, data root always comes together with the size.
{% endhint %}

## Download Chunks

## Get Transaction Data

<mark style="color:blue;">`GET`</mark> `https://arweave.net/tx/{id}/data`

The endpoint serves data regardless of how it was uploaded

#### Path Parameters

| Name | Type   | Description    |
| ---- | ------ | -------------- |
| id   | String | Transaction ID |

{% tabs %}
{% tab title="200 " %}

```
<Base64URL encoded data>
```

{% endtab %}

{% tab title="400 " %}

```
tx_data_too_big
```

{% endtab %}

{% tab title="503 " %}
When the node has not joined the network yet.

```json
{ "error": "not_joined" }
```

or

```json
{ "error": "timeout" }
```

{% endtab %}
{% endtabs %}

## Get Transaction Offset and Size

<mark style="color:blue;">`GET`</mark> `https://arweave.net/tx/{id}/offset`

Get the absolute end offset and size of the transaction

Note that the client may use this information to collect transaction chunks. Start with the end offset and fetch a chunk via `GET /chunk/<offset>`. Subtract its size from the transaction size, if there are more chunks to fetch, subtract the size of the chunk from the offset and fetch the next chunk.

#### Path Parameters

| Name | Type   | Description    |
| ---- | ------ | -------------- |
| id   | String | Transaction ID |

{% tabs %}
{% tab title="200 " %}

```json
{ "offset": "...", "size": "..." }
```

{% endtab %}

{% tab title="400 " %}

```json
{ "error": "invalid_address" }
```

{% endtab %}

{% tab title="503 " %}
When the node has not joined the network yet.

```json
{ "error": "not_joined" }
```

or

```json
{ "error": "timeout" }
```

{% endtab %}
{% endtabs %}


# Wallet FAQ

All questions surrounding wallets

## **Which wallet(s) can I use for AR tokens?**

The following are wallets (developed by the Arweave community) which are capable of storing AR tokens.

|                  | [arweave.app](https://arweave.app/)                                        | [Wander](https://www.wander.app/)                       |
| ---------------- | -------------------------------------------------------------------------- | ------------------------------------------------------- |
| AR tokens        | true                                                                       | true                                                    |
| dApp permissions | true                                                                       | true                                                    |
| Open Source      | true                                                                       | true                                                    |
| No Install       | true                                                                       | false                                                   |
| NFTs             | false                                                                      | true                                                    |
| PSTs             | false                                                                      | true                                                    |
| Page Archiving   | false                                                                      | true                                                    |
| Guide            | [Link](https://docs.arweave.org/info/wallets/arweave-web-extension-wallet) | [Link](https://docs.arweave.org/info/wallets/arconnect) |

### Arweave.app

[Arweave.app](https://arweave.app/) is an open-source web application, also available as an addon for [Chrome-like](https://chrome.google.com/webstore/detail/arweaveapp/hloekinecmafifaghekdjepphlabepkl) and [Firefox](https://addons.mozilla.org/firefox/addon/arweave-app) browsers. The source code is available on [Github](https://github.com/jfbeats/ArweaveWebWallet).

### Wander

[Wander](https://www.wander.app/) is a mobile wallet and browser extension available for Chromium-based browsers. More information is available in the [Wander documentation](https://docs.wander.app).

## **Why is it recommended to use an Arweave wallet?**

Wallets securely store your private keys and provide a bridge-like interface for dApps to sign transactions and other data with your approval. This protects your AR tokens from malicious applications, by preventing them from draining your wallet or signing a message without your consent.

## **How do I use an Arweave wallet?**

You can find the guides for each wallet above, by clicking on the links.

## **Can I use these wallets as a cold wallet?**

Yes, you can use most of the wallets available for Arweave to generate cold wallets. You can find a step by step guide for this [here](/developers/wallets/generating-cold-wallet).

**\* Please make sure to keep multiple copies of your wallet key file in secure locations, as we cannot help you to recover your wallet if you lose it \***

## **Are AR tokens compatible with any hardware wallets?**

We are almost there! Both Ledger and Keystone are working on integrating Arweave into their services. arweave.app has done the initial client integration but full support is pending an upcoming ledger release.

## **Can I send AR tokens to MyEtherWallet/another third party wallet or an ETH address?**

No, these are fundamentally incompatible. Don’t send your AR tokens to other blockchain addresses or wallets.

## **Are ECDSA wallets supported?**

Yes. Since the [2.9 hard fork](/developers/development/overview/ecdsa-keys), Arweave accounts may use either RSA or ECDSA (secp256k1) keys. Note that Arweave ECDSA addresses are **not** compatible with Ethereum addresses, even though both use secp256k1. See [ECDSA Keys](/developers/development/overview/ecdsa-keys) for details.

\## **Where can I see my AR token transfers' status?**

The [Viewblock](https://viewblock.io/arweave) block explorer allows you to discover and view statuses of Arweave transactions. To find your transfer, you can search for your wallet address or the ID of your transfer in the search bar, at the top of their site.


# Arweave.app Web Wallet

Here you will find a step-by-step guide on how to set up an Arweave.app web wallet

If you have an existing wallet you should already be familiar with the basics, however if it’s your first venture into the wonderful world of Arweave: don’t sweat it, because we’ve put together a step-by-step guide to ensure that you can get up and running in no time.

## Getting Started

Setting up your wallet is super easy, simply open up <https://arweave.app> in your browser. Arweave.app is a community developed, open source, project that gets you started on Arweave with a minimum of effort. Upon arrival you'll be presented with the welcome screen.

![arweave.app welcome screen](/files/TxJGVTgpQGi0swhWEGYr)

If you're a new arweave wallet user, continue on to the next section. If you're an existing user who already has a keyfile, you can skip to the 'Existing Users' section further down the page.

## **New Users: Generating Your Wallet**

If you're a first time user click the small <img src="/files/Ur4qkWRAjKhyyVea7XUn" alt="" data-size="line"> button in the bottom left to generate a new public/private key pair. These keys are both your password and your unique ID when interacting with arweave.

![Add Wallet Screen](/files/jKAHnO4HGO7KWIAoOSCm)

Click the "Create new wallet" button on the screen that appears.

![Passphrase window](/files/4zZzX41W87VaGfgZXyq9)

Immediately you'll be presented with a 12 word passphrase. This is a secret code that will allow you to recreate your wallets public and private key pair. Write this phrase down on a piece of paper, place it in a ziplock bag (to protect from water damage) and store it in a safe and secure location. This is your way to recover your wallet and its contents if your computer ever stops working.

It will also let you store your key pair in wallet applications on other devices. It may take a few seconds for the keys to finish generating but once they do you'll see the button change to look like this.

![Click here to proceed](/files/V1f95mq49aD72hi3HAw9)

Click the button to proceed 😀

![New Wallet](/files/02qgiaLqmf5USDAYwUPK)

Congratulations, you've added a new wallet key pair. The line of text that looks like some kind of code is your wallet address. In the image above the wallet address is `omsGXfLHi0AeE144E0uQXaNxsRoaftzPjq2TxaZyDLg`. Wallet addresses are public and sharing them will not compromise the security of your wallet.

Arweave.app generates a unique icon for each wallet key pair you add to help distinguish them from one another visually.

Along with your 12 word passphrase, you can also download your public/private key pair in a key file. The 12 word passphrase will be able to recreate this file if you lose it, but it's often convenient to have a copy of the key file as well. Not all wallet apps support restoring from a passphrase.

Click the "Download" button. This will initiate a download of the key file.

This key file is for your newly generated Arweave wallet that **you must keep safe and secure**. By safe and secure, we mean keeping it protected from loss or misplacement as it’s not possible to regenerate. In simpler terms: once it’s gone, it’s gone! We always recommend storing it in a safe location on multiple (at least 3) devices. We also recommend that you encrypt the file, as anyone who has access to it also has access to your wallet.

You only have one chance to download the key file, however if for some reason the download couldn’t be completed, you can start the process all over again and a fresh wallet will be generated.

{% hint style="info" %}
**Key File:** Your key file will be called something like *omsGXfLHi0AeE144E0uQXaNxsRoaftzPjq2TxaZyDLg.json.* The filename is your unique wallet address + ".json". Wallet addresses are 43 characters long and can contain any alphanumeric characters, as well as dashes and underscores (*a-z0–9-\_).* Your key file is a standardized and interoperable format called JSON Web Key, which you can [read more about here](https://tools.ietf.org/html/rfc7517).
{% endhint %}

*\*\*\*\**

## **New Users: Managing your key pairs**

In addition to downloading the key file to your computer/hard drive, a copy of the file will also exist in local storage for the arweave.app page. Don’t worry though, your browser storage is secure and there are lots of mechanisms to stop malicious content (like websites and other extensions) from accessing it. However this doesn't stop someone with physical access to your machine from using your wallets. Once you've stored the passphrase and/or key file for your wallet key pair you can safely delete them from the arweave.app wallet app, knowing you can re-add them later. It's a good idea not to keep wallet key pairs with a lot of AR tokens in the arweave.app wallet for this reason.

## **Existing Users: Loading Your Wallet**

If you already have an Arweave key file, you can dive straight into loading your wallet by dragging and dropping it onto the "Passphrase" area.

![Passphrase or Key File](/files/xiPXVte64ufR3iZ5k3Xo)

You can also click the little <img src="/files/PTtJgkWsftDOIDI8oGl5" alt="" data-size="line"> icon to bring up a file explore and browse for the key file.

If you'd prefer to restore your wallet using the 12 word passphrase, you can click on the little <img src="/files/VRHXtJ0QalKY8eSs5iQT" alt="" data-size="line"> icon and type or paste your 12 words into the passphrase box.

## **Wallet Options & Multiple Wallets**

You can load additional wallet key pairs into the arweave.app web wallet at any time, by clicking the <img src="/files/Ur4qkWRAjKhyyVea7XUn" alt="" data-size="line"> icon in the bottom left at any time and repeating the process of creating a new wallet or loading an existing one from passphrase or key file.

You can navigate between loaded wallets by clicking their unique icon in the top left.

![Two wallets](/files/xsDDz439mWoQC98fftoA)

## Removing a key pair from the wallet

To remove a set of wallet keys from the wallet app, click the <img src="/files/yucGPclec25hJfwPUW9O" alt="" data-size="line"> icon in the bottom left. This will bring up a settings panel for the app.

![Wallet Settings](/files/fvCLb4AhFOXislLwAvSQ)

From this screen you'll be able to re-download the key file for a particular wallet key pair or click the "Delete" button to remove it from the wallet app entirely. As long as you have your passphrase or key file you'll be able to add it back whenever you like so keep those safe and secure.

\*\*\*\*


# Generating a Cold Wallet

Here is a step-by-step guide for generating an Arweave cold wallet

The following procedure allows you to generate an extremely secure Arweave cold wallet. Using this procedure, your keys will never be exposed to an internet-connected computer before you intend to use your tokens, giving you exceptionally strong guarantees about the security of your AR.

{% hint style="info" %}
This procedure may seem long but we have broken each of its steps down into granular chunks that should be simple to follow
{% endhint %}

### Cold Wallet generation with Arweave.app

1. Open up <https://arweave.app> in your browser tab.
2. Once loaded, disconnect your computer from the internet
3. Click the \[ + ] button in the bottom left\
   ![arweave.app add wallet button in welcome screen](/files/X1BO2CjHzYn9iGL4GYbu)
4. Click the big "Create new wallet" button in the screen that pops up.\
   ![arweave.app create wallet screen](/files/SHQRPcyqxb4VAtGjeY8n)
5. Write down your passphrase on a piece of paper.
6. When the wallet generation step completes, click the "Click to proceed" button.\
   ![arweave.app proceed btn](/files/UFzvkCeYVoVrvdoGGvC4)
7. Identify your newly created wallet on the next screen and click the "Download" button to download the key file.\
   ![arweave.app download wallet](/files/OtNpL8pNjRBPXcjt5Sq2)
8. Make copies of this file on multiple offline storage mediums (for example, USB sticks or prints of the file to physical paper). **Store these copies securely**
9. Click the "Delete" button to remove your newly created wallet from the browser.\
   ![arweave.app delete wallet](/files/58GQPsN3jUqdCBYkCuXn)
10. Reconnect to the internet

### Cold Wallet generation with ArConnect

1. Download ArConnect for [Chrome](https://chrome.google.com/webstore/detail/arconnect/einnioafmpimabjcddiinlhmijaionap) or [Firefox](https://addons.mozilla.org/en-US/firefox/addon/arconnect/).
2. Once downloaded, the wallet will take you to the setup page. At this point, you'll need to disconnect your device from the internet. If the setup page has not been opened, you can click on the ArConnect icon in the extensions section (seen below) to open it.

| ![ArConnect Chrome Icon](/files/ml6e8oKdwJQAwXQOp7LE) | ![ArConnect Chrome Icon](/files/R4yvZorN09drvINXc2Ka) |
| ----------------------------------------------------- | ----------------------------------------------------- |
| Chrome                                                | Firefox                                               |

3. On the setup page, you'll need to create a password. Fill out the password inputs and click "Create". ![ArConnect Welcome Screen](/files/FV7MFy1Z5l6AbLLppR5b)
4. Click the "New Wallet" button on the next screen and wait for your new wallet to generate. While this process is in progress you can write down your seedphrase on a piece of paper. ![ArConnect New Wallet Button](/files/w5t6oarE6bUDht38e8jz)
5. Once the wallet has generated, a button with the text "Download Keyfile" will appear. Click it to download the generated keyfile. ![ArConnect Download Wallet Button](/files/wCShqkENNS5plLWD2uHY)
6. As a safety measure, this file should be stored on different offline storage mediums, like how mentioned [above](#cold-wallet-generation-with-arweaveapp).
7. Now go into your extensions settings by entering `chrome://extensions` on Chrome, `about:addons` on Firefox into your browser's address bar. There you'll have to identify the ArConnect extension/add-on and click on the "Remove" button to uninstall it.

| ![ArConnect Chrome Icon](/files/dWnUN8ShU3xDbMUMWvZk) | ![ArConnect Chrome Icon](/files/gWGuzQCXheMgUMCpV08o) |
| ----------------------------------------------------- | ----------------------------------------------------- |
| Chrome                                                | Firefox                                               |

8. Your wallet is now removed from your browser and you can reconnect to the internet.

### Cold Wallet generation with the ArDrive CLI (Advanced)

{% hint style="warning" %}
**This process is for more advanced users. If you have not used a CLI before, it is recommended to follow the guides above!**
{% endhint %}

1. You'll need to have [Node.js](https://nodejs.org/) and [npm](https://docs.npmjs.com/cli/v9/) installed for the ArDrive CLI to work.
2. Open up your OS' default terminal and install the [ArDrive CLI](https://www.npmjs.com/package/ardrive-cli) with the following command:

```sh
npm install -g ardrive-cli
```

3. Disconnect your device from the internet.
4. Generate a seedphrase with the following command, then write it down on a piece of paper.

```sh
ardrive generate-seedphrase
```

5. Copy the generated seedphrase and paste it between the quotes in the following command. Run the command to generate a keyfile.

```sh
ardrive generate-wallet -s "PASTE_GENERATED_SEEDPHRASE_HERE" > ./wallet.json
```

6. You'll be able to find you keyfile name `wallet.json` in the directory where you ran the CLI. You should copy it to an offline storage medium and delete the file from your device.
7. You can now reconnect your device to the internet.

{% hint style="success" %}
**Congratulations for completing the steps! Your AR tokens will now be stored safely and securely for months and years to come**
{% endhint %}

Had problems? Don’t worry, drop us a line at <team@arweave.org> and we'd be happy to help.

If you'd like to make transactions from your cold wallet the ArDrive command line tool has a nice writeup for how to [securely send a transaction from a cold wallet](https://github.com/ardriveapp/ardrive-cli#cold-tx).


# Privacy Policy

Privacy policy for arweave.org and tokens.arweave.org

Effective date: February 13, 2019

Minimum Spanning Technologies Ltd. ("us", "we", or "our") operates the <http://arweave.org> website (hereinafter referred to as the "Service").

This page informs you of our policies regarding the collection, use and disclosure of personal data when you use our Service and the choices you have associated with that data.

We use your data to provide and improve the Service. By using the Service, you agree to the collection and use of information in accordance with this policy. Unless otherwise defined in this Privacy Policy, the terms used in this Privacy Policy have the same meanings as in our Terms and Conditions, accessible from <http://arweave.org>

### Definitions

* **Service**

  Service is the <http://arweave.org> website operated by Minimum Spanning Technologies Ltd.
* **Personal Data**

  Personal Data means data about a living individual who can be identified from those data (or from those and other information either in our possession or likely to come into our possession).
* **Usage Data**

  Usage Data is data collected automatically either generated by the use of the Service or from the Service infrastructure itself (for example, the duration of a page visit).
* **Cookies**

  Cookies are small files stored on your device (computer or mobile device).
* **Data Controller**

  Data Controller means the natural or legal person who (either alone or jointly or in common with other persons) determines the purposes for which and the manner in which any personal information are, or are to be, processed.

  For the purpose of this Privacy Policy, we are a Data Controller of your Personal Data.
* **Data Processors (or Service Providers)**

  Data Processor (or Service Provider) means any natural or legal person who processes the data on behalf of the Data Controller.

  We may use the services of various Service Providers in order to process your data more effectively.
* **Data Subject (or User)**

  Data Subject is any living individual who is using our Service and is the subject of Personal Data.

### Information Collection and Use

We collect several different types of information for various purposes to provide and improve our Service to you.

#### Types of Data Collected

**Personal Data**

While using our Service, we may ask you to provide us with certain personally identifiable information that can be used to contact or identify you ("Personal Data"). Personally identifiable information may include, but is not limited to:

* Email address
* First name and last name
* Cookies and Usage Data

We may use your Personal Data to contact you with newsletters, marketing or promotional materials and other information that may be of interest to you. You may opt out of receiving any, or all, of these communications from us by following the unsubscribe link or instructions provided in any email we send or by contacting us.

**Usage Data**

We may also collect information on how the Service is accessed and used ("Usage Data"). This Usage Data may include information such as your computer's Internet Protocol address (e.g. IP address), browser type, browser version, the pages of our Service that you visit, the time and date of your visit, the time spent on those pages, unique device identifiers and other diagnostic data.

**Tracking & Cookies Data**

We use cookies and similar tracking technologies to track the activity on our Service and we hold certain information.

Cookies are files with a small amount of data which may include an anonymous unique identifier. Cookies are sent to your browser from a website and stored on your device. Other tracking technologies are also used such as beacons, tags and scripts to collect and track information and to improve and analyse our Service.

You can instruct your browser to refuse all cookies or to indicate when a cookie is being sent. However, if you do not accept cookies, you may not be able to use some portions of our Service.

Examples of Cookies we use:

* **Session Cookies.** We use Session Cookies to operate our Service.
* **Preference Cookies.** We use Preference Cookies to remember your preferences and various settings.
* **Security Cookies.** We use Security Cookies for security purposes.

### Use of Data

Minimum Spanning Technologies Ltd. uses the collected data for various purposes:

* To provide and maintain our Service
* To notify you about changes to our Service
* To allow you to participate in interactive features of our Service when you choose to do so
* To provide customer support
* To gather analysis or valuable information so that we can improve our Service
* To monitor the usage of our Service
* To detect, prevent and address technical issues
* To provide you with news, special offers and general information about other goods, services and events which we offer that are similar to those that you have already purchased or enquired about unless you have opted not to receive such information

### Legal Basis for Processing Personal Data under the General Data Protection Regulation (GDPR)

If you are from the European Economic Area (EEA), Minimum Spanning Technologies Ltd. legal basis for collecting and using the personal information described in this Privacy Policy depends on the Personal Data we collect and the specific context in which we collect it.

Minimum Spanning Technologies Ltd. may process your Personal Data because:

* We need to perform a contract with you
* You have given us permission to do so
* The processing is in our legitimate interests and it is not overridden by your rights
* To comply with the law

### Retention of Data

Minimum Spanning Technologies Ltd. will retain your Personal Data only for as long as is necessary for the purposes set out in this Privacy Policy. We will retain and use your Personal Data to the extent necessary to comply with our legal obligations (for example, if we are required to retain your data to comply with applicable laws), resolve disputes and enforce our legal agreements and policies.

Minimum Spanning Technologies Ltd. will also retain Usage Data for internal analysis purposes. Usage Data is generally retained for a shorter period of time, except when this data is used to strengthen the security or to improve the functionality of our Service, or we are legally obligated to retain this data for longer periods.

### Transfer of Data

Your information, including Personal Data, may be transferred to — and maintained on — computers located outside of your state, province, country or other governmental jurisdiction where the data protection laws may differ from those of your jurisdiction.

If you are located outside United Kingdom and choose to provide information to us, please note that we transfer the data, including Personal Data, to United Kingdom and process it there.

Your consent to this Privacy Policy followed by your submission of such information represents your agreement to that transfer.

Minimum Spanning Technologies Ltd. will take all the steps reasonably necessary to ensure that your data is treated securely and in accordance with this Privacy Policy and no transfer of your Personal Data will take place to an organisation or a country unless there are adequate controls in place including the security of your data and other personal information.

### Disclosure of Data

Disclosure for Law Enforcement

Under certain circumstances, Minimum Spanning Technologies Ltd. may be required to disclose your Personal Data if required to do so by law or in response to valid requests by public authorities (e.g. a court or a government agency).

Legal Requirements

Minimum Spanning Technologies Ltd. may disclose your Personal Data in the good faith belief that such action is necessary to:

* To comply with a legal obligation
* To prevent or investigate possible wrongdoing in connection with the Service
* To protect against legal liability

### Security of Data

The security of your data is important to us but remember that no method of transmission over the Internet or method of electronic storage is 100% secure. While we strive to use commercially acceptable means to protect your Personal Data, we cannot guarantee its absolute security.

Your Data Protection Rights under the General Data Protection Regulation (GDPR)

If you are a resident of the European Economic Area (EEA), you have certain data protection rights. Minimum Spanning Technologies Ltd. aims to take reasonable steps to allow you to correct, amend, delete or limit the use of your Personal Data.

If you wish to be informed about what Personal Data we hold about you and if you want it to be removed from our systems, please contact us.

In certain circumstances, you have the following data protection rights:

* **The right to access, update or delete the information we have on you.** Whenever made possible, you can access, update or request deletion of your Personal Data directly within your account settings section. If you are unable to perform these actions yourself, please contact us to assist you.
* **The right of rectification.** You have the right to have your information rectified if that information is inaccurate or incomplete.
* **The right to object.** You have the right to object to our processing of your Personal Data.
* **The right of restriction.** You have the right to request that we restrict the processing of your personal information.
* **The right to data portability.** You have the right to be provided with a copy of the information we have on you in a structured, machine-readable and commonly used format.
* **The right to withdraw consent.** You also have the right to withdraw your consent at any time where Minimum Spanning Technologies Ltd. relied on your consent to process your personal information.

Please note that we may ask you to verify your identity before responding to such requests.

You have the right to complain to a Data Protection Authority about our collection and use of your Personal Data. For more information, please contact your local data protection authority in the European Economic Area (EEA).

Service Providers

We may employ third party companies and individuals to facilitate our Service ("Service Providers"), provide the Service on our behalf, perform Service-related services or assist us in analysing how our Service is used.

These third parties have access to your Personal Data only to perform these tasks on our behalf and are obligated not to disclose or use it for any other purpose.

Analytics

We may use third-party Service Providers to monitor and analyse the use of our Service.

* **Google Analytics**

  Google Analytics is a web analytics service offered by Google that tracks and reports website traffic. Google uses the data collected to track and monitor the use of our Service. This data is shared with other Google services. Google may use the collected data to contextualise and personalise the ads of its own advertising network.

  You can opt-out of having made your activity on the Service available to Google Analytics by installing the Google Analytics opt-out browser add-on. The add-on prevents the Google Analytics JavaScript (ga.js, analytics.js and dc.js) from sharing information with Google Analytics about visits activity.

  For more information on the privacy practices of Google, please visit the Google Privacy & Terms web page: <https://policies.google.com/privacy?hl=en>

### Links to Other Sites

Our Service may contain links to other sites that are not operated by us. If you click a third party link, you will be directed to that third party's site. We strongly advise you to review the Privacy Policy of every site you visit.

We have no control over and assume no responsibility for the content, privacy policies or practices of any third party sites or services.

Children's Privacy

Our Service does not address anyone under the age of 18 ("Children").

We do not knowingly collect personally identifiable information from anyone under the age of 18. If you are a parent or guardian and you are aware that your Child has provided us with Personal Data, please contact us. If we become aware that we have collected Personal Data from children without verification of parental consent, we take steps to remove that information from our servers.

Changes to This Privacy Policy

We may update our Privacy Policy from time to time. We will notify you of any changes by posting the new Privacy Policy on this page.

We will let you know via email and/or a prominent notice on our Service, prior to the change becoming effective and update the "effective date" at the top of this Privacy Policy.

You are advised to review this Privacy Policy periodically for any changes. Changes to this Privacy Policy are effective when they are posted on this page.

Contact Us

If you have any questions about this Privacy Policy, please contact us:

* By email: <team@arweave.org>
* By visiting this page on our website: <https://docs.arweave.org/policies/privacy-policy>


