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.
- Loading branch information
Showing
2 changed files
with
40 additions
and
2 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,25 @@ | ||
# Bitcoin Whitepaper Exercises - Incentives | ||
|
||
TODO | ||
In this exercise, our focus is on the incentives we can use to motivate the time and resources spent running a blockchain node. We'll do this in a simple (greedy) way by implementing a selection algorithm for picking transactions to add to the blockchain that maximizes our payoff from transaction/block fees for each block we create. | ||
|
||
## 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. NOTE: we'll only use the public key for this exercise. | ||
|
||
## Exercise | ||
|
||
We'll create each line as a transaction, but instead of adding each transaction in order to the blockchain right away, we'll add the transactions to a "pool" (an array). | ||
|
||
Define `addPoem(..)` to loop through the lines of the poem and create a new transaction for each, adding each transaction to the `transactionPool` array. Each transaction should include not only the `data` (the line of the poem) but also a randomly generated positive integer value between `1` and `10` to use for its transaction fee, as its `fee` field. | ||
|
||
After the poem's lines have been created as transactions in the pool, we'll then process the entire pool by selecting several transactions at a time to add as a single block to the blockchain, and repeating until the pool is empty. Because our selection order will be dependent on the amounts of the transaction fees, the lines of the poem will likely not be added to the blockchain in their chronological order; that's perfectly OK for this exercise. | ||
|
||
Define `processPool(..)` to select transactions from the pool in descending order of their `fee` value, pulling them out of the `transactionPool` array for adding to a new block. Each block's list of transactions should start with an object representing the block-fee to be paid for adding this transaction; this object should include a `blockFee` field equal to the amount in the `blockFee` constant, as well as an `account` field with the public key (`PUB_KEY_TEXT`). | ||
|
||
The maximum number of transactions (including the block fee) for each block is specified by `maxBlockSize`, so make sure not to exceed that count. | ||
|
||
Finally, define `countMyEarnings(..)` that traverses the whole blockchain -- skip the genesis block! -- and adds up all the block fees and transaction fees. Print out your total earnings. NOTE: since transaction fees are randomly generated, this value will change between each run of your program. | ||
|
||
BONUS: inspect your blockchain to make sure you added all the transactions to blocks in descending order of their fee. |
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,19 @@ | ||
# Bitcoin Whitepaper Exercises - Proof of Work | ||
|
||
TODO | ||
In this exercise, we're going back to the simplicity of the first exercise; we're just adding a piece of text (a line from the poem) to a block, no transactions or signatures or inputs/outputs or any of that complication. | ||
|
||
Instead, this exercise focuses on a simple implementation of the "Proof of Work" consensus algorithm -- the goal of which being to make it "difficult" / "not worth it" for a malicious person to recompute all the hashes in an entire chain just so they can rewrite a bit of history. | ||
|
||
To implement Proof of Work, we're going to keep trying to compute a hash for a block until the hash is "lower" than a certain threshold, as defined by an incrementing `difficulty` integer. This `difficulty` value represents the required number of leading (on the left) `0`'s in the **binary representation** of the hash -- not the normal hexadecimal represtation where each character represents 4 bits. The more leading `0`'s there are, the lower that hash value is. | ||
|
||
To get a new hash each time you compute, you need to change the data in the block. For this reason, blocks need a `nonce` field added, which is simply a random number. Each time you generate a new `nonce`, recompute the hash and compare (with `hashIsLowEnough(..)`) to see if it's low enough to be accepted for the current `difficulty`. | ||
|
||
There are different ways of comparing a hash value's binary bit representation to see if it's low enough. Here are some hints to get you started: | ||
|
||
* You don't need to compare the whole hash, only the first X hexadecimal digits (characters) of it from the left, depending on how many bits the `difficulty` value implies. Remember, 4 bits is one hexadecimal digit character. | ||
|
||
* You can create a number value from a string representing its binary bits like this: `Number("0b001011011")`, which produces the number value `91`. | ||
|
||
* `difficulty` means how many leading `0`'s must be present when representing a hash's left-most characters in binary. You may do this comparison based on string characters or numeric values (of either binary or base-10 form), whichever seems best to you. But, make sure you compare values in the same kind of representation/base. | ||
|
||
* JavaScript now supports a `padStart(..)` utility for strings, which may be useful here. |