1.区块链基本构成
开篇首先笼统介绍一下区块链的基本构成,方便大家对区块链结构有一个大概的了解。区块链主要由数据层、共识层、网络层等组成,如图1所示。
图1 区块链系统架构
2.各个层的含义及其作用
在具体描述各个层应用之前,我们先假设一个虚拟环境,假设你生活在米花社村,这个村庄在进行交易时不采用实体货币,而是采用记账的形式进行交易,例如张三和狗剩初始时均有100元,张三在狗剩的肉摊上购买了20元的精肉,这时张三和狗剩就会用广播的形式对全村的人喊道:“我们直接进行了交易,交易金额为20元“,此时,全村人民就会在自己的记账本上写上狗剩和张三之间的交易,如图2所示。
图2 交易模式
这种交易方式每天都要重复上百次,米花社村民觉得很麻烦,于是他们找到村长,让村长担任记账员,负责记录每一笔账单,村长每天早上会在公示栏中公布昨天一天各家各户的收益与支出,村民们只需要将其抄下带回去核对即可,我们将每一天公布的账单称为区块,而数据层的目的就是使用区块记录包括交易账本。今天村民账号上的资金与昨天最后交易后所剩下的资金相同,这样每一天的账单就可以与前一天相挂钩,也就是说区块之间用链进行了连接,如图3所示。
图3 区块之间的连接
但村长在担任记账员时也需要收入,村民合计出来一个办法,村长每记录一笔账单,便可从中获取1元的收益,假设一天当中村长可以记录500次交易,则村长便可获得500元收益。这时,村里的二狗看不下去了,他认为他一天搬砖只能赚取一两百,而村长每天记账就可以赚500元,他觉得不公平,便和其他村民商量,他们最终达到共识———每天早上。每个村民分别掷20次色子,谁总共点数最大,谁便是今天的记账员,这便相当于区块链中的共识层(目的是让去中心化的区域链系统能够快速达成共识),此时由于每天的记账员不同,我们也就是说每个村民都有当记账员的可能,没有可信任的第三方,这就是区块链架构的特点———去中心化。
张贴账单的公示栏毕竟只能在一个地方,那些住的较远的村民不方便来回抄写,他们便可以抄写其他村民的账单以此获取村中交易的详细记录,这便是区块链结构中的另一个特点———开放性(所有节点可以查看区块链中任意区块记录的信息)。每一位村民之间互相抄写账单,组成了一个庞大的网,在这个网中,村民被称为节点,如图4所示。同时如果有一位村民想篡改交易信息时,我们认为这个是困难的,因为你要篡改所有村民所抄写的交易记录,这就是区块链架构的一个特点———不可篡改性。由于每次交易都有详细的记录,这便是区块链架构的又一个特点———可追溯性(任意数据在区块链上都可以进行追溯)。
图4 形成区块链
3.结语
本文只是简单对区块链进行了一个介绍,区块链中还包括哈希计算和智能合约等内容,后面我将持续更新相关内容。
4.区块链的简单代码(C语言)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <openssl/sha.h>
// 定义区块结构
typedef struct {
int index;
time_t timestamp;
char data[100];
char prevHash[SHA256_DIGEST_LENGTH * 2 + 1];
char hash[SHA256_DIGEST_LENGTH * 2 + 1];
} Block;
// 计算字符串的 SHA-256 散列值
void calculateHash(const char *input, char *output) {
unsigned char hash[SHA256_DIGEST_LENGTH];
SHA256_CTX sha256;
SHA256_Init(&sha256);
SHA256_Update(&sha256, input, strlen(input));
SHA256_Final(hash, &sha256);
for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
sprintf(output + 2 * i, "%02x", hash[i]);
}
output[SHA256_DIGEST_LENGTH * 2] = '\0';
}
// 创建新区块
Block createBlock(int index, const char *data, const char *prevHash) {
Block newBlock;
newBlock.index = index;
newBlock.timestamp = time(NULL);
strncpy(newBlock.data, data, sizeof(newBlock.data));
strncpy(newBlock.prevHash, prevHash, sizeof(newBlock.prevHash));
// 计算区块的哈希值
char blockData[200];
snprintf(blockData, sizeof(blockData), "%d%ld%s%s", newBlock.index, newBlock.timestamp, newBlock.data, newBlock.prevHash);
calculateHash(blockData, newBlock.hash);
return newBlock;
}
// 挖矿
Block mineBlock(int index, const char *data, const char *prevHash) {
Block newBlock;
do {
newBlock = createBlock(index, data, prevHash);
} while (strncmp(newBlock.hash, "0000", 4) != 0); // 简化的挖矿过程,要求哈希以 "0000" 开头
return newBlock;
}
int main() {
// 创建初始区块
Block genesisBlock;
genesisBlock = createBlock(0, "Genesis Block", "0000000000000000000000000000000000000000000000000000000000000000");
// 输出初始区块信息
printf("Block #%d\n", genesisBlock.index);
printf("Timestamp: %ld\n", genesisBlock.timestamp);
printf("Data: %s\n", genesisBlock.data);
printf("Previous Hash: %s\n", genesisBlock.prevHash);
printf("Hash: %s\n", genesisBlock.hash);
printf("\n");
// 挖矿创建新区块
Block block1 = mineBlock(1, "Transaction Data", genesisBlock.hash);
// 输出新区块信息
printf("Block #%d\n", block1.index);
printf("Timestamp: %ld\n", block1.timestamp);
printf("Data: %s\n", block1.data);
printf("Previous Hash: %s\n", block1.prevHash);
printf("Hash: %s\n", block1.hash);
return 0;
}