text: // Copyright (c) 2010 Satoshi Nakamoto
  // Copyright (c) 2009-2017 The Bitcoin developers
  // Copyright (c) 2017 Empinel/The Ion Developers
  // Distributed under the MIT software license, see the accompanying
  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  
  #include "assert.h"
  
  #include "chainparams.h"
  #include "main.h"
  #include "util.h"
  #include "amount.h"
  
  #include <boost/assign/list_of.hpp>
  
  using namespace boost::assign;
  
  struct SeedSpec6 {
      uint8_t addr[16];
      uint16_t port;
  };
  
  #include "chainparamsseeds.h"
  
  /**
   * Main network
   */
  
  //! Convert the pnSeeds6 array into usable address objects.
  static void convertSeed6(std::vector<CAddress> &vSeedsOut, const SeedSpec6 *data, unsigned int count)
  {
      // It'll only connect to one or two seed nodes because once it connects,
      // it'll get a pile of addresses with newer timestamps.
      // Seed nodes are given a random 'last seen time' of between one and two
      // weeks ago.
      const int64_t nOneWeek = 7*24*60*60;
      for (unsigned int i = 0; i < count; i++)
      {
          struct in6_addr ip;
          memcpy(&ip, data[i].addr, sizeof(ip));
          CAddress addr(CService(ip, data[i].port));
          addr.nTime = GetTime() - GetRand(nOneWeek) - nOneWeek;
          vSeedsOut.push_back(addr);
      }
  }
  
  static CBlock CreateGenesisBlock(const char* pszTimestamp, const CScript& genesisOutputScript, const uint64_t nTime, const uint32_t nNonce, const uint32_t nBits, const int32_t nVersion, const CAmount& genesisReward)
  {
  	std::vector<CTxIn> vin;
  	vin.resize(1);
  	vin[0].scriptSig = CScript() << nTime << CScriptNum(4) << std::vector<unsigned char>((const unsigned char*)pszTimestamp, (const unsigned char*)pszTimestamp + strlen(pszTimestamp));
  	std::vector<CTxOut> vout;
  	vout.resize(1);
  	vout[0].nValue = genesisReward;
  	vout[0].scriptPubKey = genesisOutputScript;
  	CTransaction txNew(1, nTime, vin, vout, 0);
  		
      CBlock genesis;
      genesis.nTime    = nTime;
      genesis.nBits    = nBits;
      genesis.nNonce   = nNonce;
      genesis.nVersion = nVersion;
      genesis.vtx.push_back(txNew);
      genesis.hashPrevBlock.SetNull();
      genesis.hashMerkleRoot = genesis.BuildMerkleTree();
  
      return genesis;
  }
  
  static CBlock CreateGenesisBlock(uint64_t nTime, uint32_t nNonce, uint32_t nBits, int32_t nVersion, const CAmount& genesisReward)
  {
      const char* pszTimestamp = "June 26, 2017. The MatrixNetwork release. ";
      const CScript genesisOutputScript = CScript() << ParseHex("047ce17a53d2899bc7d08eabdc145fffe21ace10b40ab87283d0da0973799c5108b078fa3decd5d5edb9d20c7a0f2e3f9a2ecd8186c7597215ffa0e3c7712c186f") << OP_CHECKSIG;
      return CreateGenesisBlock(pszTimestamp, genesisOutputScript, nTime, nNonce, nBits, nVersion, genesisReward);
  }
  
  #define PRINTPARAMS 0
  class CMainParams : public CChainParams {
  public:
      CMainParams() {
          // The message start string is designed to be unlikely to occur in normal data.
          // The characters are rarely used upper ASCII, not valid as UTF-8, and produce
          // a large 4-byte int at any alignment.
          pchMessageStart[0] = 0xb5;
          pchMessageStart[1] = 0xd2;
          pchMessageStart[2] = 0xc9;
          pchMessageStart[3] = 0xdd;
          vAlertPubKey = ParseHex("0479092544530794af3a4fe9be71d5579ec1928818cb291ed92f9edfd7bbc0db6eb22a6db93805fbc231c909aeceb48015c7fa7bff6b7805fe6ffd827c3850f0d0");
          nDefaultPort = 22616;
          nRPCPort = 22617;
          nProofOfWorkLimit = uint256S("000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
          nProofOfStakeLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
  
          genesis = CreateGenesisBlock(1498464000, 32736273, 0x1e00ffff, 1, (1 * COIN));
          hashGenesisBlock = genesis.GetHash();
  	
          assert(hashGenesisBlock == uint256("0x0000004a95cff432b947c59b46fb8f795651eb5eb3094f612a9efebe168f9b87"));
          assert(genesis.hashMerkleRoot == uint256("0x28d13889cf470fec50e85320ee429ea81c7769e7a71789c1eb9143ffa310499e"));
  
          base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,51);
          base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,110);
          base58Prefixes[SECRET_KEY] =     std::vector<unsigned char>(1,153);
          base58Prefixes[STEALTH_ADDRESS] = std::vector<unsigned char>(1,40);
          base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x04)(0x88)(0xB2)(0x1E).convert_to_container<std::vector<unsigned char> >();
          base58Prefixes[EXT_SECRET_KEY] = list_of(0x04)(0x88)(0xAD)(0xE4).convert_to_container<std::vector<unsigned char> >();
  
          vSeeds.push_back(CDNSSeedData("47.94.23.17", "47.94.23.17"));
          vSeeds.push_back(CDNSSeedData("dn1.coinbt.cc", "dn1.coinbt.cc"));
          vSeeds.push_back(CDNSSeedData("dn2.coinbt.cc", "dn2.coinbt.cc"));
          vSeeds.push_back(CDNSSeedData("dn3.coinbt.cc", "dn3.coinbt.cc"));
          
          convertSeed6(vFixedSeeds, pnSeed6_main, ARRAYLEN(pnSeed6_main));
  
  		nPoolMaxTransactions = 3;
          strDarksendPoolDummyAddress = "MjC9wSML9ERe6Yzq5pgWqbc2dcXhRsP37G";
          nLastPOWBlock 	= 30000;
      }
  
      virtual const CBlock& GenesisBlock() const { return genesis; }
      virtual Network NetworkID() const { return CChainParams::MAIN; }
  
      virtual const vector<CAddress>& FixedSeeds() const {
          return vFixedSeeds;
      }
  protected:
      CBlock genesis;
      vector<CAddress> vFixedSeeds;
  };
  static CMainParams mainParams;
  
  
  //
  // Testnet
  //
  
  class CTestNetParams : public CMainParams {
  public:
      CTestNetParams() {
          // The message start string is designed to be unlikely to occur in normal data.
          // The characters are rarely used upper ASCII, not valid as UTF-8, and produce
          // a large 4-byte int at any alignment.
          pchMessageStart[0] = 0xdb;
          pchMessageStart[1] = 0x86;
          pchMessageStart[2] = 0xfc;
          pchMessageStart[3] = 0x69;
          vAlertPubKey = ParseHex("");
          nDefaultPort = 32616;
          nRPCPort = 32617;
          strDataDir = "testnet";
     
          nProofOfWorkLimit = uint256S("000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
          nProofOfStakeLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
  
      genesis = CreateGenesisBlock(1491737471, 11529375, 0x1e00ffff, 1, (1 * COIN));
      hashGenesisBlock = genesis.GetHash();
  	
      assert(hashGenesisBlock == uint256("0x000000c31c49392a968012994859c8d72e1d10789580ebd418651af47aadc81b"));
      assert(genesis.hashMerkleRoot == uint256("0x8f4105adf3b715004a371ad5b375476f5cff5529e8eb63a8be70565eeb948da1"));
  
          base58Prefixes[PUBKEY_ADDRESS] = std::vector<unsigned char>(1,97);
          base58Prefixes[SCRIPT_ADDRESS] = std::vector<unsigned char>(1,196);
          base58Prefixes[SECRET_KEY]     = std::vector<unsigned char>(1,239);
          base58Prefixes[STEALTH_ADDRESS] = std::vector<unsigned char>(1,40);
          base58Prefixes[EXT_PUBLIC_KEY] = list_of(0x04)(0x35)(0x87)(0xCF).convert_to_container<std::vector<unsigned char> >();
          base58Prefixes[EXT_SECRET_KEY] = list_of(0x04)(0x35)(0x83)(0x94).convert_to_container<std::vector<unsigned char> >();
  
          vFixedSeeds.clear();
          vSeeds.clear();
          vSeeds.push_back(CDNSSeedData("tdn1.coinbt.cc", "tdn1.coinbt.cc"));
          
          convertSeed6(vFixedSeeds, pnSeed6_test, ARRAYLEN(pnSeed6_test));
  
  	nPoolMaxTransactions = 3;
          strDarksendPoolDummyAddress = "gCJDCcmcVZcfnwAZdEt7dg5s5jjAbDp9dZdhXAmP5NM";
          nLastPOWBlock 	= 300;
      }
  
      virtual const CBlock& GenesisBlock() const { return genesis; }
      virtual Network NetworkID() const { return CChainParams::TESTNET; }
  
      virtual const vector<CAddress>& FixedSeeds() const {
          return vFixedSeeds;
      }
  protected:
      CBlock genesis;
      vector<CAddress> vFixedSeeds;
  
  };
  static CTestNetParams testNetParams;
  
  
  static CChainParams *pCurrentParams = &mainParams;
  
  const CChainParams &Params() {
      return *pCurrentParams;
  }
  
  void SelectParams(CChainParams::Network network) {
      switch (network) {
          case CChainParams::MAIN:
              pCurrentParams = &mainParams;
              break;
          case CChainParams::TESTNET:
              pCurrentParams = &testNetParams;
              break;
          default:
              assert(false && "Unimplemented network");
              return;
      }
  }
  
  bool SelectParamsFromCommandLine() {
      
      bool fTestNet = GetBoolArg("-testnet", false);
      
      if (fTestNet) {
          SelectParams(CChainParams::TESTNET);
      } else {
          SelectParams(CChainParams::MAIN);
      }
      return true;
  }
  