本筆記為學習期間對主要知識和邏輯的記錄,根據課程內容分為BTC和ETH兩篇,本篇為BTC部分
北京大學肖臻老師《區塊鏈技術與應用》公開課筆記-ETH
文章目錄
- 01-課程簡介
- 02-BTC-密碼學原理
- 03-BTC-資料結構
- 04-BTC-共識協議
- 05-BTC-實作
- 06-BTC-網路
- 07-BTC-挖礦難度
- 08-BTC-挖礦
- 09-BTC-腳本
- 10-BTC-分叉
- 11-BTC-問答
- 12-BTC-匿名性
- 13-BTC-思考
01-課程簡介
- 參考資料(以代碼為準)
- BitCoin and Cryptocurrency Technologies A Comprehensive Introduction(2016年出版,已經比較過時)
- 以太坊白皮書、黃皮書、源代碼
- Solidity檔案
課程大綱:位元幣
- 位元幣
- 密碼學基礎
- 位元幣的資料結構
- 共識協議和系統實作
- 挖礦演算法和難度調整
- 位元幣腳本
- 軟分叉和硬分叉匿名和隱私保護
課程大綱:以太坊
- 以太坊
- 概述:基于賬戶的分布式賬本
- 資料結構:狀態樹、交易樹、收據樹
- GHOST協議
- 挖礦:memory-hard mining puzzle
- 挖礦難度調整
- 權益證明
- Casper the Friendly Finality Gadget(FFG)
- 智能合約
- 總結與展望
02-BTC-密碼學原理
位元幣主要用到了密碼學中的兩個功能:1.哈希2.簽名
- 密碼學中用到的哈希函式被稱為cryptographic hash function: 它有幾個重要的性質:
- collision(這里指哈希碰撞) resistance:找不到另外一個輸入使得其哈希值與原輸入的哈希值一致
- hiding 哈希函式的計算程序是單向的,不可逆的
- puzzle friendly 指哈希值的取值范圍事先是不可預測的,即挖礦找到亂數使其哈希小于target只能不斷嘗試
- 在位元幣系統中開賬戶:
-
在本地創立一個公私鑰匙對(public key ,private key),這就是一個賬戶,公私鑰匙對是來自于非對稱的加密技術(asymmetric encryption algorithm),
-
加密用你的公鑰,你收到之后用你自己的私鑰解密
-
簽名用私鑰,解密用公鑰
-
所以需要很好的隨機源來產生公私鑰對
03-BTC-資料結構
-
哈希指標
普通指標存盤的是某個結構體在記憶體中的地址,而位元幣中哈希指標,只保存該結構體的哈希值H(),根據哈希值找位置并判斷是否被篡改
-
位元幣中最基本的結構就是區塊鏈
-
區塊鏈和普通的鏈表相比有什么區別:
-
用哈希指標代替了普通指標(B block chain is a linked list using hash pointers)
-
普通鏈表可以改變任意一個元素,對鏈表中其他元素是沒有影響的,而區塊鏈是牽一發而動全身,因此只需要保存最后一個哈希值,就可以判斷區塊鏈有沒有改變,在哪里改變了,
-
-
區塊分為Block header以及 Block body
- block header就含有Merkle tree 里的root hash
-
-
Merkle Tree(位元幣中區塊的資料結構)
-
其中最下面一層是資料塊(data blocks),上面三層內部節點都是哈希指標(hash pointers),第一層是根節點,根節點的區塊也可以取個哈希,叫根哈希(root hash),每個資料塊是一個交易
-
作用:提供merkle proof:證明某個資料塊中的交易包含在了區塊中
-
證明黃色tx在區塊中:
根據全節點回傳的紅色哈希值,算出根哈希值是否就塊頭中的跟哈希值
輕節點只有塊頭
-
如何證明merkle tree里面沒有包含某個交易?
如果對葉節點的排列順序做一些要求,比如按照交易的哈希值排序,每一個葉節點都是一次交易,對交易的內容取一次哈希,按照哈希值從小到大排列,要查的交易先算出一個哈希值,看看如果它在里面該是哪個位置,比如說在第三個第四個之間,這時提供的proof是第三個第四個葉節點都要往上到根節點,如果其中哈希值都是正確的,最后根節點算出的哈希值也是沒有被改過的,說明第三、四個節點在原來的merkle tree里面,確實是相鄰的點,要找的交易如果存在的話,應該在這兩個節點中間,但是它沒有出現,所以就不存在,其復雜度也是log形式,代價是要排序,排好序的叫作sorted merkle tree,位元幣中沒有用到這種排好序的merkle tree,因為位元幣中不需要做不存在證明,
-
-

04-BTC-共識協議
-
數字貨幣和紙質貨幣區別是可以復制,叫作雙花攻擊 即double spending attack,
去中心化貨幣要解決兩個問題:-
問題
-
數字貨幣的發行
-
怎么驗證交易的有效性,防止double spending attack,
-
-
解決方法:
-
位元幣的發行是由挖礦決定的
每一個位元幣的最終來源都是每一個新挖出來區塊里面的鑄幣交易
-
依靠區塊鏈的資料結構
指明幣的來源以及來源余額,來源的最終源頭都是每個新區塊里的鑄幣交易
-
-
-
轉賬交易
-
資訊
-
付款人通過其他渠道獲得收款人公鑰
-
收款人、其他人需要知道付款人公鑰(交易中付款人給出的)
- 驗證付款人身份
- 幣的來源中,鑄幣交易的輸出就有付款人公鑰的哈希,能夠驗證合法
-
如何防范別人用自己公鑰偽造簽名?
-
這些是靠輸入輸出腳本來執行的,輸入輸出腳本在一起能夠正確執行,就說明交易合法
本質上就是看之前收款的公鑰哈希跟此次交易的公鑰的哈希對不對得上
-
-
-
-
分布式共識:賬本的內容要取得分布式的共識
-
還有一個著名結論:CAP Theorem
-
Consistency【系統狀態的一致性】
-
Availability【別人都可以用】
-
Partition tolerance
該理論內容是:任何一個分布式系統,比如分布式哈希表,這三個性質中,最多只能滿足兩個,假如想要前兩個性質,那么就不會得到第三個性質,
-
-
位元幣的共識協議:
-
按照計算力來投票
每個節點都可以在本地組裝出一個候選區塊,把它認為合法的交易放在里面,然后開始嘗試各種nonce值(占4 byte),看哪一個能滿足不等式H(block header)≤target的要求,如果某個節點找到了符合要求的nonce,它就獲得了記賬權,
所謂的記賬權,就是往位元幣賬本里寫入下一個區塊的權利,只有找到這個nonce,獲得記賬權的節點才有權利發布下一個區塊,其他節點收到這個區塊之后,要驗證這個區塊的合法性,
-
驗證合法性:
- nBits域(目標閾值的編碼)
- nonce
- 交易合法:合法簽名、沒有被雙花
如果同時找到了nonce,那么就看誰在最長合法鏈上
-
-
-

05-BTC-實作
-
基于交易的賬本模式
區塊鏈是去中心化的賬本,位元幣使用的是基于交易的賬本模式(transaction【交易】-based ledger【賬本】),系統當中并不會顯示每個賬戶有多少錢,
-
基于賬戶的賬本模式:以太坊
-
UTXO:
位元幣全節點要維持一個UTXO集合,即還沒有被花掉的輸出的集合,以便快速檢測double spending,
-
Transaction fee
-
total inputs=total outputs
有些交易total inputs略微大于total outputs,
假如輸入1位元幣,輸出0.99位元幣,另外0.01位元幣作為交易費給獲得記賬權發布區塊的節點, -
主要還是出塊獎勵
出塊獎勵每隔21萬個區塊減半,21萬個區塊大概要挖4年,位元幣系統設計的平均出塊時間是10分鐘,就是整個系統平均10分鐘會產生一個新的區塊,
-
-
Block Example

-
注釋:
一個區塊的例子
第一行:該區塊包含了686個交易
第二行:總輸出XXX個位元幣
第四行:總交易費(686個交易的交易費之和)
最下面一行:區塊獎勵(礦工挖礦的主要動力)
第五行:區塊的序號
第六行:區塊的時間戳
第九行:挖礦的難度(每隔2016個區塊要調整挖礦的難度,保持出塊時間在10分鐘左右)
倒數第二行:挖礦時嘗試的亂數右邊:第一行:該區塊塊頭的哈希值
第二行:前一個區塊塊頭的哈希值
(注意:計算哈希值只算塊頭)
兩個哈希值的共同點:前面都有一串0,是因為,設定的目標預值,表示成16進制,就是前面一長串的0,所以凡是符合難度要求的區塊,塊頭的哈希值算出來都是要有一長串的0,
第四行:merkle root 是該區塊中包含的那些交易構成的merkle tree的根哈希值,
-
提高搜索空間
挖礦時只改亂數不夠,nonce只有2的32次方個可能的取值,還可以更改根哈希值,
可以改變鑄幣交易中的coinbase域,從而改變block header里的hashMerkleRoot,搜索空間增大到了2的92次方,
可以理解為,鑄幣交易沒有輸入資訊,銷毀位元幣沒有輸出資訊,所以可以輸入額外的資訊,因此人們常常通過銷毀位元幣的方式往區塊鏈中增添他們想要的內容,
-
Bernoulli trial(伯努利實驗)
挖礦程序每次嘗試一個nonce可以看作是一個Bernoulli trial(伯努利實驗),每一個隨機的伯努利實驗就構成了一個伯努利程序,它的一個性質是:無記憶性,
可以用泊松程序來代替伯努利程序,我們真正關心的是系統出塊時間,出塊時間是服從指數分布,
-
progress free
指數分布也是無記憶性的,因為概率分布曲線的特點是:隨便從一個地方截斷,剩下一部分曲線跟原來是一樣的,比如:已經等十分鐘了,還沒有人找到合法的區塊,那么還需要等多久呢?仍然參考概率密度函式分布 ,平均仍然要等十分鐘,將來還要挖多長時間,跟過去已經挖了多長時間是沒有關系的,
-
保證挖礦公平性
算力強的礦工過去做的作業是更多的,過去嘗試了那么多不成功的nonce之后,后面nonce成功的概率就會增大,以此progress free 是挖礦公平性的保證
-
-
/** Nodes collect new transactions into a block, hash them into a hash tree,
* and scan through nonce values to make the block's hash satisfy proof-of-work
* requirements. When they solve the proof-of-work, they broadcast the block
* to everyone and the block is added to the block chain. The first transaction
* in the block is a special one that creates a new coin owned by the creator
* of the block.
*/
class CBlockHeader
{
public:
// header
int32_t nVersion;
uint256 hashPrevBlock;
uint256 hashMerkleRoot;
uint32_t nTime;
uint32_t nBits;
uint32_t nNonce;
CBlockHeader()
{
SetNull();
}
SERIALIZE_METHODS(CBlockHeader, obj) { READWRITE(obj.nVersion, obj.hashPrevBlock, obj.hashMerkleRoot, obj.nTime, obj.nBits, obj.nNonce); }
void SetNull()
{
nVersion = 0;
hashPrevBlock.SetNull();
hashMerkleRoot.SetNull();
nTime = 0;
nBits = 0;
nNonce = 0;
}
bool IsNull() const
{
return (nBits == 0);
}
uint256 GetHash() const;
int64_t GetBlockTime() const
{
return (int64_t)nTime;
}
};
06-BTC-網路
-
網路結構
- 應用層:BitCoin Block Chain
- 網路層:P2P Overlay network
-
傳播
-
種子節點
要加入P2P網路首先得知道至少有一個種子節點,然后你要跟種子節點聯系,它會告訴你它所知道的網路中的其他節點,節點之間是通過TCP通信的,這樣有利于穿透防火墻,當你要離開時不需要做任何操作,不用通知其他節點,退出應用程式就行了,別的節點沒有聽到你的資訊,過一段時間之后就會把你刪掉,
-
鄰居節點
位元幣網路的設計原則是:簡單、魯棒,而不是高效,每個節點維護一個鄰居節點的集合,訊息傳播在網路中采取flooding的方式,節點第一次聽到某個訊息的時候,把它傳播給去他所有的零度節點,同時記錄一下這個訊息我已經收到過了,下次再收到這個訊息的時候,就不用轉發給零度節點了,
鄰居節點的選取是隨機的,沒有考慮底層的拓撲結構,比如一個在加利福尼亞的節點,它選的零度節點可能是在阿根廷的,這樣設計的好處是增強魯棒性,它沒有考慮底層的拓撲結構,但是犧牲的是效率,你向身邊的人轉賬和向美國的人轉賬速度是差不多的,
-
等待上鏈
位元幣系統中,每個節點要維護一個等待上鏈的交易的集合,假如一個集合的交易都是等待寫入區塊鏈里的,那么第一次聽到某個交易的時候,把這個交易加入這個集合,并且轉發這個交易給節點,以后再收到這個交易就不用轉發了,這樣避免交易會在網路上無線的傳播下去,轉發的前提是該交易是合法的,
-
帶寬
位元幣協議對區塊的大小有1M位元組的限制,位元幣系統采用的傳播方式是非常耗費帶寬的,帶寬是瓶頸,按1M的區塊大小限制來算的話,一個新發布的區塊有可能需要幾十秒,才能傳輸到網路大部分境地,這已經是挺長時間了,所以這個限制值不算小,
-
07-BTC-挖礦難度
- 位元幣演算法:SHA-256
2 256 2^{256} 2256
H ( b l o c k ? h e a d e r ) ≤ t a r g e t H(block \, header) \leq target H(blockheader)≤target
d i f f i c u l t y = d i f f i c u l t y 1 t a r g e t t a r g e t difficulty = {difficulty1target \over target} difficulty=targetdifficulty1target?
-
調整動機:出塊時間變短
如果后面分岔多的話,前面某個區塊里的某個交易,很可能就遭受分岔攻擊,惡意節點會試圖回滾,因為后面分岔多,算力就會分散,惡意節點得逞的概率更大,這個時候惡意節點就不需要51%的算力了,可能10%的算力就夠了,因此出塊時間不是越短越好,
-
調整內容
位元幣協議中規定,每2016個區塊后就要調整目標預值,這大概是每兩個星期調整一次,即平均出塊時間10分鐘
t a r g e t = t a r g e t ? a c t u a l ? t i m e e x p e c t e d ? t i m e target = target*{actual \, time \over expected \, time} target=target?expectedtimeactualtime?
08-BTC-挖礦
-
全節點
- 一直在線
- 在本地硬碟上維護完整的區塊鏈資訊
- 在記憶體里維護UTXO集合,一邊快速檢驗交易的正確性
- 監聽位元幣網路上的交易資訊,驗證每個交易的合法性
- 決定哪些交易會被打包到區塊里
- 監聽別的礦工挖出來的區塊,驗證其合法性
- 挖礦
- 決定沿著哪條鏈挖下去
- 當出現等長的分叉鏈的時候,選擇哪一個分叉
-
輕節點
- 不是一直在線
- 不用保存整個區塊鏈,只要保存每個區塊的塊頭
- 不用保存全部交易,只保存與自己有關的交易
- 無法檢驗大多數交易的合法性,只能校驗與自己相關的那些交易的合法性
- 無法檢測網上發布區塊的正確性
- 可以驗證挖礦的難度
- 只能檢測那個是最長鏈,不知道哪個是最長合法鏈
-
挖礦設備演變
- CPU
- GPU
- ASIC( Application Specific Integrated Circuit )芯片
-
mining puzzle
一些新區塊鏈可能采用相同演算法,merge mining
-
礦池
礦主下連著很多礦工,礦工只負責計算哈希值,解決收入不穩定的問題,
-
計算礦工收入:
-
降低礦工難度
增大target,挖到一個nonce叫做share,計算這個礦工提交了多少share就可以了
coinbase域已經被礦主設定好了,所以偷不了
-
-
弊:
算力集中化,惡意攻擊不一定要自己掌握算力
-
09-BTC-腳本

-
介紹
如圖是位元幣的一個交易實體,該交易有一個輸入兩個輸出,左上角寫著output,其實是這個交易的輸入,右邊兩個輸出,上面unspent即沒有花出,下面spent表示已花出,該交易已經收到了23個確認,所以回滾的可能性很小了,
下面是這個交易的輸入輸出腳本,輸入腳本包含兩個操作,分別把兩個很長的數壓入堆疊里,位元幣使用的腳本語言是非常簡單的,唯一能訪問的記憶體空間就是一個堆疊,不像通用的編程語言,像C語言C++那樣有全域變數、區域變數、動態分配的記憶體空間,它這里就是一個堆疊,所以叫做基于堆疊的語言,這里輸出腳本有兩行,分別對應上面的兩個輸出,每個輸出有自己單獨的一段腳本,
交易結構
"result":{
"txid": "921a...dd24", // transaction id
"hash": "921a...dd24",
"version": 1,
"size": 226,
"locktime": 0, // 用來設定交易的生效時間,0:立即生效
"vin": {...}, // 輸入腳本
"vout": {...}, // 輸出腳本
"blockhash": "0000000000000000000002c510d...4c0b",
"confirmations": 23,
"time": 1530846727, // 交易時間
"blocktime": 1530846727
}
"vin": [{
"txid": "c0cb...c57b", // 來源交易的哈希值
"vout": 0, // 這個交易里的第幾個輸出
"scriptSig": { // 輸入腳本,下文寫成input script
"asm": "3045...0018", // 輸入腳本內容
"hex": "4830...0018"
},
}],
"vout": [{
"value": 0.22684000, // 單位是位元幣
"n": 0, // 第幾個輸出
"scriptPubKey":{ // 輸出腳本, 下文寫成 output script
"asm": "DUP HASH160 628e...d743 EQUALVERIFY CHECKSIG", // 輸出腳本內容
"hex": "76a9...88ac",
"reqSigs": 1, // 需要多少個簽名才能兌現(單重多重)
"type": "pubkeyhash", // 公鑰哈希
"address": ["19z8LJkNXLrTv2QK5....."] // 輸出地址
}
},{
"value": 0.53756644,
"n": 1,
"scriptPubKey":{
"asm": "DUP HASH160 628e...d743 EQUALVERIFY CHECKSIG",
"hex": "76a9...88ac",
"reqSigs": 1,
"type": "pubkeyhash",
"address": ["1LvGTpdye....."]
}],
-
注:
輸入輸出結構為一個陣列,它可以有多個輸入輸出組成
輸入輸出腳本的形式
-
執行方式
先執行當前交易的輸入腳本,然后執行源交易的輸出腳本
P2PK(Pay to Public Key)
// P2PK
// input script
PUSHDATA(Sig)
// output script
PUSHDATA(PubKey)
CHEKSIG
P2PKH(Pay to Public Key Hash)
// P2PKH(Pay to Public Key Hash) 最常用
// input script
PUSHDATA(Sig)
PUSHDATA(PubKey)
// output script
DUP // 復制堆疊頂元素
HASH160
PUSHDATA(PubKeyHash)
EQUALVERIFY
CHECKSIG
P2SH(Pay to Script Hash)
-
給出的不是收款人公鑰的哈希,而是贖回腳本的哈希
- 贖回腳本形式
- P2PK
- P2PKH
- 多重簽名形式
- 贖回腳本形式
-
input script需要給出一些簽名及一段序列化的 redeemScript,驗證分為兩步
- 驗證序列化的 redeemScript是否與output script 中的哈希值匹配
- 反序列化并執行 redeemScript,驗證input script中給出的簽名是否正確
-
本質:
把復雜度從輸出腳本轉移到輸入腳本
// P2SH實作P2PK
// input script
PUSHDATA(Sig)
PUSHDATA(serialized redeemScript)
// output script
HASH160
PUSHDATA(redeemScriptHash)
EQUAL
// redeemScript
PUSHDATA(PubKey)
CHECKSIG
// P2SH實作多重簽名
// input script
FALSE // 忽略這一行,這個是應對內部bug的
PUSHDATA(Sig_1)
PUSHDATA(Sig_2)
...
PUSHDATA(Sig_M)
PUSHDATA(serialized RedeemScript)
// output script
HASH160
PUSHDATA(RedeemScriptHash)
EQUAL
// redeemScript
M
PUSHDATA(pubkey_1)
PUSHDATA(pubkey_2)
...
PUSHDATA(pubkey_N)
N
CHECKMULTISIG
-
注
這個輸入腳本,是電商花掉這筆輸出的時候提供的,用戶付款的交易,輸出腳本只要知道這個哈希值就可以了
所有代碼都省略了OP_前綴
Proof of Burn
// output script
RETURN
[zero or more ops or text]
這樣的輸出永遠花不出去,這個證明銷毀位元幣的方法
其實輸出金額為0,就相當于只付了交易費,這樣不用保存在UTXO里
10-BTC-分叉
-
state fork
- deliberate fork:forking attack
-
protocal fork:對協議產生分歧
-
hard fork:硬分叉
-
位元幣中的區塊大小限制(block size limit),1M->4M
1M=1百萬 ,一個交易大概認為是250個位元組 1百萬/250=4000 一個區塊大概是4000個交易 平均10分鐘出現一個區塊 4000/(60×10)=7 大概每秒鐘產生7筆交易即7tx/sec 這個傳輸速度是非常低的,
新節點會認為4M和1M都是合法的,舊節點不認4M的,所以這兩條鏈都不會消失
-
-
soft fork:軟分叉
-
block size limit,假設1M->0.5M
新節點不認原來區塊,舊節點都認,所以就節點如果不更新軟體,會一直跟在最長合法鏈之后然后被丟棄,所以不會產生永久分叉,
-
coinbase域
coinbase前8個位元組作為隨機nonce,
有人建議把后面的位元組作為UTXO的根哈希值
-
Pay to Script Hash
-
-
舊節點不認的是硬分叉,舊節點認可的是軟分叉,
軟分叉:只要系統有多數節點更新,就不會產生永久分叉
硬分叉:只要系統中有節點不更新協議,就會產生永久分叉
-
11-BTC-問答
-
轉賬交易時如果接收者不在線怎么辦?
這個時候不需要接收者在線,轉賬交易只不過是在區塊鏈上記錄一下,把一個人賬戶上的位元幣轉移到他人的賬戶上,他人是否當時連接在位元幣網路上是沒有影響的,
-
假設某個全節點收到了一個轉賬交易,有沒有可能轉賬交易中接收者的收款地址是這個節點以前從來沒有聽說過的?
這是可能的,位元幣賬戶在創建的時候是不需要通知其他人的,在本地產生一個公私鑰對就可以了,只有在產生收款地址以后第一次收到錢時,其他節點才知道這個賬戶的存在,
-
如果賬戶的私鑰丟失了,該怎么辦?
私鑰丟失之后是沒有辦法的,該賬戶上的錢就變成了死錢,永遠取不出來了,在去中心化的系統里,是沒有人可以給你重置密碼的,
-
如果私鑰泄露了怎么辦?
比如你發現自己賬戶上出現一些可疑的交易,這個時候該怎么辦?這時應該盡快把自己賬上的錢轉到另外一個安全的賬戶上,這個也跟我們平時的生活體驗不太一樣,如果在銀行賬戶上出現一些可疑的交易,我們首先想到的是通知銀行,能否把密碼重置,賬戶凍結,免得別人把錢取走,而這些在區塊鏈的世界里都是做不到的,
-
如果轉賬的時候寫錯了地址怎么辦?
這是沒有辦法的,如果寫錯了地址而轉錯了人,我們也沒有辦法取消已經發布了的交易,位元幣當中轉賬交易一旦發布到區塊鏈里,就沒有辦法取消了,當轉錯了地址,如果我們知道是轉給了誰,可以跟對方進行聯系,如果不知道轉的是誰的地址,或者是不存在的地址,那就沒有辦法了,
-
接著問一個問題:proof of burn 、OP_RETURN這些實際當中是怎么操作的?當一個全節點收到一個轉賬交易的時候,它首先要檢查一下,這個交易的合法性,只有合法的交易才會被寫入區塊鏈里,而OP_RETURN這個陳述句是無條件的回傳錯誤,既然如此,它怎么可能通過驗證,怎么可能被寫到區塊鏈里呢?
驗證當前交易合法性的時候,不會執行這個陳述句,即當前交易的輸出腳本在驗證交易合法性的時候,是不會被執行的,只有有人想花這筆錢,后面再有一個交易,要花這個交易的輸出的時候才會執行這個交易的輸出腳本,
-
挖礦時會不會有的礦工偷答案?
不會,發布的區塊里有coinbase transaction,里面有一個收款人地址,是挖到礦的礦工的地址,假如A挖到了礦,里面就是A的收款地址,如果要偷答案的話,就要把A的地址換成自己的地址,而地址如果一變化,coinbase transaction的內容就發生了改變,這樣會導致什么?導致merkle tree的根哈希值變化,因為這個交易和區塊中所包含的其他交易是合在一起構成了merkle tree,任何一個地方發生改變,根哈希值就會變,而nonce是在塊頭里面,根哈希值也是在塊頭里面,block header的內容發生了變化之后,原來找到的nonce就作廢了,所以不可能偷答案,因為每個礦工挖到的nonce是和他自己的收款地址系結在一起的,
-
怎么判斷交易費該給哪個礦工?即事先怎么知道哪個礦工會挖到礦?
事先不需要知道哪個礦工會得到這個交易費,交易費是怎么算的?total inputs>total outputs,其差額就是交易費,發布的交易里面,一個交易可以有很多個輸入,也可以有很多個輸出,總輸入減總輸出就是交易費,給誰不需要事先知道,哪個礦工挖到礦了,就可以把這個區塊里所包含的交易差額收集起來,作為他自己的交易費
12-BTC-匿名性
-
位元幣系統中什么情況下有可能破壞匿名性?
比如網上購物,位元幣交易允許有多個輸入多個輸出,而多個輸入有可能是同一個人,因為這個人可能同時控制了這兩個賬戶的私鑰,
-
位元幣系統是運行于應用層(application layer)的,底層是(network layer),所以要提高匿名性可以從兩個方面入手,
-
網路層怎么提高匿名性?
而網路層的匿名性是比較好解決的,區塊鏈是個新生事物,但網路層的匿名性學術界已經有了很好的方案:多路徑轉發,跟洋蔥路由(TOR)是一樣的原理,即訊息不是由發出者直接發送給接收者,中間要經過很多次轉發,中間的每一個節點,只知道它的上一個節點是誰,但并不知道最早發出訊息的人是誰,當然中間一些節點可能是壞的,但路徑上只要有一個節點是誠實的,就能夠把最初發起人的身份隱藏起來,這也是洋蔥路由的基本原理, -
應用層怎么提高匿名性?
把不同人的幣混在一起(coin mixing),即把你的身份跟別人的身份混在一起,讓別人分不清楚誰是誰,不光是區塊鏈,在其他各個需要匿名的領域都能用到,有一些專門做coin mixing的網站,提供一定的服務收取一定的服務費,所有想做coin mixing的人把幣發給網站,網站內部進行一些重組,然后你再把幣取回來,這時取出的幣就不是發布到網站上的幣了,它是隨機抽取一些幣給你,
-
-
為什么保護隱私性難度挺大?
本質原因是區塊鏈是公開的,而且是不可篡改的,不可篡改性對于隱私保護來說是災難性的,
零知識證明
-
概念:
零知識證明是指一方(證明者)向另一方(驗證者)證明一個陳述是正確的,而無需透露除該陳述是正確的外的任何資訊,
-
例子:
要證明一個賬戶是我的,只需要我給出私鑰就行,但私鑰不能直接泄露,所以就給出由私鑰產生的簽名,假設對方是知道這個賬戶的公鑰的,那么就可以驗證簽名的正確性,這是不是一個零知識證明其實是有爭議的,因為我給出了私鑰之外的其他資訊,具體算不算要看應用場合,
同態隱藏
零知識證明的數學基礎是同態隱藏

-
第一個性質說明加密函式值E不會出現碰撞,這跟哈希函式有所不同,哈希函式是可能出現碰撞的,這個性質反過來說明如果E(x)和E(y)是相等的,那么x、y也是相等的,(該陳述句是上面陳述句的逆否命題)
-
第二個性質說明加密函式是不可逆的,知道加密后的值,沒辦法推出加密前的值,
-
第三個性質是最重要的,叫作同態運算,它說的是對加密之后的函式值進行某些代數運算,等價于對這些輸入直接進行代數運算然后再加密,
同態加法:加密值的和等于和的加密,
同態乘法:加密值的乘積等于積的加密, -
例子:
所示Alice想要向Bob證明她知道一組數x和y使得x+y=7,
同時不讓Bob知道x和y的具體數值,-
解答
Alice把E(x)和E(y)的數值發給Bob
Bob通過收到的E(x)和E(y)計算出E(x+y)的值
Bob同時計算E(7)的值,如果E(x+y)=E(7),那么驗證通過,否則驗證失敗
-
盲簽方法
- 用戶A提供SerialNum,銀行在不知道SerialNum的情況下回傳簽名Token,減少A的存款
- 用戶A把SerialNum和Token交給B完成交易
- 用戶B拿SerialNum和Token給銀行驗證銀行驗證通過,增加B的存款
- 銀行無法把A和B聯系起來
零幣和零鈔(專為匿名性設定的加密貨幣)
零幣和零鈔在協議層就融合了匿名化處理,其匿名屬性來自密碼學保證
-
零幣(zerocoin )系統中存在基礎幣和零幣,通過基礎幣和零幣的來回轉換,消除舊地址和新地址的關聯性,其原理類似于混幣服務
零幣中存在基礎幣(比如位元幣)和零幣,用的時候要證明本來是有一個基礎幣,讓基礎幣變得不能花費(unspendable),然后換取一個零幣,零幣在花的時候只需要用零知識證明你花掉的幣是系統中存在的某一個合法的幣就行了,但是不用透露你花的是系統中具體的哪一個幣,
-
零鈔(zerocash)系統使用zk-SNARKs協議,不依賴一種基礎幣,區塊鏈中只記錄交易的存在性和礦工用來驗證系統正常運行所需要關鍵屬性的證明,區塊鏈上既不顯示交易地址也不顯示交易金額,所有交易通過零知識驗證的方式進行,
零鈔沒有基礎幣,是完全的零幣,零鈔和零幣也不是100%匿名安全的,在影響匿名安全的因素中依然有一個因素無法解決,就是與物體發生互動的時候,比如有人想拿這些幣干壞事,把很大的金額轉換成這種加密貨幣的時候,或者是把這些加密貨幣轉換成現金的時候,仍然要暴露身份,這些加密貨幣數學上設計的再好,只是說對已經在區塊鏈當中的轉賬有匿名性,跟外界互動的匿名性仍然是一個弱點,所以它依然無法提供100%的匿名,
13-BTC-思考
-
哈希指標
哈希值本身就是指標
-
那么怎么才能找到前一個區塊的內容呢?
全節點一般是把這些區塊存盤在一個(key,value)資料庫里面,key是區塊的哈希,value就是區塊的內容,一個常用的key value資料庫是level DB,所謂的區塊鏈這種鏈表結構實際上是在level DB里面用哈希值算出來的,只要你掌握了最后一個區塊的哈希值,那么你通過level DB的查找,哈希值key對應的value就可以把最后一個區塊的內容取出來,然后這個區塊塊頭里面,又有指向前一個區塊的哈希值,那么再去查找key和value,可以找到前一個區塊的內容,以此類推,一步一步往前找,最終能夠把整個區塊鏈都找出來,
-
-
區塊戀
就是指,把一個私鑰分成幾份,有幾個人各自保管,只有最終大家都拿出自己的部分私鑰,才能合成完整的私鑰
但是如果從中截斷,一對情侶中一個人分手之后想把錢取出來,他已經知道了其中一半的私鑰,只要把剩下的128位私鑰猜出來就行了,私鑰長度減少一半并不意味著難度降低一半,難度由2的256次方降到了2的128次方,前者遠遠大于后者,破解難度降了很多,如果是四個合伙人的例子,有三個人瞞著另一個人要把錢取出來,那么他們只需要嘗試2的64次方就可以了,
因此對于多個人的共享賬戶,不要用截斷私鑰的方法,而最好采用多重簽名,多重簽名中用到的每一個私鑰都是獨立產生的,而且多重簽名也提供一些別的靈活性,比如可以要求N個人當中任意給出M個簽名就可以了,
-
分布式共識
嚴格來說,位元幣并沒有取得真正意義上的共識,因為取得的共識隨時有可能被推翻,比如出現了分叉攻擊,你以為已經取得了一個共識,分叉攻擊后系統會回滾到前一個狀態,從理論上說甚至有可能回滾到創世紀塊,
-
位元幣的稀缺性
礦工挖礦的原因是為了獲得收益,挖礦的收益要大于開銷才是有利可圖的,要吸引別人來挖礦,要么增加挖礦的收益,要么降低挖礦開銷,任何一個新發行的加密貨幣,都有一個能啟動的問題,早期為了吸引礦工來挖礦,可以給礦工更多的收益,位元幣的做法是:①早期難度設定的比較低,②早期的出塊獎勵比較高,
實際上,位元幣這種總量恒定的性質是不適合用來做貨幣的,后面講的以太坊就沒有出塊獎勵定期減半的做法,一些新型的貨幣甚至要自帶通脹的功能,每年要把貨幣的通行量提高一定的比例,因為稀缺的東西是不適合用來做貨幣的,通貨膨脹會導致錢變得更不值錢了,但一個好的貨幣是要有通貨膨脹的功能的,
-
量子計算
隨著量子計算的發展,量子計算機計算力變得越來越強大,加密貨幣會不會變得不安全了?
這種擔心是沒必要的:
①量子計算技術離實用還有很長一段距離,在位元幣的有生之年不一定能產生實質性的聯系,如果量子計算在將來能強大到破壞加密體系的話,首先會沖擊的是傳統金融業,比如我們在網上進行的很多金融活動:網上銀行、網上轉賬、網上支付,都會變得不安全了,所以與其擔心量子計算對位元幣的沖擊,還不如擔心量子計算對傳統金融業的沖擊,因為大多數的錢還是放在傳統金融業里面的,加密貨幣的市值只占了現代金融體系當中的很小一部分,
②位元幣當中沒有把賬戶的公鑰直接暴露出來,而是用公鑰取哈希之后得到一個地址,位元幣當中用的非對稱加密體系,從私鑰是可以推匯出公鑰的,所以只要把私鑰保管好,公鑰其實丟了也沒有關系,從公鑰顯然是不能推出私鑰的,否則就麻煩了,
假設將來量子計算技術發達了,能夠從公鑰中推出私鑰,那怎么辦呢?位元幣在設計的時候又加了一層保護,沒有用公鑰本身,而是用公鑰的哈希,所以如果有人想偷你賬戶上的錢的話,首先是要用地址推匯出你的公鑰,相當于把公鑰的哈希值進行逆運算,而這一點即使是用量子計算機也是沒有辦法完成的,
北京大學肖臻老師《區塊鏈技術與應用》公開課筆記-ETH
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/287663.html
標籤:區塊鏈
上一篇:HTTPS底層實作原理
