上午
1>部署智能合约网络 语法 require
2>利用第三方的节点 同步到以太坊
3>智能合约部署的步骤:
1.查看区块
2.发布合约
deploy后台经历的事情:就是部署合约的代码
显示部署到的智能合约
前端和测试用例的开发
编译合约
测试合约
创建账户
提供 测试
交互
使用web3转账
以太坊水龙头
下午#
使用web3转账
1.脑子里是整个流程
2.细化到每一个api的使用
新建空工程,操作步骤
1>
2>
老师笔记
node开发环境搭建
nodejs的版本必须大于8.0.0
下载地址 https://nodejs.org/en/download/
配置npm的镜像仓库
命令行指定
npm --registry https://registry.npm.taobao.org info underscore
编辑 ~/.npmrc
加入下面内容
registry = https://registry.npm.taobao.org
智能合约编译
源代码---> solidity 编译器 ---> abi/ bytecode --->部署到某个网络
truffle (智能合约创建,本地测试,部署) ---> rinkeby, 网上的demo大多数都是基于truffle的
truffle的问题, 1. api不稳定, 2.bug比较多 3.一些功能缺失
以太坊的很多工具集都处于不稳定的版本,开发状态.
我们从最底层,手把手实现每一个步骤.手动操作理解每一个底层工具的细节.
源代码类型 | 字节码类型 | 执行环境 | 调用者 |
---|---|---|---|
.java源文件 | .class字节码 | jvm执行 | java代码调用 |
.sol源文件 | bytecode字节码 | 区块链环境执行 | javascript代码调用 |
solidity开发环境搭建
- solidity编译器,编译环境
- mocha 抹茶测试环境
- 部署智能合约的脚本 到指定网络
npm init
一路yes下来
开发环境的目录结构
- contracts目录
- Inbox.sol
- test
- Inbox.test.js
- package.json
- compile.js
- deploy.js
-
编写js
-
部署js
-
package.json配置
-
.test.js测试代码
-
.sol的智能合约
插件安装
https://plugins.jetbrains.com/plugin/9475-intellij-solidity
solidity编译
npm install --save solc
https://www.npmjs.com/package/solc
读文件
const path = require('path');
const fs = require('fs');
const solc = require('solc')
const inboxPath = path.resolve(__dirname,'contracts','Inbox.sol');
const source = fs.readFileSync(inboxPath,'utf-8');
solc.compile(source,1)
把编译后的结果打印到控制台
对照java的字节码 和 机器码
编译脚本优化
node compile.js
看看编译出来的json对象
:Inbox
- bytecode(机器码)
- interface(ABI)
module.exports = solc.compile(source,1).contracts.[':Inbox']
题外话,智能合约的安全问题
http://baijiahao.baidu.com/s?id=1599034807067855966&wfr=spider&for=pc
http://www.bitcoin86.com/szb/eth/20518.html
软分叉,硬分叉
- 软分叉:如果区块链的共识规则改变后,这种改变是向前兼容的,旧节点可以兼容新节点产生的区块,即为软分叉。
- 硬分叉:如果区块链软件的共识规则被改变,并且这种规则改变无法向前兼容,旧节点无法认可新节点产生的区块,即为硬分叉
区块链的价值在于共识, 所有人达成一致,这种一致性带来的价值是无法衡量的, 为什么只有比特币有价值?现在事实给了你们一些答案,你可以复制比特币的代码,创造无数个比特币,但是比特币背后的生态(开发者、矿工、交易所、商家、用户)你无法复制。就像如果把淘宝、微信的源码给你,你能再造一个淘宝和微信吗?
以太坊硬分叉
https://baijiahao.baidu.com/s?id=1574463853064616&wfr=spider&for=pc
以太坊的智能合约测试
每一行代码都价值千金, 一行代码就可能搞死一个家公司
npm install --save mocha
使用ganache环境进行测试,
ganache是testrpc的升级版, (一个local test network)
npm install --save ganache-cli
bytecode--->部署到ganache-cli
ABI--->使用web3.js进行调用
npm install --save web3
区块链开发就学两个新东西:
- web3.js
- 智能合约
剩下来的内容都是传统技术解决的
区块链项目是解决传统业务中心化,不信任,数据不公开可能被篡改的痛点.
web3.js的安装
npm install --save web3
- 创建test文件夹
- 创建Inbox.test.js
- 引入断言库
const asset = require('assert');
const ganache = require('ganache-cli');
const Web3 = require('web3');
注意Web3 是构造函数, 首字母大写
若安装报错, 注意,部分windows电脑可能要安装的工具
npm install --global --production windows-build-tools
终极大招,安装visual studio
web3.js的版本
Web3的版本, v0.x.x v1.x.x
网上的教材基本上都是v0.x.x 只能用回调来完成异步代码, 写起来是回调地狱
v1.x.x 是支持async/await. 新版本. 但是基本上没有教程.
我们上课采用v1.x.x的web3
Web3的工作模式
Web3 大写的Web3是构造函数,
通过构造函数 生成web3的实例.
web3的实例需要装入provider电话卡(联通卡,移动卡,电信卡)
才可以去以太坊网络进行交互
const web3 = new Web3(ganache.provider());//测试电话卡
小括号里面的参数,接不同的电话卡, 不同的电话卡接入不同的网络
后面我们会修改这个参数, 连接到rankybe网络等.
mocha测试框架的使用
函数 | 作用 |
---|---|
it | 跑一个测试或者断言 |
describe | it函数分组 |
beforeEach | 执行一些初始化代码 |
class Dog{
say(){
return 'wangwang';
}
happy({
return 'wuwu';
})
}
describe('dog',()=>{
it('test say',()=>{
const dog = new Dog();
assert.equal(dog.say(),'wangwang');
}) ;
});
package.json添加 scripts
"test":"mocha"
npm run test
- 抽取new Dog()的过程 到beforeEach()
- 每个测试函数it 需要使用到dog, 声明类的全局变量 let
mocha代码测试流程
- mocha start
- 部署智能合约 beforeEach
- 调用智能合约 it
- 进行断言 it
web3的常见api
web3.version
web3.currentProvider
web3.utils.toHex
var str = "abcABC";
var obj = {abc: 'ABC'};
var bignumber = new BigNumber('12345678901234567890');
var hstr = web3.utils.toHex(str); //新版api web3 1.x.x
var hobj = web3.toHex(obj); //旧版api 0.2.x 0.6.x
var hbg = web3.toHex(bignumber);
web3.utils.toAscii
var str = web3.utils.toAscii("0x657468657265756d000000000000000000000000000000000000000000000000");
console.log(str); // "ethereum"
web3.utils.fromAscii
var str = web3.utils.fromAscii('ethereum');
console.log(str); // "0x657468657265756d"
var str2 = web3.utils.fromAscii('ethereum', 32);
console.log(str2); // "0x657468657265756d000000000000000000000000000000000000000000000000"
web3.utils.fromWei
var value = web3.fromWei('21000000000000', 'finney');
console.log(value); // "0.021"
web3.utils.toWei
var value = web3.toWei('1', 'ether');
console.log(value); // "1000000000000000000"
web3.eth.getBalance
var balance = web3.eth.getBalance("0xa23D7B053aBce4500b2cD452ce6d680CA8b114ff");
console.log(balance); // instanceof BigNumber
console.log(balance.toString(10)); // '1000000000000'
console.log(balance.toNumber()); // 1000000000000
从ganache测试框架获取测试账户
beforeEach()=>{
web3.eth.getAccounts().then(account =>{
console.log(account)
});
}
descirbe('Inbox',()=>{
it('test',()=>{
});
});
es6的async和await
let accounts;
accounts = await web3.eth.getAccounts();
函数体用async修饰
使用web3部署智能合约
const {interface, bytecode} = require('../compile');
inbox = await new web3.eth.Contract(JSON.parse(interface)).deploy({
data:bytecode, arguments:['hi']
}.send({from:accounts[0],gas:'1000000'}));
打印inbox
回顾部署智能合约的流程
- 设置web3 模块部署的智能合约有什么接口可以供交互 contract(interface)
- 设置web3 模块要部署的智能合约真正的字节码 deploy(bytecode)
- send方法 指引web3去发送transaction,部署智能合约 send(trans)
web3 不仅可以部署智能合约 abi ,bytecode
也可以调用部署好的智能合约 abi, address
注意异步的代码
对部署的智能合约进行测试
- 测试智能合约是不是已经拿到了address
assert.ok(inbox.options.address)
- 测试验证message设置
call的调用和invoke
inbox.methods.message().call();
inbox.methods.setMessage('hello').send({
from: accounts[0]
});
返回值是hash
部署智能合约到真实网络
修改电话卡provider
介绍infura api
注册infura api
安装 新的module
https://www.npmjs.com/package/truffle-hdwallet-provider
npm install --save truffle-hdwallet-provider
var HDWalletProvider = require("truffle-hdwallet-provider");
var mnemonic = "opinion destroy betray ..."; // 12 word mnemonic
var provider = new HDWalletProvider(mnemonic, "http://infura/xxx");
const web3 = new Web3(provider);
const deploy = async()=>{
const accounts = await web3.eth.getAccounts();
console.log(accounts[0]);
new web3.eth.Contract(xxxx;).deploy(xxx).send(xxx);
}
etherscan使用介绍
介绍www.etherscan.io
输入智能合约的地址.
智能合约开发总结
- solc 编译智能合约
- mocha测试框架 beforeEach describ it
- ganache 创建账户
- provider 测试provider hd-wallet provider
- web3 交互
使用web3转账
let accounts;
const deploy = async () => {
accounts = await web3.eth.getAccounts();
console.log(accounts);
const translation = await web3.eth.sendTransaction({from: accounts[0], to: accounts[1], value: 3000000})
console.log(translation);
console.log(await web3.eth.getBalance(accounts[0]));
console.log(await web3.eth.getBalance(accounts[1]));
};
deploy();
开发以太坊水龙头
var express = require('express');
var Web3 = require('web3');
var HDWalletProvider = require("truffle-hdwallet-provider");
var mnemonic = "skill fragile view aspect tragic depend flock river uncover century pioneer xxxx"; // 12 word mnemonic
var provider = new HDWalletProvider(mnemonic, "https://rinkeby.infura.io/xxxxx");
const web3 = new Web3(provider);
var app = express();
app.get('/:address', async (req,res) => {
console.log('begin');
try {
var accounts = await web3.eth.getAccounts();
var str = 'info.'
let data = Buffer.from(str).toString('hex');
data = '0x'+data;
var id = await web3.eth.sendTransaction({from: accounts[0],
data:data,
to: req.params.address, value: 100000000000000});
res.send('黑马程序员送您0.0001个以太币,转账id为: ' + id.transactionHash)
}catch (error){
res.send('转账失败,请检查地址合法性'+error);
}
console.log('end');
});
app.listen(3000);