Intro
The purpose of this blog post is to explain how blockchain technology, and in particular a cryptocurrency like Bitcoin, works by example. A simple blockchain bash script, named bashCoin, will be used for illustration.
Digital Currency and Blockchain Overview
A blockchain is a series of files arranged so that when a new file is inserted, it both verifies the previous file and renders it unchangeable. The files (blocks) in the chain are safeguarded from alteration since all files are linked to one another. This proves to be extremely useful for both record retention in a records management system and a trust-less decentralized digital currency.
A digital currency can use a blockchain to create an immutable list of transactions. This means that, under the correct circumstances, once a transaction is saved to a block it cannot be altered or deleted without breaking the chain.
When people need to exchange goods and services they most often use physical currency. Trading a dollar bill for a soda is much easier than trying to figure out for how long a painter would paint the store owner’s house in exchange for the soda if the store owner needed painting at all. As long as both the painter and the store owner agree that the dollar bill is worth something, they can exchange it instead of bartering.
Instead of physically exchanging something during a monetary transaction, however, participants can simply keep track on a ledger: a running list of financial transactions. For example, a transaction such as “Alice sends Bob 100 dollars” can be written into a ledger that both Bob and Alice trust. The transaction information can then be used to calculate how much money both Alice and Bob have at any moment.
If the ledger is shared amongst all users then anyone should be able to submit transactions and calculate how much money anyone has at any moment. A public ledger setup as a blockchain has the added capability of keeping past transactions secure as well as protecting users from future fraud. Users are also required to use a public key / private key pair as their account address which they use to encrypt transactions. This encryption prevents participants from writing false transactions to the ledger.
Transactions are grouped into blocks before being added to the blockchain. The frequency at which they are added depends on other users verifying the block through a process called mining. Mining a block consists of adding a random number (called a nonce) to the block so that when it is hashed the resulting hash starts with a certain number of zeros. This process is extremely difficult and time-consuming but once the random number has been found, reversing the process to check the answer is simple and quick. The miner who found the random number that produces a qualifying hash is then rewarded with a predetermined amount of digital currency as well as fees paid by users. The transaction that pays the miner is listed first in the next block in the ledger.
Mining a block and being financially rewarded is one of the things that give value to the currency. Forcing users to work for the monetary reward makes it so that others that are not mining appreciate their effort and value the currency in circulation. The reward is automatically given to the miner and it is created as if it were mined out of the Earth. It was not owned by anyone before the miner and is a finite resource. The financial reward given to miners decreases over time and will eventually reach zero.
To better keep track of the ledger as well as ensuring security, a cryptocurrency such as Bitcoin can use change transactions. When a user sends another user coins, he or she will send themselves their remaining balance to a brand new address. The new address is encrypted and unrelated to the address before it. For example, if Alice has a total of 300 coins and she wants to send Bob 100, she would send Bob 100 coins and send 200 coins to a brand new public/private key pair address. She would generate this new address when she sends the coins to Bob. Alice would be the only owner of the new private key.
Genesis
Blocks in the blockchain are assembled with the hash of the previous block. Starting a blockchain requires a block that does not rely on a previous block. This block is called the genesis block. The genesis block is special in that its hash is not calculated using the hash of another block.
bashCoin has a function called mineGenesis() that mines a file without checking the hash of another file. This function is called at the terminal with the command:
./bashCoin.sh minegen <file>
The function first checks to see if a genesis block exists so that it can abort before overwriting it:
[[ -f 1.blk.solved ]] && echo "A mined Genesis block already exists in this folder!" && exit 1
Next, the function will enter a loop, adding a nonce to the file and checking if its md5 hash starts with the same number of $ZEROS. $DIFFZEROS is the difficulty variable that is calculated by bashCoin.
while [ $ZEROS != $DIFFZEROS ] do let "NONCE += 1" HASH=$(printf -- "`cat $1`\n\n## Nonce: #################################################################################\n$NONCE\n" | md5sum) HASH=$(echo $HASH | cut -d" " -f1) echo $HASH ZEROS=$(echo $HASH | cut -c1-$DIFF) done
When the nonce is found that produces a hash that begins with the correct number of zeros bashCoin will display the results and, more importantly, build the next block in the chain. The next block includes the hash of the genesis block.
echo "Success!" echo "Nonce: " $NONCE echo "Hash: " $HASH printf -- "`cat $1`\n\n## Nonce: #################################################################################\n$NONCE\n" > 1.blk.solved printf "## Previous Block Hash: ###################################################################\n" >> 2.blk printf "$HASH\n\n" >> 2.blk
bashCoin starts the blockchain with the files “1.blk.solved” and “2.blk”. The file that was used as the genesis is not deleted from the system but it is no longer needed for the blockchain. When subsequent blocks are solved the “.solved” file remains but the “.blk” is deleted.
While Bitcoin rewards miners with coins, bashCoin currently does not. Because of this, it is a good idea to include a large transaction in the genesis block before mining so that at least one participant has wealth. bashCoin uses a specific schema for transactional data. The following two lines can be included in the genesis file for ease of use.
tx1:user1:user1:1000000 tx2:user1:user1:1000000
When the genesis block is mined, user1 will “own” 1 million bashCoins. user1 can then send up to 1 Mil coins to any other address.
Sending Bash Coins
After the first two transactions are included in the genesis block and it is mined, user1 can send coins to another address. Addresses in bashCoin can be thought of as accounts that don’t need to be set up prior to receiving coins. In Bitcoin, addresses are essentially public/private key pairs. They must be calculated before they are used. After an address in Bitcoin receives payment the private key is the only thing that allows a user to spend the balance. In bashCoin, however, any user can send transactions from any account. There is currently no security on bashCoin addresses.
The following command allows a user to send coins in bashCoin.
./bashCoin.sh send <numOfCoins> <toAddress> <fromAddress>
The <toAddress> can be any string of letters and numbers as in “user2”. bashCoin will go through the blockchain and calculate the balance of <fromAddress> so it must be associated with a positive balance for the transaction to work. Use the following example to send the first transaction:
./bashCoin send 10 user2 user1
The send() function in bashCoin first assigns the arguments to variables. (The arguments are first shifted before the send() function is called.)
SENDER=$3 RECEIVER=$2 AMOUNT=$1
After checking the current block to make sure there is a valid and live chain, send() greps the current block for the latest transaction number. If the current block does not have transactions listed it will look to the previous block for the latest transaction number. If the last transaction number cannot be found then the script exits.
if [[ `cat $CURRENTBLOCK | grep "tx[0-9]*:"` ]] then #echo "block has transactions" # Get next tx number LASTTRAN=`cat $CURRENTBLOCK | tail -1 | cut -d":" -f 1 | sed 's/tx//g' | sed 's/^0*//g'` NEXTTRAN=`echo $LASTTRAN + 1 | bc` #echo Next transaction number $NEXTTRAN else #echo "block is void of transactions!" # Get next tx number from previous block LASTTRAN=`cat $PREVIOUSBLOCK | grep tx | tail -1 | cut -d":" -f 1 | sed 's/tx//g' | sed 's/^0*//g'` NEXTTRAN=`echo $LASTTRAN + 1 | bc` #echo Next transaction number $NEXTTRAN fi [[ -z $LASTTRAN ]] && echo "ERROR: Couldn't find last transaction number" && exit 1
When the next transaction number is known, bashCoin will check the balance of the sending address. checkAccountBalance() is explained below.
checkAccountBal $3 echo "Amount to send: $AMOUNT" [[ $AMOUNT -gt $TOTAL ]] && echo "Insufficient Funds!" && exit 1
If the address has a balance greater than the sending amount, a transaction is written to the current block.
echo "Success! Sent $1 bCN to $2" echo tx$NEXTTRAN:$SENDER:$RECEIVER:$AMOUNT >> $CURRENTBLOCK CHANGETRAN=`echo $NEXTTRAN+1 | bc` CHANGE=`echo $TOTAL-$AMOUNT | bc` echo tx$CHANGETRAN:$SENDER:$SENDER:$CHANGE >> $CURRENTBLOCK
Checking Balance
bashCoin checks the balance of an address by reverse searching through the blockchain for the last time that address sent itself change. The last change transaction in the blockchain for an address is the current balance plus any receiving transactions after it. After bashCoin knows which block contains the users last change transaction, it can search the remaining blocks for receiving transactions. For instance, if Alice sent Bob 100 coins and sent herself her remaining 200 coins she would end up with 200 coins. bashCoin finds this last transaction first and then searches forward in time for any other transactions to Alice from other users. If Bob sent Alice 10 coins after Alice sent him 100, Alice would own 210 coins.
checkAccountBal () { ACCTNUM=$1 # Get the value of the last change transaction (the last time a user sent money back to themselves) if it exists for i in `ls *.blk* -1r`; do LASTCHANGEBLK=`grep -l -m 1 .*:$ACCTNUM:$ACCTNUM:.* $i` [[ $LASTCHANGEBLK ]] && break done # If there was a change transaction get the value, if not print "Account has never spent money." [[ $LASTCHANGEBLK ]] && LASTCHANGE=`grep $ACCTNUM:$ACCTNUM $LASTCHANGEBLK | tail -1` || echo "Account has never spent bashCoin." # If account has never spent money then set LASTCHANGE to zero, if it has, separate out the tx number and value of that transaction [[ $LASTCHANGE ]] && LASTCHANGETX=`echo $LASTCHANGE | cut -d":" -f 1 | sed 's/tx//'` && LASTCHANGE=`echo $LASTCHANGE | cut -d":" -f 4` || LASTCHANGE=0 # Get all of the receiving transactions after last change in the last change block and add them together if [[ $LASTCHANGEBLK ]] then RECAFTERCHANGE=`sed "1,/tx$LASTCHANGETX/d" $LASTCHANGEBLK | grep .*:.*:$ACCTNUM:.* | cut -d":" -f4 | paste -sd+ | bc` [[ $RECAFTERCHANGE ]] || RECAFTERCHANGE=0 #echo "Received after last change tx (same blk) = $RECAFTERCHANGE" else LASTCHANGEBLK=1.blk.solved RECAFTERCHANGE=`grep .*:.*:$ACCTNUM:.* $LASTCHANGEBLK | cut -d":" -f4 | paste -sd+ | bc` [[ $RECAFTERCHANGE ]] || RECAFTERCHANGE=0 #echo "Received after last change tx (same blk)(genesis) = $RECAFTERCHANGE" fi #echo $LASTCHANGEBLK # Get all the receiving transactions after last change block and add them together SUM=0 if [[ $LASTCHANGEBLK == 1.blk.solved ]] then for i in `ls -1 *.blk*`; do [[ `grep .*:.*:$ACCTNUM:.* $i` ]] && SUM=$SUM+`grep .*:.*[^$ACCTNUM]*:$ACCTNUM:.* $i | cut -d":" -f4 | paste -sd+ | bc` || SUM=$SUM+0 done else for i in `ls -1 *.blk* | sed "1,/$LASTCHANGEBLK/d"`; do [[ `grep .*:.*:$ACCTNUM:.* $i` ]] && SUM=$SUM+`grep .*:.*[^$ACCTNUM]*:$ACCTNUM:.* $i | cut -d":" -f4 | paste -sd+ | bc` || SUM=$SUM+0 done fi SUM=`echo $SUM | bc` [[ $SUM ]] || SUM=0 #echo "Received after last change tx (remaining blk's)= $SUM" # Add last change value and received money since then TOTAL=`echo $LASTCHANGE+$RECAFTERCHANGE+$SUM` TOTAL=`echo $LASTCHANGE+$RECAFTERCHANGE+$SUM | bc` echo "Current Balance for $ACCTNUM: $TOTAL" }
Validation
The only reason we can trust transactions in this system is because we can validate every transaction from the beginning. Every transaction ever recorded is grouped together in blocks and hashed. Each block includes the hash of the block before it. If a nefarious user tried to change a transaction in a previous block, the hash chain would break. The hash of that changed block would not match the hash that was listed in the next block when it was mined.
bashCoins’s validation function is named validate(). This function first checks to see if there is more than one block in the chain.
NUMSOLVEDFILES=`ls -1 *.solved | wc -l` (( $NUMSOLVEDFILES < 2 )) && echo "Blockchain must be greater than 1 block to validate" && exit 1
Next, it enters a loop that hashes a block, inserts the result into the next block, and hashes the result. As long as the hashes continue to match, it will continue until the end of the chain. If the function finds a hash mismatch it will stop and warn the user from trusting any block after the block with the bad hash.
for i in `ls -1 *.solved | tail -n +2`; do h=`ls -1 | grep solved$ | grep -B 1 $i | head -1` j=`ls -1 | egrep "solved$|blk$" | grep -A 1 $i | grep -v $i | tail -1` PREVHASH=`md5sum $h | cut -d" " -f1` CALCHASH=`sed "2c$PREVHASH" $i | md5sum | cut -d" " -f1` REPORTEDHASH=`sed -n '2p' $j` echo "Checking $i" echo "Previous Hash: $PREVHASH" #echo "Calculated Hash: $CALCHASH Reported Hash: $REPORTEDHASH" [[ $CALCHASH != $REPORTEDHASH ]] && echo "Hash mismatch! $i has changed! Do not trust any block after and including $i" && exit 1 || echo "Hashes match! $i is a good block." done echo "Blockchain validated. Unbroken Chain."
Mining
Mining in bashCoin is almost the same process as mining the genesis block. The main difference is that mine() will search for the blocks in the current directory and figure out which one needs to be mined. Also, the validate() function is called before mine() to first verify that the blockchain is unbroken. Mining the genesis block does not.
mine() { while [ $ZEROS != $DIFFZEROS ] do # increase the nonce by one let "NONCE += 1" # do the hashing HASH=$(printf "`cat $CURRENTBLOCK.wip`\n\n## Nonce: #################################################################################\n$NONCE\n" | md5sum) HASH=$(echo $HASH | cut -d" " -f1) # print the hash to the screen because it looks cool echo $HASH # cut the leading zeros off the hash ZEROS=$(echo $HASH | cut -c1-$DIFF) done echo "Success!" echo "Nonce: " $NONCE echo "Hash: " $HASH printf "`cat $CURRENTBLOCK.wip`\n\n## Nonce: #################################################################################\n$NONCE\n" > $CURRENTBLOCK.solved rm -f $CURRENTBLOCK.wip rm -f $CURRENTBLOCK # Setup the next block. Add previous hash first printf "## Previous Block Hash: ###################################################################\n" >> $NEXTBLOCK printf "$HASH\n\n" >> $NEXTBLOCK }
The mine() function automatically creates the next block and includes the hash for the freshly mined block at the top of the file.
Summary
The simple concepts within Bitcoin solve several complex problems. Namely, safeguarding wealth with strong encryption and recording an immutable, anonymous, and public ledger can be easily replicated with a bash script. See below for the current version on bashCoin. Copy and paste into a Linux terminal to use.
bashCoin.sh
#!/bin/bash ## Set difficulty ##################################### # Set to number of 0's that starts hash. # 1 = Easy, 2 = Not bad, > 3 = Difficult DIFF=2 ## Set Nonce ########################################## # Number at which to start guessing the nonce # No reason to change NONCE=0 ## Other Variables #################################### # Leave alone ZEROS=ff DIFFPLUS=1 DIFFZEROS=0 ## Functions ########################################## getGoogleHeadline () { HEADLINE=$(curl -s -k "https://news.google.com/news/headlines?hl=en&ned=us&gl=US" | grep -m 1 heading | sed 's/.*aria-level\=\"2\" >//g' | sed 's/<\/a>.*//g') } findBlocks() { CURRENTBLOCK=`ls -1 *.blk | tail -1` # If there is no current block in the current directory then exit [[ -z $CURRENTBLOCK ]] && echo "No blockchain in current folder! Try using ./bashcoin minegenesis to start a new blockchain." && exit 1 # Get the current block's number CURRENTBLOCKNUM=`echo $CURRENTBLOCK | sed 's/.blk//g'` # If the genesis block is the only block then break out of the findBlocks function before we look for previous blocks if [[ $CURRENTBLOCK == "1.blk" ]] then return fi PREVIOUSBLOCKNUM=`echo $CURRENTBLOCKNUM-1 | bc` PREVIOUSBLOCK=`echo $PREVIOUSBLOCKNUM.blk.solved` NEXTBLOCKNUM=`echo $CURRENTBLOCKNUM+1 | bc` NEXTBLOCK=`echo $NEXTBLOCKNUM.blk` PREVHASH=`md5sum $PREVIOUSBLOCK | cut -d" " -f1` } checkSyntax () { # Checks to see if difficulty was setup properly if [ $DIFF -lt 1 ] || [ $DIFF -gt 32 ] then echo "Please set difficulty to 1 through 32" exit 1 fi echo "Previous Block: "$PREVIOUSBLOCK echo "Current Block: "$CURRENTBLOCK } setup () { # Build the difficulty zeros based on DIFF variable while [ $DIFFPLUS != $DIFF ] do DIFFZEROS=$(echo $DIFFZEROS"0") let "DIFFPLUS += 1" done printf "Difficulty set to: $DIFFZEROS\n" } buildWIPBlock () { getGoogleHeadline DATE=$(date) printf "`cat $CURRENTBLOCK`\n\n" > $CURRENTBLOCK.wip printf "## Google News Headline: ##################################################################\n" >> $CURRENTBLOCK.wip printf "$HEADLINE\n\n" >> $CURRENTBLOCK.wip printf "## Mine Date and Time: ####################################################################\n" >> $CURRENTBLOCK.wip printf "$DATE\n\n" >> $CURRENTBLOCK.wip } mine () { # start mining, check to see if the hash starts with the winning number of zeros and if it does complete the loop while [ $ZEROS != $DIFFZEROS ] do # increase the nonce by one let "NONCE += 1" # do the hashing HASH=$(printf "`cat $CURRENTBLOCK.wip`\n\n## Nonce: #################################################################################\n$NONCE\n" | md5sum) HASH=$(echo $HASH | cut -d" " -f1) # print the hash to the screen because it looks cool echo $HASH # cut the leading zeros off the hash ZEROS=$(echo $HASH | cut -c1-$DIFF) done echo "Success!" echo "Nonce: " $NONCE echo "Hash: " $HASH printf "`cat $CURRENTBLOCK.wip`\n\n## Nonce: #################################################################################\n$NONCE\n" > $CURRENTBLOCK.solved #printf "$HASH\n" > $CURRENTBLOCK.hash rm -f $CURRENTBLOCK.wip rm -f $CURRENTBLOCK # Setup the next block. Add previous hash first printf "## Previous Block Hash: ###################################################################\n" >> $NEXTBLOCK printf "$HASH\n\n" >> $NEXTBLOCK } mineGenesis () { # first check to see if there is a blockchain already, if so exit so we don't overwrite [[ -f 1.blk.solved ]] && echo "A mined Genesis block already exists in this folder!" && exit 1 # start mining, check to see if the hash starts with the winning number of zeros and if it does complete the loop while [ $ZEROS != $DIFFZEROS ] do # increase the nonce by one let "NONCE += 1" # do the hashing HASH=$(printf -- "`cat $1`\n\n## Nonce: #################################################################################\n$NONCE\n" | md5sum) HASH=$(echo $HASH | cut -d" " -f1) # print the hash to the screen because it looks cool echo $HASH # cut the leading zeros off the hash ZEROS=$(echo $HASH | cut -c1-$DIFF) done echo "Success!" echo "Nonce: " $NONCE echo "Hash: " $HASH printf -- "`cat $1`\n\n## Nonce: #################################################################################\n$NONCE\n" > 1.blk.solved #printf "$HASH\n" > 1.blk.hash # Setup the next block. Add previous hash first printf "## Previous Block Hash: ###################################################################\n" >> 2.blk printf "$HASH\n\n" >> 2.blk } checkAccountBal () { ACCTNUM=$1 # Get the value of the last change transaction (the last time a user sent money back to themselves) if it exists for i in `ls *.blk* -1r`; do LASTCHANGEBLK=`grep -l -m 1 .*:$ACCTNUM:$ACCTNUM:.* $i` [[ $LASTCHANGEBLK ]] && break done # If there was a change transaction get the value, if not print "Account has never spent money." [[ $LASTCHANGEBLK ]] && LASTCHANGE=`grep $ACCTNUM:$ACCTNUM $LASTCHANGEBLK | tail -1` || echo "Account has never spent BashCoin." # If account has never spent money then set LASTCHANGE to zero, if it has, separate out the tx number and value of that transaction [[ $LASTCHANGE ]] && LASTCHANGETX=`echo $LASTCHANGE | cut -d":" -f 1 | sed 's/tx//'` && LASTCHANGE=`echo $LASTCHANGE | cut -d":" -f 4` || LASTCHANGE=0 # Print the value of the last change transaction (the value of the users account before any other received transactions) #echo Last Change = $LASTCHANGE #echo Last Change Transaction Number = $LASTCHANGETX # Get all of the receiving transactions after last change in the last change block and add them together if [[ $LASTCHANGEBLK ]] then RECAFTERCHANGE=`sed "1,/tx$LASTCHANGETX/d" $LASTCHANGEBLK | grep .*:.*:$ACCTNUM:.* | cut -d":" -f4 | paste -sd+ | bc` [[ $RECAFTERCHANGE ]] || RECAFTERCHANGE=0 #echo "Received after last change tx (same blk) = $RECAFTERCHANGE" else LASTCHANGEBLK=1.blk.solved RECAFTERCHANGE=`grep .*:.*:$ACCTNUM:.* $LASTCHANGEBLK | cut -d":" -f4 | paste -sd+ | bc` [[ $RECAFTERCHANGE ]] || RECAFTERCHANGE=0 #echo "Received after last change tx (same blk)(genesis) = $RECAFTERCHANGE" fi #echo $LASTCHANGEBLK # Get all the receiving transactions after last change block and add them together SUM=0 if [[ $LASTCHANGEBLK == 1.blk.solved ]] then for i in `ls -1 *.blk*`; do [[ `grep .*:.*:$ACCTNUM:.* $i` ]] && SUM=$SUM+`grep .*:.*[^$ACCTNUM]*:$ACCTNUM:.* $i | cut -d":" -f4 | paste -sd+ | bc` || SUM=$SUM+0 done else for i in `ls -1 *.blk* | sed "1,/$LASTCHANGEBLK/d"`; do [[ `grep .*:.*:$ACCTNUM:.* $i` ]] && SUM=$SUM+`grep .*:.*[^$ACCTNUM]*:$ACCTNUM:.* $i | cut -d":" -f4 | paste -sd+ | bc` || SUM=$SUM+0 done fi SUM=`echo $SUM | bc` [[ $SUM ]] || SUM=0 #echo "Received after last change tx (remaining blk's)= $SUM" # Add last change value and received money since then TOTAL=`echo $LASTCHANGE+$RECAFTERCHANGE+$SUM` TOTAL=`echo $LASTCHANGE+$RECAFTERCHANGE+$SUM | bc` echo "Current Balance for $ACCTNUM: $TOTAL" } send() { SENDER=$3 RECEIVER=$2 AMOUNT=$1 # Check if current block is solved just to make sure the blockchain is still live CURRENTBLOCKCHECK=`ls -1 *.blk | tail -1 | grep solved` if [[ $CURRENTBLOCKCHECK ]] then echo "The current block is already solved!" echo "ERROR: need unsolved block" exit 1 fi # Check to see if current block has transactions listed if [[ `cat $CURRENTBLOCK | grep "tx[0-9]*:"` ]] then #echo "block has transactions" # Get next tx number LASTTRAN=`cat $CURRENTBLOCK | tail -1 | cut -d":" -f 1 | sed 's/tx//g' | sed 's/^0*//g'` NEXTTRAN=`echo $LASTTRAN + 1 | bc` #echo Next transaction number $NEXTTRAN else #echo "block is void of transactions!" # Get next tx number from previous block LASTTRAN=`cat $PREVIOUSBLOCK | grep tx | tail -1 | cut -d":" -f 1 | sed 's/tx//g' | sed 's/^0*//g'` NEXTTRAN=`echo $LASTTRAN + 1 | bc` #echo Next transaction number $NEXTTRAN fi [[ -z $LASTTRAN ]] && echo "ERROR: Couldn't find last tranasction number" && exit 1 checkAccountBal $3 echo "Amount to send: $AMOUNT" #echo Your current account balanace: $TOTAL [[ $AMOUNT -gt $TOTAL ]] && echo "Insufficient Funds!" && exit 1 echo "Success! Sent $1 bCN to $2" echo tx$NEXTTRAN:$SENDER:$RECEIVER:$AMOUNT >> $CURRENTBLOCK CHANGETRAN=`echo $NEXTTRAN+1 | bc` CHANGE=`echo $TOTAL-$AMOUNT | bc` echo tx$CHANGETRAN:$SENDER:$SENDER:$CHANGE >> $CURRENTBLOCK } validate() { # Check that there are blocks to validate NUMSOLVEDFILES=`ls -1 *.solved | wc -l` (( $NUMSOLVEDFILES < 2 )) && echo "Blockchain must be greater than 1 block to validate" && exit 1 for i in `ls -1 *.solved | tail -n +2`; do h=`ls -1 | grep solved$ | grep -B 1 $i | head -1` j=`ls -1 | egrep "solved$|blk$" | grep -A 1 $i | grep -v $i | tail -1` PREVHASH=`md5sum $h | cut -d" " -f1` CALCHASH=`sed "2c$PREVHASH" $i | md5sum | cut -d" " -f1` REPORTEDHASH=`sed -n '2p' $j` echo "Checking $i" echo "Previous Hash: $PREVHASH" #echo "Calculated Hash: $CALCHASH Reported Hash: $REPORTEDHASH" [[ $CALCHASH != $REPORTEDHASH ]] && echo "Hash mismatch! $i has changed! Do not trust any block after and including $i" && exit 1 || echo "Hashes match! $i is a good block." done echo "Blockchain validated. Unbroken Chain." } case "$1" in mine) validate findBlocks checkSyntax setup buildWIPBlock mine exit 0 ;; minegenesis|minegen) shift [[ -z $@ ]] && echo "Usage: ./bashCoin minegenesis <filename>" && echo "This command mines the first block (any file you like)." && exit 1 setup mineGenesis $1 ;; send) shift [[ -z $@ ]] && echo "Usage: ./bashCoin send <amount> <toAddress> <fromAddress>" && exit 1 findBlocks send $@ exit 0 ;; checkbalance|checkbal|bal) shift [[ -z $@ ]] && echo "Usage: ./bashCoin bal <address>" && exit 1 checkAccountBal $1 exit 0 ;; findblocks) findBlocks ;; validateblockchain|validate|val) validate exit 0 ;; *) echo $"Usage: $0 {mine|send|checkbalance(bal)|minegenesis(minegen)}" exit 1 ;; esac exit 0
0 Comments