区块链2
结构体:
全局变量就是区块链上的变量,它没有memory和storage之说,当一个memory类型传递给全局变量(区块链上的变量)时,修改memory变量是不会改动到区块链的变量的,但是当memory变量之间相互
传值时,只是在传递指针:
枚举:enum 类型{成员1,成员2,....}
哈希函数:
获得随机数:
自定义库并使用库函数:
assert和require是一个效果
此处的for uint,就会把a.add(b)中的a视为uint,然后调用对应函数
接口:
最下面的函数中,第一行是获得LuckNumber的对象(只要LuckNumber实现了接口中的getNum就行),实参是LuckyNumber的合约地址,第二行是调用了LuckyNumber的getNum方法。
继承一个接口之后就得实现接口中的方法:
animal合约调用cat合约的test方法:
部署animal合约时,需要在deploy右边写入cat的合约地址:
或者使用call来调用cat的方法:
当call没有找到对应的方法时,就会调用cat中的回滚方法:
若cat中的函数有参数:
call调用的test函数所更改的c变量也是cat里面的变量,而不是animal的c,且animal合约调用cat合约时,此时的msg.sender是animal合约的地址:
而delegatecall则修改的是animal的c变量:
下面2个事件:SenderLogger,。。。
from:谁触发了事件,topic:事件的唯一标识,args传入给事假的参数。
内联汇编:
汇编代码需要用assemly{}起来,jumpi(loop,lt(i,10)):若i<10,则跳转到loop处。它花费的gas更少
ERC20是个协议
在A测试网络中部署的合约不会影响到其他测试网络的合约,转账也不影响,只是账户的地址一样。
以太坊全结点:
以太坊轻结点和远程客户端:
提供8545端口的那个节点会提供provider服务,metamask也会提供provider服务。
geth:
以太坊客户端满足黄皮书的规定并与其他以太坊客户端通信
geth是一种以太坊客户端,它基于go
全结点保存区块链上的所有数据,还能校验区块的合法性,必须同步网络区块数据。新节点进来后就需要和全结点交互拿上数据。
远程客户端:metamask,不保存区块链数据,仅仅是钱包的功能,创建和广播交易,与全节点通信。
轻结点只保存区块链状态,如有哪些合约,合约有什么数据,块上其他东西不保存,可以校验区块和交易。
公链:有其他用户和合约在上面,例如主网和测试网络,只供自己本地用的是私链,矿工只有自己。
windows 安装geth:https://ethfans.org/wikis/Ethereum-Geth-Mirror
启动geth:
如果直接geth --datadir .:则会同步全结点把区块链数据下载到本地
geth --datadir . --syncmode fast:同步全结点,把区块数据都下载下来到当期目录,但是不做交易校验,同步完毕后获取一下最后的状态。默认是full,操作都会做。
加个--testnet:表示同步测试网络(Ropsten)的区块
linux中,nohup:持续运行命令,&:命令在后台运行
genesis.json设定了私链的id和创世块:
balance单位是wei
启动本地测试网络(本地私链),并开放rpc接口供外部访问:
--networkid:要和上面指定的私链id一样
若想从外部连接这个客户端进而访问以太坊时,需要--rpc,此时就打开了rpc服务器的8545端口, 这样外部metamask就能访问了,web3也能连接上,此时web3.isConnected()也为true。
--datadir 目录:启动geth,并指定区块链的存储位置,若已经有此文件,则会读取已有的区块链,如果在上面命令后面加上console可以进入交互模式
--rpcapi db,eth,net,web3,personal,miner:指定了这个服务器开放哪些模块供外部(如node平台中的web3)调用
以太坊客户端,服务器都是节点 ,
只要开放了端口供外部访问的都可以称为服务器
eth.accounts:获得区块链上的账户(根据keystore文件夹);
但是初始eth.accounts为空,因为.json文件只是指定了账户有多少钱而已
查钱:eth.getBalance(“账户”)
以wei为单位的转换到ether:
eth.blockNumber:区块链长度
创建新账户:personal.newAccount(),此时就有keystore文件了,它保存加密后的私钥
转账,但是完了得再挖矿打包交易:
但是解锁账户后才能转账:
miner.start(1):开启挖矿,miner.stop():停止挖矿
挖出一个矿可以获得区块奖励,奖励给矿工,若geth只有1个账户,则该账户作为矿工,最后奖励给他
将中间产生的信息重定向输出到文件中:
tail -f output.log:动态查看output.log
转成以wei单位的:
接下来打开metamask,切换到localhost,连接到geth客户端(2节点通信),进而查看账户余额
系统自动启动一个私链(不看配置的json文件),并含有一个开发者账户,他还有钱,且转账让权威挖就行了,难度很小所以很快出块,不会有挖矿麻烦,且开发者账户也解锁了
进入一个空目录,然后输入:
geth --datadir . --dev --rpc console
通过交易哈希可以确定交易是否成功:
获得第二个块中的交易数:
获得第二块信息:eth.getBlock(2)
json-rpc:geth控制台都是把用户输入的命令转换成json-rpc格式发送给rpc服务器才能获返回结果的。
另外开启一个终端,直接向rpc服务器询问blockNumber有多少,因此需要手动把自己的请求封装成json-rpc格式,curl:发送网络请求,POST:采用post请求,定义请求头为json格式,请示的数据中的id是与geth之间通信的暗号,最后是发送地址
智能合约本质上是一个账户,即合约账户。普通账户又叫EOA
消息调用:一个合约调用另一个合约的函数
交易:
nonce:某个账户发送第一笔交易时记1,第二笔则2。。。
gasUsed:消耗的gas数量,gasPrice:一个gas量对应的费用;最终交易手续费fee=gasUsed*gasPrice,最后的交易费都给了矿工。
gasLimit:gas数量的界限
estimateGas:估计的gas数量
创建合约交易时,目的地址是零地址,from地址是remix右上角的account,交易不应包含value值,但包含data,内容是合约编译的字节码,交易当中的input就是data
调用合约的函数时,此时产生一个交易,交易的目的地址是合约地址名,交易的data包含函数选择器(用于识别要调用的函数)和函数参数
npm:
-g:安装到node安装目录
全结点保存有完整的区块链,轻结点则部分。
查看版本:npm list web3
运行ganache-cli:搭建以太坊环境,在内存启动一个以太坊节点,开启8545端口。里面有10个账户,默认有100个ether,部署合约就能够部署。
npm init:npm管理,初始化package.json。
npm安装中,--save-dev:会把安装包信息写到package.json的devDependencies里面,当发布产品时是不会打包这些包到产品中,
而--save,则把安装包写到dependencies里面,发布产品时就会连带把包的打包进产品中去。
建立一个简易合约:
solcjs --abi aa.sol:编译aaa.sol后生成abi文件,abi是合约的接口,它描述了合约中的函数和事件,通过它才能操控合约,服务于web3
socljs --bin aa.sol:获得合约的字节码
node a.js:执行a.js文件
由于require不能被js引擎识别,只能被node识别,所以需要webpack翻译:webpack index.js indexed.js,然后html页面引用indexed.js。
IPFS:分布式文件系统,存到各个节点,类似于世界硬盘
安装:https://pan.baidu.com/s/1H9DRYZLKmGvdEzP0-DzjJA,再配置环境变量path,输入ipfs init初始化仓库,输入ipfs daemon开启守护进程,随后可以访问127.0.0.1:5001/webui
上传文件到ipfs,同时会得到一个哈希值:
通过此哈希访问此文件:
本地访问: http://localhost:8080/ipfs/QmekZaRsMQXHwwDT7qu41khcPspwFLANnv1QEv8xdAR7Cz
js文件里的require无法由浏览器直接识别,需要通过webpack index.js index2.js,转到index2.js才行。
web3:
通过web3获得区块链信息:
web3.eth.getBlock(0):获得第0个区块信息(同步方式,同步是顺序的,就怕得等)
web3.eth.getBlock(0,function(error,result){console.log(JSON.stringify(result))}):JSON.stringify对对象序列化(异步方式)
web3.version:看版本
大数都用bigNumber来处理,精度不损失:
0.20.1:
1.0.0:
web3.utils.函数
0.20.1:
查看挖到第N块时的余额:
估计一笔交易所需的gas:
此时仅仅是把一个交易放到交易池,如果挖一个块后,就会把该交易写到块里面。在ganache里面自动帮忙挖了块,而且解锁了账户。
监听区块链的变化,(事件latest)当出一个区块时,就会触发回调函数,打印区块的哈希:
此时每挖一个块,就会自动调用函数。
清除掉filter:
pending:每当产生了一个交易,就触发函数:
web3可以部署新合约到区块链上,再new合约对象:
本质上只是产生了交易,所以VotingContract没有address,只有挖了矿它就有地址了:
或者:直接拿到区块链上已有的合约(无新的交易),然后构建对象:
web31.0.0调用合约的函数:
(1)调用不更改状态变量,不消耗gas的函数:
(2)调动会更改变量,会产生交易的函数,此时就会产生交易,需要多传递一个调用者参数:
js脚本获得从node进来的参数,splice(2)把第2个往后的参数组成一个数组,此处为:[地址,value]:
经由geth启动personal模块后,才能在web3里面解锁账户:
给命令起别名:npm run pretest:就会执行冒号后面的命令,npm run compile,随后继续执行node scripts/...
1ether=10^18wei
以太坊账户由公钥算出,公钥由私钥算出。
私钥由一个密码(personal.newAccount时的)
和一个keyfile
组成,keyfile
是你在创建账户后自动生成的json格式
的文件,他一般保存在~/keystore/
目录下。私钥用来生成数字签名,在交易中用于证明对以太币的所有权。
私钥等价于助记词。
metamask中,deposit是存钱进去,send是转钱出去
以太坊网络:
poa指的是不用在挖矿了,由权威来出块
gas price:每笔交易的手续费。
remix的javascript VM:没有连接到主网和测试网的以太坊节点