Lab 4 Details for MPCS 56600

Each lab will consist of a small problem and details of how to proceed. Each lab is intended to give every student hands-on experience with the core concepts and technologies covered during the course.  A student may concentrate, as a team member, on one technology over another for the final project, but labs are designed to give each and every student exposure to all the technologies that come into play.  You need to submit labs to the TAs for grading--see submission instructions below.  Generally, unless otherwise specified, you will have one week to complete each assigned lab.

See the syllabus for information on grading.  Turning in lab assignments on time is required, without exception, and all late deliveries will be penalized, regardless of cause.  Submit your assignments to the subversion repository according to the directions on the syllabus page.

You may write these solutions in any programming language of your choice.  Our suggestion is now is not the time to learn a new programming language along with the concepts themselves.  So our suggestion is to use whatever programming language you  know best.

Lab 4   Due: 5:00 pm, Thursday, July 19, 2018

Problem 1:  Transaction laboratory: 

BACKGROUND:

You will create a new raw transaction and you will send it to the TESTNET blockchain.  You will submit a text file named "my.transaction.out".  This lab assumes you have successfully accomplished Lab 1.

WHAT YOU NEED TO DO:

YOU ARE TO WORK IN THE TESTNET ENVIRONMENT.  This means running the bitc alias that you created in Lab 1.  Make sure bitd is running.

STEP 1:

You need to install some software.  Simple go to:  https://stedolan.github.io/jq/ and grab the appropriate installation for your system and install it.  Make sure you environment is updated so that you can call jq.  JQ is a lightweight and flexible command-line JSON processor that does nice things with the JSON output from bitcoin-core tools (and others).  A tutorial on JQ is here.  The user manual is here.  Validate that you've got JQ installed by typing at a command prompt:

$ jq --version
jq-1.5

The precise version will not matter.

STEP 2:

Open a terminal window, and type the following (of course you will not type the initial '$' prompt):

$ echo $BLOCKCHAIN

You should see:  testnet

If you do not see testnet output, execute:

$ export BLOCKCHAIN='testnet'

STEP 3:

At the command line, execute:

$ bitc getbalance

Note your balance.  It may be 0.00.  That's ok, and that's about to change. 


STEP 4:
 
At the command line, execute:

$ recipient=$(bitc getnewaddress)

Then type:

$ echo $recipient

You should see a bitcoin address print out.  Copy this address to your clipboard.

STEP 5:

Open a browser and navigate to the following TESTNET faucet:  https://testnet.manu.backend.hamburg/faucet
Prove you're not a robot and in the prompt area, paste your bitcoin address you created in STEP X.  Then click on the "Send me some bitcoins" button.

Note the "Sent! TX ID: [some transaction id]" output in green.

STEP 6:

At the command line, execute:

$ bitc getbalance

Note your balance. 
Let's pretend the faucet delivered and your balance is now 2.0000.

At the prompt, enter:

$ bitc listunspent

and pick an available transaction output (you may have just one...the transaction the faucet just sent you), AND NOTE ITS TRANSACTION ID AND 'vout' NUMBER.  Your output should look something like (at a minimum):

 {
    "txid": "3b8ebc563b843d9b89d3e6JoZ5Xgw26669b66e9347a43c6c2c1e15944be3fe2",
    "vout": 1,
   ...
    "amount": 2.00000000,
    ...
}

Select and copy the hexadecimal "txid" value (in our example,
3b8ebc563b843d9b89d3e6JoZ5Xgw26669b66e9347a43c6c2c1e15944be3fe2)

STEP 7:

At the prompt, create a txn_id variable and paste the transaction id that you copied above:

$ txn_id='3b8ebc563b843d9b89d3e6JoZ5Xgw26669b66e9347a43c6c2c1e15944be3fe2'

Confirm this by typing:

$ echo $txn_id

And you should see:

3b8ebc563b843d9b89d3e6JoZ5Xgw26669b66e9347a43c6c2c1e15944be3fe2
 

STEP 8:

At the prompt, enter:

$ changeaddress=$(bitc getrawchangeaddress)

$ echo $changeaddress
2NBAZ5Xebpo5DRbrTHhhqCJbkBPUikogwK1

Your own changeaddress will of course be different.  This one is made up.
 
STEP 9:

Go back to the output from listunspent command above, and note the transaction 'vout' number for transaction $txn_id.  It should look something like:

"vout": 1,

It may say 0, or some other number.  At the prompt, enter (assuming the vout for the transaction you want to use is '1'):

$ utxo_vout_no=1
 
STEP 10:


NOW DO THE MATH:

Assume an amount (from listunspent) of 2.0000 (as per our example).

I want you to pay half of the available output of 2.0000 (or half of whatever value you have in the transaction), which in our example is 1.0000, to the recipient address that you created above (stored in $recipient).

That leaves 1.0000 (or whatever) change available to come back to you.
 
BUT, you also need to calculate the transaction fee (let's be safe and set it to .0005 BTC to be sure to get some miners interested...), so:

Your remaining 1.0000 - .0005 = 0.9995 remainder that will be coming back to you, via your changeaddress that you created earlier in STEP X.  So to sum up, you are taking a transaction in the amount of 2.0000 (again per our example) and sending 1.0000 to your (own) recipient address and you are sending 0.9995 to your change address, and the miners will take .0005.  Thus:

2.0000 - 1.0000 - 0.9995 - 0.0005 = 0 (you've absorbed the entirety of the transaction's value).

STEP 11:

NOW
PACKAGE UP AND SEND YOUR TRANSACTION TO TESTNET (Note you will need to change the amounts in the command below to whatever math you've calculated!!!):

$ rawtxhex=$(bitc -named createrawtransaction inputs='''[ { "txid": "'$txn_id'", "vout": '$utxo_vout_no' } ]''' outputs='''{ "'$recipient'": 1.0000, "'$changeaddress'": 0.9995 }''')

Note you do not specify the transaction fee of 0.0005.  The miners will calculate that automatically.

Now sign the transaction:

$
signedtx=$(bitc -named signrawtransaction hexstring=$rawtxhex | jq -r '.hex')

Now send the transaction to TESTNET:

$ bitc -named sendrawtransaction hexstring=$signedtx
6c3733d8c958e36033ec3a56760a74e59065b936bb23bcda2424a6b980fa2780 (returned txid...note this is made up...)

The value returned is the transaction id of your new transaction you just created on the TESTNET blockchain.  Note this as you will use it below in Step 13.

STEP 12:

AFTER CLEARING:

Look at your transaction on the TESTNET (MAY TAKE A FEW MINUTES):

bitc getrawtransaction
6c3733d8c958e36033ec3a56760a74e59065b936bb23bcda2424a6b980fa2780 1

(copy and paste your own transaction id returned from the sendrawtransaction command above and do not forget the '1' at the end...)

Now, look at your new balance (again, if you received no error messages, you may need to wait a few minutes...)

$ bitc getbalance
1.99950000   [Should reflect slight deduction for transaction fee, as per our example:  2.0000 - 0.0005 =
1.9995]

Finally, look at your new list of unspent transactions

$ bitc listunspent
(see unspent transactions modified...original one is gone but the change address amount is new)

STEP 13:

When done: 

Copy the raw transaction id that you got (we are using our example id of
6c3733d8c958e36033ec3a56760a74e59065b936bb23bcda2424a6b980fa2780).

Execute the following command, substituting your actual new transaction id for our sample below, and submit the file:

echo '
6c3733d8c958e36033ec3a56760a74e59065b936bb23bcda2424a6b980fa2780' > my.transaction.out; bitc getbalance >> my.transaction.out; bitc listunspent >> my.transaction.out

REMEMBER, you will substitute YOUR actual new transaction id you obtained in step 11 above for the '6c3733...' transaction above.

Submit my.transaction.out file as per the instructions below.

Problem 2:  Blockchain laboratory: 

BACKGROUND:

Now it is time to begin to build your own blockchain.  From scratch.  Needless to say, our intention here is not to replicate Bitcoin Core.  That might be a bit much.  Over the remaining labs, you will build a simple blockchain that implements a simple cryptocurrency that can be mined and distributed across nodes.  You will generally find the References section below helpful in addition to the required and recommended reading. 

WHAT YOU NEED TO DO:

STEP 1:

You are to produce the following UML description in code using a programming language of your choice.  For those using non- or quasi-object-oriented-languages, use some alternate form of a class, whatever makes the most sense, for instance, a structure or other such data type that makes the most sense to you.  For those of you using an object-oriented-capable language (such as python, ruby, C++, Java, C#, etc.), you are to use classes.

The UML for the blockchain you are to build is this:



When we specify types in the above, these are indicators.  What that means is that you are to come as close as you can to that datatype in the language that you are using.  For those using strongly-typed languages (C++, Java, etc.), this will be trivial.  For those using late-binding languages (python, ruby, etc.), just do your best.  You will not be downgraded because a data is not of the correct "type".  In the above, if you see a default type specified (such as "int" for 0xD9B4BEF9 for the MagicNumber in the Block class), you are expected to implement that default at the time of class instantiation.  For further elucidation as to the meanings of the above, see the bitcoinwiki pages in the References section below.

Specifics:

The Header's hashPrevBlock is a double-SHA256 hash of the previous block's header (serialized/stringified as necessary and concatenated).  You do not need to worry about big-endian or little-endian issues with your blockchain.  Simply use whatever comes most natural to you.  We are not looking for a precise algorithm to do this.  Just do it and be consistent for your own sake.  The minimum set of specific fields you are to concatenate (and hash) from the header are:  TimeStamp + hashMerkleRoot + Bits + Nonce + previousHash.  These fields will represent a Block's Blockhash.  If you find that your implementation would benefit from hashing additional information, such as an index or count, etc., that is entirely up to you.  You are free to add to the above UML model as your implementation evolves.  You do not need to ask permission to add attributes (data fields) or methods or functions.  The Block's Blockhash is a hash of the current block's header.  What this means is that in our simplified case, a block holds a hash of it's own Header information, and it's header holds a hash of the previous block's hash, and so on.

For the Transactions ListOfIntputs, any list object or list-like data structure will be fine, including a map or a dictionary; this is all up to you.  The actual inputs and outputs can be a string for the moment (i.e., making the ListOfIntputs a list of strings).  The Transaction's TransactionHash is a hash of the concatenated (serialized/stringified) fields of VersionNumber, InCounter, ListOfInputs, OutCounter, and ListOfOutputs.  We will leave it to you to decide some means of serializing/stringifying your ListOfInputs and ListOfOutputs (which again, can be lists of simple strings).  You may wish to implement the Block's Transactions list as a map or dictionary, where each key is the actual Transaction's TransactionHash. 

For the hashMerkleRoot in the Header, you are to create a Merkle Tree and store its Merkle Root hash in this field.  You may actually store the transactions internally in the Block as a Merkle Tree (is in Block's Transactions list), what data structure you actually use to construct your tree is entirely up to you.  We've simply designated it as a "list".  That is not meant to be prescriptive.  You may re-use your Merkle Tree work from Lab 3 here.  Even if it's not a list.

The character and form and parameters of constructors, methods, etc., are entirely up to you.  You will notice that we have only specified data elements in the above UML model.  You are granted carte blanche to design and implement your blockchain as you see fit, as long as these core requirements are met.

Finally, you will notice that we have not specified a particular class called a Blockchain!  This is intentional.  You may design your Blockchain class or structure as you see fit, as long as it stores blocks (in memory only) that are cryptographically linked and the blocks themselves contain Transactions as specified above (Transaction inputs and outputs do not need to be linked or associated at this time).  For example, you may implement your blockchain as a list or other data structure, such a stack or a queue, in memory.  There are no requirements that your blockchain be persisted on disk.

If you have no immediate need for a given element (for instance, a Block's Nonce or Bits values), you can simply leave them with a default value for the time being.  Again, default values should be set at the time of object instantiation.

You are free to implement the printing of block data and transaction data (via printBlock() and printTransaction()) as you see fit.  This may imply a less anonymous blockchain where plain data is printed (i.e., from input strings and output strings) or you may encrypt these strings and print out the hashes (thus creating a more anonymous blockchain).  This again, is up to you.  You might find it simply easier to leave the data in plaintext in this first version to make debugging a little easier.

Other than the above requirements, there are a few other general requirements:

Function 1.  There must be some means of asking your Blockchain for a given block by block height and by block hash.  It is up to you how to implement this.
Function 2.  There must be some means of searching the Blockchain for a given Transaction by TransactionHash, which should return the Transaction being searched.  It is up to you how to implement this.

Everything else should be self-explanatory, including the meaning of the indicator "SHA256Doublehash".  You should know what that means by now. 

Most importantly:  Anything not specifically spelled out as a requirement above may be interpreted and implemented as you wish.  You can think of this as creative license.

STEP 2:

You are to write a test case (can be a simple main function or an actual test harness from a framework) in which you manually (read:  hard-code) instantiate 10 new transactions, where each transaction has one input and one output (can be anything you wish at the moment).  You will create a new Blockchain and by doing so you will create your genesis blockWhen instantiating the Blockchain, you are to create a Genesis Block which will have the hashPrevBlock hash set to all 0's.  You can set the genesis block's Transaction Input and Output strings to be anything you wish.  You may set the genesis block's Transaction Output string to be anything you wish.  Basically understand that the genesis block and its transactions are hard-coded.

You will manually add the first 5 transactions to a new block that you instantiate at height number 1.  Block 0 will be your genesis block.  You are to create a third block which will be at height number 2, and you will add the remaining 5 transactions to that third block.    After building your blockchain,  you are to use Function 1 above to find and return a block by height and then print that block.  You are then to use Function 2 to find and return a transaction from the blockchain (searching by transaction id hash) and print out that transaction.  Again, you may implement these two functions any way you see fit.

Submit all code and related files (if any) as specified below.

Finally, and importantly, there are many implementations of "simple block chains" around the internet.  Feel free to look at any of them.  But remember, your submission had best not closely resemble any of them in such a way that it would indicate direct copying.

References:

You may find the following references helpful (in addition to the links from previous labs):

Learning Bitcoin from the Command Line
The Bitcoinwiki Page on Transactions
The Bitcoinwiki Page on Raw Transactions
The Bitcoinwiki Page on Blocks

Submitting:

Use the folder named "lab4" in your Subversion repository. See the syllabus for more info about submission using Subversion. Upload your Lab 4 code and any supporting materials to the repo. Please include a README text file to explain what parts of the work you are submitting, where the different parts of the work are located and please provide a little info on how to compile and run your code.