区块链1
通过钱包的公钥生成地址:
比特币:
哈希碰撞:不同的输入哈希后得到相同的输出
哈希函数的目标是collision resistance
哈希函数的hiding:哈希函数的计算过程是单向的,不可逆的
puzzle friendly:已知输入,不确定哈希后的输出是什么情况
A给B发送加密信息:A用B的公钥加密,然后B用他自己的私钥解密。
A签名:A用自己的私钥签名消息,然后外界用A的公钥验证
比特币中的账号相当于公钥,账号的密码相当于私钥。比特币系统中,一般先对消息取哈希值,在对他签名
由于哈希值的存在,改变一个区块的内容,后面区块都得改动
第一个区块:创世纪块
区块链:
merkle tree:
下面的数据块就是某个区块内部的所有交易.
根哈希值放在区块的头中
数据块取个哈希,然后放上面去,和旁边的哈希值拼接,结果再取哈希值放到上面。只要检测根哈希值,就能检测到树中任何位置的修改。
merkle proof:从某个交易到根哈希值到路径
轻结点不保存全部,只保存有区块的头,因此看不见交易。
当他要证明某个区块的交易是否合法(在merkle tree中),比如某个转账交易是否存在,则向全结点发送请求.
全结点啥都有,这个树也有。
全节点返回红色的哈希值(merkle proof),然后由轻结点自己计算往上验证:
该证明方法称为proof of membership
double spending attack:对着一个货币再复制一份假钱,伪造使用。区块链的交易输出和交易输入的结构就解决了这个问题
铸币权:发行货币的权利
区块要满足:区块头的哈希《=目标阈值target
区块头存储上一个区块头的哈希
节点找到满足不等式的nonce值后(hash rate:每秒能试多少次nonce),具备记账权,就能广播已打包的区块
分叉攻击:通过往区块链中插入一个区块来回滚已经发生的交易
获得记账权(挖矿成功)的节点(矿工)能够产生coinbase transaction(铸币交易),该交易凭空这个节点奖励一些BTC,即比特币 (出块奖励)。
A节点将B节点广播出来的交易要打包到区块里,则B节点就要给A节点支付gas
分叉中的短链所奖励的比特币都要废掉
sybil attack:创建很多虚假账户来攻击
UTXO:未花费的交易输出,可以抵挡double spending
每隔10分钟产生一个新区块。每21万个区块,则出块奖励减半
单个区块包含的信息:
Transaction Fees:把所有交易打包到这个块中所获得的交易费
height:块的序号
Block reward:挖出这个块所获得奖励
Hashes:区块头的哈希
Previous Block:前一个区块头的哈希
version:比特币协议的版本
nBits:目标阈值的编码
每个区块都含有coinbase Transaction,钱是挖出这个区块的矿工的
比特币总量=2100万
每个节点要维护一个等待上链的交易集合,当收到一个新交易时,就把该交易写到这个集合。
当交易被写到了区块中,则在集合中删掉对应交易
调整挖矿难度就是调整目标空间(最终哈希的正确结果)占输出空间(哈希值的所有可能结果)的比例
比特币用sha-256,哈希后的值是256位
挖矿难度越大,target越小
target每隔一段时间调整一次,其中右边分数的分子是挖出最近2016个区块所需的总时间,分子是理论上挖出2016个所需时间,但是右边的分数最小是1/4,最大是4:
矿池:由一堆矿机构成,共同挖矿
工作量:挖矿所做的工作量
coinbase Transaction的内容被更改了,会影响merkle root,也就影响了区块头的哈希值
交易输入的scriptSig叫做输入脚本,交易输出的那个叫做输出脚本。
要花UTXO中的某个交易时,所产生的交易输入的脚本要和交易输出的输出脚本能够拼接起来执行无误才行。
若比特币协议内容发生变化导致分叉,可分为硬分叉和软分叉。
协议有扩大的新功能时,如把块大小限制变大,则更新后的节点认4M大小的块,但是原来的节点就不认了。除非所有节点都更新协议,否则产生分叉,不可调和的
协议有新限制时,如把块的大小限制变小,则新节点只认小块,而旧节点都认,也会产生分叉,但是暂时的,不过旧节点吃亏。
比特币若私钥丢失,则这个账户的钱再也取不出来了。
比特币账户:公钥的哈希
矿工挖到区块后,他获得这个区块里面的所有交易输入-交易输出的钱
levelDB以key,value的形式存储区块的哈希值和对应区块的内容
私钥长度为256位
截断账户的做法会因为所猜的私钥长度变短从而容易反推出来,安全性下降
取哈希会造成原信息丢失
比特币基于交易
以太坊:
基于账户
重放攻击:收款人再次发布相同的转账交易,这样能拿2次钱
nonce:某个账户所发布的交易的次数
EOA(普通账户):含有余额和nonce,由公私钥控制,可发布交易
合约账户:含有余额,nonce,代码,存储,不能主动发起交易
账户地址是160位
Trie:同一组输入但不同顺序,最后树都一样
压缩后为:patricia tree
状态树:
保存(key,value),value是账户状态RLP序列化后的数据
所有账户状态组成一个状态树merkle patricia tree(MPT)上一个节点存储下一个节点的哈希值(指向它),并将树根的值存储到区块头中
交易树(一个块内的所有交易)和收据树(每个交易结束后会返回一个收据,收据含有bloom filter数据结构,该结构记录交易信息,如类型和地址,区块包含总的bloom filter。记录着块内所有交易的信息)也是MPT,key是块内交易所属的序号
比特币和以太坊都运行在应用层
以太坊goast共识机制:
不在最长合法链上的区块如果被后面的区块所包含,则叫叔块,挖到也能获得一定奖励,后面的区块不执行叔块的交易。
同时末尾区块自己也能额外获得奖励。
叔块的子代不给奖励
但是不同代叔叔所获得的奖励不同:
实际区块:
权益证明:根据所拥有的币的多少来投票
所有节点必须都要执行相同的交易以保持状态的一致
gas只给具有记账权的旷工
当合法的区块被广播过来后,全结点就得执行一下里面的所有交易来更新状态同时对比root值达到验证的目的
发布的区块的交易不一定都是能成功执行的,但是只要能发布成功就能获得gas
solidity是智能合约的一个语言:
块头的gasUsed:块中所有交易所耗费的gas;gasLimit:所有交易最多消耗的gas
交易中的gasLimit:结点收到该交易后名,先扣除gasLimit押金,然后消耗gas,最后把剩余的gas返还
THE DAO:一个去中心化组织,一个智能合约,能众筹以太币,人用以太币买他的代币然后进行项目投票,最后项目受益分成
THE DAO事件后,产生2条链,新链上的币还叫ETH,旧的叫ETC,2条链有了不同的chainID
智能合约发布到区块上,就不能再改动了
去中心化属于分布式,要用到多台计算机
美链是智能合约
编译合约后生成abi和字节码,abi供外部的web3使用
transfer失败后连锁式回滚,send仅仅返回false,它俩只发送少量gas,而通过call来转账要发送所有的gas
命令中的
[]:内的内容意思是:可写可不写
{}:必须要在{}内给出的选择里选一个。
<>:表示必选
pragma solidity ^0.4.0; : 能被0.4.x的编译器编译,但是不能被0.5.0的编译,还要加上分号。实验的当前版本:0.4.18-nightly.2017.10.3+commit.5c284589.Emscripten.clang
pragma solidity >0.4.0:只要大于0.4.0都能用
remix中injected web3:检测metamask给浏览器注入的web3,同时把账号也拿下来
view:只读变量但是不改写,点击函数不用花ether,外部调用函数会显示出来,不改变全局变量
部署合约会花费gas
点击函数会花费gas
pure:只读不写,不花费gas
bytes1类型存储1B,bytes2存储2B
public修饰的变量会自动的生成1个get方法,且只能修饰全局变量
num.length:返回num所占的字节数
new动态数组可以修改其中元素和数组长度,数组.push(a)能把a加到数组的后面:
对于string修饰的关键字而言,不能直接获取它的长度和数组里面的元素,或修改它的元素,除非把它转换成byte,changeName2也改掉了全局变量name了:
bytes12->bytes2转化时,只要前面的,从前往后截:
bytes->string:
for:
注意name要求它的索引得是uint类型
uint=uint256
bytes32->string:
固定数组:
可变长度数组,可以push,还能更改数组长度:
二维数组:
注意,下图表示3*2列的矩阵,有3组,每组里面有2个元素。第一个返回length是3,第二个返回2
注意,取第i行第j列是grade[i][j],如grade[2][0]:5
可变长度的二维数组:
为了使得数组字面量和返回值类型匹配:
账户地址160bit,合约也有地址,地址有address类型,等价于uint160
转账操作就得有payable修饰,payable给pay方法修饰之后,点击pay按钮,就能把value输入框的数值10转移给合约账户,随后通过getBalance来获得合约账户上的钱:
注意:1ether=10^18wei
获取特定账户的余额:
获得当前合约地址:
transfer的参数单位是wei
remix当中,部署合约时,右上角的account作为交易的from值,gas是扣他的
msg.sender.transfer(123):点击部署后,合约向合约调用者转123wei
涉及到转账的就需要有payable关键字
点击transfer之后,合约调用者(账户ca3)首先给合约转账value=10,它对应第一笔交易,from是合约调用者,value=10,input包含所调用的函数类型和传递的函数参数
然后合约再给账户1472转msg.value = 10:
以太坊虚拟机EVM是智能合约的运行环境,是基础设施,每个节点都得运行它。合约被EVM编译成字节码,并以字节码的形式保存到区块链上。
EVM也负责执行合约代码
委托调用:A合约调用B合约的代码时,B合约的执行上下文是在A里面,即B里面的msg.sender和msg.value和A合约一致。
合约内部也能创建合约,合约从区块链上移除则执行selfdestruct操作
变量idmaping里面就是一个个的键值对,msg.sender是合约调用者:
函数重载,同一个函数名字:
函数参数:
函数返回多个值:
internal修饰的方法只能在内部调用,而external则只能在外部界面点击调用,除非在函数体内部通过this.fun,来调用该external函数
合约继承:
constant:
构造函数在合约部署之后执行,函数名字与合约相同,只能有1个构造函数。若有参,则在右边传值:
或者新版本:
msg.sender:获得合约的部署者账户,或者执行函数的账户:
require若不成立,则不会继续往下执行代码:
modifier:当执行test函数时,就是替换了mod1里面的_;为test里面的内容,此时先调用mod1的a=1,然后再执行a=100,最后执行a=2
带参数的:
多重modifier:
继承的权限:
总结笔记:
get:
多重继承:
selfgdestrcut销毁合约,之后不能在和合约交互了:
storage类型:
引用类型包含:不定长字节数组(bytes),字符串(string),数组(Array),结构体(Struts),函数体内部默认是storage类型,函数参数默认是memory类型,如fun(student s)的s
类型memory即(值传递)
storage类型为指针传递,改变新指针的值会影响旧的
memory类型就放在内存,而storage类型是永久存在的
回退函数:
事件:
函数体会执行事件