Forking TurtleCoin

This is the definitive guide to creating your own blockchain based on TRTL technology, and launching a successful community around it.

Minimum Viable Coin

These are the minimum changes you need to make in order to create a TRTL fork. This is suitable for making a TRTL testnet, for example.

Change the following blocks of code to suit your fork's parameters.

src/config/CryptoNoteConfig.h  Network ID

  const static   boost::uuids::uuid CRYPTONOTE_NETWORK         =
      {  0xb5, 0x0c, 0x4a, 0x6c, 0xcf, 0x52, 0x57, 0x41, 0x65, 0xf9, 0x91, 0xa4, 0xb6, 0xc1, 0x43, 0xe9  }

src/config/CryptoNoteConfig.h  Blockchain Cache Folder
  const char     CRYPTONOTE_NAME[]                    = "TurtleCoin";

src/config/CryptoNoteConfig.h  Seed Nodes
  const char* const SEED_NODES[] = {
    "", //cision
    "", //tom
    "" //iburnmycd };

Fully Custom Network

This is the full set of changes you make to create your own basic fork of the TurtleCoin code. When we finish this section, you'll have a complete rebrand of TurtleCoin with your own name on it.

Change the following blocks of code to suit your fork's parameters.

Creator's License

Before we begin, you'll see a license at the beginning of every file. It is important not to remove or alter that license statement other than how we've detailed here.

  // Copyright (c) 2012-2017, The CryptoNote developers, The Bytecoin developers
  // Copyright (c) 2014-2018, The Monero Project
  // Copyright (c) 2018, The TurtleCoin Developers
  // Copyright (c) 2018, YOUR NAME GOES HERE
  // Please see the included LICENSE file for more information.

src/CMakeLists.txt  Binary Names

Change the property output names to suit your project.

  # Finally build the binaries
  set_property(TARGET TurtleCoind PROPERTY OUTPUT_NAME "TurtleCoind")
  set_property(TARGET zedwallet PROPERTY OUTPUT_NAME "zedwallet")
  set_property(TARGET service PROPERTY OUTPUT_NAME "turtle-service")
  set_property(TARGET miner PROPERTY OUTPUT_NAME "miner")

  # Additional make targets
  add_custom_target(pool DEPENDS TurtleCoind service)
  add_custom_target(solominer DEPENDS TurtleCoind zedwallet miner)
  add_custom_target(cli DEPENDS TurtleCoind zedwallet)

src/config/Ascii.h  ASCII Art

This is the ASCII art displayed on launching many of the binary programs. Depending on the ASCII art you wish to use, you may need to provide different a version for Windows. The ASCII art generator over at works well.

 const std::string windowsAsciiArt =
      "\n _______         _   _       _____      _        \n"
              "|__   __|       | | | |     / ____|    (_)      \n"
              "   | |_   _ _ __| |_| | ___| |     ___  _ _ __  \n"
              "   | | | | | '__| __| |/ _ \\ |    / _ \\| | '_ \\ \n"
              "   | | |_| | |  | |_| |  __/ |___| (_) | | | | |\n"
      "   |_|\\__ _|_|   \\__|_|\\___|\\_____\\___/|_|_| |_|\n";

 const std::string nonWindowsAsciiArt =
      "\n                                                                            \n"
        "████████╗██╗  ██╗██████╗ ████████╗██╗    ██████╗ █████╗ █████╗ ██╗███╗   ██╗\n"
        "╚══██╔══╝██║  ██║██╔══██╗╚══██╔══╝██║    ██╔═══╝██╔═══╝██╔══██╗██║████╗  ██║\n"
        "   ██║   ██║  ██║██████╔╝   ██║   ██║    ████╗  ██║    ██║  ██║██║██╔██╗ ██║\n"
        "   ██║   ██║  ██║██╔══██╗   ██║   ██║    ██╔═╝  ██║    ██║  ██║██║██║╚██╗██║\n"
        "   ██║   ╚█████╔╝██║  ██║   ██║   ██████╗██████╗╚█████╗╚█████╔╝██║██║ ╚████║\n"
        "   ╚═╝    ╚════╝ ╚═╝  ╚═╝   ╚═╝   ╚═════╝╚═════╝ ╚════╝ ╚════╝ ╚═╝╚═╝  ╚═══╝\n";

src/config/CryptoNoteConfig.h  Block Time

Block time is measured in seconds. TRTL has 30 second blocks.

  const uint64_t DIFFICULTY_TARGET                      = 30; // seconds

src/config/CryptoNoteConfig.h  Address Prefix

TurtleCoin has an address prefix of TRTL, and every wallet address generated begins with the wallet prefix.

The address prefix is calculated using the generator on this page. The prefix you generate will be in hexadecimal, ex: 0xb1, but the config works best with decimal. You can convert hexadecimal to decimal using this converter.

  const uint64_t CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 3914525;

src/config/CryptoNoteConfig.h  Unlock Mined Coins

Mined coins need to wait about 20 minutes before being awarded to miners. Adjust the number of blocks in this parameter to suit your coin. TRTL has 30 second blocks, so 40 means 20 minutes.

  const uint32_t CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW          = 40;

src/config/CryptoNoteConfig.h  Coin Supply

Coin supply is measured in Atomic Units. The amount of decimal places you have will determine how many coins this number truly represents. This is the minimum amount of divisible units in your network.

TurtleCoin has 1 Trillion total coins, and only two decimal places, so it has 100 Trillion Atomic Units.

  const uint64_t MONEY_SUPPLY          = UINT64_C(100000000000000);

src/config/CryptoNoteConfig.h  Decimal Points

Change this number to suit your needs.

TurtleCoin has 2 decimal points, Bitcoin has 8.

  const size_t   CRYPTONOTE_DISPLAY_DECIMAL_POINT      = 2;

src/config/CryptoNoteConfig.h  Difficulty Algorithm Milestones

These are different versions of our difficulty algorithm, and the heights at which you'll upgrade to each one. It is best to activate them in the first 4 blocks of your chain so that you can get to the most recent version sooner.

  const uint32_t ZAWY_DIFFICULTY_BLOCK_INDEX                = 187000;


  const uint64_t LWMA_2_DIFFICULTY_BLOCK_INDEX              = 620000;
  const uint64_t LWMA_2_DIFFICULTY_BLOCK_INDEX_V2           = 700000;
  const uint64_t LWMA_2_DIFFICULTY_BLOCK_INDEX_V3           = 800000;

src/config/CryptoNoteConfig.h  Block Emission Speed

This number governs how much of the total available supply is awarded to miners with each block. Use this generator to look at a graph of how this number changes your emission.

TurtleCoin has an emission of 25, and takes over 100 years to emit the last coin. The minimum and fastest number you can use is 9.

  const unsigned EMISSION_SPEED_FACTOR                    = 25;

src/config/CryptoNoteConfig.h  Transaction Fees

Set the fee in Atomic Units for each transaction.

If this number is too low, you'll be susceptible to transaction spamming attacks.

  const uint64_t MINIMUM_FEE = UINT64_C(10);

src/config/CryptoNoteConfig.h  Security Mixing Level

Mixin determines how private transactions are, however, due to the way a transaction must match inputs from previous transactions, a high mixin on a new network can cause transactions to fail. Thus, we would suggest starting off with some reasonably limits, still allowing 0 mixin, and increasing the minimum mixin later.

Change the values below to suit the needs of your network. It is strongly recommended to make mixin a static number.

  const uint64_t MINIMUM_MIXIN_V1                      = 0;
  const uint64_t MAXIMUM_MIXIN_V1                      = 100;

  const uint64_t MINIMUM_MIXIN_V2                      = 7;
  const uint64_t MAXIMUM_MIXIN_V2                      = 7;

  const uint64_t MINIMUM_MIXIN_V3                      = 3;
  const uint64_t MAXIMUM_MIXIN_V3                      = 3;

  /* The heights to activate the mixin limits at                     */
  const uint32_t MIXIN_LIMITS_V1_HEIGHT                = 440000;
  const uint32_t MIXIN_LIMITS_V2_HEIGHT                = 620000;
  const uint32_t MIXIN_LIMITS_V3_HEIGHT                = 800000;

  /* The mixin to use by default with zedwallet and turtle-service   */
  /* DEFAULT_MIXIN_V0 is the mixin used before MIXIN_LIMITS_V1_HEIGHT*/
  /* is started                                                      */

  const uint64_t DEFAULT_MIXIN_V0                      = 3;
  const uint64_t DEFAULT_MIXIN_V1                      = MAXIMUM_MIXIN_V1;
  const uint64_t DEFAULT_MIXIN_V2                      = MAXIMUM_MIXIN_V2;
  const uint64_t DEFAULT_MIXIN_V3                      = MAXIMUM_MIXIN_V3;

src/config/CryptoNoteConfig.h  Dust Limits

Dust is the word for the smallest pieces of a coin that are too small to be bothered with including in a block. Amounts lower than this will not be spendable. This number is measured in Atomic Units.

Lowering dust to 0 can fatten transactions somewhat, and also make some transactions hang around in the memory pool waiting to be processed because they can't be mixed with the mixin level you've set because the network can't find inputs of a mathing size. Use this script to generate odd-sized inputs to help clear your memory pool, or consider using a tipping bot heavily to break up transactions into uneven numbers.

  const uint64_t DEFAULT_DUST_THRESHOLD = UINT64_C(10);
  const uint64_t DEFAULT_DUST_THRESHOLD_V2 = UINT64_C(0);

src/config/CryptoNoteConfig.h  Hashing Algorithm

We forked to the Cryptonight Lite Variant 1 hashing algorithm to defeat ASIC minering at height 350,000. If you want to be an ASIC mined coin, make this number very high. If you don't want to be ASIC mined, set this number to 3.

ASIC is not inherently bad, it will allow you to acheive a relatively high hashrate fairly easily. Consider supporting ASIC if you have a very low block time.

  const uint32_t UPGRADE_HEIGHT_V4 = 350000;


src/config/CryptoNoteConfig.h  Fork Monitor Heights

When you type status in the daemon window, you get a status monitor telling you how long until the next fork upgrade. This signals to users that they need to upgrade their software. This is set manually with a list of heights. Set those according to your custom fork schedule.

  /* Block heights we are going to have hard forks at */
  const uint64_t FORK_HEIGHTS[] =
      187000,  // 0
      350000,  // 1
      440000,  // 2
      620000,  // 3
      700000,  // 4
      800000,  // 5 *you are here*
      1000000, // 6
      1200000, // 7
      1400000, // 8
      1600000, // 9
      1800000, // 10
      2000000, // 11

src/config/CryptoNoteConfig.h  Network ID

This is the signature of your network. Not changing this risks of collisions with the TurtleCoin network if you'd encounter any of our peers.

  const static   boost::uuids::uuid CRYPTONOTE_NETWORK         =
      {  0xb5, 0x0c, 0x4a, 0x6c, 0xcf, 0x52, 0x57, 0x41, 0x65, 0xf9, 0x91, 0xa4, 0xb6, 0xc1, 0x43, 0xe9  }

src/config/CryptoNoteConfig.h  Blockchain Cache Folder

This is the hidden folder in your home directory that holds your blockchain and p2p peer data.

  const char     CRYPTONOTE_NAME[]                    = "TurtleCoin";

src/config/CryptoNoteConfig.h  Seed Nodes

These are the first point of entry for new users. They are machines that are running full daemons that serve up the first download of the blockchain data for peers just joining the network. The minimum is 1, but you ideally have many.

There is no risk in allowing community members to host seed nodes, and it is advisable to allow the community to share this role.

  const char* const SEED_NODES[] = {
    "", //cision
    "", //tom
    "" //iburnmycd };

src/config/CryptoNoteConfig.h  P2P and RPC Ports

Set these according to your preferences.

  const int      P2P_DEFAULT_PORT                       =  11897;
  const int      RPC_DEFAULT_PORT                       =  11898;

src/config/CryptoNoteConfig.h  Software Update URL

Set this according to your preferences.

  const char     LATEST_VERSION_URL[]   = "";

src/config/CryptoNoteCheckpoints.h  Checkpoints

You likely don't have any checkpoints yet, so remove all the checkpoints.

const std::initializer_list CHECKPOINTS = {};

src/config/WalletConfig.h  CLI Wallet Config

Set these parameters to suit your network.

  /* Make sure everything in here is const - or it won't compile! */
  namespace WalletConfig
      /* The prefix your coins address starts with */
      const std::string addressPrefix = "TRTL";

      /* Your coins 'Ticker', e.g. Monero = XMR, Bitcoin = BTC */
      const std::string ticker = "TRTL";

      /* The filename to output the CSV to in save_csv */
      const std::string csvFilename = "transactions.csv";

      /* The filename to read+write the address book to - consider starting with
         a leading '.' to make it hidden under mac+linux */
      const std::string addressBookFilename = ".addressBook.json";

      /* The name of your deamon */
      const std::string daemonName = "TurtleCoind";

      /* The name to call this wallet */
      const std::string walletName = "zedwallet";

      /* The name of service/walletd, the programmatic rpc interface to a
         wallet */
      const std::string walletdName = "turtle-service";

      /* The full name of your crypto */
      const std::string coinName = std::string(CryptoNote::CRYPTONOTE_NAME);

      /* Where can your users contact you for support? E.g. discord */
      const std::string contactLink = "";

src/config/WalletConfig.h  Address Length

Your address length should be 95 + the number of letters in your address prefix.

  /* The length of a standard address for your coin */
  const long unsigned int standardAddressLength = 99;

src/config/WalletConfig.h  Minimum Transaction Size

This is measured in Atomic Units

  /* The minimum amount allowed to be sent - usually 1 (in ATOMIC units!) */
  const uint64_t minimumSend = 1;

src/config/WalletConfig.h  Allow Zero Mixin

Do you allow zero mixin transactions on your network?

  /* Is a mixin of zero disabled on your network? */
  const bool mixinZeroDisabled = true;

Compile & Deploy

This step turns the human readable code you just edited into machine executable programs. This step is easiest in Linux, but there are instructions for Windows and Apple also.

These instructions are meant for Ubuntu LTS, visit the link above for Windows and Apple instructions.

~/your-dev-folder/  Compile Your Code

Open an Ubuntu LTS terminal prompt, and type the following commands.

  sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
  sudo apt-get update
  sudo apt-get install aptitude -y
  sudo aptitude install -y build-essential g++-8 gcc-8 git libboost-all-dev python-pip
  sudo pip install cmake
  export CC=gcc-8
  export CXX=g++-8
  git clone -b master --single-branch
  cd turtlecoin
  mkdir build
  cd build
  cmake ..

The compile process can take up to an hour on slower systems. You will need adequate RAM or Swap space in order to compile without errors. Compiling on a cheap VPS will often give Swap errors because of this.

~/your-seed-nodes/  Deploy Your Code

On the seed nodes listed in your CryptoNoteConfig.h, launch your daemon that you just compiled. In most cases, it is best to run the daemon inside tmux while using a loop or high availability monitor to keep the seeds running. High volume daemons can crash, and this helps maintain uptime. This is especially important if you have a high mixin level or fast block time.

  while true ; do ./TurtleCoind ; done

This is the most basic loop to automatically relaunch the daemon if it fails, but it is recommended to use a high availability monitor.

Advanced Parameters

Next Section >>

Copyright 2018 TurtleCoin Developers