Run Mainnet Node

About Mainnet.

NOTE: Ensure you meet the prerequisites before running a node.

Run a Mainnet Unit Zero node by following the steps:

Prerequisites

Step 1: Configure Node

  1. Create the main directory and go to it:

    mkdir main
    cd main

    NOTE: Ensure you have the read and write access to the directory.

  2. In the main directory, create the subdirectories:

    mkdir -p data/besu logs/besu data/waves
  3. In the data/waves subdirectory, unpack the blockchain_last.tar archive.

  4. Grant the user with the uid 1000 the write access to the subdirectories:

    chown 1000 data/besu logs/besu
  5. Generate a node key and a JWT secret:

    mkdir -p data/secrets
    openssl rand -hex 32 | tr -d "\n" > data/secrets/p2p-key
    openssl rand -hex 32 | tr -d "\n" > data/secrets/jwtsecret
  6. In the main directory:

    1. Create the waves.conf file and paste the code block into it:

      WARNING: You must:

      • Insert your Mainnet account's seed converted to a base58-encoded byte array.

      • Set a password as a string.

      • Specify your server's static IP address. If your server does not have a static IP address, remove the declared-address line.

      waves {
        blockchain.type = MAINNET
        extensions = [
          units.ConsensusClient
        ]
      
        wallet {
          seed = <YOUR-BASE58-ENCODED-SEED>
          password = <YOUR-PASSWORD-AS-STRING>
          file = null
        }
      
        network {
          port = 6868
          declared-address = "<YOUR_SERVER_IP_ADDRESS>:6868" # Example: 11.22.33.44:6868.
        }
      
        rest-api.bind-address = "0.0.0.0"
      }
      
      units {
        defaults {
          jwt-secret-file = /etc/secrets/jwtsecret
        }
        chains = [{
          execution-client-address = "http://besu:8551"
          chain-contract = 3PKgN8rfmvF7hK7RWJbpvkh59e1pQkUzero
          network {
            port = 6865
            known-peers = [
              "mainnet-htz-fsn1-1.unit0.dev:6865"
              "mainnet-htz-hel1-12.wavesnodes.com:6865"
            ]
            declared-address = "<YOUR_SERVER_IP_ADDRESS>:6865" # Example: 11.22.33.44:6865.
          }
          mining-enable = yes # Set to `no` to run a validating node that doesn't mine.
        }]
      }
    2. Create the genesis.json file and paste the code block into it:

      {
        "alloc": {
          "0x0000000000000000000000000000000000006a7e": {
            "code": "0x60806040526004361061006e575f3560e01c806396f396c31161004c57806396f396c3146100e3578063c4a4326d14610105578063e984df0e1461011d578063fccc281314610131575f80fd5b806339dd5d1b146100725780637157405a146100b957806378338413146100ce575b5f80fd5b34801561007d575f80fd5b506100a161008c36600461059e565b5f6020819052908152604090205461ffff1681565b60405161ffff90911681526020015b60405180910390f35b3480156100c4575f80fd5b506100a161040081565b6100e16100dc3660046105b5565b61015c565b005b3480156100ee575f80fd5b506100f761044e565b6040519081526020016100b0565b348015610110575f80fd5b506100f76402540be40081565b348015610128575f80fd5b506100f7610468565b34801561013c575f80fd5b506101445f81565b6040516001600160a01b0390911681526020016100b0565b61016c6402540be40060016105fc565b34101561017834610478565b61019061018b6402540be40060016105fc565b610478565b6040516020016101a1929190610630565b604051602081830303815290604052906101d75760405162461bcd60e51b81526004016101ce9190610688565b60405180910390fd5b506101ef6402540be400677fffffffffffffff6105fc565b3411156101fb34610478565b61021561018b6402540be400677fffffffffffffff6105fc565b6040516020016102269291906106bd565b604051602081830303815290604052906102535760405162461bcd60e51b81526004016101ce9190610688565b50435f8181526020819052604090205461ffff166104009081119061027790610478565b604051602001610287919061070c565b604051602081830303815290604052906102b45760405162461bcd60e51b81526004016101ce9190610688565b505f818152602081905260408120805461ffff16916102d283610786565b91906101000a81548161ffff021916908361ffff160217905550505f6402540be400346102ff91906107a6565b9050346103116402540be400836105fc565b1461031b34610478565b6103296402540be400610478565b60405160200161033a9291906107c5565b604051602081830303815290604052906103675760405162461bcd60e51b81526004016101ce9190610688565b506040515f90819034908281818185825af1925050503d805f81146103a7576040519150601f19603f3d011682016040523d82523d5f602084013e6103ac565b606091505b50509050806103fd5760405162461bcd60e51b815260206004820152601e60248201527f4661696c656420746f2073656e6420746f206275726e2061646472657373000060448201526064016101ce565b604080516bffffffffffffffffffffffff1986168152600784900b60208201527ffeadaf04de8d7c2594453835b9a93b747e20e7a09a7fdb9280579a6dbaf131a8910160405180910390a150505050565b6104656402540be400677fffffffffffffff6105fc565b81565b6104656402540be40060016105fc565b6060815f0361049e5750506040805180820190915260018152600360fc1b602082015290565b815f5b81156104c757806104b181610814565b91506104c09050600a836107a6565b91506104a1565b5f8167ffffffffffffffff8111156104e1576104e161082c565b6040519080825280601f01601f19166020018201604052801561050b576020820181803683370190505b509050815b851561059557610521600182610840565b90505f61052f600a886107a6565b61053a90600a6105fc565b6105449088610840565b61054f906030610853565b90505f8160f81b90508084848151811061056b5761056b61086c565b60200101906001600160f81b03191690815f1a90535061058c600a896107a6565b97505050610510565b50949350505050565b5f602082840312156105ae575f80fd5b5035919050565b5f602082840312156105c5575f80fd5b81356bffffffffffffffffffffffff19811681146105e1575f80fd5b9392505050565b634e487b7160e01b5f52601160045260245ffd5b8082028115828204841417610613576106136105e8565b92915050565b5f81518060208401855e5f93019283525090919050565b6a029b2b73a103b30b63ab2960ad1b81525f61064f600b830185610619565b7f206d7573742062652067726561746572206f7220657175616c20746f20000000815261067f601d820185610619565b95945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b6a029b2b73a103b30b63ab2960ad1b81525f6106dc600b830185610619565b7f206d757374206265206c657373206f7220657175616c20746f20000000000000815261067f601a820185610619565b7f4d6178207472616e7366657273206c696d6974206f662000000000000000000081525f61073d6017830184610619565b7f207265616368656420696e207468697320626c6f636b2e2054727920746f207381527232b732103a3930b739b332b9399030b3b0b4b760691b60208201526033019392505050565b5f61ffff821661ffff810361079d5761079d6105e8565b60010192915050565b5f826107c057634e487b7160e01b5f52601260045260245ffd5b500490565b6a029b2b73a103b30b63ab2960ad1b81525f6107e4600b830185610619565b7f206d7573742062652061206d756c7469706c65206f6620000000000000000000815261067f6017820185610619565b5f60018201610825576108256105e8565b5060010190565b634e487b7160e01b5f52604160045260245ffd5b81810381811115610613576106136105e8565b60ff8181168382160190811115610613576106136105e8565b634e487b7160e01b5f52603260045260245ffdfea2646970667358221220106399f534da089226c14e2f183f8421d059a924c65c97d7e4f3e931c54fe1bb64736f6c634300081a0033",
            "balance": "0x0"
          }
        },
        "baseFeePerGas": "0x3b9aca00",
        "blobGasUsed": null,
        "coinbase": "0x0000000000000000000000000000000000000000",
        "config": {
          "chainId": 88811,
          "arrowGlacierBlock": 0,
          "berlinBlock": 0,
          "byzantiumBlock": 0,
          "cancunTime": 0,
          "constantinopleBlock": 0,
          "daoForkBlock": 0,
          "eip150Block": 0,
          "eip155Block": 0,
          "eip158Block": 0,
          "ethash": {},
          "grayGlacierBlock": 0,
          "homesteadBlock": 0,
          "istanbulBlock": 0,
          "londonBlock": 0,
          "muirGlacierBlock": 0,
          "petersburgBlock": 0,
          "shanghaiTime": 0,
          "terminalTotalDifficulty": 0,
          "terminalTotalDifficultyPassed": true
        },
        "difficulty": "0x0",
        "excessBlobGas": null,
        "extraData": "0x",
        "gasLimit": "0x989680",
        "gasUsed": "0x0",
        "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
        "nonce": "0x0",
        "number": "0x0",
        "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
        "timestamp": "0x6720960b"
      }
    3. Create the log4j2.xml file and paste the code block into it:

      <?xml version="1.0" encoding="UTF-8"?>
      <Configuration status="INFO" monitorInterval="5">
      
          <Properties>
              <Property name="root.log.pattern">%date %-5level [%-25.25thread] %35.35c{1.} - %msg%n%throwable</Property>
          </Properties>
      
          <Appenders>
              <Console name="Console" target="SYSTEM_OUT">
                  <PatternLayout alwaysWriteExceptions="false" pattern='${root.log.pattern}'/>
              </Console>
              <RollingFile name="RollingFile" fileName="/opt/besu/logs/besu.log" filePattern="/opt/besu/logs/besu-%d{yyyy-MM-dd}-%i.log.gz" >
                  <PatternLayout alwaysWriteExceptions="false" pattern='${root.log.pattern}'/>
                  <Policies>
                      <TimeBasedTriggeringPolicy />
                      <SizeBasedTriggeringPolicy size="1000 MB" />
                  </Policies>
                  <DefaultRolloverStrategy max="20"/>
              </RollingFile>
          </Appenders>
      
          <Loggers>
              <Logger name="oshi" level="OFF" additivity="false"/>
              <Logger name="io.vertx" level="OFF" additivity="false"/>
              <Root>
                  <AppenderRef ref="Console" level="INFO" />
                  <AppenderRef ref="RollingFile" level="TRACE" />
              </Root>
          </Loggers>
      
      </Configuration>
    4. Create the static-nodes.json file and paste the code block into it:

      [
        "enode://02718d9a9c6f829c14ea3fd143e526130c70ae43956682cd234046ec932b1c21ca321c484bbb6aa766322ee7e0089d3405747f31d156ec0d67cd80482aede5d7@81.82.238.146:30301",
        "enode://02884ba9163fe92e1aa5a940a050d12c7d857fed092e43d242ebb63472a3e16e77d3b626d50ad790ed454e0e93607ba7ccebd5ac8423d5745df5066708709ac9@185.241.151.12:30303",
        "enode://1937134aff8287fddfc80d2583c9218521b15719dc7782ec85322493b973d02a76edf23ad30657f2d827e04a573e8a5bb2a0052a696a960365c2f13e69cbc0f3@95.216.152.163:30303",
        "enode://5355b769f711ab1951c788d664d0ccbf4bc989013ea3a4f419ab01d9930b524956be65442fa4b72e7de9c470ceeac796235fb198ad9ef49dab559139f17282e2@38.242.222.27:30303",
        "enode://6b534a07943cbca55d6dff834cac2c77f3e82895f51b25fa8cca1689b5cc0921f68453165fa5c736e55e4c61d0b73795445ed2099c09008358805467d07d2066@81.82.238.146:30302",
        "enode://85389460716e3e3247b51139de2f11f1b886c7eb3dc849e2e9673447c81922f9955b2d271834cae9c1625e69f7805e2c89362d4dd8cb0ca972668d7262252790@63.250.53.184:30303",
        "enode://b232ad7ca7bd6156e1adaa28ee0d064f3d973a67c0ad507a1b9dc32b3d64b307c754bc48c274aa96852f0041c2f85792681495e21f5baa62f06d3db8097af258@142.132.251.180:30303",
        "enode://ded10bb464eea90d2a61ab7fef15531dca698845d93f7fc191a5383c22b09de282982872515f398ae527d300c2d5324bae61199dbb354843e6792f2d13b87880@172.104.241.53:30303",
        "enode://e15d6f32cddc2a8e69885fc5c445b8ca7bafd91e9a7a834e89ed688150aa55df20fc7ff14d1fc5dd1e266c2b6a2f9dc75b1d6ed5f80ac71cb27f6ba8af12ba4b@213.238.172.133:30303",
        "enode://e8f7dbec4b146ef0ed1852cd05e3c0654f78a5784a7584f45bc0073bf6206d55764600b586148dfca42bd711c1c1bc02cb20abb2210320f830f003aacf074396@95.217.59.114:30303",
        "enode://edab526402907ccbbdf51950f09b964d9ebc1b51e1a9a1dca44fdaf823d85f84e513e95503f1e4d9e4e90355674819d52e46b014e054da5f199d5406ae6a5e22@185.31.163.22:30303"
      ]
    5. Create the docker-compose.yml file and paste the code block into it:

      services:
        besu:
          container_name: besu
          image: hyperledger/besu:latest
          pull_policy: always
          stop_grace_period: 5m
          command:
            - --logging=ALL
            - --host-allowlist=*
            - --rpc-http-enabled
            - --rpc-http-api=ETH,NET,WEB3,TXPOOL,TRACE
            - --rpc-http-cors-origins=all
            - --rpc-ws-enabled
            - --discovery-enabled=true
            - --engine-rpc-enabled
            - --engine-jwt-secret=/etc/secrets/jwtsecret
            - --engine-host-allowlist=*
            - --node-private-key-file=/etc/secrets/p2p-key
            - --data-path=/var/lib/besu
            - --genesis-file=/etc/besu/genesis.json
            - --static-nodes-file=/etc/besu/static-nodes.json
            - --data-storage-format=BONSAI
            - --network-id=88811
            - --target-gas-limit=20000000
          volumes:
            - ./genesis.json:/etc/besu/genesis.json
            - ./data/secrets:/etc/secrets:ro
            - ./log4j2.xml:/etc/besu/log4j2.xml
            - ./data/besu:/var/lib/besu
            - ./logs/besu:/opt/besu/logs
            - ./static-nodes.json:/etc/besu/static-nodes.json
          ports:
            - '30303:30303/tcp'
            - '30303:30303/udp'
            - '127.0.0.1:8545:8545'
          environment:
            - LOG4J_CONFIGURATION_FILE=/etc/besu/log4j2.xml
      
        waves-node:
          container_name: waves-node
          image: ghcr.io/unitsnetwork/consensus-client:latest
          stop_grace_period: 5m
          ports:
            - "6865:6865"
            - "6868:6868"
            - "127.0.0.1:6869:6869"
          environment:
            - JAVA_OPTS=-Dwaves.config.directory=/etc/waves -Dlogback.file.level=TRACE --add-opens=java.base/sun.nio.ch=ALL-UNNAMED
          volumes:
            - ./data/secrets:/etc/secrets:ro
            - ./data/waves:/var/lib/waves/data
            - ./waves.conf:/etc/waves/waves.conf:ro
            - ./logs/waves:/var/log/waves
          depends_on:
            besu-check:
              condition: service_completed_successfully

Step 2: Launch Node

WARNING: Docker and UFW have a known incompatibility. This issue makes it impossible to map a container's port to a host port (e.g., '8545:8545') and restrict external access using UFW at the same time.

In the docker-compose.yml file, Besu's JSON-RPC port (8545) and Waves node's HTTP API port (6869) are mapped to the host's local address: 127.0.0.1:8545:8545 and 127.0.0.1:6869:6869. This configuration ensures the endpoints are accessible only to consumers running locally on the host machine.

If you need to allow access from external addresses, adjust the port mappings to 8545:8545 and 6869:6869. Alternatively, consider using a reverse proxy like nginx for controlled access.

  1. Launch your node via the command:

    docker-compose up -d

    NOTE: The Execution chain is synced with the network log indicates that the Consensus Client is synchronized with the network.

Step 3 (Optional): Start Mining

  1. Go to the Waves dApp page.

  2. In the header of the page, click Sign in. The Connect a wallet to get started window will open.

  3. In the Connect a wallet to get started window, select one of the sign-in options:

    • Sign in with Keeper.

    • Sign in with Exchange(Seed).

    • Sign in with Exchange(Email).

    • Sign in with Metamask.

    The wallet extension will open.

  4. In the wallet extension, sign in to your node account.

  5. In the join block:

    1. In the rewardAddressHex field, enter your account address.

      LIMITATIONS: The data field accepts input only in string format.

    2. Click Invoke.

      NOTE: The transaction fee is 0.005 WAVES.

    3. Confirm the transaction in your wallet. Nodes chosen for block creation receive both epoch rewards and transaction fees. Learn more about block generation probability.

NOTE: If you need help, contact us via our Developer chat for assistance.

Last updated