来吧,创造一条区块链(下)

上一篇介绍了一条迷你区块链‘蛇链’的诞生,用了不到50行代码。为了把‘蛇链’变成正真可以使用的区块链,本篇给‘蛇链’添加了一些新的功能,发行‘蛇币’,真的能收发币了!下面是文章的翻译。

蛇币来了!

Note: This article assumes you’ve read part one.
警告:没看上一篇不许看这篇(ง ˙o˙)ว。

The tiniest blockchain was extremely simple, and it was relatively easy to make. But, with its simplicity came a few flaws.
迷你区块链非常简单,简单也带来一些问题。

First, SnakeCoin only ran on one single machine, so it was far from distributed, let alone decentralized.
第一个问题,目前‘蛇链’只能单机运行,离分布式还很远,更别说去中心化了。

Second, blocks could be added to the chain as fast as the host computer could create a Python object and add it to a list.
第二个问题,区块增长的速度和计算机速度一样快,其实就是计算机创建Python对象并添加到列表的速度。

In the case of a simple blockchain, that’s not a problem, but we’re now going to let SnakeCoin be an actual cryptocurrency so we’ll need control the amount of blocks (and coins) that can be created at a time.
在迷你区块链中,出块速度快不是什么问题,但如果想让‘蛇币’成为正真的加密货币,我们必须限制出块速度。

From now on, SnakeCoin’s data will be transactions, so each block’s data field will be a list of some transactions. We’ll define a transaction as follows. Each transaction will be a JSON object detailing the sender of the coin, the receiver of the coin, and the amount of SnakeCoin that is being transferred.
‘蛇链’的区块数据存放交易记录,也就成了‘蛇币’。每条交易记录是JSON格式,包含发币人、收币人和交易金额。

Note: Transactions are in JSON format for a reason I’ll detail shortly.
交易记录为啥用JSON格式后面会讲。

{
  "from": "71238uqirbfh894-random-public-key-a-alkjdflakjfewn204ij",
  "to": "93j4ivnqiopvh43-random-public-key-b-qjrgvnoeirbnferinfo",
  "amount": 3
}

Now that we know what our transactions will look like, we need a way to add them to one of the computers in our blockchain network, called a node.
知道交易记录长啥样了,接下来我们需要把交易记录添加到区块链网络中的一台电脑(或者叫节点)。

To do that, we’ll create a simple HTTP server so that any user can let our nodes know that a new transaction has occurred.
为了实现这个功能,我们创建一个简单的HTTP服务,任何用户可以让节点知道新交易记录来了。

A node will be able to accept a POST request with a transaction (like above) as the request body. This is why transactions are JSON formatted; we need them to be transmitted to our server in a request body.
节点将能够接收POST请求,请求中包含交易记录。这就是为啥我们用JSON格式表示交易记录。我们需要交易记录作为请求体发送到服务器。

pip install flask # Install our web server framework first
node = Flask(__name__)

# Store the transactions that
# this node has in a list
this_nodes_transactions = []

@node.route('/txion', methods=['POST'])
def transaction():
  if request.method == 'POST':
    # On each new POST request,
    # we extract the transaction data
    new_txion = request.get_json()
    # Then we add the transaction to our list
    this_nodes_transactions.append(new_txion)
    # Because the transaction was successfully
    # submitted, we log it to our console
    print "New transaction"
    print "FROM: {}".format(new_txion['from'])
    print "TO: {}".format(new_txion['to'])
    print "AMOUNT: {}\n".format(new_txion['amount'])
    # Then we let the client know it worked out
    return "Transaction submission successful\n"

node.run()

Awesome! Now we have a way to keep a record of users when they send SnakeCoins to each other. This is why people refer to blockchains as public, distributed ledgers: all transactions are stored for all to see and are stored on every node in the network.
666!我们已经有办法记录‘蛇币’交易了。可以看出,为什么人们把区块链当作公开的、分布式的账本,因为所有的交易记录都能被所有人看到而且存储在网络中每个节点上。

But, a question arises: where do people get SnakeCoins from? Nowhere, yet. There’s no such thing as a SnakeCoin yet, because not one coin has been created and issued yet.
问题又来了,从哪里得到‘蛇币’呢?目前还没发行出‘蛇币’。

To create new coins, people have to mine new blocks of SnakeCoin. When they successfully mine new blocks, a new SnakeCoin is created and rewarded to the person who mined the block. The coin then gets circulated once the miner sends the SnakeCoin to another person.
为了发行‘蛇币’,需要在‘蛇链’上挖出新的区块,俗称‘挖矿’。当新的区块被挖出,新的‘蛇币’也就产生了,并奖赏给挖出的人,俗称‘矿工’。矿工把‘蛇币’发送给别人,‘蛇币’就流通起来了。

We don’t want it to be too easy to mine new SnakeCoin blocks, because that will create too many SnakeCoins and they will have little value.
我们不能轻易产生区块了,这会导致‘蛇币’通货膨胀而贬值。

Conversely, we don’t want it to be too hard to mine new blocks, because there wouldn’t be enough coins for everyone to spend, and they would be too expensive for our liking.
当然,我们也不能使得挖矿太难,否则没有足够的货币流通了,通货紧缩。

To control the difficulty of mining new SnakeCoins, we’ll implement a Proof-of-Work (PoW) algorithm. A Proof-of-Work algorithm is essentially an algorithm that generates an item that is difficult to create but easy to verify.
为了控制‘蛇币’的挖矿难度,需要使用‘工作量证明’算法。‘工作量证明’算法其实就是一个很难得到计算结果而很容易验证计算结果的算法(比如数独游戏)。

The item is called the proof and, as it sounds, it is proof that a computer performed a certain amount of work.
算法名称叫‘证明’,也就是证明计算机做出了一定量的计算。

In SnakeCoin, we’ll create a somewhat simple Proof-of-Work algorithm. To create a new block, a miner’s computer will have to increment a number. When that number is divisible by 9 (the number of letters in “SnakeCoin”) and the proof number of the last block, a new SnakeCoin block will be mined and the miner will be given a brand new SnakeCoin.
在‘蛇币’中,我们采用一个简单的‘工作量证明’算法。矿工计算机只需要把一个数字(证明数)递增来挖矿。具体就是,这个增长的数字一旦能同时被9整除和上个区块的证明数同时整除,就挖到了一个‘蛇币’,矿工也就得到这个‘蛇币’作为奖励。

# ...blockchain
# ...Block class definition

miner_address = "q3nf394hjg-random-miner-address-34nf3i4nflkn3oi"

def proof_of_work(last_proof):
  # Create a variable that we will use to find
  # our next proof of work
  incrementor = last_proof + 1
  # Keep incrementing the incrementor until
  # it's equal to a number divisible by 9
  # and the proof of work of the previous
  # block in the chain
  while not (incrementor % 9 == 0 and incrementor % last_proof == 0):
    incrementor += 1
  # Once that number is found,
  # we can return it as a proof
  # of our work
  return incrementor

@node.route('/mine', methods = ['GET'])
def mine():
  # Get the last proof of work
  last_block = blockchain[len(blockchain) - 1]
  last_proof = last_block.data['proof-of-work']
  # Find the proof of work for
  # the current block being mined
  # Note: The program will hang here until a new
  #       proof of work is found
  proof = proof_of_work(last_proof)
  # Once we find a valid proof of work,
  # we know we can mine a block so 
  # we reward the miner by adding a transaction
  this_nodes_transactions.append(
    { "from": "network", "to": miner_address, "amount": 1 }
  )
  # Now we can gather the data needed
  # to create the new block
  new_block_data = {
    "proof-of-work": proof,
    "transactions": list(this_nodes_transactions)
  }
  new_block_index = last_block.index + 1
  new_block_timestamp = this_timestamp = date.datetime.now()
  last_block_hash = last_block.hash
  # Empty transaction list
  this_nodes_transactions[:] = []
  # Now create the
  # new block!
  mined_block = Block(
    new_block_index,
    new_block_timestamp,
    new_block_data,
    last_block_hash
  )
  blockchain.append(mined_block)
  # Let the client know we mined a block
  return json.dumps({
      "index": new_block_index,
      "timestamp": str(new_block_timestamp),
      "data": new_block_data,
      "hash": last_block_hash
  }) + "\n"

Now, we can control the number of blocks mined in a certain time period, and we can issue new coins for people in the network to send to each other.
好了,我们已经能够控制挖矿的速度,也能发行新货币用于流通。

But like we said, we’re only doing this on one computer. If blockchains are decentralized, how do we make sure that the same chain is on every node?
但是这还是一台电脑在计算。区块链应该是分布式的,怎么同步每个节点中的账本呢?

To do this, we make each node broadcast its version of the chain to the others and allow them to receive the chains of other nodes. After that, each node has to verify the other nodes’ chains so that the every node in the network can come to a consensus of what the resulting blockchain will look like. This is called a consensus algorithm.
为了实现同步,可以让每个节点广播自己的账本,并接收其他节点的账本。每个节点检查其他节点的账本,全网最后得到共识-哪条链是最终版。这个过程被称为‘共识算法’。

Our consensus algorithm will be rather simple: if a node’s chain is different from another’s (i.e. there is a conflict), then the longest chain in the network stays and all shorter chains will be deleted. If there is no conflict between the chains in our network, then we carry on.
我们的共识算法很简单,当一个节点的链(账本)和别人不同时(也就是产生冲突时),只保留最长的链,其他短链删除。如果全网没有节点冲突,就继续保持。

@node.route('/blocks', methods=['GET'])
def get_blocks():
  chain_to_send = blockchain
  # Convert our blocks into dictionaries
  # so we can send them as json objects later
  for block in chain_to_send:
    block_index = str(block.index)
    block_timestamp = str(block.timestamp)
    block_data = str(block.data)
    block_hash = block.hash
    block = {
      "index": block_index,
      "timestamp": block_timestamp,
      "data": block_data,
      "hash": block_hash
    }
  # Send our chain to whomever requested it
  chain_to_send = json.dumps(chain_to_send)
  return chain_to_send

def find_new_chains():
  # Get the blockchains of every
  # other node
  other_chains = []
  for node_url in peer_nodes:
    # Get their chains using a GET request
    block = requests.get(node_url + "/blocks").content
    # Convert the JSON object to a Python dictionary
    block = json.loads(block)
    # Add it to our list
    other_chains.append(block)
  return other_chains

def consensus():
  # Get the blocks from other nodes
  other_chains = find_new_chains()
  # If our chain isn't longest,
  # then we store the longest chain
  longest_chain = blockchain
  for chain in other_chains:
    if len(longest_chain) < len(chain):
      longest_chain = chain
  # If the longest chain wasn't ours,
  # then we set our chain to the longest
  blockchain = longest_chain

We’re just about done now. After running the full SnakeCoin server code, run the following commands in your terminal. Assuming you have cURL installed.
快完工了!运行‘蛇币’服务端代码后,需要在你的终端运行几行命令。假设你已经安装了cURL。

1.Create a transaction.
创造交易

curl "localhost:5000/txion" \
     -H "Content-Type: application/json" \
     -d '{"from": "akjflw", "to":"fjlakdj", "amount": 3}'

(实际运行代码中,译者使用以下命令才能创造交易)

curl "http://localhost:5000/txion"  -d"{\"from\": \"akjflw\", \"to\":\"fjlakdj\", \"amount\": 3}" -H "Content-Type: application/json"
  1. Mine a new block.
    挖矿
curl localhost:5000/mine
  1. Check out the results. From the client window, we see this.
    查看结果,在客户端界面可以看到下图。


    图片发自简书App

With a little bit of pretty printing we see that after mining we get some cool information on our new block.
从显示中我们得到一些有意思的挖矿信息。

{
  "index": 2,
  "data": {
    "transactions": [
      {
        "to": "fjlakdj",
        "amount": 3,
        "from": "akjflw"
      },
      {
        "to": "q3nf394hjg-random-miner-address-34nf3i4nflkn3oi",
        "amount": 1,
        "from": "network"
      }
    ],
    "proof-of-work": 36
  },
  "hash": "151edd3ef6af2e7eb8272245cb8ea91b4ecfc3e60af22d8518ef0bba8b4a6b18",
  "timestamp": "2017-07-23 11:23:10.140996"
}

And that’s it! We’ve made a fairly sized blockchain at this point. Now, SnakeCoin can be launched on multiple machines to create a network, and real SnakeCoins can be mined.
看呐!我们已经创造了一个相当规模的区块链。‘蛇币’可以发行在一个多设备构造的网络中,而且可以挖‘蛇币’了。

Please feel free to tinker with the SnakeCoin server code as much as you’d like, and ask as many questions as you need! In the next part, we’ll discuss creating a SnakeCoin wallet, so users can send, receive, and store their SnakeCoins.
关于‘蛇币’代码可以随便问我。下一部分,我们将讨论如何创建一个‘蛇币’钱包,大家可以用这个钱包收币、发币、存币。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,277评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,689评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,624评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,356评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,402评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,292评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,135评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,992评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,429评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,636评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,785评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,492评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,092评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,723评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,858评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,891评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,713评论 2 354

推荐阅读更多精彩内容