-
Notifications
You must be signed in to change notification settings - Fork 37
block.ex
This file is responsible for storing all the functions related to blocks.
The index is an integer value that determines the position of the block within the chain. This is similar to how a database has an "id" field, which it uses to index the values in it. The index of a block must be exactly 1 higher than the block before it. It's important to note that our chain is reverse sorted, due to how Elixir handles list modification; it is exponentially more computationally intensive to add an item to the end of the list, while it is very easy to add to the beginning of the list. Because of this, the first block in the chain will always be the latest, and the last block in the chain will always be the genesis block. An index is not necessarily unique. Because an index is just the representation of the location of the block within the chain, when 2 miners mine a block at the same time, if a fork is successfully created, both block indexes will be the same.
The hash of a block is a SHA3 representation of the block header. The block header is not stored in the block, but is made up of items in the block. The block header is the concatenated version of the block index, the hash of the block that came before it (previous_hash
), the timestamp of the block, the nonce, and the merkle root of all transactions within the block.
The previous_hash
of a block refers to the hash of the block that came directly before it. This is what links blocks together; if a block earlier in the chain changes, then its hash will also change, meaning all blocks that came after it will now have different hashes (since the previous_hash
is used to calculate the hash
).
This is a float representing the difficulty that was used to mine the block. The higher the difficulty, the harder it is to mine the block (more PoW). The difficulty scales as the network hashrate increases/decreases. This difficulty is used to calculate the target number of the block hash. When a miner mines the block, they need the number represented by the hash to be lower than the target.
For example, the (minimum) difficulty 0 would mean that the target number is 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
, which is 115792089237316195423570985008687907853269984665640564039457584007913129639935
. The miner would need to generate a hash that, when converted from base 16 to base 10, would be lower than that number. As the difficulty increases, the target number becomes proportionally lower, making it harder to generate a hash that is lower than the target.
The nonce is an integer that the miner increments every time they attempt to hash a block. Since hashing the block header (index
, previous_hash
, timestamp
, merkle_root
) creates the same hash no matter how many times you hash, the process of mining a block would never work, you would always be producing the same hash. The nonce is added to the block header before it is hashed in order to make it different on each iteration, which means you generate a different hash on every iteration.
A utc representation of the time when the block was generated (right before it starts getting mined)
The merkle root is a hexadecimal string representing all of the transactions withing the block. Because the SHA3 hashing algorithm takes longer to hash when representing a larger set of data, miners would be discouraged from including transactions into blocks if the block header consisted of all transactions. Instead, we find the merkle root of the id
s of the transactions within the block before we start mining and use that, so hashing isn't slowed down -- no matter how many transactions are included in the block, the size of the merkle root is the same.
This is a list containing every transaction in the block