What I understand about blockchain is that:
Blocks are secured by the hash.
Transactions are secured by the markle-tree.
Does this mean that the markle-tree is not involved at all in securing the blocks?
If so, what prevents us from changing the transactions if we know the hash of older blocks in the chain?
Please note that I'm assuming that we are using a blockchain with only one node. And I want to know how hard it is to hack the blockchain in one node. Because as far as i understand, the hashing alone is very secure, but distributing the blockchain on multiple nodes will make it even more secure.
Blocks are secured with the proof of work. The proof of work is a measure related to how many hashes (on average) it would take to get a block hash equal to the network target value. The lower the target value, the more work was done on the block, and the harder it is to change or "hack" the data in the block and still remain a valid block (because you must do the work again).
The merkle root is just a way to represent all of the transactions in the block in a single hash value, which is part of the data that is hashed to produce the block hash. If you change any of the transaction data, it will produce a different merkle root, and that will make the resulting block hash different too, and now the proof of work must be done again before the block would be considered valid.
Now, with only one node, it does not matter. If you are able to change the data in a block and rehash that block with a new valid hash (one that is equal to or lower than the network target value), you have a new block, but the node will reject it because it already has that block. You must mine the next block also before anyone else because one of the consensus rules is that the longest valid chain always wins.
Having only one node running means that node can be changed by the person who is running it, possibly without anyone else knowing. This might remove certain rules that you thought we're being followed, which could reverse one of your transactions, so it is good to run your own node to make sure the rules are being followed.
Related
Our blockchain consists of a range of blocks that are chained together with a linked list, going only backward, where each block header has a prevHash (bitcoin) or parentHash (ethereum).
Here's my question: If I can't go forward, how do I know I'm on the latest block?
Do I ask other peers in the network what block they are on?
And, theoretically, if I'm the only one on the network, what happens then?
If I can't go forward, how do I know I'm on the latest block?
Each miner, after they created a block, broadcasts the new block (including its number) to the network.
So each node (both miners and non-miners) gets the latest block from this broadcasted message.
Plus, you can also ask other peers directly about their current block to validate if you're on the current block as well.
Note: Sometimes multiple miners create and broadcast a valid block with the same number. Only one of them is accepted by the network (usually the one with the lowest timestamp) and the others are discarded as "uncle blocks".
And, theoretically, if I'm the only one on the network, what happens then?
Then you're the only miner as well, so you also have the last block number from the block that you mined.
After reading Grokking Bitcoin I now have a broad idea of how Bitcoin works, but I still have a doubt that, generally, how a blockchain-based system can guarantee the immutability of a random block? I know every block has a stored hash value of the content of the previous block plus some nonce.
Let's say this blockchain(for simplicity, we use a linked-list style rather than a Merkle tree style) has 1000 blocks, and a hacker just changed the content inside of the 10-th block. Of course, if we recompute the hash of this 10-th block and compare it with the hash stored inside of the 11th block, it will be different, most probably.
My question is, should a blockchain-based system periodically check the hash inside of every block to detect if the content of a block is changed? In this case, if the system does not have a function to periodically recompute the hash of the 10-th block, it will not be able to detect the change, right? In other words, my question is how a blockchain-based system detects the change of a block?
Thanks
When you change the content of the 10th block you have to find the hash to meet the difficulty for that block. This is called "mining" and it takes time/energy. When you finally found the hash value for that block you can propagate your new block to the blockchain to all the other nodes.
However, they will ignore this block which would create a new branch of the blockchain at the 9th block because it is 991 blocks behind the current blockchain (that's about 7 days behind in the blockchain). The miners will work only on the longest chain for new blocks, not on the most recent received chain. So, your new 10th block will not be saved or used at all. Your effort in calculating the hash is wasted. Furthermore, the original 10th block is still inside the blockchain known by every other node and it has not been changed. You have just mined a different 10th block no other node cares about.
I want my smart contract to return 7 or 8 UNIQUE random numbers ranging from 1 to 100 upon calling the contract. What can be the best approach to obtain such result?
Probably if you are trying to build roulettes, lotteries, and card games using the Ethereum blockchain, as the Ethereum blockchain is deterministic, it imposes certain difficulties for those who have chosen to write their own pseudo-random number generator (PRNG).
Some Vulnerable Methods Currently Used
If you are using the block variables like block.coinbase, block.difficulty, block.timestamp etc.. as the source of entropy, all these block variables can be manipulated by miners, so they cannot be used as a source of entropy because of the miners’ incentive. As the block variables are obviously shared within the same block, you can easily use internal messages to yield the same outcome.
Other methods are like using blockhash of current or some past block
or blockhash of a past block combined with a private seed. block.blockhash(block.number) function is used in these cases. However, at the moment of transaction execution in the EVM, the blockhash of the block that is being created is not yet known for obvious reasons and the EVM will always yield zero. If we are trying it with the blockhash of a previous block, an attacker can make an exploit contract with the same code in order to call the target contract via an internal message. The “random” numbers for the two contracts will be the same.
Even if we combine the blockhash with a private seed, being transparent in nature, the blockchain must not be used to store secrets in plaintext. It is trivial to extract the value of the private variable pointer from the contract storage and supply it as an argument to an exploit.
Some Areas Worth Exploring
External oracles
Signidice
Commit–reveal approach
With External oracles like Oraclize, smart contracts can request data from web APIs such as currency exchange rates, weather forecasts, and stock prices (like random.org). The key drawback of this approach is that it is centralized. Will Oraclize daemon tamper with the results? Can we trust random.org?
Instead of Oraclize, we can also use BTCRelay which is a bridge between Ethereum and Bitcoin blockchains. Using BTCRelay, smart contracts in the Ethereum blockchain can request future Bitcoin blockhashes and use them as a source of entropy.
Signidice is an algorithm based on cryptographic signatures that can be used for random number generation in smart contracts involving only two parties: the player and the house. The algorithm works as follows:
The player makes a bet by calling a smart contract.
The house sees the bet, signs it with its private key, and sends the signature to the smart contract.
The smart contract verifies the signature using the known public key.
This signature is then used to generate a random number.
Commit–reveal approach consists of two phases:
A “commit” stage, when the parties submit their cryptographically protected secrets to the smart contract.
A “reveal” stage, when the parties announce cleartext seeds, the smart contract verifies that they are correct, and the seeds are used to generate a random number.
A better implementation of the commit–reveal approach is Randao. Commit–reveal can be combined with future blockhashes to make it more secure.
This pretty much covers all the methods for random number generation using Ethereum.
Like Raghav said, random numbers on the blockchain are hard. The public nature of the network makes it very hard to generate a number that cannot be pre-calculated.
With that said, one of the best solutions is to use an oracle that gets the random number from an external (read: non-blockchain based) source. Take a look at this guide. The Ethtroll Dapp is a good example of this, so take a look at the code here. They use Oraclize to get a random number from Random.org.
An issue with using an oracle is the centralization factor. If you set up your Dapp in the way I have described above, you are at the mercy of a rouge employee at two different centralized services—Oraclize and Random.org. Though it would be unlikely for someone to manipulate either of these sources, people will perform irrational acts for potential economic gain.
Use a Chainlink VRF.
There are a number of issues with using the blockhash or similar as the method of random seeding. If an attacker knows the blockhash before your contract, they can use that information to gain a malicious advantage on whatever it is you're trying to do. An oracle can help here, but they are a central source of failure and must be able to prove they are random.
You need to have an oracle network that can:
Prove that the numbers generated are random.
Have enough oracles/nodes that even if one fails/is corrupt, your smart contract will persist.
At this time, the example below shows how to solve #1. You can solve #2 by pulling from a sufficient number of nodes who support the Chainlink VRF.
For an exact implementation, see this answer from a similar question.
You'll want to make a request to a node with a function that takes a seed generated by you:
function rollDice(uint256 userProvidedSeed) public returns (bytes32 requestId) {
require(LINK.balanceOf(address(this)) > fee, "Not enough LINK - fill contract with faucet");
uint256 seed = uint256(keccak256(abi.encode(userProvidedSeed, blockhash(block.number)))); // Hash user seed and blockhash
bytes32 _requestId = requestRandomness(keyHash, fee, seed);
emit RequestRandomness(_requestId, keyHash, seed);
return _requestId;
}
And when the value is returned, you'll mod it by 100 and add 1. You'll need to call this 7 or 8 times if you want 7 or 8 random numbers.
function fulfillRandomness(bytes32 requestId, uint256 randomness) external override {
uint256 d6Result = randomness.mod(100).add(1);
emit RequestRandomnessFulfilled(requestId, randomness);
}
I have a brainstorming idea, maybe helps somebody.
It is a simplified Commit–reveal approach with just one participant.
It wil be needed a title for every random generation. That tittle should be and standard, and easy to audit.
First I Commit("Alice's Lotery") on the smartContract. If title is repeated (check hashes) it will be rejected.
And for reveal will be needed to wait at least 1 extra block confirmation, this 2 blocks should come from different miners to ensure miner is not attacking this smartcontract.
And then you execute Reveal("Alberto's Lottery").
The magic happens here; The sources for random will be the titlle, msg.sender, block.blockhash of the commit block, and the block.blockhash(commitBlockNumber+1) because nobody can predict the future hash nor which miner will discover it [you could add coinbase or timestamp also to get more random value].
Also you could check if timestamps of commitBlockNumber and commitBlockNumber+1 are too much close or too much separated, this could indicate that some minner is trying to force some block, so you could reject this lottery.
And of course if you can watch too much close tx with commits like ("Alice's Lottery") || ("AAlice's Lottery") you can probe that this lottery is being tricked.
Also you could do this with more than 2 "interval" blocks
for example if a certain block requires certain 5 leading zeros then can't we write a 32 byte random hash which has 5 leading zeroes like
00000C66DA510B7C524F7EF33279BCA641E2E8BF94B6B15AC6343CD2B706F673
or
00000C66DA510B7C524F7EF33279BCA641E2E8BF94B6B15AC6343CD2ASDFERTY
Also, if i am designing my own blockchain,then will choosing any random number without hashing make a difference in security of the blockchain?
You can't choose the hash of a blockchain block. Each block has some data (including the hash of the previous block), and then a "nonce", and then a cryptographic hash of the whole thing. One of the essential design properties of a cryptographic hash is that nobody knows how to choose the input to make the output come out a particular value.
What a blockchain miner does all day is compute HASH(prev_hash || new data || 1), HASH(prev_hash || new data || 2), HASH(prev_hash || data || 3), ... until they reach a number that makes the hash come out with the required number of leading zeroes. That's the work that they are proving they have done. And then they publish the block, with its nonce and hash, and it takes only a trivial amount of work by comparison to verify that HASH(prev_hash || new data || n) has the required number of leading zeroes, so the block is accepted.
Proof of work is not a mandatory feature of a blockchain, and in fact it would be really nice if we could figure out a good alternative, because proof of work is what makes Bitcoin consume as much electricity as the entire country of Sweden or whatever it's up to these days. A blockchain is just a sequence of blocks of data, chained together with cryptographic hashes and signatures. What proof-of-work does - what including the "hash must have so many leading zeroes" rule does - is make it difficult for someone to control which miner will successfully mine the next block, and that is argued to mean "no one individual can force the distributed system to accept their next block instead of someone else's."
If some of the assertions in the previous paragraph seem a bit, um, shaky to you, you are absolutely correct. That is why cryptocurrency is still a field of active research rather than something everyone uses all the time.
AFAIK after block validation node runs all transactions in the block, changing the state (list of UTXOs)
Let's imagine that at some point node realizes that it was on the wrong chain and there is longer chain available, which forked some blocks before.
How does it make the switch? I imagine that it should run all transactions in reverse till the fork happened to restore the state and than replay all transactions in the blocks from the longer chain?
Thanks!
Each node receives individual transactions as well as individual blocks from the network.
It also keeps the most updated blockchain locally.
For every new transaction it receives, the node validates it, and if valid, propagates to its peers.
For every block the node receives, it validates it. The validation includes several steps, among which:
1. checking that the block points to the most recent block in the blockchain (it's preceding block)
2. all transactions included in the block are valid.
A fork is a temporary situation, possible when there are 2 valid blocks (or more) which arrive to a node pretty much at the same time, so the node doesn't know which is the right one. It keeps the first one added to it's local blockchain as the main chain, and keeps the second one as a fork chain (also locally), until a next node arrives, and is added to one of the two. When it happens - the longer chain is chosen to be the main blockchain (at that node!), and the second is kept as a side chain.
All such side chains are kept in the node's memory for some time, until it can be sure they are not relevant anymore (since they are shorter than the main blockchain by several blocks), and then removed.
I don't know why you have the picture that anything has to be "rolled back". Yes, it's rolling back, but no calculations with transactions have to be done at all. Here's why:
When node A has N+5 blocks and node B has N+2 block, then all node B has to do is drop these additional two blocks and take the 5 new blocks from A.
That's all! Yes, it effectively is rolling back, but nothing has to be run in reverse, because dropping blocks is effectively equivalent to reversing transactions.
Remember that transactions are directed, so they happen only in one direction in time. Meaning: For valid blocks, every non-coinbase transaction in block number N has to have some history in every previous blocks, so block number N is dependent on that history, but the opposite is not true. Previous blocks don't depend on block number N, so dropping N won't invalidate them.