区块链中级.以太坊开发
From:JamesZou & 传智播客研究院 & 传智播客区块链
1.比特币选择的是安全和去中心化,牺牲了效率,只有约 7TPS 的吞吐量,难以支撑大规模的商业应用。
2.PPC、EOS、IOTA等采用POS、DPOS、DAG共识机制,选择的是安全和效率,吞吐量可达几千乃至几万TPS,一定程度上牺牲了去中心化。
3.如果选择去中心化和效率,那么安全将不能保证,一般不会这么选择。
目前的创新公链项目一般有两个思路:
1.是在保证安全的前提下,在去中心化和效率之间寻找平衡,比如侧链、分片、闪电网络、雷电网络等都是这个思路。
2.是分层和子链技术,底层母链采用去中心化的POW共识,上层采用POS、DPOS或者DAG这些效率较高的共识,尽量兼顾中心化和效率的优势。也可以将分层、分片、闪电网络、跨连等多种技术综合起来,集成创新,当然难度也更大。
区块链特点
不可能三角
区块链世界存在“不可能三角”问题,讲的是安全、效率、去中心化,三者之间不可共存,只能取其二
应用层
合约层
“智能合约”(smart contract)这个术语至少可以追溯到1995年,是由多产的跨领域法律学者尼克·萨博(Nick Szabo)提出来的。他在发表在自己的网站的几篇文章中提到了智能合约的理念。他的定义如下:
“一个智能合约是一套以数字形式定义的承诺(promises),包括合约参与方可以在上面执行这些承诺的协议。”
激励层
共识层
共识机制是指可以使所有节点对某一种状态达成一致的方式,有共识机制去中心化才有意义,才具备可信度,否则只是数据共享,目前主流的共识机制有:POW、POS、DPOS、PBFT等。
特点
算一道很难的谜题,系统给予挖矿奖励。
多劳多得【社会主义】
优点
所有节点均可参与,记账权公平的分派到每个节点,去中心化。
多劳多得,矿工积极性高。
安全性高,欺诈成本高,如果能够欺诈成功,那么做诚实节点收益更大。
缺点
主流矿池垄断严重,存在51%算力攻击风险。
浪费资源严重(2018年底消耗全球0.5%电量)。
持币人没有话语权,算力决定一切。
网络性能低,共识时间长。
项目 :比特币、以太坊、比原链等。
POS(ProofOfStake,股权证明),类似于财产储存在银行,这种模式会根据你持有数字货币的量和时间,分配给你相应的利息。 举个例子,就是一个根据你持有货币的量和时间,给你发利息的一个制度,在股权证明POS模式下,有一个名词叫币龄,每个币每天产生1币龄,比如你持有100个币,总共持有了30天,那么,此时你的币龄就为3000,这个时候,如果你发现了一个POS区块,你的币龄就会被清空为0。你每被清空365币龄,你将会从区块中获得0.05个币的利息(假定利息可理解为年利率5%),那么在这个案例中,利息
= 3000 * 5% / 365 = 0.41个币,持币有利息。具体的利息不同币种不一样。
特点
不挖矿,依靠币龄(币持有数量 * 持有天数)决定记账权,利息即为奖励,记账后币龄清零。
按钱分配,钱生钱【资本主义】。
优点
在一定程度上缩短了共识达成的时间。
节约资源。
防作弊,币龄越大,获得记账权几率越大、避免51%攻击, 因为攻击会使自己权益受损。
缺点:数字货币过于集中化,富者越来越富有,散户参与积极性低
项目:ADA 等
DPOS(Delegated Proof Of Stake, 委托权益证明),它的原理是让每一个持有币的人进行投票,由此产生n个代表 , 我们可以将其理解为n个超级节点或者矿池,这n个超级节点彼此的权利是完全相等的。从某种角度来看,DPOS有点像是议会制度或人民代表大会制度。如果代表不能履行他们的职责(当轮到他们时,没能生成区块),他们会被除名,网络会选出新的超级节点来取代他们。DPOS的出现最主要还是因为矿机的产生,大量的算力在不了解也不关心比特币的人身上,类似演唱会的黄牛,大量囤票而丝毫不关心演唱会的内容。
网络层
数据层
包括:区块链数据、链式结构、哈希函数、Merkle树、非对称加密、时间戳。
问题:需要突破的就是区块容量的问题
分叉
代码升级时不同社区意见发生分歧时的结果、重大bug修复是会分叉
硬分叉是指区块格式或交易格式发生改变时,未升级的节点拒绝验证已经升级的节点生产出的区块,不过已经升级的节点可以验证未升级节点生产出的区块,然后大家各自延续自己认为正确的链,所以分成两条链。
旧节点拒绝接收新节点创造的区块,从此分裂为两条独立的链
案例:以太坊分叉,分为ETC(以太经典),ETH(以太坊v神)
在同一时间出现两个矿工同时挖出矿的情况,此时出现临时的分叉,区块链会同时保留两条链,并等待新生成的区块,新区块选择链接的链就是最长链,即主链,那么另外一个区块就被称为叔块(以太坊,有奖励)/孤块(比特币,无奖励)
BIP
BIP(Bitcoin Improvement Proposals),是提出 比特币的新功能或改进措施的文件。可由任何人提出,经过审核后公布(git可查)。说白了就是 比特币节点软件 的各种改进升级意见。
BIP32
提出定义了 HD Wallet (Hierarchical Deterministic wallet),是一个可以从单一个 seed 产生一树状结构储存多组 私钥和公钥 的方案。
BIP39
提出定义了助记词方案,将 seed 用 字词表示。一般由 12 个字词组成,称为 mnemonic(助记词)。
这样可以方便普通用户记忆 - 毕竟和钱相关。
BIP44
基于 BIP32 的系统,赋予树状结构中的各层特殊的意义。让同一个 seed 可以支援多币种、多帐户等。
格式:m / purpose' / coin_type' / account' / change / address_index
//purporse': 固定值44', 代表是BIP44
//coin_type': 这个代表的是币种, 可以兼容很多种币, 比如BTC是0', ETH是60'
//btc一般是 m/44'/0'/0'/0
//eth一般是 m/44'/60'/0'/0
ERC-20
以太坊 Token作为代币的标准,每个代币都一样,就像人民币。
ERC20 是各个代币的标准接口。这个标准提供了代币的基本功能,以及允许代币被批准,这样它们就可以由另一个链第三方使用。(这个标准相当于定义了一个接口,当你的智能合约实现了这个接口以后,钱包软件就能通过调用这些接口,监听事件等操作你的代币。)
ERC-20标准规定了每个代币的基本功能,非常适合第三方使用,在开发人员的编程下,5分钟 就可以发行一个ERC-20代币。因为它可以快速发币,而且使用又方便,因此空投币和空气币基本上就是用ERC-20标准开发的。
体验 ERC20 标准【参考】
contract ERC20 {
//代币的名字,例如"Gavin token"
function name() constant public returns (string name);
//代币的简称,例如:GAVC 也是我们一般在代币交易所看到的名字
function symbol() public constant returns (string symbol);
//代币的最小分割量 token使用的小数点后几位。比如如果设置为3,就是支持0.001表示
function decimals() public constant returns (uint8 decimals);
//token的总量
function totalSupply() public constant returns (uint totalSupply);
//余额 返回某个地址(账户)的账户余额
function balanceOf(address _owner) public constant returns (uint balance);
//转账 交易代币 从消息发送者账户中往_to账户转数量为_value的token
从代币合约的调用者地址上转移 _value的数量token到的地址 _to,并且必须触发Transfer事件*/
function transfer(address _to, uint _value) public returns (bool success);
/**【替某人个别人转账】
从账户_from中往账户_to转数量为_value的token,与approve方法配合使用
从地址 _from发送数量为 _value的token到地址 _to,必须触发Transfer事件。
transferFrom方法用于允许合约代理某人转移token。条件是from账户必须经过了approve。这个后面会举例说明*/
function transferFrom(address _from, address _to, uint _value) public returns (bool success);
//允许量值 限定_spender能从合约调用账户中转出数量为_value的token
function approve(address _spender, uint _value) public returns (bool success);
//限额 获取账户_spender可以从账户_owner中转出token的数量
function allowance(address _owner, address _spender) public constant returns (uint remaining);
//发生转账时必须要触发的事件,一般位于 transfer 和 transferFrom 函数中
event Transfer(address indexed _from, address indexed _to, uint _value);
//当函数approve(address _spender, uint256 _value)成功执行时必须触发的事件
event Approval(address indexed _owner, address indexed _spender, uint _value);
}
ERC223
ERC721
Token作为数字资产的标识,每个标识都可以代表不一样,就像每只猫都不同。
contract ERC721 {
// ERC20 compatible functions
function name() constant returns (string name);
function symbol() constant returns (string symbol);
function totalSupply() constant returns (uint256 totalSupply);
function balanceOf(address _owner) constant returns (uint balance);
// Functions that define ownership
function ownerOf(uint256 _tokenId) constant returns (address owner);
function approve(address _to, uint256 _tokenId);
function takeOwnership(uint256 _tokenId);
function transfer(address _to, uint256 _tokenId);
function tokenOfOwnerByIndex(address _owner, uint256 _index) constant returns (uint tokenId);
// Token metadata
function tokenMetadata(uint256 _tokenId) constant returns (string infoUrl);
// Events
event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);
}
/**
针对 可替代token的
https://github.com/ethereum/EIPs/issues/1155
*/
contract ERC1155 {
// Events
event Approval(address indexed _owner, address indexed _spender, uint256 indexed _itemId, uint256 _value);
event Transfer(address indexed _from, address indexed _to, uint256 indexed _itemId, uint256 _value);
// Required Functions
/**
【两个方法一个处理单个的一个批量处理】 【请参照 ERC20的transfer函数】
将每个itemId[]的数量转移到指定的地址。
每个参数数组应该是相同的长度,每个索引都是相关的。
必须触发 Transfer事件
itemId 可以看做是某个特定的tokenId
*/
function transfer(address _to, uint256 _itemId, uint256 _value) external;
function batchTransfer(address _to, uint256[] _itemIds, uint256[] _values) external;
/**
【两个方法一个处理单个的一个批量处理】 【请参照 ERC20的transferFrom函数】
将每一个itemId[]的数量从一个或多个地址转移到指定地址。
每个参数数组应该是相同的长度,每个索引都是相关的
必须触发 Transfer事件
itemId 可以看做是某个特定的tokenId
*/
function transferFrom(address _from, address _to, uint256 _itemId, uint256 _value) external;
function batchTransferFrom(address _from, address _to, uint256[] _itemIds, uint256[] _values) external;
/**
【两个方法一个处理单个的一个批量处理】 【请参照 ERC20的approve函数】
批准一个帐户可以替代表另一个帐户(使用转账)转移最大数量的多个itemId数目
必须触发 Approval事件
*/
function approve(address _spender, uint256 _itemId, uint256 _value) external;
function batchApprove(address _spender, uint256[] _itemIds, uint256[] _values) external;
/**
增加一个或多个itemId的余量,而不需要重置为0 【及变更approve函数指定的允许转移量?】
必须触发 Approval事件
*/
function increaseApproval(address _spender, uint256 _itemId, uint256 _addedValue) external;
function batchIncreaseApproval(address _spender, uint256[] _itemIds, uint256[] _addedValues) external;
/**
减少一个或多个itemId的余量,而不需要重置为0
必须触发 Approval事件
*/
function decreaseApproval(address _spender, uint256 _itemId, uint256 _subtractedValue) external;
function batchDecreaseApproval(address _spender, uint256[] _itemIds, uint256[] _subtractedValues) external;
// Required View Functions
function totalSupply(uint256 _itemId) external view returns (uint256);
/**
根据对应的tokenId查看余额
*/
function balanceOf(uint256 _itemId, address _owner) external view returns (uint256);
/**
根据对应的tokenId及拥有者及代替拥有者花钱者(注意 钱还是话拥有者的,只是拥有者给予某些权力给 第三者可以挪用她的部分资金) 具体参照ERC20 自明
*/
function allowance(uint256 _itemId, address _owner, address _spender) external view returns (uint256);
// Optional View Functions
function name(uint256 _itemId) external view returns (string);
function symbol(uint256 _itemId) external view returns (string);
function decimals(uint256 _itemId) external view returns (uint8);
}
/**
针对不可替代token的拓展
*/
contract ERC1155NonFungible {
// Optional Functions for Non-Fungible Items
/**
For NFTs, this returns the owner of a specific _itemId.
在【 Non-Fungible Items】,返回当前tokenId 所属者 【参照ERC721】
*/
function ownerOf(uint256 _itemId) external view returns (address);
/**
返回当前tokenId的描述的URL 【参照ERC721】
*/
function itemURI(uint256 _itemId) external view returns (string);
/**
列举可用的Non-Fungible Items
*/
function itemByIndex(uint256 _itemId, uint128 _index) external view returns (uint256);
/**
列举分配给所有者的Non-Fungible Items
*/
function itemOfOwnerByIndex(uint256 _itemId, address _owner, uint128 _index) external view returns (uint256);
}
自从基于区块链技术的 比特币 被世人所知后,越来越多的人意识到区块链技术的好处,并想到很多可以用区块链技术解决的行业或业务问题。但为每个业务都开发一个全新的区块链软件,成本会非常高(开发、维护、社区建设等),有没有一种区块链软件能让大家不操心p2p、数据一致性、安全、漏洞等一大堆问题,只需要专注业务的功能实现呢?
以太坊应运而生,它区别于比特币最大的特点:智能合约,就解决了上面的问题。本质上,你在同一个区块链软件上可以开发其它的区块链软件。说得再大一点:以太坊的目的是让拥有以太币的人能使用通过数千节点提供动力的分布式世界计算机。
基本信息
以太坊(Ethereum):是一个开源的有 智能合约 功能的 公共区块链平台,通过加密货币以太币(Ether)提供去中心化的虚拟机(“以太虚拟机” Ethereum Virtual Machine)来执行智能合约代码。 gas - eth
作者 | V神 (Vitalik Buterin - 俄罗斯人,1994.1.31) |
---|---|
以太坊系统 | 下一代加密货币与去中心化应用平台 |
发布时间 | 2013.12 |
以太币(Eth) | 以太坊系统奖励并流通的电子货币(积分、通证) |
官网 | www.ethereum.org |
交易浏览器 | www.etherscan.io |
黄皮书 | www.github.com/ethereum/yellowpaper |
简而言之:比特币系统是一套 分布式的账本,而以太坊则更进一步,可以看作是一台 分布式的计算机
以太坊用来分布式储存数据并且计算。这些小型的电脑运行程序叫做智能合约,合约由参与者在他们自己的机器上通过一种称为 “以太坊虚拟机(EVM)”的操作系统运行。
以太坊 是一个可以运行智能合约程序的去中心化平台,那些应用程序,不存在停机、审查、欺诈或第三方干扰的可能性。
以太坊开发生态
以太坊主网络
网络名 | 介绍 | 共识机制 |
---|---|---|
Morden(退役) | 2016年11月时,难度炸弹(太难)严重影响出块速度,退役 | PoW |
Ropsten | 解决Morden难度炸弹问题而重新启动的一条区块链 | PoW |
Kovan | 解决测试网络中PoW共识机制的问题 | PoA |
Rinkeby(推荐) | 以太坊团队提供了Rinkeby的PoA共识机制说明文档 | PoA |
本地私有测试网络
钱包的分类
冷钱包
冷即离线、断网,也就是说私钥存储的位置不能被网络所访问。例如纸钱包、脑钱包、硬件钱包等等。
例:下载比太钱包到手机客户端后,关闭网络,生成比特币钱包地址,备份密语。另外一个手机联网,安装比太钱包后,添加离线手机中的比特币地址作为监控地址。在联网手机中生成未签名的交易数据后, 使用离线手机扫描联网手机中的未签名交易二维码进行签名,然后再使用联网手机扫描离线手机上的签名后的二维码,再进行交易数据广播。
热钱包
热即联网,也就是私钥存储在能被网络访问的位置。 例如存放在交易所的、在线钱包网站、手机App钱包都属于热钱包。通常而言,冷钱包更加安全,热钱包使用更加方便。
on-chain
给一个钱包地址发送数字货币, 这笔交易在全网广播、被确认、被打包进区块。这是发生在链上的,被称为on-chain交易。on-chain钱包需要自己保管私钥。
off-chain
相对于on-chain交易是off-chain交易。通常,通过交易所进行的交易是off-chain的,本人并没有私钥。私钥在交易所,由交易所托管。所以交易所的钱包也是中心化的钱包。
全节点钱包
除了保存私钥外,全节点钱包还有保存了所有区块的数据,最为著名的是bitcoin-core。
轻钱包
它不必保存所有区块的数据,只保存跟自己相关的数据。基本可以实现去中心化。
钱包地址和秘钥
用户平时一般使用 地址(账号) 和 私钥(密码),不需要知道或使用公钥
**私钥:**私钥可以计算出公钥,公钥 可以经过一系列数字签名生成钱包地址。所以, 私钥的持有者才是数字货币的持有者。
私钥通过随机数来生成,如连续抛 256 次硬币,根据每次硬币的正反面可以得到的一个私钥。 下面是使用 keyconv 命令行工具随机生成的一个比特币公私钥和地址:
Address: 1NpSVmyeJvFg3YNxp1QeCj51XsyceSZXT
Privkey: 5J4jzNpmZTaA2hpsTqAzAf1fVRALr7Es4ciSjtjvGTR7i94Qrm2
公钥:它是密码学上的概念,它由私钥推算出来。公开密钥的算法属于不对称加密算法,该算法拥有两个密钥:公钥和私钥。
**钱包地址:**由于公钥字符数太长,为了方便使用,使用一些列算法将它转成字符数很短的 地址。
一个比特币钱包中包含一系列的密钥对,每个密钥对包括一个私钥和一个公钥。私钥(k)是一个数字,通常是随机选出的。有了私钥,我们就可以使用椭圆曲线算法这个单向加密函数产生一个公钥(K)。有了公钥(K),我们就可以使用一个单向加密哈希函数生成比特币地址(A)
Solidity语言
pragma solidity ^0.4.25;
contract HelloWorld{
uint public balance;
//public int aaa(){return 1;}
function update(uint amount) public view returns (address,int){
balance += amount;
return (msg.sender, balance);
}
}
Web3
npm install --save web3 // 安装 web3
npm install --save ganache-cli // 安装 本地测试节点
const Web3 = require('web3');
const ganache = require('ganache-cli');
if (typeof web3 !== 'undefined') {
let web3 = new Web3(web3.currentProvider);
} else {
let web3 = new Web3(ganache.provider());
}
infrua 代理节点
ganache 本地测试节点