12月北京区块链培训总结

对12月份北京区块链培训总结

前言

上周,我们团队组织前往北京进行为期一周的区块链培训,写一篇来总结这次培训,白嫖许多知识/滑稽,也算不虚此行。

这里感谢布比区块链公司对我们团队提供的支持!


区块链总结

概念

首先从区块链的概念开始,什么是区块链。简单笼统地说,一种多方共同维护同一份“账本”的技术就是区块链。当然,此处不止局限于账本,账本仅作为举例。

特点

区块链的特点: 不可伪造、全程留痕、可以追溯、公开透明、集体维护

区块链之所以具有这些特点,具体就要追溯到数学算法和密码学上。

共识算法

区块链拥有多种共识算法,用于验证该笔交易是否有效。

注:这里的交易不止是金融上交易的概念,在区块链中,每次的上链统称交易(transaction)

共识算法有很多种,各有优劣。了解共识算法之前需要先了解拜占庭将军问题。
这里采用百度百科的概念简单介绍:

拜占庭将军问题

拜占庭位于如今的土耳其的伊斯坦布尔,是东罗马帝国的首都。由于当时拜占庭罗马帝国国土辽阔,为了达到防御目的,每个军队都分隔很远,将军与将军之间只能靠信差传消息。 在战争的时候,拜占庭军队内所有将军和副官必须达成一致的共识,决定是否有赢的机会才去攻打敌人的阵营。但是,在军队内有可能存有叛徒和敌军的间谍,左右将军们的决定又扰乱整体军队的秩序。在进行共识时,结果并不代表大多数人的意见。这时候,在已知有成员谋反的情况下,其余忠诚的将军在不受叛徒的影响下如何达成一致的协议,拜占庭问题就此形成。

拜占庭将军问题是一个协议问题,拜占庭帝国军队的将军们必须全体一致的决定是否攻击某一支敌军。问题是这些将军在地理上是分隔开来的,并且将军中存在叛徒。叛徒可以任意行动以达到以下目标:欺骗某些将军采取进攻行动;促成一个不是所有将军都同意的决定,如当将军们不希望进攻时促成进攻行动;或者迷惑某些将军,使他们无法做出决定。如果叛徒达到了这些目的之一,则任何攻击行动的结果都是注定要失败的,只有完全达成一致的努力才能获得胜利。

实用拜占庭容错算法(PBFT)

在实际开发中,我们采用的是实用拜占庭容错算法,改进型实用拜占庭容错的共识机制是少数服从多数,根据信息在分布式网络中节点间互相交换后各节点列出所有得到的信息,一个节点代表一票,选择大多数的结果作为解决办法。PBET将容错量控制在全部节点数的1/3,即如只要有超过2/3的正常节点,整个系统便可正常运作。


包括PBFT在内,还有许多种共识算法,这里通过一张图介绍,概括优劣。

其中,POW工作量证明就是我们常说的“挖矿”。

加密方式

简单介绍完几种常见的共识算法,接下来关注密码学上常见的两种加密方式。如图所示:

流程清晰明了。

交易流程

区块链中的交易主要分为以下两种模型: UTXO模型的账本、Account模型的账本。

UTXO模型的账本

UTXO即未花费交易输出,通俗的讲,相当于你把100元存入某个地方,呃,就叫银行吧,然后银行在存储这笔钱时,将其分为10元、20元、20元、50元进行存储,也可以理解为现实中的找零。。较为抽象

优点

计算是在链外的,交易本身既是结果也是证明。节点只做验证即可,不需要对交易进行额外的计算,也没有额外的状态存储。交易本身的输出 UTXO 的计算是在钱包完成的,这样交易的计算负担完全由钱包来承担,一定程度上减少了链的负担。

交易的 Input 始终是链接在某个 UTXO 后面。交易无法被重放,并且交易的先后顺序和依赖关系容易被验证,交易是否被消费也容易被举证。

UTXO 模型是无状态的,更容易并发处理。

安全性比Account高

缺点

无法实现一些比较复杂的逻辑,可编程性差。对于复杂逻辑,或者需要状态保存的合约,实现难度大,且状态空间利用率比较低。

当 Input 较多时,见证脚本也会增多。而签名本身是比较消耗 CPU 和存储空间的。

Account模型的账本

顾名思义,Account模型即账户模型,也就是每笔交易都有对应的账户,围绕账户进行。Account模型保存了交易的事件状态,交易只是事件本身,不包含结果,交易的共识和状态的共识本质上可以隔离的。

优点

合约以代码形式保存在 Account 中,并且 Account 拥有自身状态。这种模型具有更好的可编程性,容易使开发人员理解,场景更广泛。

批量交易的成本较低。

缺点

Account 模型交易之间没有依赖性,需要解决重放问题。

对于实现闪电网络/雷电网络,Plasma 等,用户举证需要更复杂的 Proof 证明机制,子链向主链进行状态迁移需要更复杂的协议。

工作原理如图所示


上链流程

上链是交易的关键一步,直接关系到此次交易是否成功,流程如下图所示。

最后,我以以太坊为平台,成功发布了自己的智能合约(YlhCoin),具体发布流程请自行查阅手册。

代码如下:

ylhCoin.sol

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
pragma solidity ^0.5.14;
contract MyCoin{
address public god;
uint256 public total;
mapping(address => uint256) public balances;

constructor() public{
god = msg.sender;
total = 10000000;
balances[god] = total;
}
//获取余额
function getBal(address owner) public view returns(uint256){
return balances[owner];
}
//转账
function transaction(address payee,uint256 amount) public returns(bool){
address owner = msg.sender;
require(amount > 0);
require(balances[owner] >= amount);
balances[owner] -= amount;
balances[payee] += amount;
return true;
}
}

ylhCoin_OpenSource.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

let fs = require('fs');
let Web3 = require('web3');
let privateKey = Buffer.from("你的私钥","hex");
let Tx = require('ethereumjs-tx').Transaction;
//打开服务器
let provider = new Web3.providers.HttpProvider("https://ropsten.infura.io/v3/8a4622e55aa842d99e232dafdece2605");
let web3 = new Web3(provider);
//console.log(web3);

//读取ABI和BIN
ylhCoinABIObj = fs.readFileSync('ylhCoin_sol_MyCoin.abi');
ylhCoinABIJson = JSON.parse(ylhCoinABIObj.toString());
//console.log("ABI:" + ylhCoinABIObj.toString());
console.log("-------------------------");
ylhCoinBinObj = fs.readFileSync('ylhCoin_sol_MyCoin.bin');
ylhCoinByte = ylhCoinBinObj.toString();
//console.log("BIN:" + ylhCoinByte);
console.log("-------------------------");

//部署合约
account = {
address: "钱包地址",
privateKey: "你的私钥"
}
//console.log("当前账户: " + account);
contract = new web3.eth.Contract(ylhCoinABIJson);
//contract = new web3.eth.Contract(ylhCoinABIJson);//合约核心文件(ylhCoinABIJson)
//console.log(contract);

(async()=>{
let nowNonce = await web3.eth.getTransactionCount(account.address);
console.log("Nonce: " + nowNonce);
//构建交易(合约数据)
txData = {
nonce: nowNonce,
data: "0x" + ylhCoinByte,
from: account.address,
gasPrice: '0x01',
gasLimit: '0xfffff',
value: web3.utils.toHex(web3.utils.toWei("1","ether")),
to: '收款人的钱包地址'
}
//签发交易(使用私钥)
let tx = new Tx(txData,{
chain: "ropsten",
//hardfork: "petersburg"
});
tx.sign(Buffer.from(privateKey,"hex"));
let serializedTx = tx.serialize();
//sendSignedTransaction
//签发!
web3.eth.sendSignedTransaction('0x' + serializedTx.toString('hex')).on('receipt',console.log);
})();

最终运行效果如图:

代码地址:Yeliheng-Github

完结撒花