主页 > imtoken怎么注册 > 以太坊教程:学习以太坊 Dapp 开发
以太坊教程:学习以太坊 Dapp 开发
本文约11700字+,阅读(观看)需66分钟
1. 区块链
1.分布式去中心化
比特币设计的初衷是避免依赖中心化机构。 没有发行机构,就无法操纵发行数量。 由于没有中心化的信用机构,在电子货币运行过程中,必然需要一种机制来识别运行在区块链上的行为(包括比特币的运行,或者其他运行在区块链上的业务),这机制就是共识机制。 比特币运行在完全去中心化的区块链上,采用PoW(Proof of Work),完美解决了拜占庭一般问题(在异常情况下仍能达成共识)。 由于基础网络架构是分布式的,单个节点不可能控制或破坏整个网络。 只有掌握了网络中51%的算力(不是节点数量)才有可能进行交易,成本大概在270亿美元以上。
2. 无需信任
整个区块链网络中的数据是公开透明的,每个节点(参与者)都可以自由加入网络并下载所有数据。 任意两个节点之间的数据交换不需要相互信任,完全依赖区块链中的交易历史和数据溯源,以及共识机制来保证数据交换的正确和不可逆执行。
3. 不可变和加密安全
类似于目前银行网银系统(尤其是企业网银系统)的加密机制,在区块链的数据结构和交易过程中使用大量的公钥和私钥进行加密和解密,以保证数据安全。 基于这个技术基础,甚至可以应用群签名来保证共享数据的安全。 既然任何事物都有优点,那么它也有缺点。 植根于分布式网络架构和共识机制,运行在区块链上的交易确认时间会比较长(比特币的确认时间在15分钟左右),并发交易数有限(比特币每秒交易数)比特币是7Pen,而淘宝的并发数可以达到每秒10万左右),区块容量限制(目前1M,区块链的扩容一直在讨论),监管难以介入,基于工作量证明的共识机制是浪费系统资源和带宽的问题。
4.区块链技术
一种。 堵塞
块是包含在区块链(公共分类账)中的聚合交易信息的容器。 它由一个包含元数据的块头组成,后跟一长串构成块体的交易。 区块头80字节,平均每笔交易至少250字节,每个区块平均至少包含500多笔交易。
块结构如下图
交易(Tx)详情中的结构如下
b. 区块链
当一个节点从网络接收到传入的块时,它会验证这些块,然后链接到现有的区块链。 该链接如下所示:
由于每个区块都包含前一个区块的HASH值,所以从创世区块到当前区块形成一条区块链,每个区块都必须按照时间顺序跟在前一个区块之后,因为如果不知道前一个区块的HASH值区块无法生成当前区块。 改变已经在区块链中一段时间的区块在计算上是不可行的,因为如果它被改变,它之后的每个区块都必须随之改变。 这些特点使得比特币很难双花,区块链是比特币最大的创新。
5. 比特币钱包
一种。 比特币钱包的产生
首先使用随机数生成器生成私钥。 一般来说,这是一个256bits的数字。 有了这串数字,就可以对对应钱包地址中的比特币进行操作,所以一定要妥善保管。
私钥经过SECP256K1算法处理生成公钥。 SECP256K1 是一种椭圆曲线算法。 知道私钥就可以算出公钥,但是知道公钥就不能反算出私钥。 这是保护比特币安全的算法基础。
与 SHA256 一样,RIPEMD160 也是一种 Hash 算法。 公钥哈希可以从公钥计算出来以太坊根据地址计算私钥,但是反过来是不行的。
将一个字节地址版本号连接到公钥散列头(对于比特币网络的公钥地址,这个字节为“0”),然后对其进行两次SHA256运算,并将结果的前4个字符转换为 section用作公钥散列的验证值,并在其末尾连接。
使用BASE58(定制版比特币)对上一步的结果进行编码,得到钱包地址。
流程图如下
b. 转移
比特币钱包之间的转账是通过交易来实现的。 交易数据由钱包私钥的所有者生成,也就是说有了私钥,就可以花掉钱包的比特币余额。 生成交易的过程如下:
交易的原始数据包括“转账金额”和“转入钱包地址”,但仅有这些是不够的,因为无法证明交易的生成者有权使用“转账”的余额-出钱包地址”。 所以原始数据需要用私钥进行签名。
生成“转账钱包公钥”,过程同第二步生成钱包地址。
在原始交易数据上加上“转账签名”和“转账公钥”生成正式的交易数据以太坊根据地址计算私钥,以便广播到比特币网络进行转账。
2.以太坊
一、概念
一种。 什么是以太坊
简而言之,以太坊是一种新的法律形式。 现行法律的本质是契约。 这是(社区的)人们和他们的领导人之间关于彼此应该如何行动的协议。 个人之间也有一些合同。 这些合同可以理解为一种私法。 相应地,该私法仅对合同的参与方有效。
比如你跟一个人立约,借给他一笔钱,他却毁约,不打算还钱。 这时你很可能会将对方告上法庭。 在现实生活中,诉讼之类的事情往往是杂乱无章、充满不确定性的。 将对方告上法庭通常也意味着你需要支付高额费用聘请律师帮助你在法庭上对法律条文进行辩论,而且这个过程通常是漫长的。 另外,即使你赢了官司,你仍然可能会遇到问题(例如,对方拒绝执行法院命令)。
好消息是你和借款人写下了条款并签订了合同。 然而,无论是立法者还是合同起草者都必须面临一个不容忽视的挑战:即在理想情况下,法律或合同的内容应该是明确无歧义的,但现行的法律和合同都是通过句子来制定的,而句子饱满是出了名的的歧义。
因此,现行的法律制度一直存在两大问题:一是合同或法律的界定含糊不清,二是合同或法律的执行成本非常高。
而以太坊,通过数字货币和编程语言的结合,解决了当前法律体系中的这两大难题。
以太坊系统本身有一种称为以太币的数字货币。 以太坊与众所周知的数字货币比特币(Bitcoin)有很多相似之处。 两者都是不可伪造的数字储值货币,并且都以去中心化的方式运作,以确保货币供应不受单一方控制。 两者都可以作为货币在世界范围内自由流通,就像电子邮件一样。 并且,因为它们可以做传统货币做不到的事情,所以用户期待它们未来的价值。
此外:
1. 详情请阅读以太坊白皮书(中文、英文)
2.以太坊教程
b. 基础知识
2.工作流程
一种。 环境建设
推荐使用Mac OS环境,否则可能会出现各种坑。
安装 NodeJS 并安装 Python。
安装testrpc(测试环境使用),安装go-ethereum(真实环境使用)。
安装解决方案。
安装松露。
如果是windows,推荐使用ethbox工具,一键安装以太坊开发环境的工具:ethbox
b. Solidity语言简介
以下是官网智能投票合约的示例代码
contract Ballot { //一个选民的构造体
struct Voter {
uint weight; // 权重(即他可以投几票)
bool voted; //是否已经投过票
address delegate; // 代表地址
(他可以代表某个人进行投票)
uint vote; // index of the voted proposal
} // 投票的提案的构造体
struct Proposal
{
bytes32 name; // 提案名称
uint voteCount; //获得的票数
}
address public chairperson;//会议主席
//地址 -选民 的map
mapping(address => Voter) public voters;
// 投票种类的动态数组
Proposal[] public proposals; ///构造函数
function Ballot(bytes32[] proposalNames) {
chairperson = msg.sender;//初始化会议主席
voters[chairperson].weight = 1;
//初始化所有的提案
for (uint i = 0; i < proposalNames.length; i++) {
proposals.push(Proposal({
name: proposalNames[i],
voteCount: 0
}));
}
} // 给予投票权
function giveRightToVote(address voter) returns
(bool b) { if (msg.sender != chairperson ||
voters[voter].voted) { //对于会议主席和
已经投过票的选民这里不处理
return false;;
}
voters[voter].weight = 1; return true;
} /// 投票权转移函数
function delegate(address to) {
// 投票权转移的发起人
Voter sender = voters[msg.sender];
if (sender.voted) throw;
//递归找到没有转移投票权的 选民
while (
voters[to].delegate != address(0) &&
voters[to].delegate != msg.sender
) {
to = voters[to].delegate;
} if (to == msg.sender) { throw;
} //将发起人设置为已经投过票的状态
sender.voted = true; //
将代表设置为刚才递归获取的选民
sender.delegate = to;
Voter delegate = voters[to];
if (delegate.voted) {
//如果代表已经投过票就
在他投票的提案的票数增加
proposals[delegate.vote].voteCount
+= sender.weight;
} else { //将代表的的票数增加
delegate.weight += sender.weight;
}
} /// 投票函数
function vote(uint proposal) {
Voter sender = voters[msg.sender];
if (sender.voted)
throw;
sender.voted = true;
sender.vote = proposal;
//将投的提案票数增加
proposals[proposal].voteCount +
= sender.weight;
} ///获得票数最多的提案
function winningProposal() constant
returns (uint winningProposal)
{
uint winningVoteCount = 0;
for (uint p = 0; p
< proposals.length; p++)
{ if
(proposals[p].voteCount
> winningVoteCount) {
winningVoteCount =
proposals[p].voteCount;
winningProposal = p;
}
}
}
}
解释
想要更深入的了解solidity语言,可以阅读官方文档。
C。 使用geth部署合约
启动测试节点
geth --testnet --fast --cache=512 --genesis CustomGenesis.json 控制台
这里的CustomGenesis.json是给测试账户分配ether
{ "coinbase": "0x000000000000000000
0000000000000000000000", "difficulty":
"0x20000", "extraData": "", "gasLimit":
"0x2fefd8", "nonce": "0x000000000000
0042", "mixhash": "0x00000000000000
000000000000000000000000000000000
00000000000000000", "parentHash": "
0x0000000000000000000000000000000
000000000000000000000000000000000
", "timestamp": "0x00", "alloc": {
"0xe49c283bc6bf92c5833cc981b976792
38dd3b5da": { "balance": "11111
1111000000000000000000000000000"
}, "0xd8927c296b3ebe454a640
9770a0c323ec4ed23ba": {
"balance": "22222222200000000000000
0000000000000"
}
}
}
solc下的内容要替换成你的测试账号地址。 geth的具体用法可以参考官方文档和源码介绍。
使用solc编译智能合约,得到二进制代码
例如下面的代码
contract test {
function multiply(uint a) returns(uint d) {
return a * 7;
}
}
输入geth
source = "contract test { function multiply(uint a) returns(uint d) { return a * 7; } }"
clientContract = eth.compile.solidity(source).test
编译返回结果的JSON格式如下
在,
编译器返回的 JSON 结构反映了合约部署的两种不同路径。 info信息实际存在于中心化云端,作为元数据信息公开验证合约代码在区块链中的执行情况。 通过创建交易将代码信息部署到区块链中。
使用solc编译智能合约,得到二进制代码
在部署合约之前,请确保您有一个未锁定的账户并且账户中有余额,因为部署合约的过程会消耗以太币。 输入 web3.fromWei(eth.getBalance(eth.accounts[0]), "ether") 查看账户余额。
解锁帐户
personal.unlockAccount(eth.accounts[0])
获取帐户
primaryAddress = eth.accounts[0]
定义一个abi(abi是js的数组,否则不成功)
abi = [{ 常数:false,输入:[{ 名称:'a',类型:'uint256'}]}]
创建智能合约
我的合约 = eth. 合同(abi)
发送交易部署合约
contract = MyContract.new({from: primaryAddress, data:"0x6060604052602a8060106000396000f3606060405260e060020a6000350463c6888fa18114601a575b005b600760043502606092030"}20}
如果交易处于待处理状态,则表示您的矿机没有在挖矿
开始一个矿工
miner.setEtherbase(eth.primaryAddress) //设置挖矿账户
矿工开始(8)
eth.getBlock("pending", true).交易
这时候发现交易已经在区块中了
但是,您会发现交易仍在进行中。 这是因为没有人协助计算和验证交易区块。 这时候你只需要再启动一台矿机即可。
矿工开始(8)
与合约交互
Multiply7 = eth.contract(clientContract.info.abiDefinition);
var myMultiply7 = 乘法 7。 在(合同。地址);
我的乘法7。 乘。 呼叫(3)
或者
我的乘法7。 乘。 sendTransaction(3, {from: contract.address})
d. 使用松露框架
使用 truffle 部署智能合约的步骤:
truffle init(在新目录中)=>创建 truffle 项目目录结构,
编写合约代码并将其保存到 contracts/YourContractName.sol 文件中。
比如Ballot.sol,此时找到migrations文件夹,在deploy_contracts.js文件中添加deployer.deploy(Ballot);
truffile compile 编译合约代码。
启动以太坊节点(例如在另一个终端运行 testrpc)。
truffle migrate(在 truffle 项目目录中)。
1.编写单元测试
在测试文件夹中新建一个 ballot.js 文件
contract('Ballot',function(accounts)){
//accounts是所以账户得数值
it("获取投票权",function(){
var meta = Ballot.deployed();
return meta.giveRightToVote
(accounts[1]).then(function(b){
assert.equal(Boolean(b),
true,"获取投票权失败");
});
});
}
在项目根目录运行truffle测试,应该可以看到测试通过,如果使用自己构造的ballot对象,可以这样写:
contract('Ballot',function(accounts)){
//accounts是所以账户得数值
it("获取投票权",function()
{ var proposals = [];
proposals.push("proposal0");
Ballot.new(proposals).then
(function(meta){
return meta.giveRightToVote
(accounts[1]).then(function(b){
assert.equal(Boolean
(b),true,"获取投票权失败");
});
});
});
}
2.为合约创建接口
在app目录下,可以编写自己的html和js文件。 js和智能合约的交互基本和单元测试一样。 例如,界面上有一个输入框和一个按钮,用于获取选民的投票权。
Ballot App
Ballot
Example Truffle Dapp
Send
"e.g., 0x453468394hdfg84858345348">
"getRight()">Get Right Vote
app.js 中的代码是
function getRight() { var account = document
.getElementById("account").value; var meta
= Ballot.deployed();
meta.giveRightToVote(account).
then(function(b){ if(Boolean(b)){
setStatus("Get Right Vote Success");
}else{
setStatus("Get Right Vote Error");
}
}).catch(function(e){
setStatus("Get Right Vote Error");
console.log(e);
});
};