# BTC [要捲舌ㄉ線上課](https://www.youtube.com/channel/UCBtnEPEpvAyEGXNarIPzqaA) ## BTC 用到的密碼學和他的原理 + **比特幣稱為加密貨幣(Crypto-currency),但其實加密貨幣是不加密的** > 所有交易都是公開可讓人看見的。 + **比特幣主要用到 Hash(Cryptographic Hash Function)** + **Collision resistance (collision free)** + **Ex : x≠y , H(x)≠H(y) >> 這就叫做 collision resistance** + 但由於輸入空間遠大於輸出空間,因此 H(x) = H(y) 是不可避免的 + 除了 brute-force 目前沒有一個好辦法能夠人為製造 collision resistance + 此性質可用於驗證訊息的真偽 + Ex : m -> H(m) , m2 -> H(m2) 只要訊息被竄改過,那麼取 Hash 運算的結果 H(m) ≠ H(m2) 一定成立 + **但目前也沒有任何辦法證明此性質確實存在,唯人為操作的經驗可以佐證** + 也有已經被找到人為製造 collision 的 Hash function + Ex : Md5 + **Hiding** + Hash Function 的運算是單向的 + Ex : x -> H(x) , ( H(x) -> x )(impossiple) + **Collision resistance + Hiding** 實現 **Digital commitment(Digital equivalent of a sealed envelope)** + 可以用來驗證預測結果 + Ex : 預測 會發生XXXX -> 作為 m 保存,給出 H(m),之後只要驗證,訊息 m 取 Hash 是否為 H(m) 即可 + **Puzze friendly** + 除了 brute-force 以外,事先無法預測 Hash 的結果 + **也代表了,挖礦的過程沒有除了 brute-force 以外更快的方法** + 也因此,這樣執行的過程才可以用來當作**工作量證明(proof of work)** + **nonce** + 一個隨機數 + 挖礦就是再找 H(block header) <= target + **其中 block header 裡面有一個可以人為控制的域稱為 nonce** + difficult to solve, but easy to verify + **SHA - 256(Secure Hash Algorithm)** + 比特幣使用的 Hash Function + 滿足 + collision resistance + hiding + puzzle friendly + **比特幣的簽名方式** + **去中心化** + 無類似銀行的機構在保管每個使用者的帳戶 + 每個用戶自己開戶,只要產生**公私鑰對**即為一組帳戶 + 公私鑰對 + (public key , private key) -> 即為一組帳戶 + Asymmetric encryption algorithm(非對稱加密) + **public key -> encrypt message** + **private key -> decrypt message** + public key 讓所有人知道也沒問題,只要保存 private key 即可完成解密 + 別人要轉帳給你只要知道公鑰即可 ## BTC 的數據結構 + **比特幣使用的數據結構** + 區塊鏈 + 去中心化的帳本 + ![](https://i.imgur.com/frADdW5.png) + Linked list + 用 **Hash pointers** 取代了一般的 pointers + **Hash Pointers** + **Hash pointers 不只儲存了區塊的地址也儲存了區塊的 Hash 值** + 保存 Hash 值能夠檢測該節點有沒有被竄改過 + ![](https://i.imgur.com/TRbE6Fx.png) + 這是一個小型區塊鏈 + 第一個區塊叫做 genesis block + 最後一個區塊是最後產生的區塊 **most recent block** + 每個區塊都包含一個 Hash Pointer + 把整個區塊的內容包含 Hash 值取 Hash 才能求出下一個區塊 + **每一個 block 內的內容/Hash值更改,下一個區塊的都得改,所以只要儲存最後一個 Pointer 就能檢測前面的內容是否被改變過** + 因此區塊不需要每個都儲存,只需要儲存最後面幾個就可以 + 透過這樣的結構能實現 tamper-evident log + **Merkle tree** + 用 Hash Pointer 取代一般的 binary tree 的 Pointer + ![](https://i.imgur.com/KuM0gqU.png) + 這是一棵 Merkle tree + 最下面的一層叫 **data blocks** + **每個 data block 都可看做一個交易(transaction)** + 上面的節點都是 Hash pointers + **Ex : data blocks 的 hash 值存在上面的區塊,兩個 hash 值的 hash 結果又儲存在更上一層的節點** + 根節點的 hash 值稱作 **root hash** + **只要記住 root hash 就能檢測各節點的修改** + root hash 儲存在 block header + transaction 存在 block body + **Merkle proof** : 證明某個交易寫入到了區塊鏈裡面 + ![](https://i.imgur.com/HsMB1Qm.png) + 只要向全結點請求 Hash 值就能一步一步檢測各個值,直到 root hash,root hash 和原定的 root hash 一樣就代表正確。 + 複雜度 : O(log(n)) + Q : 能不能改變 TX() 旁的 Block 找到另一個 Hash 值以便塞入惡意的交易 ? + A : 不可能,因為 Collsision resistance 性質保證 ## BTC 的協議 + **double spending attack** + 數字貨幣面臨的最大的挑戰 + **BTC 如何避免 double spending attack** + 由區塊鏈系統以避免 + ![](https://i.imgur.com/OMjp0IP.png) + 有兩個指針,一個是指向前一個區塊,一個是指向幣的來源 + 輸入部分要表明幣的來源,輸出部分要給出收款人公鑰的 Hash 值 + 如果沒有標明幣的來源則此交易無效,則該次交易不會被納入區塊鏈裡面 + 轉帳後收款人需要知道匯款人的 Public key,為了要驗證合法性 + 驗證方式是驗證 Public key 的 Hash 值 + 就是由這些交易組成 Merkle tree + **Block header** + 取 hash 值時只對 **Block header** 取 hash 不動 **Block body** + **version** + 當前使用的 BTC 協議的版本號 + **hash of previous block header** + 前一個 Block header 的 hash 值 + **Merkle root hash** + Merkle 根哈希值 + **Coinbase 裡塞甚麼東西基本沒人管,nonce 不夠大時會寫在這邊,前八個零也能當作 nonce,搜索範圍提高至2^96** + **target** + 挖礦的時候用的目標域值,按照協議要求定期調整 + **time** + 區塊產生的時間,BTC 系統並不要求非常精確的區塊產生時間,可以稍加調整 + **nonce** + **挖礦的隨機數(2^32)** + **Block body** + transaction list + **full node(fully validating node)** + 保存區塊鏈的所有訊息,也要負責驗證每筆交易 + **light node** + 只保存 **Block header** 的訊息 + **distributed consensus** + 需要 **distributed hash table**的 value key pair + Ex : Hack -> 12345 此結果在全部結點必須一致 + **Consensus in BitCoin** + 假設惡意結點佔少數的情況下 + 採投票制決定下一個區塊的合法性 + **Sybil attack** + 惡意結點瘋狂製造 key pair 進行投票 + **BTC 避免 Sybil attack 的方法** + 以算力進行投票 + 每個結點都能提出一個認為合法的區塊,將其放入候選區塊後就開始嘗試 nonce (挖礦),找到 nonce 後的區塊就取得**記帳權** + **記帳權** : 將區塊寫入區塊鏈的權力 + 其餘區塊則驗證 **Block header** 裡的內容物是否合法 & **Block body** 內的交易列表是否合法 + ![](https://i.imgur.com/ZJ4ReB2.png) + **Q :** 若一合法區塊, **Block header** 內容物合法, **Block body** 交易列表也無誤,但將區塊發布在前一個區塊之間 ? + **A :** 他不再最長鏈(**longest valid chain**)上,**因為 BTC 協議內規定,新的區塊一定要接在最長合法鏈上** + **forking attack** + **平常也可能產生 forking attack** + 兩結點同時擁有記帳權(同時找到符合要求的 nonce),又同時發布結點,將會出現兩個等長的分岔最長鏈 + ![](https://i.imgur.com/BW1ZWLK.png) + 會不斷維持直到某個分岔又找到下一個結點,而多出來的那個結點稱為 **Orphan block** + **為甚麼要爭奪記帳權 ?** + **Block reward** + **Coinbase transaction** 是 BTC 系統中發行新的貨幣唯一的方法 + 一開始每個發布的區塊可以取得 50 個 BTC,每 21 萬個區塊之後出塊獎勵會減半,目前每個區塊只能產生 6.25 個 BTC (2020) + 平均每 10 分鐘產生一個區塊 -> 約每 4 年獎勵減半一次 + 若交易鏈分岔後,短鏈得到的 BTC **完全無用** + 由 **puzzle friendly** 保證取得 nonce 沒有捷徑 + hash rate + 每秒鐘能測試的 **nonce** 數 . + hash rate 影響投票的權重 + (Extra) CAP Theorem + Consistency + Availability + Partition tolerance + 此理論表明任何一個分部式系統,一次只能滿足其中兩個 + (Extra) hyperledger fabric ## BTC的實現 + **Transaction-based ledger** + **UTXO** (Unspent Transaction output) + **儲存尚未花用的 BTC** + Ex : A -> B(5),B -> D(5),A -> C(5) + A -> B(5) (不在 UTXO 裡面), B -> D(5) (在 UTXO 裡面),A -> C(5) (在 UTXO 裡面) + 不論是誰、甚麼形式,**存入 UTXO 的 BTC 只要不花用就會永久地保留在 UTXO 裡面** + 除了 Block reward 以外的獎勵機制 **transaction fee** + total input(1 BTC) = total output(0.99 BTC) + 不見的 0.1 個 BTC 就是 **transaction fee** + 因為 **BTC 的 Block reward 減半機制**,或許到了 BTC 系統成熟時,**transaction fee** 會取代 Block reward 成為最有效率的 BTC 取得手段 + **Account-based ledger** + 以太坊主要使用的模式 + [Blockchain.com](https://www.blockchain.com/?utm_campaign=expnav_logo) + [Example](https://www.blockchain.com/btc/block/529709) + ![](https://i.imgur.com/rbbkfFd.png) + Difficult : 每隔 2016 個區塊要調整一次難度 + 由此可知目前獲取 BTC 的方法還是 **Block reward** 為大宗 + **Script** + ![](https://i.imgur.com/Xl3AYIo.png) + 把這個交易裡的輸入腳本和前一個交易的輸出腳本配對,能執行才是合法的交易 + **挖擴**(mining) + 不斷嘗試 **nonce** 以解決 **puzzle** 的過程 + **Bernoulli trial** + A random experiment with binary outcome + 就像擲硬幣一樣,每次挖礦的成功率要一致 + Bernoulli process : a sequence of independent Bernoulli trial + **memoryless(progress free)** + 挖礦公平性的保證 + 出塊時間 + 指數分布 **(exponential distribution)** + 平均時間為 10 分鐘 + 已經挖超過 10 分鐘了,所以快要出塊了(X) + 已經挖超過 10 分鐘了,還沒挖到,那下一個塊還是要等 10 分鐘 + **若沒有此性質,則算力越強的礦工優勢越大** + BTC 的挖礦 + 只是算力比拚,並無任何意義,但這個算力比拚的過程對 BTC 安全性的維護非常重要 **(Bitcoin is secure by mining)** + 通常一個節點後有 6 個新節點,才會認為該節點的交易是不可竄改的 + 寫入的時間越短的交易紀錄,越有可能被更改 **(區塊鏈是不可更改的帳本,只是概率性的說法)** + BTC 越來越少,因為 Block reward 所致,因此,**BTC 的稀缺性是人為造成的** + BTC 總數約為 2100 萬 + **21萬 x 50 + 21萬 x 25 + 21萬 x 12.5...** + = 21萬x50(1+1/2+1/4) + = 21萬x50x2 = 2100萬 + 記帳權落入惡意節點手裡 + 誠實的節點不會受理,因此會繼續從上一個節點往下挖 + 因此攻擊者不但攻擊會失敗,還會喪失 Block reward + **Selfish mining** + 一種攻擊手段,先挖好一堆惡意的節點,6 個以上,比最長鏈還長之後一次發布 + 成功的可能性很低 + 可能會失去非常多 Block reward,因為 BTC 的公平性機制所致 + 有惡意的節點佔據 51% 以上的算力比較有可能成功 ## BTC 的網路 + Simple robust, but not efficient + 工作原理 + **application layer : Bitcoin Block chain** + **network layer : P2P Overlay Network** + 非常簡單的網路結構,所有節點都是對等的 + 要加入該網路,必須先知道一個 seed node 聯繫他才能得知其他的網路節點 + 節點間透過 TCP 來聯繫,目的是為了穿過防火牆 + 每個節點維護一個臨近節點, + 效率不高,向身邊的人轉帳和向國外的人轉帳的效率差不多 + 每個節點有一個集合,保存交易,若裡面的交易成功寫入區塊鏈則將該交易從集合中刪除 + 對每個區塊,有 **1 兆大小的字節限制** + **在 BTC 系統中,若有交易糾紛,並無辦法回穩該次的交易,只能尋求其他管道** + 銀行也沒辦法回穩,而是依靠再交易一次進行回穩,而 BTC 系統也能在交易一次 ## BTC 的挖礦難度 + H(Block header) <= target + 不斷的改變 block header 裡的 nonce 值,使 block header 的 Hash 值 <= 給定的目標值 + SHA-256 + **difficult = difficult_1_target / target** + difficult_1_ : 代表 difficult 為 1 時的對應的目標域值非常大,表示挖礦難度不高 + **difficult 低表示產出新的 block 的速度很快,會一直有交易寫入 block,未必是好事** + 容易出現分岔 + ![](https://i.imgur.com/ItWB23s.png) + **51% attack** + **惡意節點掌握了所有算力的 51%,這時候他想幹嘛都可以** + **forking attack** + 如果分岔過多,惡意節點就能集中算力,完整自己的分岔 + **Boycott** + 封鎖某個使用者,使其無法使用 BTC 交易 + Ex : 想要封鎖某使用者 A 因此只要和 A 有關的交易通通不允許其上鏈,其他區塊包含此交易就立刻分岔 + 10分鐘的出塊時間 + **是不是最好的? 不知道** + 乙太坊的出塊時間為 15 秒,因此有其他的共識協議 + **每 2016 個區塊會調整一次 difficult** + **約 2 個星期調整一次** + **target = target x (actual time / expected time)** + **actual time** : 最近 2016 個區塊的實際花費時間,(time spent mining the last 2016 blocks) + **expected time** : 理論上產生 2016 個區塊所需時間 2016 x 10 + **target 變大** : 挖礦難度降低 + **target 變小** : 挖礦難度增加 + 有關 **target** 的調整是寫在 BTC 的 code 裡面的,每 2016 個節點就必須調整一次 **diffidcult** + 如果有惡意節點不調 **target** ? + 檢查 block header 內的 nBits 域,就能確定該 block 是否有調整 target + **nBits** : **4 個字節的 target 壓縮編碼** + [關於 BTC 的各項數據](https://btc.com/stats) + **若難度上升 : 表示大家對該幣的熱度逐漸升高** + **若難度下降 : 表示大家對該幣的熱度逐漸降低** ## BTC 的挖礦 + **全節點(full node)** + 一直在線 + 在本地硬碟維護完整的區塊鏈訊息 + 在內存裡維護 UTXO 集合,以便快速檢驗交易的正確性 + 監聽 BTC 網路上的交易訊息,檢驗每個交易的合法性 + 決定哪些交易要被放到區塊裡 + 監聽別的礦工挖出來的區塊的合法性,驗證其合法性 + 挖礦 + 決定沿著哪條鏈挖下去 + 當出現等長的分岔時,選擇哪一個分岔 + **輕節點(light node)** + 不用一直在線 + 不用保存整個區塊鏈,只需保存每個區塊的 block header + 大小約相差 1000 倍 + 不用保存全部交易,只保存與自己相關的交易 + 無法檢驗大多數交易的合法性,只能檢驗與自己相關的交易的合法性 + 無法檢驗網路上發布的區塊的合法性 + 可以驗證挖礦的難度 + 因為挖礦時只用到 block header 的訊息 + 只能檢驗哪個是最長鏈,不知道哪個是最長合法鏈 + 因為只有儲存 block header + BTC 網路中,大部分節點都是 light node + 如果監聽到別人已經發布了一個合法的區塊,應該要立刻組裝一個後選區塊,重新開始挖礦 + **BTC 是如何保證安全性的** + **公私鑰對**(非對稱加密) + 必須要建立在大部分礦工都是誠實的情況下 + **挖礦的設備** + **起初 : CPU** (電腦或筆記型電腦都行) + 非常不划算,因為挖礦的運算只用上 CPU 的很小一部份,而且電腦裡的其他設備都用不上 + **進化 : GPU** + GPU 主要用於大規模的併行運算,含有大量的矩陣乘法,但其實還是有點浪費,裡面還是有很多部件浪費掉了,譬如浮點數運算的部分 + **專業化 : ASIC(application specific integrated circuit)** + 整個晶片就是為了挖礦,為了計算 Hash 值的操作而設計的,除了挖礦以外甚麼都幹不了 + 而且這個晶片只能 for 單一種加密貨幣,除非兩種貨幣使用的 mining puzzle 是一樣的 + 某個階段的 Hash rate 突然暴升可能就代表某個大廠的礦機生產出來了 + 一旦過時了就只能報廢了 + **merge mining** + 有些貨幣為了能啟動會用和某些加密貨幣同一種的 mining puzzle + **礦池 mining pool** + **pool manager** + 礦主,管理底下的礦工 + 分配計算 hash 的任務給礦工 + 將來有 block reward 時一起分紅 + 依照各礦工的貢獻大小進行獎金分配 + **工作量證明(proof of work)** + **share** + **almost valid block** + 礦工把 share 交給 礦主,作為工作量證明 + 因為 **coinbase tx** 裡的收款地址是礦主,因此礦工即使自己發布了 block 也得不到 **block reward** + 每個礦工只負責計算 hash 值,並不知道礦主是否為惡意 + **礦池資料** + ![](https://i.imgur.com/HKtP9za.png) + 目前各國的算力(hash rate)排行 + ![](https://i.imgur.com/JIwpHPK.png) + Ghash.io 曾在 2014 年 6/17 時算力達到近 51% 引起 BTC 的一波大跌潮,爾後 Ghash 主動降低算力佔比,以提升大眾對 BTC 的信心 + ![](https://i.imgur.com/5QxQSxS.png) + BTC pool distribution(latest) ## BTC 交易腳本 > **底下腳本執行實例都省略了 ( OP_ )** + **結構** + **TxID** + **Hash** + **Version** + **size** + 交易的大小 + **locktime** + 交易的生效時間 (大部分時候都是 0) + **vin** + 輸入 + **TxID** + 幣的來源的 Hash 值 + **vout** + 表示這是這個交易裡的第幾個輸出 + **scriptSig** + **asm** + **hex** + **vout** + 輸出 + **value** + 輸出多少 BTC 最小單位為 1 Satoshi (10^-8) + **n** + 序號,表示這是這個交易裡第幾個輸出 + **scriptPubKey** + **asm** + 輸出腳本的內容,包含一系列的操作 + **hex** + **reqSigs** + 需要多少個簽名(signature)才能兌現 + **type** + **輸出的類型** + **address** + **輸出的地址** + **blockhash** + 這個交易所在區塊的 hash 值 + **confirmations** + 這個交易已經有多少個確認了 + **time** + 這個交易產生的時間 (秒) + **blocktime** + 這個區塊產生的時間 (秒) + **交易概念圖** + ![](https://i.imgur.com/6Q8hPBZ.png) + **只要將 B->C 的輸入腳本和 A->B 的輸出腳本拼接後吻合就是合法的** + ![](https://i.imgur.com/DPOLGZ0.png) + **P2PK (Pay to Public Key)** + 最簡單的形式 + **inputScript** + **PUSHDATA(Sig)** + **outputScript** + **PUSHDATA(PubKey)** + 直接給出收款人的公鑰 + **CHECKSIG** + 檢查簽名的操作 + 腳本執行 + 實際執行時腳本是分開執行的 + **PUSHDATA(Sig)** + **把 inputScript 提供的 Sig 押入** + **PUSHDATA(PubKey)** + **用 PubKey 檢查一下這個 Sig 是否正確** + **CHECKSIG** + **檢測頂端兩個元素,用 PubKey 檢查 Sig 是否正確** + **若是正確則回傳 TRUE,不是則回傳 FALSE** + ![](https://i.imgur.com/PEZ7vhC.png) + ![](https://i.imgur.com/WRb2hdA.png) + **a914013.... 就是幣的來源的 Hash 值** + **P2PKH (Pay to Public Key Hash)** + **inputScript** + **PUSHDATA(Sig)** + **PUSHDATA(PubKey)** + **outputScript** + **DUP** + **HASH160** + **PUSHDATA(PubKeyHash)** + **EQUALVERIFY** + **CHECKSIG** + 腳本執行 + **PUSHDATA(Sig)** + **先把簽名 Sig 押入** + ![](https://i.imgur.com/4Y0XHh6.png) + **PUSHDATA(PubKey)** + **把 PubKey 押入** + ![](https://i.imgur.com/sb4VBmF.png) + **DUP** + 把最上面的元素在複製一次 **(PubKey)** + ![](https://i.imgur.com/Yo7uIjc.png) + **HASH160** + 把最上面的元素取出求 Hash 後再把結果押入 + ![](https://i.imgur.com/DiSe8K0.png) + **PUSHDATA(PubKeyash)** + 把公鑰的 Hash 押入 + ![](https://i.imgur.com/fI5X2iR.png) + **EQUALVERIFY** + 比較頂端的兩個元素是否相等(防止有人冒名頂替) + ![](https://i.imgur.com/m3sFYAZ.png) + **CHECKSIG** + 取頂端的兩個元素,用 PubKey 檢查 Sig 是否正確 + ![](https://i.imgur.com/4EPPle5.png) + **P2SH(Pay to Script Hash)** + 形式 + **P2PK** + **P2PKH** + **多重簽名** + **inputScript** + **PUSHDATA(Sig)** + **PUSHDATA(serialized redeemScript)** + **outputScript** + **HASH160** + **PUSHDATA(redeemScriptHash)** + **EQUAL** + 腳本執行步驟 + **Step1.** + 驗證 **serialized redeemScript** 是否和 **output script** 中的 Hash 值匹配 + **Step2.** + **Deserialization(反序列化) redeemScript 並執行 redeemScript**,驗證 input script 中給出的 Sig 是否正確 + 腳本執行 + **redeemScript** + **PUSHDATA(PubKey)** + **Step7** + 把 PubKey 押入 + ![](https://i.imgur.com/RykUj7F.png) + **CHECKSIG** + **Step8** + 最後用 CHECKSIG 驗證公私鑰 + ![](https://i.imgur.com/hXxYv8F.png) + **inputScript** + **PUSHDATA(Sig)** + **Step1** + 首先把 Sig 押入 + ![](https://i.imgur.com/v9wofKF.png) + **PUSHDATA(serialized redeemScript)** + **Step2** + 接著把 RS 押入 + ![](https://i.imgur.com/8Klmzd9.png) + **Step6** + 反序列化 redeemScript + **outputScript** + **HASH 160** + **Step3** + 得到 RS 的 Hash + ![](https://i.imgur.com/CVhokDh.png) + **PUSHDATA(redeemScriptHash)** + **Step4** + 把 RSH 押入 + ![](https://i.imgur.com/sxi0Ex4.png) + **EQUAL** + **Step5** + 比較兩個 Hash 是否正確 + ![](https://i.imgur.com/EDcX5zp.png) + **一般的多重簽名實例** + Ex : 5 個合夥人,要求 3 個簽名才能取出錢 + **inputScript** + **X** + **CHECKMULTISIG** : 執行時會產生 BUG,會多取出上面的一個元素,因此多塞一個空值來保證順利執行,因為區塊鏈是去中心化的系統,目前已經無法更改了 + **PUSHDATA(Sig_1)** + **PUSHDATA(Sig_2)** + **PUSHDATA(Sig_3)** + **...** + **PUSHDATA(Sig_M)** + **outputScript** + **M** + **PUSHDATA(PubKey_1)** + **PUSHDATA(PubKey_2)** + **...** + **PUSHDATA(PubKey_N)** + **N** + **CHECKMULTISIG** + 多重簽名腳本執行 + **X** + 首先將 FALSE 押入 + ![](https://i.imgur.com/CxPkpUW.png) + **PUSAHDATA(Sig_1)** + **PUSAHDATA(Sig_2)** + 一次押入全部 Sig + ![](https://i.imgur.com/6NMb6fC.png) + **M** + 押入 N + ![](https://i.imgur.com/gQ2A6Xm.png) + **PUSHDATA(PubKey_1)** + **PUSHDATA(PubKey_2)** + **PUSHDATA(PubKey_3)** + 一次押入全部 Pubkey + ![](https://i.imgur.com/TVNJYvk.png) + **N** + 把 N 押入 + ![](https://i.imgur.com/jU3zLoA.png) + **CHECKMULTISIG** + 檢查 Sig 和 PubKey 的數量是否和 N,M 給定的一樣,並檢查 Sig 的數量是否如同給定的 N 值一樣,含有 N 把 PubKey 中的 M 把 Sig + ![](https://i.imgur.com/r1yhhyx.png) + **P2KH** 完成多重簽名實例 + 把複雜度轉移至 **inputScript(由收款人提供)** + **inputScript** + **X** + **PUSHDATA(Sig_1)** + **PUSHDATA(Sig_2)** + **...** + **PUSHDATA(Sig_M)** + **outputScript** + **HASH160** + **PUSHDATA(redeemScriptHash)** + **EQUAL** + **redeemScript** + **M** + **PUSHDATA(PubKey_1)** + **PUSHDATA(PubKey_2)** + **...** + **PUSHDATA(PubKey_N)** + **N** + **CHECKMUTLISIG** + 腳本執行 + **FALSE** + 押入 FASLE + ![](https://i.imgur.com/fxBiW78.png) + **PUSHDATA(Sig_1)** + **PUSHDATA(Sig_2)** + 一次押入兩個 Sig + ![](https://i.imgur.com/3VUO68T.png) + **PUSHDATA(seriRS)** + 押入 seriRS + ![](https://i.imgur.com/69rqC7u.png) + **HASH160** + 把 seriRS 取 Hash + ![](https://i.imgur.com/RuUyKc7.png) + **PUSHDATA(RSH)** + 把 RSH 也押入 + ![](https://i.imgur.com/rY8oyuL.png) + **EQUAL** + 判斷兩個 Hash 是否相等 + ![](https://i.imgur.com/MHx3lLG.png) + **M** + 押入 M + ![](https://i.imgur.com/andkbo2.png) + **PUSHDATA(PubKey_1)** + **PUSHDATA(PubKey_2)** + **PUSHDATA(PubKey_3)** + 一次押入全部 PubKey + ![](https://i.imgur.com/wyJRhhV.png) + **N** + 把 N 押入 + ![](https://i.imgur.com/Klzsw5o.png) + **CHECKMUTLISIG** + 檢查正確性 + ![](https://i.imgur.com/nbi91g8.png) + **Proof of Burn** + 銷毀 BTC 的方法 + **使用時機** + 由於區塊鏈的無法修改,有些人會利用此特性往裡面寫入內容,例如智慧財產權,將其內容取 Hash 放入 RETURN 內,往後有糾紛就拿出來看 + **AlternativeCoin (AltCoin)** + 有些小幣會要求你銷毀一定 BTC 才能獲得他 + 由於區塊鏈無法修改,有人會利用此特性往裡面增加一堆內容, + **outputScript** + **RETURN** + 看到就不需要將其加入 UTXO + RETURN 將會無條件返回 FALSE,因此腳本內內容隨便塞或是留空 + **...任意內容...** + [Example1](https://www.blockchain.com/btc/tx/090a9343da1158dce3634076f3df0ff868ea777c97b3b2cf6f3d85ca7ea1f7b2) + [Example2](https://www.blockchain.com/btc/tx/1a2e22a717d626fc5db363582007c46924ae6b28319f07cb1b907776bd8293fc) ## BTC 的分岔 + **分岔(fork**) + **一條鏈產生了分岔** + 分岔攻擊 **(forking attack)or(deliberate fork)** + 同時挖到礦的臨時分岔 **(State fork)** + 協議發生了改變 **(protocal fork)** + 升級協議時不能保證所以節點都升級了他使用的協議 + **硬分岔 (hard fork : 由協議改變產生的分岔)** + **除非所有系統都更新,否則分岔將永久存在** + **BTC 新增/改變了某項功能,但其他節點不承認** + Ex : **Block size limit** + **一個區塊約只能接受 4000 個交易,每秒鐘只能接受約 7 筆交易** + **彈性非常低** + 只要舊節點不更新,其產生的分岔將會永久存在 + **彼此分岔開來所取得的 Block reward 將可以繼續使用在原先的鏈** + ![](https://i.imgur.com/3HGKAnR.png) + **在未分岔前挖到的幣,上下都能使用,所以可能會導致非常多的錯誤** + 之後只要產生分岔,會在鏈上加上一個 **Chain_ID** + 實例 : **(BTC, BCC)** **(ETC, ETH)** + **軟分岔 (soft fork)** + **只要半數以上算力更新了系統,那分岔就會消失** + 如果對協議加上更多的限制,原來合法的區塊可能會變成非法的 + Ex(不太可能發生) : **Block size limit 縮小** : 1M -> 0.5M + ![](https://i.imgur.com/eR6z30e.png) + 原節點承認小區塊,但小區塊不承認大區塊 + **舊節點也承認小區塊,因此他會放棄原區塊,而改到小區塊去挖(最長合法鏈)** + ![](https://i.imgur.com/Gm60bcY.png) + **舊節點若還是沒更新協議,可能又會挖到大區塊,又白挖了** + 實際可能產生 **Soft fork** 的情況 : 對某個域新增一些規則,如 **CoinbaseTx** 規定後面沒用到的字節放入 UTXO 集合的 Hash 值 + 再製作一棵 UTXO Merkle tree,因為要確認 UTXO 的內容很困難,正確性也無從得知 + coinbase 一旦更改,Merkle root hash 也會更改,這樣就能用 Merkle proof 證明出 UTXO 的結果 + 此為軟分岔 **(Soft fork)** + 舊節點覺得 coinbase 裡寫甚麼都沒差,但新節點有差 + 實際出現過的例子 : **P2SH** 就是依靠 **Soft fork** 加入 BTC 系統的 ## BTC 問答 + **1.** 若轉帳時收款人不在線能順利轉帳嗎 ? > 可以,因為轉帳只需要將記錄寫入區塊鏈。 + **2.** 全節點在接收收款交易時有沒有可能收到一個從未出現過的地址 > 可能,因為 BTC 創建帳戶不需要通知其他人,使用過該帳戶後其他節點才會知道這個帳戶的存在。 + **3.** 如果私鑰 **(Private Key)** 遺失了該怎麼辦 > 完全沒辦法,帳戶裡的錢取不出來了 **Q**A**Q**。 + **4.** 私鑰 **(Private Key)** 洩漏了怎麼辦 > 盡快把錢轉到另一個帳戶裡。 + **5.** 轉帳時寫錯地址怎麼辦 > 沒有辦法取消交易,只能聯繫對方能否還錢,不認識對方或地址是空的就 **GG**,也是銷毀 BTC 的一種方式,可以換取向全節點寫入 Hash 的機會。 + **6.** RETURN 無條件返回錯誤,該怎麼寫入 Block chain 裡面 > **由於 BTC 驗證交易時是把當前交易的輸入腳本和幣的來源的輸出腳本拼接做驗證, RETURN 是把動作寫入當前交易的輸入腳本,因此可以被記錄。** + **7.** 挖礦的 nonce 的答案有沒有可能被偷取 > 發布的區塊裡有收款人地址,因此 nonce 要是被偷取,收款人地址也必須要更改,但整體的 Merkle root hash 會發生改變,這樣 nonce 即作廢。 + **8.** 要怎麼知道交易費要給哪個礦工 > 不需要知道,因為total inputs - total outputs = Tx fee,先找到礦的礦工就可以收集這些交易費。 ## BTC 的匿名性(anonymity) + **帳戶 : 都是用 Key Pair 所以有一定的匿名性,或被稱為化名 (pseudonymity)** + 跟法幣相比,其匿名性並沒有比法幣要好 + 如果銀行不是實名制的話匿名性比 BTC 要更好 + 因為區塊鍊是公開的 + 即使是用公私鑰對作為帳戶的 BTC 其實也是有些細節能找出哪個地址是哪個使用者的 + ![](https://i.imgur.com/XbtA138.png) + 譬如上圖是某一筆買賣,addr1,addr2 就很有可能是同一個人的輸入,要是 addr1 的餘額不足就需要 addr2 的金額來補齊 + 或是有些 BTC 錢包會自動生成新的帳戶給用戶找零,這些都可以從交易腳本,輸入輸出的差額去推斷 + **增強匿名性的方法 : 每次交易都生成一堆假帳戶去混淆他人,但目前沒什麼軟體會這麼做** + **大筆的資金流動也很容易被找到真實身分** + BTC 曾被用於洗錢 + **解決方法 : 精確的盯住每筆 BTC 上的 Tx** + **要是現實世界使用 BTC 支付時,帳戶也很容易和使用者產生聯繫** + 匿名性保持得最好的 BTC 大戶 + **中本聰(Satoshi Nakamoto)** + 因為他的帳戶根本沒有使用過 + 要是他把帳戶裡的 BTC 拿去使用就一定會和真實世界發生聯繫,進而暴露自己的身分,也因此到目前為止都沒辦法確定中本聰的真實身分 + **某些暗網使用的交易手段就是 BTC** + **silk road** + 賺來的 BTC 幾乎都不敢花,原因正是因為會被抓到身分 + **hide your identity from whom ?** + 只是為了不讓身邊的人知道自己的身分這是辦的到的 + **BTC 改良匿名性的方法** + **applicition layer** + **coin mixing** + 把幣交給某個組織做 random 的組合或操作,最後再把幣取回,目的在打亂幣的來源 + 目前沒有高信譽的 coin mixing 服務 + 因為 coin mixing 的組織也是保持匿名的 + **network layer** + **多路徑轉發**(Extra) + **BTC 的匿名性為甚麼難保持 : 因為 Block chain 是公開的** + **Zero knowledge proof** + **證明者向另一方證明某項知識是正確的,但除了提供"該訊息是正確的"以外甚麼都不用提供** + 數學基礎 : 同態隱藏 **(Homomorphic Hidings)** + 如果 x,y 不同,那麼他們的加密數值 E(x) 和 E(y) 也不同 + 給定 E(x),非常難推出 x ,類似 **hiding property** + 給定 E(x),E(y) 可以很容易地算出和 x y 相關的加密數值 + 同態加法 : 對 E(x) 和 E(y) 能夠計算出 E(x+y) + 同態乘法 : 對 E(x) 和 E(y) 能夠計算出 E(xy) + **具體例子 : A 要向 B 證明他知道一組數字(x, y),x + y = 7 ,同時不讓 B 知道 (x, y) 的具體數值** + A 把 E(x) E(y) 發給 B , B 用 E(x) E(y) 算出 E(x+y),同時計算出 E(7) 如果 E(x+y) = E(7) 則驗證通過 + **盲簽名** + 用戶 A 提供一組 **(Serial Num)** 編號 ,銀行在不知道編號的情況下簽名 + A 把 編號和簽名拿去給 B 完成交易 + B 拿編號和簽名去給銀行驗證交易 + 銀行無法將 A B 連結起來 + **Zerocoin and Zerocash**(Extra) + **在設計上就使用了密碼學的原理保證了匿名性** + **Zerocoin : 用以存在的基礎幣(Ex : BTC)換取 Zerocoin** + **使用 Zero knowledge proof 證明你花掉的幣式系統中存在的某一個合法的幣就行了,不用透露你花的是哪一個幣** + **Zerocash : 使用 zk-SNARKs 協議,不依賴任何一種基礎幣,區塊鏈中只記錄交易的存在性和礦工用來驗證系統運行所需要的訊息,區塊鏈上既不顯示地址也不顯示金額,所有交易通過 zero knowledge proof 進行** + 目前都不是主流,因為需要匿名性的人本來就少,而且實體交付時還是會暴露自己的身分 ## BTC 總結&思考 + **Hash pointer 只有 hash 沒有 pointer** + Full node 一般將資料存於 **(Key, value) 數據庫** + Ex Level DB + 區塊戀 + 截斷私鑰作為共同擁有帳戶的象徵 : 愚蠢 + **BTC 私鑰為 2^256 位數,但截斷後僅剩 2^128, 2^256 >> 2^128 , 因此安全性很低** + 採取 **(MULTISIG)** 多重簽名的方式安全一些 + **分布式共識** + 如何證明非常遠的某個實驗室裡的伺服器死機了 + 不可能證明得出來,異步的環境中絕對不可能分辨得出來 + **BTC 的稀缺性** + BTC 總量固定,其實並不適合做為貨幣 + **量子計算** + 若是量子計算發展起來 BTC 還有安全性嗎 ? + 其實量子計算要真的能使用還要好幾年,BTC 的生命週期都不一定能碰到量子計算 + 量子計算首當其衝的應該是傳統金融業,不該擔心 BTC + 從安全性來看, BTC 使用完後的地址就不再次使用了,應該一次用完所有的錢,如此一來即使是量子計算都不一定能偷出你的錢 + **Hash 的運算過程是會丟失訊息的**