赞
踩
参考教程:北大肖臻老师
记账(挖矿)就是计算Nonce(随机数)的过程,让Nonce匹配给定的Hash值,Hash值前面的0越多,则说明难度越大
相同数据生成的哈希值不变,不同数据哈希值不同
哈希加密算法不可逆,知道数据可以推出哈希值,但知道哈希值无法推出源数据内容(非对称加密)
/* 判断生成的Hash值是否符合难度 */ function isValidHashDifficulty(hash, difficulty){ for(var i = 0, b = hash.length; i < b; i++){ if(hash[i] != '0'){ break; } } return i >= difficulty; } /* 通过不断测试Nonce来找到符合条件的Hash值 */ let nonce = 0; let hash; let input; let difficulty = 3; while(!isValidHashDifficulty(hash, difficulty)){ nonce = nonce + 1; input = index + previousHash + timestamp + data + nonce; hash = CryptoJS.SHA256(input) }
比如现在有一笔交易需要写入区块中,那么当前分布式网络节点就会去计算“交易数据+一些其他数据+Nonce”的哈希值,若算出的哈希值(00asdjkh213jk)不匹配难度(假设难度为3),那么让Nonce加1,继续计算哈希值,直到哈希值满足难度为止,比如000sajdh213hiuh
工作量证明,GHOST协议
股权证明,Casper协议
BTC的出块时间大约是10分钟产生一个新区块
BTC出块时间慢,交易效率低,若使用BTC作为支付工具,则转账的BTC最多可能需要10分钟才能到账(被确认),因为每一笔交易都是记录在区块里的,只有当记录该笔交易的区块被挖出且被全网节点确认之后才算合法,此时转账才是有效的
BTC虽然出块时间慢,但恰是较长的出块时间保证了BTC系统的稳定性。
ETH的出块时间大约是10秒钟产生一个新区块
ETH出块时间快,交易效率高。
ETH出块时间虽然块,但存在一定程度上的不稳定性。试想两个算力不同的节点A与B(A:10,B:100),若在ETH系统中,当B挖出新区块并广播全网节点时,A可能还未挖出新区块,当B新挖出的区块得到全网确认后继续挖下一个新区块时,A可能才挖出新区块,但此时显然A挖出的新区块就被抛弃了,这样有算力优势的节点会越来越有优势,造成一定程度的中心化。
BTC:UTXO
ETH:Account
BitCoin(BTC),非图灵完备
BTC用到了密码学中的哈希和签名
三个性质:Collision resistance(防止哈希碰撞)、Hiding(根据哈希无法推出原输入值)、Puzzle Friendly(Difficult to Solve but Easy to verify)
MD5:不安全,可以人为制造Hash Collision
SHA-256(Secure Hash Algorithm)
Symmetrical Encryption & Asymmetric Encryption
对称加密:单密钥。通信双方商定一个共同的密钥,在传输信息时用密钥加密,接收方收到时再用密钥解密。但密钥的分发过程较繁琐,且容易被窃听。
非对称加密:密钥对(公钥和私钥)。每个通信节点都拥有一对公钥和私钥,公钥可公开,私钥存于本地。当发送方给某一接收方发送信息时,用接收方的公钥对信息进行加密,接收方收到信息后用自己保存在本地的私钥进行解密。
验证交易的真实性,即是否由“本人”发出
后一个块的哈希指针指向前一个块,当某个块被篡改时,其后的所有块都会被改动
默克尔树(其实就是把二叉树的指针改成哈希指针)
Block:Block Header + Block Body
Block Header
version
hash of previous block header
merkle root hash
target
nonce
Block Body
全节点(Full Node):保存整个区块的内容
轻节点(Light Node):只保存Block Header
Merkle Proof
Consensus
Unspent Transaction Output
每笔交易都需满足Input = Output,所以要知道某一地址的账户余额,只需查询UTXO中,转入该地址的交易额总量
例子:Coinbase => A(10),A(10) => B(4) + A(6)
当前块挖出后收到的确认为One Confirmation,其后紧跟的一个块挖出后得到的是Two Confirmation,BTC设计当前块在Six Confirmation后被篡改的可能性才很低(因为可能有恶意节点分叉攻击,恶意构造最长链覆盖主链)
挖矿:Hash(Block Header) <= Target
2016个区块调一次
矿池
State Fork
临时性分叉
Fork Attak
Deliberate Attack
Protocol Fork
协议升级造成的分叉,假设新节点占51%以上
Hard Fork
硬分叉:新节点认可旧节点的协议,旧节点不认可新节点的协议
Soft Fork
软分叉:新节点不认可旧节点的协议,旧节点认可新节点的协议
加密的目的是为了保证传输的可靠性以及接收方的可解密性,所以加密算法是不会造成信息丢失的。但哈希不同,以BTC中的哈希算法SHA-256为例,无论是多少位的输入,输出均为256位的哈希,这个过程是不可逆的,会造成信息的丢失。(如果可逆,那这个算法就是一个无敌的压缩算法了,因为多大的数据都能压到256位并且能回解出原数据)
Ethereum(ETH),图灵完备
以太坊账户之间的交易是在Ethereum的主链上进行的,例如一个账户要给另一个账户转账,那么就(利用MetaMask等钱包)向目标账户地址发起一个Transaction,value参数设置为转账数目即可。
基于以太坊的各种代币(如HT、BNB等)其实本质上就是Ethereum主链上布署的一个合约,该合约包含了代币本身之间互相交易的solidity代码。如要在代币之间进行交易,则就其本质上来说,是向该代币的合约地址发送Transaction,data参数设置为合约代码需要调用的函数选择器以及参数,进而调用合约内部的交易函数,进行Transfer,所以代币之间的转账其实是发生在代币合约内部,代币转账在以太坊主链上Transaction的value其实为0,Tranfer的参数才是真正的代币交易数目。而且各用户所拥有的代币余额其实都存储在该代币合约的存储空间中。
Frontier
Homestead
Metropolis
Byzantium
Constantinople
Saerenity
P2P Network
Transaction
EVM
以太坊虚拟机
Blockchain
Google的LevelDB
Client
Go-Etheruem(Geth)
Parity
Account
EOA(Externally Owned Account,外部账户):存储和代码均为空
Contract Account(合约账户):包含存储和代码
Address
Transaction
Gas
Gas Limit
防止ETH程序无限循环消耗资源
Gas Used
addr(160 bit) => state
字典树
路径压缩字典树
MPT
MPT
幽灵协议(Greedy Heaviest Observed SubTree)
区块奖励(Block Reward)
叔块奖励(Uncle Reward)
解决“临时性分叉”
叔块引用奖励(Uncle Referencing Reward)
普通区块收入
固定奖励
区块内包含的所有程序的gas花费的总和
若普通区块引用了叔块,则每引用一个叔块可以得到固定奖励的1/32
叔块收入
ethash
Memory Hard
ASIC Resistance
每个区块都有可能调整
D
(
H
)
≡
{
D
0
=
131072
if
H
i
=
0
max
(
D
0
,
P
(
H
)
H
d
+
x
×
ς
2
)
+
ϵ
otherwise
D(H) \equiv
D(H)是本区块的难度,由基础部分 P ( H ) H d + x × ς 2 P(H)_{H_{\mathrm{d}}}+x \times \varsigma_{2} P(H)Hd+x×ς2和难度炸弹部分 ϵ \epsilon ϵ相加得到
P ( H ) H d \mathrm{P}(H)_{H_{d}} P(H)Hd为父区块的难度,每个区块的难度都是在父区块难度的基础上进行调整
x × ζ 2 x \times \zeta_{2} x×ζ2用于自适应调节出块难度,维持稳定的出块速度
x
≡
⌊
P
(
H
)
H
d
2048
⌋
ς
2
≡
max
(
y
−
⌊
H
s
−
P
(
H
)
H
s
9
⌋
,
−
99
)
x x x 是调整的单位, ς 2 \varsigma_{2} ς2 为调整的系数。
y y y 和父区块的uncle数有关。如果父区块中包括了uncle ,则 y y y 为2, 否则 y \mathrm{y} y 为 1 。
难度降低的上界设置为-99,主要是应对被黑客攻击或其他目前想不到的黑天鹅事件
y − ⌊ H s − P ( H ) H s 9 ] y-\left\lfloor\frac{H_{\mathrm{s}}-P(H)_{H_{\mathrm{s}}}}{9}\right] y−⌊9Hs−P(H)Hs]
ϵ
≡
⌊
2
⌊
H
i
′
÷
100000
⌋
−
2
]
H
i
′
≡
max
(
H
i
−
3000000
,
0
)
设置难度炸弹的原因是要降低迁移到PoS协议时发生Fork的风险:到时挖矿难度非常大,所以矿工有意愿迁移到PoS协议
ϵ \epsilon ϵ 是2的指数函数, 每十万个块扩大一倍, 后期增长非常快,这就是难度“炸弹”的由来。
H i ′ H_{i}^{\prime} Hi′ 称为fake block number, 甴真正的block number H i H_{i} Hi 减少三百万得到。这样做的原因是低估了PoS协议的开发难度, 需要延长大概一年半的时间(EIP100)。
PoS(Proof of Stake)
挖矿算法完全无意义,只是为了抢夺打包交易的记帐权,挖矿算法对记帐完全没有帮助
Smart Contract
Decentralized Autonomous Organization
Beauty Chain
私钥(Private Key):256位的随机数,用于发送以太的交易中创建签名来证明自己对资金的所有权
公钥(Public Key):由私钥通过椭圆曲线加密secp256k1算法单向生成的512位(64字节)数
地址(Address):由公钥的keccak-256单向哈希,取最后20个字节(160位)派生出来的标识符
例如发送1个ETH,还需算上手续费(发送方付)= Gas Num * Gas Price,发送方总消耗为(1 + Gas Num * Gas Price) ETH,而手续费最终是奖励给挖出该笔交易所在区块的矿工
给地址0x0发送一笔不带value的特殊交易创建合约(0x0既不是EOA也不是CA)
传递value值,即转账给对方
发给EOA:
发给合约:32字节的十六进制序列化编码
函数选择器:函数原型的Keccak256哈希的前4个字节,这允许EVM明确地识别将要调用的函数
函数参数:根据EVM定义的各种基本类型的规则进行编码
以太坊虚拟机
以太坊客户端
CMD
geth --datadir ./private/data init ./private/genesis.json //初始化创世区块
geth --datadir ./private/data --networkid 15 console //启动
geth --datadir ./private/data --networkid 15 console 2>./private/output.log //重定向启动
geth --datadir ./private/data --networkid 15 --rpc console 2>./private/output.log //可通过MetaMask Localhost 8545连接本地私链
geth --datadir ./private/data --dev console //开发者模式(无需.json配置文件,自动创建私链,自动挖矿)
--allow-insecure-unlock //HTTP连接允许解锁账户
--nodiscover //不寻找P2P节点
--rpcapi db,eth,net,web3,personal,web3 //开放给web3.js远程调用的api
Console-web3
web3.fromWei(int num) //wei => ether
web3.toWei(int num) //ether => wei
Console-personal
personal.newAccount() //创建新账户
personal.unlockAccount(string account) //解锁账户
Console-eth
eth.blockNumber //获取当前链区块数
eth.getBalance(string account) //获取当前账户余额
eth.coinbase //查看当前默认挖矿账户
eth.mining //查看当前是否在挖矿
eth.sendTransaction({from: string account, to: string account, value: int num}) //交易
Console-miner
miner.start(int thread) //开始挖矿(参数为线程数)
miner.stop() //停止挖矿
miner.setEtherbase(string account) //设置挖矿进账主账户
var abiArray = xxx //.abi
var byteCode = xxx //.bin
var myContract = new web3.eth.Contract(abiArray)
myContract.deploy({
data: byteCode,
arguments: [arg1, arg2, ...] //The arguments of Constructor of Contract
}).send({
from: xxx,
gas: xxx,
gasPrice: xxx
}).then(instance => {
console.log(instance.options.address) //The allocated address of contract
})
myContract.options.address = instance.options.address
.<FUNC_NAME>() //函数名直接调用
.call() //有view字段,函数不更改状态,故不发送交易(默认调用call())
.sendTransaction() //无view字段,函数可更改状态,故可发送交易(默认调用sendTransaction())
以太坊客户端
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。