forked from cooganb/bitcoin-whitepaper-exercises
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
adding exercise READMEs for hashing, transactions, and wallet
- Loading branch information
Showing
3 changed files
with
97 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,39 @@ | ||
# Bitcoin Whitepaper Exercises - Hashing | ||
|
||
TODO | ||
In this exercise, you will practice writing code to create blocks, compute block hashes, and verify blocks based on those hashes. | ||
|
||
## Part 1 | ||
|
||
You are provided lines of text from a poem, and you should loop through them and add each line as its own block of data to the provided blockchain. | ||
|
||
Define a `createBlock(..)` function which takes the text for its data, creates an object for the block, and computes its hash, finally returning the block object. Insert this object into the `blocks` array for the blockchain. | ||
|
||
Each block should have the following fields: | ||
|
||
* `index`: an incrementing number that's the 0-based position of the new block within the `blocks` array; the genesis block has `index` of `0`, so the next block will have `index` of `1`, and so on | ||
|
||
* `prevHash`: the value of the `hash` field from the last block in the `blocks` array | ||
|
||
* `data`: the string value passed into `createBlock(..)` | ||
|
||
* `timestamp`: the numeric timestamp (from `Date.now()`) of the moment the block is created | ||
|
||
* `hash`: the SHA256 hash of the block's other fields (`index`, `prevHash`, `data`, and `timestamp`) | ||
|
||
Verify that your blockchain includes all 8 lines of the poem, each as separate blocks, for a total of 9 blocks including the genesis block. | ||
|
||
## Part 2 | ||
|
||
Define a `verifyChain(..)` function that checks all blocks in the chain to ensure the chain is valid, and returns `true` or `false` accordingly. It may be useful to define a `verifyBlock(..)` function that can be called for each block object. | ||
|
||
Each block should be checked for the following: | ||
|
||
* `data` must be non-empty | ||
* for the genesis block only, the hash must be `"000000"` | ||
* `prevHash` must be non-empty | ||
* `index` must be an integer >= `0` | ||
* the `hash` must match what recomputing the hash with `blockHash(..)` produces | ||
|
||
In addition to verifying a block, the linkage between one block and its previous block must be checked, throughout the whole chain. That is, the block at position 4 needs to have a `prevHash` equal to the `hash` of the block at position `3`, and so on. | ||
|
||
Print out verification that the blockchain is valid after having added all the poem text as blocks. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,31 @@ | ||
# Bitcoin Whitepaper Exercises - Transactions | ||
|
||
TODO | ||
Similar to the previous Hashing exercise, in this exercise you will add the 8 lines of text from the provided poem to a blockchain. But this time, you will add each one as a separate transaction, authorize the transaction with a key and signature, and then add all 8 transactions to a single block. Finally, you'll validate the blockchain, including all the transaction signatures. | ||
|
||
## Setup | ||
|
||
Run `npm install` in this exercise folder to install the dependencies listed in the included `package.json` file. | ||
|
||
Run `node generate-keys.js` from the command-line to create the `keys/` sub-directory which includes a keypair to use for digital signatures. | ||
|
||
## Part 1 | ||
|
||
Define a `createTransaction(..)` function that takes the text (line of a poem) and creates a transaction object. The transaction object should have a `data`. The transaction then needs a `hash` field with the value returned from `transactionHash(..)`. | ||
|
||
Define an asynchronous `authorizeTransaction(..)` function which then adds to the transaction object, a `pubKey` field with the public key text (`PUB_KEY_TEXT`), and a `signature` field with the signature created by `await`ing a call to `createSignature(..)`. | ||
|
||
In `addPoem()`, for each line of the poem, create and authorize a transaction object and store it in the `transactions` array. Then add set those transactions as the data for a new block, and insert the block into the blockchain. | ||
|
||
## Part 2 | ||
|
||
Modify `verifyBlock(..)` to validate all the transactions in the `data` of a block. It may be useful to define a `verifyTransaction(..)` function. | ||
|
||
Each transaction should be verified according to: | ||
|
||
* `hash` should match what's computed with `transactionHash(..)` | ||
|
||
* should include `pubKey` string and `signature` string fields | ||
|
||
* the `signature` should verify correctly with `verifySignature(..)` | ||
|
||
Print out verification that the blockchain is valid after having added all the poem text as transactions. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,33 @@ | ||
# Bitcoin Whitepaper Exercises - Wallet | ||
|
||
TODO | ||
In this exercise, you will create and authorize transactions which "spend" money by transferring from one account to the other, and back. You will define a wallet that tracks two accounts, including `outputs` that determine each account's balances, and spend those `output`s as `input`s to the other account, and vice versa. One of the expenditures must be rejected for insufficient balance, and gracefully noted. | ||
|
||
Finally, you will add all these transactions to the blockchain, verify the chain, and compute and print out the final balances after the transactions. | ||
|
||
## Setup | ||
|
||
Run `npm install` in this exercise folder to install the dependencies listed in the included `package.json` file. | ||
|
||
Run `node generate-keys.js` from the command-line to create the `keys/` sub-directory which includes two keypairs, one for each account, to use for digital signatures. | ||
|
||
## Part 1 | ||
|
||
Notice that `addAccount(..)` (which is called twice for you) creates two entries in our wallet, with each entry tracking the keypair for that account as well as its current list of valid `outputs` that represent all the funds available to that account to spend. | ||
|
||
In addition to recording our transactions on the blockchain, this list of outputs, for each account, will be updated each time an expenditure is made. | ||
|
||
Unlike the previous Transactions exercise, where all we added to a transaction object was `data` that was a string value (line of a poem), the `data` for a transaction will be an object that holds two arrays, `inputs` and `outputs`. Each element in these arrays will be an object that represents either the source (`inputs`) or target (`outputs`) of funds, as well as a signature to verify each input. | ||
|
||
Modify `spend(..)` to create the transaction data as just described as an object, including verifying each input, then create that transaction, then insert it into a block. | ||
|
||
The rules for spending dictate that we should sort the outputs we have in an account in greatest to least order, and spend the biggest ones first. For whatever amount we're spending, we need to add up enough `outputs` to equal or exceed that amount. Each of the selected `outputs` are recorded as `inputs` in the transaction data, and each of these should include a signature signed by the private key of the originating account. | ||
|
||
If our total selected `outputs` (aka `inputs`) amounts exceeds the intended amount to spend, we'll need another `output` for this transaction that represents the change/refund back to the originating account for the difference. If we don't have enough `outputs` in an account for the amount we're spending, that should be noted as an error and the expenditure transaction should be aborted. | ||
|
||
For example, if you have outputs of `5`, `10`, and `15`, and you want to spend `23`, you'd sort the list to `15`, `10`, and `5`, and thus `15` and `10` would be used. But since that exceeds `23`, you need to give "change" of `2` back as an `input` to the originating account (from whom these two `outputs` were selected). | ||
|
||
## Part 2 | ||
|
||
Define `accountBalance(..)` to compute the total balance for an account in the wallet by adding up all its `outputs` amounts. | ||
|
||
The notice that one of the expenditures was not possible because of lack of funds should be printed, along with the balances of both accounts. Finally, print out the result of calling `verifyChain(..)` to verify the state of the blockchain. |