Add script
This commit is contained in:
239
altcoin_generator.sh
Normal file
239
altcoin_generator.sh
Normal file
@@ -0,0 +1,239 @@
|
|||||||
|
#!/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"
|
||||||
Reference in New Issue
Block a user