Run Testnet node

Unit Zero is an EVM-compatible blockchain network built on top of the Waves blockchain. This section explains how to operate a node on Unit Zero Testnet.

You have two options:

  • Run a validating node without mining blocks

  • Run a mining node and get rewards

In both options, your node synchronizes with the blockchain network and can propose new transactions. Running a validating node has no requirements for token balances.

Prerequisites

Additionally, if you'd like your node to mine:

  • Transfer some WAVES to the node’s account to cover fees.

    Note: The Consensus Client will invoke the Chain Contract on behalf of the account. Therefore, if you set a verifier for the account, the verifier must allow such transactions.

  • Lease (delegate) at least 20,000 WAVES to the node’s account to achieve the minimum generating balance.

  • Contact the Waves team via Developer chat to obtain an L2MP generating balance on Waves Testnet.

Configuration

  1. Create a directory to serve as the main directory for storing data and configurations. Ensure the current user has read and write access to this directory.

  2. Create the data subdirectory and place the Waves Testnet blockchain data inside it.

  3. Create the following subdirectories in the main directory:

    • besu

    • log

    • log/waves

    • log/besu.

  4. Grant the user with uid 1000 write access to the besu and log/besu subdirectories:

    chown 1000 besu log/besu
  5. Prepare the waves.conf file using the template provided below:

    • Insert your Waves Testnet account's seed converted to a byte array and then encoded in base58, and choose an arbitrary string as a password.

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

    Place this file in the main directory.

    waves {
      blockchain.type = TESTNET
      extensions = [
        units.ConsensusClient
      ]
    
      wallet {
        seed = <your-base58-encoded-seed>
        password = <some-string-as-password>
        file = null
      }
    
      network {
        port = 6868
        declared-address = "<your server's IP address>:6868"   # Example: 11.22.33.44:6868.
      }
    
      rest-api.bind-address = "0.0.0.0"
    
      l2 {
        chain-contract = 3MsqKJ6o1ABE37676cHHBxJRs6huYTt72ch
        execution-client-address = besu
    
        network {
          port = 6865
          known-peers = [
            "testnet-l2-htz-hel1-2.wavesnodes.com:6865"
            "testnet-htz-nbg1-1.wavesnodes.com:6865"
          ]
          declared-address = "<your server's IP address>:6865"   # Example: 11.22.33.44:6865
        }
        mining-enable = yes
      }
    }
  6. Place the following genesis.json file into the main directory.

    {
      "config": {
        "terminalTotalDifficulty": 0,
        "homesteadBlock": 0,
        "daoForkBlock": 0,
        "eip150Block": 0,
        "eip158Block": 0,
        "byzantiumBlock": 0,
        "petersburgBlock": 0,
        "istanbulBlock": 0,
        "muirGlacierBlock": 0,
        "berlinBlock": 0,
        "londonBlock": 0,
        "arrowGlacierBlock": 0,
        "grayGlacierBlock": 0,
        "shanghaiTime": 0,
        "cancunTime": 0,
        "ethash": {},
        "chainID": 88817
      },
      "nonce": "0x0",
      "timestamp": "0x660e5e00",
      "gasLimit": "0x1000000",
      "difficulty": "0x0",
      "coinbase": "0x0000000000000000000000000000000000000000",
      "alloc": {}
    }
  7. Place the following log4j2.xml file into the main directory.

    <?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>
    
    
      <!-- Example with JSON: https://github.com/Consensys/quorum-dev-quickstart/blob/b72a0f64d685c851bf8be399a8e33bbdf0e09982/files/besu/config/besu/log-config.xml -->
      <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>
        </RollingFile>
      </Appenders>
    
      <Loggers>
        <Logger name="oshi" level="OFF" additivity="false"/>
    
    
        <Logger name="io.netty" additivity="false">
          <AppenderRef ref="RollingFile" level="TRACE" />
        </Logger>
    
        <Logger name="io.vertx" additivity="false">
          <AppenderRef ref="RollingFile" level="TRACE" />
        </Logger>
    
        <Logger name="org.hyperledger.besu.ethereum.eth.transactions.BlobCache" additivity="false">
          <AppenderRef ref="RollingFile" level="WARN" />
        </Logger>
    
        <Root>
          <AppenderRef ref="Console" level="INFO" />
          <AppenderRef ref="RollingFile" level="TRACE" />
        </Root>
      </Loggers>
    
    </Configuration>
  8. Place the following static-nodes.json file into the main directory.

    [
      "enode://2e620d7214392b1e3ff3ac0e0342b90ee4984d57e0a1b90be16d4f60aac1ff68dd9b7a9fae3c68f77f6f3631c4227cf5c317770a78827f7f9ee02f35795e8ba2@213.199.56.23:30303",
      "enode://cd6935c8f68987ff46fe826f9e28762958520ee4a62a10d8eedb507008c47919bc2b5b1f3c601bdd35f136d91ba0096f942708ac1bda7f2ad4517fbf62e29ad7@85.190.243.26:30303",
      "enode://fee48af34229c70af99fe58c8da48124f0e9e2adb3853c1928f936fe5f3c0e8dce12d5a2fa98d4bf672f3802fce3a0d62026f275bf176a0187c3b20a543f4751@213.238.172.133:30303",
      "enode://f632e549c9c44980f43f99a9218dda01cd6771379c154dec9dc84e9d039c9124294fab63ab45a2232ba23b1bbbb56a9ea913d98a212579ff114e80f36ab7e8f5@95.31.7.226:30303",
      "enode://ac0c711a1905bcfeb00b2bfd6e97fa3ca9c23e9053a5939ce124d2bd389dfdf604e29d793d428a1d88d9bf5a3cd3479eecb6b7450c1054edd67fe4a21799883a@194.61.28.96:30303",
      "enode://a597a7e9648f43435751d12b69f6dfa48c34169d20e645b91ae131c1e6ff1b295a5858c9a4dbc5bad867df020a92e303fd6073343fe2c58090f7667a32844205@217.76.63.73:30303",
      "enode://4af5930b51cd10a80b347d4c78720145eb9c053a4df8d48b66d3d69f07bafb4b081da5351fd2f2320deee9c5ca6187f7ef4f6a6437f34f4d9088267b5e2c42e7@172.245.243.21:30303",
      "enode://0a4d389579cfe536da57e2c1699d682d053eccac26412d1a23eca88fc4bdc0d3e2c45ef8fdfeca6eb20ee4ce0ded06fe37625c7e3bee7e097932d85a1b45308c@65.108.122.140:30303",
      "enode://116d602e8da9a87e643909d3864b12a931ff0d4e402dd4922a0842d66a49469c6fc392da0ead182a336962dd64ae9a655ceb9ffc9e6c2376efa7d3857f4aac90@94.130.105.239:30303",
      "enode://4425cf397612fb5477521ec1501754516e6dd26ad0bd3d3e1a5a8311d2d2d8bc30c761acbbe47634291d857d8aab7bb134a62e1eac0d08e78c8fa1546f759f5c@95.31.7.226:30303",
      "enode://b6d46ed1b4f7ea995a701f67609c8b301a9786b4923a618787ed71dc9a7a4d4cadd421a934906a8ca9cc3dac3a21b1002dae4ea55648930ca1262436c4f8ad8b@37.27.27.236:30303"     
    ]
  9. Set up the docker-compose.yml file as follows, assuming all data resides in the same directory. You may adjust the paths on your as necessary.

services:
  besu:
    container_name: besu
    image: hyperledger/besu:latest
    pull_policy: always
    command:
      - --logging=ALL
      - --bootnodes=enode://0a4d389579cfe536da57e2c1699d682d053eccac26412d1a23eca88fc4bdc0d3e2c45ef8fdfeca6eb20ee4ce0ded06fe37625c7e3bee7e097932d85a1b45308c@65.108.122.140:30303,enode://116d602e8da9a87e643909d3864b12a931ff0d4e402dd4922a0842d66a49469c6fc392da0ead182a336962dd64ae9a655ceb9ffc9e6c2376efa7d3857f4aac90@94.130.105.239:30303
      - --host-allowlist=*
      - --rpc-http-enabled
      - --rpc-http-api=ETH,NET,WEB3,TXPOOL,TRACE,DEBUG
      - --rpc-http-cors-origins=all
      - --engine-rpc-enabled
      - --engine-jwt-disabled
      - --engine-host-allowlist=*
      - --rpc-ws-enabled
      - --genesis-file=/etc/besu/genesis.json
      - --data-path=/var/lib/besu
      - --static-nodes-file=/etc/besu/static-nodes.json
    volumes:
      - ./besu:/var/lib/besu
      - ./log/besu:/opt/besu/logs
      - ./genesis.json:/etc/besu/genesis.json
      - ./log4j2.xml:/etc/besu/log4j2.xml
      - ./static-nodes.json:/etc/besu/static-nodes.json
    ports:
      - "8545:8545"
      - "30303:30303/tcp"
      - "30303:30303/udp"
    environment:
      - LOG4J_CONFIGURATION_FILE=/etc/besu/log4j2.xml

  besu-check:
    image: curlimages/curl:8.8.0
    command: >
      --retry 20 
      --retry-all-errors 
      --retry-max-time 60 
      -d '{"jsonrpc":"2.0","method":"engine_exchangeCapabilities","params":[[]],"id":1}' 
      http://besu:8551
    depends_on:
      - besu

  waves-node:
    container_name: waves-node
    image: ghcr.io/unitsnetwork/consensus-client:testnet
    ports:
      - "6865:6865"
      - "6868:6868"
      - "6869:6869"
    environment:
     - JAVA_OPTS=-Dlogback.file.directory=/var/log/waves -Dwaves.config.directory=/etc/waves -Dlogback.file.level=TRACE
    volumes:
      - ./data:/var/lib/waves/data
      - ./waves.conf:/etc/waves/waves.conf:ro
      - ./log/waves:/var/log/waves
    depends_on:
      besu-check:
        condition: service_completed_successfully

Launch node

Start your node using the following command:

docker-compose up -d

Ensure the Consensus Client is synchronized with the network, as indicated by the message "Execution chain is synced" in the Waves log.

Start mining

Invoke the join() function of the Testnet Chain Contract on behalf of your node’s Waves account. Specify your address on the Unit Zero Testnet as an argument to receive epoch rewards and transaction fees.

You can convert your address from 0x… format to base64 like this:

echo <paste 0x… address> | xxd -r -p | base64

Your node will begin mining when its turn comes.

If you encounter any difficulties, feel free to reach out via Developer chat for assistance.

Last updated