Blog

Blockchain Technology by Example: A Walkthrough of a Simple Blockchain Program Written in Bash

by | May 14, 2018 | Blockchain | 0 comments

blockchain technology

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

Categories

0 Comments

Submit a Comment

Your email address will not be published. Required fields are marked *