The translation of the series of articles I have put on the GitHub: blockchain-tutorial, follow-up updates will be on the GitHub, may not be synchronized here. If you want to run the code directly, you can also clone GitHub on the Tutorial warehouse and go to the SRC directory to execute make. Introduction
Timestampis the current timestamp, which is the time the block was created.Datais the actual valid information that is stored in the block.PrevblockhashThe hash of the previous block is stored.HashIs the hash of the current block.In the Bitcoin specification,Timestamp, prevblockhash, Hash is the chunk header (block header), and the chunk header is a separate data structure. And the transaction, which is here, is another separate data structure. For the sake of simplicity, I mixed the two together.
So how do we compute the hash? How to compute the hash is a very important part of the block chain. It is this feature that makes the chain of blocks safe. Calculating a hash is a very difficult operation to compute. Even on high-speed computers, it takes time (which is why people buy GPU to dig bitcoin). This is an intentional architectural design that makes it very difficult to add new blocks, so it is hard to make changes once the blocks are added. In the next few articles in this series, we will discuss and implement this mechanism.
Currently, we take only a few fields of the block structure (Timestamp, Data, and Prevblockhash), connect them to each other, and then compute a SHA-256 hash on the result of the connection. Let's complete this task in the Sethash method:
Func (b *block) Sethash () {
timestamp: = []byte (StrConv. Formatint (B.timestamp))
headers: = bytes. Join ([][]byte{b.prevblockhash, B.data, timestamp}, []byte{})
Hash: = sha256. Sum256 (headers)
B.hash = hash[:]
}
1
2
3
4
5
6
7
Next, according to Golang's convention, we implement a function that simplifies the creation of a block:
Func newblock (data string, Prevblockhash []byte) *block {block
: = &block{time. Now (). Unix (), []byte (data), Prevblockhash, []byte{}} block
. Sethash () return block
}
1
2
3
4
5
This is our first block chain. I never thought it would be so easy.
Now, let's add a block to it:
Func (BC *blockchain) addblock (data string) {
Prevblock: = Bc.blocks[len (Bc.blocks)-1]
Newblock: = Newblock ( Data, Prevblock.hash)
bc.blocks = append (Bc.blocks, Newblock)
}
1
2
3
4
5
Complete. But is that really the case?
In order to add a new block, we have to have an existing block, but now our chain is empty, not one block. So, in any block chain, there must be at least one block. Such a block, which is the first block in the chain, is usually called the Genesis block (Genesisblocks). Let's implement a way to create a creation block:
Func Newgenesisblock () *block {return
newblock ("Genesis block", []byte{})
}
1
2
3
Now we can implement a function to create a block chain with a Genesis block:
Func Newblockchain () *blockchain {return
&blockchain{[]*block{newgenesisblock ()}}
}
1
2
3
To check whether our block chain is working as scheduled:
Func Main () {
BC: = Newblockchain ()
BC. Addblock ("Send 1 BTC to Ivan")
BC. Addblock ("Send 2 more BTC to Ivan")
for _, Block: = Range bc.blocks {
fmt. Printf ("Prev. Hash:%x\n", block. Prevblockhash)
FMT. Printf ("Data:%s\n", block.) Data)
FMT. Printf ("Hash:%x\n", block. Hash)
FMT. Println ()
}
1
2 3 4 5 6 7 8
9
ten
12
13
Output:
Prev. Hash:
data:genesis block
hash:aff955a50dc6cd2abfe81b8849eab15f99ed1dc333d38487024223b5fe0f1168
Prev. hash:aff955a50dc6cd2abfe81b8849eab15f99ed1dc333d38487024223b5fe0f1168
Data:send 1 BTC to Ivan
hash:d75ce22a840abb9b4e8fc3b60767c4ba3f46a0432d3ea15b71aef9fde6a314e1
Prev. Hash: D75ce22a840abb9b4e8fc3b60767c4ba3f46a0432d3ea15b71aef9fde6a314e1
data:send 2 BTC to Ivan
Hash: 561237522BB7FCFBCCBC6FE0E98BBBDE7427FFE01C6FB223F7562288CA2295D1
1
2
3
4
5
6
7
8
9
11