区块链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,只有挖了矿它就有地址了:

var VotingContract = web3.eth.contract(abi)//创建抽象的合约对象
var deployTxObj = {data:合约字节码,from:web3.eth.accounts[0],gas:1000000}//构建一个交易对象
var instance =  VotingContract.new(deployTxObj); //产生对象实例,部署合约,同时产生交易, 第一个参数可选,是合约的构造函数要接受的参数

或者:直接拿到区块链上已有的合约(无新的交易),然后构建对象:

var instance = web3.eth.contract(abi).at(合约地址); 

web31.0.0调用合约的函数: 

(1)调用不更改状态变量,不消耗gas的函数: 

instance.methods.合约函数名(参数).call().then(p=>console.log(p));

(2)调动会更改变量,会产生交易的函数,此时就会产生交易,需要多传递一个调用者参数:

   web3.eth.getAccounts().then(accounts=>
        instance.methods.合约函数(参数).send({from:accounts[0]})
        .on('receipt', receipt=>console.log('该交易入块了,receipt:',receipt)) 
        .on('error', error=>console.log('交易出错了,error:',error))
    )

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:没有连接到主网和测试网的以太坊节点

 

posted @ 2020-07-25 17:52  Jary霸  阅读(207)  评论(0编辑  收藏  举报