用R语言编码理解区块链的数据形式
目录
参考资料
Understanding Blockchains by Coding One in R:这篇文章使用了另外一个proof-of-work算法,有助于理解设计和评估算法的思路。
Building your own blockchain in R:这篇文章非常详细,并且在本地建立了可交互的API。
整体思路
-
区块链中的每一个block在R中使用一个list表示,包含需要储存的内容;
-
新建的block通过将前一个block的内容取hash值来确保前一个block的内容不被修改,目前的算力下不能通过穷举倒推出hash值代表的内容;
-
加入proof-of-work算法来增加建block的难度,即在每个block中加入额外的验证来判断新block是否有效。
建立第一个block
数据类型list可以在一个对象中存放多个不同类型的数据。
一个block中,除了需要存储的数据,还有时间、block序号、前一个block的hash和用来校验proof-of-work的字段。
1# Create a list to store our blockchain
2blockchain <- list()
3
4# Create the first block in the blockchain
5blockchain[[1]] <- list(index = 1,
6 timestamp = Sys.time(),
7 data = "Genesis Block",
8 previous_hash = "0",
9 nonce = 0)
计算单个block的hash
使用digest计算一个block的hash:
1# Function to calculate the hash of a block
2hash_block <- function(block) {
3 return(digest::digest(toString(block)))
4}
“挖矿”函数
通常说的“挖矿”即通过proof-of-work算法的校验新建一个block。BTC使用的校验是新建block的hash满足开头为连续的$n$个0,$n$通过过去2周实际新建的block数量调整,目标是达到平均每10分钟新建一个block。
最新区块
在本文撰写时,BTC.com上播报的最新区块高度
760,446,hash为00000000000000000004ee4fcb027dce239c91568cbbc367790a26c06d5b5e2c。这是以16进制表示的256Bit,第一个4表示为0100,因此当前校验要求的前导0个数为 77 / 256.在单个block中加入一个计数器字段nonce,通过不断穷举nonce使这个block的hash满足校验。
以$n=4$ (16进制表示) 为示例,函数的输入参数为当前区块链和新block需要存储的数据,输出为增加了1个block的区块链。
1# Function to mine a new block
2mine_block <- function(blockchain, data) {
3 # Get the last block in the blockchain
4 last_block <- blockchain[[length(blockchain)]]
5
6 # Create a new block
7 new_block <- list(index = last_block$index + 1,
8 timestamp = Sys.time(),
9 data = data,
10 previous_hash = hash_block(last_block),
11 nonce = 0)
12
13 # Find a nonce that satisfies the proof-of-work requirement
14 while(substr(hash_block(new_block), 1, 4) != "0000") {
15 new_block$nonce <- new_block$nonce + 1
16 }
17
18 # Add the new block to the blockchain
19 blockchain[[new_block$index]] <- new_block
20
21 return(blockchain)
22}
应用示例
以下是在区块链中新增block,存储自定义数据的示例。
1# Add some data to our blockchain
2blockchain <- mine_block(blockchain, "Block 1 Data")
3blockchain <- mine_block(blockchain, "Block 2 Data")
4blockchain <- mine_block(blockchain, "Block 3 Data")
5
6# View the blockchain
7blockchain