Skip to content

Instantly share code, notes, and snippets.

@rizplate
Created May 13, 2018 00:18
Show Gist options
  • Save rizplate/e40c61c0764fe7df402fbdcd42a587a9 to your computer and use it in GitHub Desktop.
Save rizplate/e40c61c0764fe7df402fbdcd42a587a9 to your computer and use it in GitHub Desktop.
AltcoinGenerator

Altcoin Generator

Easiest way to create your own cryptocurrency.

What does this script do?

This script is an experiment to generate new cryptocurrencies (altcoins) based on litecoin. It will help you creating a git repository with minimal required changes to start your new coin and blockchain.

What do I have to do?

You need to make sure you have at least docker and git installed. The other requirements will be installed automatically in a docker container by the script.

Simply open the script and edit the first variables to match your coin requirements (total supply, coin unit, coin name, tcp ports..) Then simply run the script like this:

bash altcoin_generator.sh

What will happen then?

The script will perform a couple of actions:

  • Create a docker image ready to build and run your new coin nodes
  • Clone GenesisH0 and mine the genesis blocks of main, test and regtest networks in the container (this might take a lot of time)
  • Clone litecoin
  • Rename files and replace variables in litecoin code (genesis hashes, merkle tree hashes, tcp ports, coin name, supply...)
  • Build your new coin
  • Run 4 docker nodes with your coin daemon and connect each other.
    • A directory mapped for each node will be created: miner2, miner3, miner4, miner5. They contain data and configuration of each independent node.

What can I do next?

You can first check if your nodes are running and then ask them to generate some blocks. Instructions on how to do it will be printed once the script execution is done.

Is there anything I must be aware of?

Yes.

  • This is a very simple script to help you bootstrap. More changes will be needed to launch a cryptocurrency for real.
  • You have to manually change the pictures in mycoin/share/pixmaps.
  • You will need change the checkpoints in mycoin/src/chainparams.cpp.
  • Consider adding a seed node and add it to src/chainparams.cpp as well.
    • Currently all seeds are getting disabled.
  • The script connects to the regression test network by default. This is a special network that will let you mine new blocks almost instantly (nice for testing). To launch the nodes in the main network, simply leave the CHAIN variable empty.

I think something went wrong!

Then you can just remove all directories that were created by the script and start all over again.

Can I help the project?

Sure. You can either submit patches, or make a donation if you found this project useful:

LTC: Lcaey9FP2zdu4C9TSVffDG1DuKh78yCDYT BTC: 1BB44xSWSHwgM2AMP7MScqk2CALuo6A6UY

#!/bin/bash -e
# This script is an experiment to clone litecoin into a
# brand new coin + blockchain.
# The script will perform the following steps:
# 1) create first a docker image with ubuntu ready to build and run the new coin daemon
# 2) clone GenesisH0 and mine the genesis blocks of main, test and regtest networks in the container (this may take a lot of time)
# 3) clone litecoin
# 4) replace variables (keys, merkle tree hashes, timestamps..)
# 5) build new coin
# 6) run 4 docker nodes and connect to each other
#
# By default the script uses the regtest network, which can mine blocks
# instantly. If you wish to switch to the main network, simply change the
# CHAIN variable below
# change the following variables to match your new coin
COIN_NAME="MyCoin"
COIN_UNIT="MYC"
# 42 million lite coins at total
TOTAL_SUPPLY=42000000
MAINNET_PORT="54321"
TESTNET_PORT="54322"
PHRASE="Some newspaper headline that describes something that happened today"
# First letter of the wallet address. Check https://en.bitcoin.it/wiki/Base58Check_encoding
PUBKEY_CHAR="20"
# leave CHAIN empty for main network, -regtest for regression network and -testnet for test network
CHAIN="-regtest"
# dont change the following variables unless you know what you are doing
GENESISHZERO_REPOS=https://github.com/lhartikk/GenesisH0
LITECOIN_REPOS=https://github.com/litecoin-project/litecoin.git
LITECOIN_PUB_KEY=040184710fa689ad5023690c80f3a49c8f13f8d45b8c857fbcbc8bc4a8e4d3eb4b10f4d4604fa08dce601aaf0f470216fe1b51850b4acf21b179c45070ac7b03a9
LITECOIN_MERKLE_HASH=97ddfbbae6be97fd6cdf3e7ca13232a3afff2353e29badfab7f73011edd4ced9
LITECOIN_MAIN_GENESIS_HASH=12a765e31ffd4059bada1e25190f6e98c99d9714d334efa41a195a7e7e04bfe2
LITECOIN_TEST_GENESIS_HASH=4966625a4b2851d9fdee139e56211a0d88575f59ed816ff5e6a63deb4e3e29a0
LITECOIN_REGTEST_GENESIS_HASH=530827f38f93b43ed12af0b3ad25a288dc02ed74d6d7857862df51fc56c416f9
COIN_NAME_LOWER=${COIN_NAME,,}
COIN_NAME_UPPER=${COIN_NAME^^}
DIRNAME=$(dirname $0)
DOCKER_NETWORK="172.18.0"
if [ $DIRNAME = "." ]; then
DIRNAME=$PWD
fi
cd $DIRNAME
# sanity check
if ! which docker &>/dev/null; then
echo Please install docker first
exit 1
fi
if ! which git &>/dev/null; then
echo Please install git first
exit 1
fi
docker_build_image()
{
IMAGE=$(docker images -q ubuntu-newcoin)
if [ -z $IMAGE ]; then
echo Building docker image
if [ ! -f ubuntu-litecoin/Dockerfile ]; then
mkdir -p ubuntu-litecoin
cat <<EOF > ubuntu-litecoin/Dockerfile
FROM ubuntu:16.04
RUN echo deb http://ppa.launchpad.net/bitcoin/bitcoin/ubuntu xenial main >> /etc/apt/sources.list
RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv D46F45428842CE5E
RUN apt-get update
RUN apt-get -y install ccache git libboost-system1.58.0 libboost-filesystem1.58.0 libboost-program-options1.58.0 libboost-thread1.58.0 libboost-chrono1.58.0 libssl1.0.0 libevent-pthreads-2.0-5 libevent-2.0-5 build-essential libtool autotools-dev automake pkg-config libssl-dev libevent-dev bsdmainutils libboost-system-dev libboost-filesystem-dev libboost-chrono-dev libboost-program-options-dev libboost-test-dev libboost-thread-dev libdb4.8-dev libdb4.8++-dev libminiupnpc-dev libzmq3-dev libqt5gui5 libqt5core5a libqt5dbus5 qttools5-dev qttools5-dev-tools libprotobuf-dev protobuf-compiler libqrencode-dev python-pip
RUN pip install construct==2.5.2 scrypt
EOF
fi
docker build --label ubuntu-newcoin --tag ubuntu-newcoin $DIRNAME/ubuntu-litecoin/
else
echo Docker image already built
fi
}
docker_run_genesis() {
mkdir -p $DIRNAME/.ccache
docker run -v $DIRNAME/GenesisH0:/GenesisH0 ubuntu-newcoin /bin/bash -c "$1"
}
docker_run() {
mkdir -p $DIRNAME/.ccache
docker run -v $DIRNAME/GenesisH0:/GenesisH0 -v $DIRNAME/.ccache:/root/.ccache -v $DIRNAME/$COIN_NAME_LOWER:/$COIN_NAME_LOWER ubuntu-newcoin /bin/bash -c "$1"
}
docker_run_node()
{
local NODE_NUMBER=$1
local NODE_COMMAND=$2
mkdir -p $DIRNAME/miner${NODE_NUMBER}
if [ ! -f $DIRNAME/miner${NODE_NUMBER}/$COIN_NAME_LOWER.conf ]; then
cat <<EOF > $DIRNAME/miner${NODE_NUMBER}/$COIN_NAME_LOWER.conf
rpcuser=${COIN_NAME_LOWER}rpc
rpcpassword=$(</dev/urandom tr -dc '12345qwertQWERTasdfgASDFGzxcvbZXCVB' | head -c32)
EOF
fi
if ! docker network inspect newcoin &>/dev/null; then
docker network create --subnet=$DOCKER_NETWORK.0/16 newcoin
fi
docker run --net newcoin --ip $DOCKER_NETWORK.${NODE_NUMBER} -v $DIRNAME/miner${NODE_NUMBER}:/root/.$COIN_NAME_LOWER -v $DIRNAME/$COIN_NAME_LOWER:/$COIN_NAME_LOWER ubuntu-newcoin /bin/bash -c "$NODE_COMMAND"
}
generate_genesis_block()
{
if [ ! -d GenesisH0 ]; then
git clone $GENESISHZERO_REPOS
pushd GenesisH0
else
pushd GenesisH0
git pull
fi
if [ ! -f ${COIN_NAME}-main.txt ]; then
echo "Mining genesis block... this procedure can take many hours of cpu work.."
docker_run_genesis "python /GenesisH0/genesis.py -a scrypt -z \"$PHRASE\" 2>&1 | tee /GenesisH0/${COIN_NAME}-main.txt"
else
echo "Genesis block already mined.."
cat ${COIN_NAME}-main.txt
fi
if [ ! -f ${COIN_NAME}-test.txt ]; then
echo "Mining genesis block of test network... this procedure can take many hours of cpu work.."
docker_run_genesis "python /GenesisH0/genesis.py -t 1486949366 -a scrypt -z \"$PHRASE\" 2>&1 | tee /GenesisH0/${COIN_NAME}-test.txt"
else
echo "Genesis block already mined.."
cat ${COIN_NAME}-test.txt
fi
if [ ! -f ${COIN_NAME}-regtest.txt ]; then
echo "Mining genesis block of regtest network... this procedure can take many hours of cpu work.."
docker_run_genesis "python /GenesisH0/genesis.py -t 1296688602 -b 0x207fffff -n 0 -a scrypt -z \"$PHRASE\" 2>&1 | tee /GenesisH0/${COIN_NAME}-regtest.txt"
else
echo "Genesis block already mined.."
cat ${COIN_NAME}-regtest.txt
fi
MAIN_PUB_KEY=$(cat ${COIN_NAME}-main.txt | grep "^pubkey:" | sed 's/^pubkey: //')
MERKLE_HASH=$(cat ${COIN_NAME}-main.txt | grep "^merkle hash:" | sed 's/^merkle hash: //')
TIMESTAMP=$(cat ${COIN_NAME}-main.txt | grep "^time:" | sed 's/^time: //')
BITS=$(cat ${COIN_NAME}-main.txt | grep "^bits:" | sed 's/^bits: //')
MAIN_NONCE=$(cat ${COIN_NAME}-main.txt | grep "^nonce:" | sed 's/^nonce: //')
TEST_NONCE=$(cat ${COIN_NAME}-test.txt | grep "^nonce:" | sed 's/^nonce: //')
REGTEST_NONCE=$(cat ${COIN_NAME}-regtest.txt | grep "^nonce:" | sed 's/^nonce: //')
MAIN_GENESIS_HASH=$(cat ${COIN_NAME}-main.txt | grep "^genesis hash:" | sed 's/^genesis hash: //')
TEST_GENESIS_HASH=$(cat ${COIN_NAME}-test.txt | grep "^genesis hash:" | sed 's/^genesis hash: //')
REGTEST_GENESIS_HASH=$(cat ${COIN_NAME}-regtest.txt | grep "^genesis hash:" | sed 's/^genesis hash: //')
popd
}
newcoin_replace_vars()
{
if [ -d $COIN_NAME_LOWER ]; then
echo "Warning: $COIN_NAME_LOWER already existing"
return 0
fi
# clone litecoin
git clone $LITECOIN_REPOS $COIN_NAME_LOWER
pushd $COIN_NAME_LOWER
# first rename all directories
for i in $(find . -type d | grep -v "^./.git" | grep litecoin); do
git mv $i $(echo $i| sed "s/litecoin/$COIN_NAME_LOWER/")
done
# then rename all files
for i in $(find . -type f | grep -v "^./.git" | grep litecoin); do
git mv $i $(echo $i| sed "s/litecoin/$COIN_NAME_LOWER/")
done
# now replace all litecoin references to the new coin name
for i in $(find . -type f | grep -v "^./.git"); do
sed -i "s/Litecoin/$COIN_NAME/g" $i
sed -i "s/litecoin/$COIN_NAME_LOWER/g" $i
sed -i "s/LITECOIN/$COIN_NAME_UPPER/g" $i
sed -i "s/LTC/$COIN_UNIT/g" $i
done
sed -i "s/84000000/$TOTAL_SUPPLY/" src/amount.h
sed -i "s/1,48/1,$PUBKEY_CHAR/" src/chainparams.cpp
sed -i "s/1317972665/$TIMESTAMP/" src/chainparams.cpp
sed -i "s;NY Times 05/Oct/2011 Steve Jobs, Apple’s Visionary, Dies at 56;$PHRASE;" src/chainparams.cpp
sed -i "s/= 9333;/= $MAINNET_PORT;/" src/chainparams.cpp
sed -i "s/= 19335;/= $TESTNET_PORT;/" src/chainparams.cpp
sed -i "s/$LITECOIN_PUB_KEY/$MAIN_PUB_KEY/" src/chainparams.cpp
sed -i "s/$LITECOIN_MERKLE_HASH/$MERKLE_HASH/" src/chainparams.cpp
sed -i "s/$LITECOIN_MERKLE_HASH/$MERKLE_HASH/" src/qt/test/rpcnestedtests.cpp
sed -i "0,/$LITECOIN_MAIN_GENESIS_HASH/s//$MAIN_GENESIS_HASH/" src/chainparams.cpp
sed -i "0,/$LITECOIN_TEST_GENESIS_HASH/s//$TEST_GENESIS_HASH/" src/chainparams.cpp
sed -i "0,/$LITECOIN_REGTEST_GENESIS_HASH/s//$REGTEST_GENESIS_HASH/" src/chainparams.cpp
sed -i "0,/2084524493/s//$MAIN_NONCE/" src/chainparams.cpp
sed -i "0,/293345/s//$TEST_NONCE/" src/chainparams.cpp
sed -i "0,/1296688602, 0/s//1296688602, $REGTEST_NONCE/" src/chainparams.cpp
sed -i "0,/0x1e0ffff0/s//$BITS/" src/chainparams.cpp
sed -i "s,vSeeds.push_back,//vSeeds.push_back,g" src/chainparams.cpp
# TODO: fix checkpoints
popd
}
build_new_coin()
{
if [ ! -x $COIN_NAME_LOWER/src/${COIN_NAME_LOWER}d ]; then
docker_run "cd /$COIN_NAME_LOWER ; bash /$COIN_NAME_LOWER/autogen.sh"
docker_run "cd /$COIN_NAME_LOWER ; bash /$COIN_NAME_LOWER/configure"
docker_run "cd /$COIN_NAME_LOWER ; make -j2"
fi
}
docker_build_image
generate_genesis_block
newcoin_replace_vars
build_new_coin
docker_run_node 2 "cd /$COIN_NAME_LOWER ; ./src/${COIN_NAME_LOWER}d $CHAIN -listen -noconnect -bind=$DOCKER_NETWORK.2 -addnode=$DOCKER_NETWORK.1 -addnode=$DOCKER_NETWORK.3 -addnode=$DOCKER_NETWORK.4 -addnode=$DOCKER_NETWORK.5" &
docker_run_node 3 "cd /$COIN_NAME_LOWER ; ./src/${COIN_NAME_LOWER}d $CHAIN -listen -noconnect -bind=$DOCKER_NETWORK.3 -addnode=$DOCKER_NETWORK.1 -addnode=$DOCKER_NETWORK.2 -addnode=$DOCKER_NETWORK.4 -addnode=$DOCKER_NETWORK.5" &
docker_run_node 4 "cd /$COIN_NAME_LOWER ; ./src/${COIN_NAME_LOWER}d $CHAIN -listen -noconnect -bind=$DOCKER_NETWORK.4 -addnode=$DOCKER_NETWORK.1 -addnode=$DOCKER_NETWORK.2 -addnode=$DOCKER_NETWORK.3 -addnode=$DOCKER_NETWORK.5" &
docker_run_node 5 "cd /$COIN_NAME_LOWER ; ./src/${COIN_NAME_LOWER}d $CHAIN -listen -noconnect -bind=$DOCKER_NETWORK.5 -addnode=$DOCKER_NETWORK.1 -addnode=$DOCKER_NETWORK.2 -addnode=$DOCKER_NETWORK.3 -addnode=$DOCKER_NETWORK.4" &
echo "Docker containers should be up and running now. You may run the following command to check the network status:
for i in \$(docker ps -q); do docker exec \$i /$COIN_NAME_LOWER/src/${COIN_NAME_LOWER}-cli -regtest getinfo; done"
echo "To ask the nodes to mine some blocks simply run:
for i in \$(docker ps -q); do docker exec \$i /$COIN_NAME_LOWER/src/${COIN_NAME_LOWER}-cli -regtest generate 2 & done"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment