区块链2.0

以太坊

智能合约

DAPP

  • CryptoKitties 养猫App

POS+POW共识

AE

状态通道

  • 闪电网络雷电网络链下交易

  • 侧链技术

扩容方案

  • 比特币扩容方案
  • 以太坊分片技术
  • AE状态通道

预言机

//======================================

区块链2.0

以太坊数据结构

智能合约(可编程区块链)

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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
pragma solidity ^0.4.8;

contract ERC20Interface {
function totalSupply() public constant returns (uint256 supply);
function balance() public constant returns (uint256);
function balanceOf(address _owner) public constant returns (uint256);
function transfer(address _to, uint256 _value) public returns (bool success);
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
function approve(address _spender, uint256 _value) public returns (bool success);
function allowance(address _owner, address _spender) public constant returns (uint256 remaining);

event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}

contract Simoleon is ERC20Interface {
string public constant symbol = "SIM";
string public constant name = "Simoleon";
uint8 public constant decimals = 2;

uint256 _totalSupply = 0;
uint256 _airdropAmount = 1000000;
uint256 _cutoff = _airdropAmount * 10000;

mapping(address => uint256) balances;
mapping(address => bool) initialized;

// Owner of account approves the transfer of an amount to another account
mapping(address => mapping (address => uint256)) allowed;

function Simoleon() {
initialized[msg.sender] = true;
balances[msg.sender] = _airdropAmount * 1000;
_totalSupply = balances[msg.sender];
}

function totalSupply() constant returns (uint256 supply) {
return _totalSupply;
}

// What's my balance?
function balance() constant returns (uint256) {
return getBalance(msg.sender);
}

// What is the balance of a particular account?
function balanceOf(address _address) constant returns (uint256) {
return getBalance(_address);
}

// Transfer the balance from owner's account to another account
function transfer(address _to, uint256 _amount) returns (bool success) {
initialize(msg.sender);

if (balances[msg.sender] >= _amount
&& _amount > 0) {
initialize(_to);
if (balances[_to] + _amount > balances[_to]) {

balances[msg.sender] -= _amount;
balances[_to] += _amount;

Transfer(msg.sender, _to, _amount);

return true;
} else {
return false;
}
} else {
return false;
}
}

// Send _value amount of tokens from address _from to address _to
// The transferFrom method is used for a withdraw workflow, allowing contracts to send
// tokens on your behalf, for example to "deposit" to a contract address and/or to charge
// fees in sub-currencies; the command should fail unless the _from account has
// deliberately authorized the sender of the message via some mechanism; we propose
// these standardized APIs for approval:
function transferFrom(address _from, address _to, uint256 _amount) returns (bool success) {
initialize(_from);

if (balances[_from] >= _amount
&& allowed[_from][msg.sender] >= _amount
&& _amount > 0) {
initialize(_to);
if (balances[_to] + _amount > balances[_to]) {

balances[_from] -= _amount;
allowed[_from][msg.sender] -= _amount;
balances[_to] += _amount;

Transfer(_from, _to, _amount);

return true;
} else {
return false;
}
} else {
return false;
}
}

// Allow _spender to withdraw from your account, multiple times, up to the _value amount.
// If this function is called again it overwrites the current allowance with _value.
function approve(address _spender, uint256 _amount) returns (bool success) {
allowed[msg.sender][_spender] = _amount;
Approval(msg.sender, _spender, _amount);
return true;
}

function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
return allowed[_owner][_spender];
}

// internal private functions
function initialize(address _address) internal returns (bool success) {
if (_totalSupply < _cutoff && !initialized[_address]) {
initialized[_address] = true;
balances[_address] = _airdropAmount;
_totalSupply += _airdropAmount;
}
return true;
}

function getBalance(address _address) internal returns (uint256) {
if (_totalSupply < _cutoff && !initialized[_address]) {
return balances[_address] + _airdropAmount;
}
else {
return balances[_address];
}
}
}

对比区块链1.0(比特币系统)

  • 增加账户概念,合约账户,私人账户

  • 增加智能合约

什么是智能合约,智能合约能做什么

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
55
56
57
58
59
60
61
62
63
64
65
pragma solidity ^0.4.0;
contract Ballot {

struct Voter {
uint weight;
bool voted;
uint8 vote;
address delegate;
}
struct Proposal {
uint voteCount;
}

address chairperson;
mapping(address => Voter) voters;
Proposal[] proposals;

/// Create a new ballot with $(_numProposals) different proposals.
function Ballot(uint8 _numProposals) public {
chairperson = msg.sender;
voters[chairperson].weight = 1;
proposals.length = _numProposals;
}

/// Give $(toVoter) the right to vote on this ballot.
/// May only be called by $(chairperson).
function giveRightToVote(address toVoter) public {
if (msg.sender != chairperson || voters[toVoter].voted) return;
voters[toVoter].weight = 1;
}

/// Delegate your vote to the voter $(to).
function delegate(address to) public {
Voter storage sender = voters[msg.sender]; // assigns reference
if (sender.voted) return;
while (voters[to].delegatet != address(0) && voters[to].delegate != msg.sender)
to = voters[to].delegate;
if (to == msg.sender) return;
sender.voted = true;
sender.delegate = to;
Voter storage delegateTo = voters[to];
if (delegateTo.voted)
proposals[delegateTo.vote].voteCount += sender.weight;
else
delegateTo.weight += sender.weight;
}

/// Give a single vote to proposal $(toProposal).
function vote(uint8 toProposal) public {
Voter storage sender = voters[msg.sender];
if (sender.voted || toProposal >= proposals.length) return;
sender.voted = true;
sender.vote = toProposal;
proposals[toProposal].voteCount += sender.weight;
}

function winningProposal() public constant returns (uint8 _winningProposal) {
uint256 winningVoteCount = 0;
for (uint8 prop = 0; prop < proposals.length; prop++)
if (proposals[prop].voteCount > winningVoteCount) {
winningVoteCount = proposals[prop].voteCount;
_winningProposal = prop;
}
}
}

如上面的两个合约代码,一个实现了代币系统,一个实现了智能投票。

智能合约代码经过编译后,被永久封存在以太坊区块链中。通过合约可以创建无数种代币,并且代币的代码逻辑都是可以通过以太坊浏览器查看到的。

通过以太坊浏览器,可以看到各种排名代币

image

image

点击排名第一的代币合约,可以查看到它的具体运行逻辑,包括该代币的转账记录,发放逻辑。

代币转账

代币转账是通过调用智能合约的转账方法,通用代币一般都按照 ERC20的标准,其实就是实现一系列大家共用的方法,方便调用。

代币转账会被当成以太坊的一个交易,交易内容就是某个代币的转账,矿机通过调用合约方法执行。其中要消耗一定的gas

GAS

gas的字面定义就是汽油燃料,因为合约代码执行逻辑是需要消耗cpu的,每一段代码执行消耗都不一样,而以太坊智能合约又是图灵完备的,也就是有任意复杂难度的。可能一个方法中会有无限个循环,会导致矿机在打包交易的时候无线被消耗。所以gas就是用来给旷工执行合约的时候的费用,如果gas用完了还没执行完合约,那么会报出gas不足。

  • gas price 这个代表执行调用代码的人,愿意给旷工gas的单价,旷工会优先对单价高的进行打包。

  • gas limit 代表你转账愿意付出的gas的数量

image

通过imtoken的例子可以看出,gas是可以自己设定的。

image

通过查询这个token交易,可以看到,这个token转账消耗了多少gas,转化成eth大概是多少钱。

可以看出0.36美元,大概两块钱交易费用。gaslimit可能用不完,但是会退还

DAPP

一个分布式App是指,服务端运行于以太坊网络上一个或多个智能合约。

image

这是一个养猫Dapp例子

上线两周就超过十五万用户,合约交易占用了1/4的以太坊资源。导致拥堵。

合约地址

AE合约地址

以太坊面临的问题

蛋糕太大,消化不了。交易拥堵和交易费用过高问题

随意找一个交易

image

相对于小的交易来说,交易费用过高。交易拥堵

image

可以看到待打包的交易,有四万多,但是一个块只有一百多比,也就是现在在等待结果的交易,最迟还得等待一百多个出块,也就是可能还得等一小时。15s的出块速度仍然不能满足交易的吞吐

比特币 以太坊 交易拥堵问题

状态通道解决的是交易吞吐量的问题。

挖矿方式耗电问题

全网络节点通过算力的方式竞争出块资格,也就是记账权会有浪费资源的问题。

POS股权证明

省去了旷工这个媒介,避免了POW的电力浪费。

SHA256(SHA256(Bprev),A ,t)≤balance(A)m

这其中,H为某个哈希函数;t为UTC时间戳;Bprev指的是上个区块;balance(A)代表账户A额余额。

唯一可以不断调整得到参数的是t,等式右边是某个固定实数,因此当balance(A)越大,找到合理的t概率越大,普遍对t的范围有所限制,如可尝试的时间不能超过标准时间戳一小时,也就是一个及诶单可以尝试7200次,一个账户的余额越多,就越容易发现下一个区块。

当你打开钱包客户端就会参与挖矿计算,挖矿的概率根据你的持有币的多少和币龄决定。

例如,你持有100个币,总共持有30天,你的币龄就是3000,此时,若你发现了一个PoS算法支持的区块(直观来说就是你拥有币的数量和时间越长,你新建区块的几率越大),你的币龄就会被置0。你每被清空365币龄,你将会从区块中获得0.05个币的利息(相当于年利率5%),那么在这个案例中,利息 = 3000 * 5% / 365 = 0.41个币。

也就是打开客户端就可以获得利息。你的挖矿收益和算力无关。

DPOS 委任权益证明

POS参与出块就要求客户端必须打开,在DPOS权益证明下,更加进一步节约电能。让每个持有币的人进行投票产生101位代表,这101代表用于出块,出块的速度更快,每个块时间为10秒,一笔交易大概一分钟,6个确认。

如何从POW转到POS

ETH变POS以后,也就是再次分叉以后是不会有所谓的ETH(POW)链的,因为这是废链,没办法出块就等于没办法转账、交易。只会有ETC和ETH(POS)两条链。

从POW转POS可以解决矿机耗电问题,闪电网络可以解决小比交易快捷支付问题,并且减少主链的交易打包问题。

分片技术