分散式帳本與衝突交易 === 先說說什麼是帳本 帳本就是用來紀錄收入與支出用的 所以上面會有消費的明細 例如今天去7-11買了個飯糰 那就紀錄成: :::success 我 給 7-11 飯糰的價格 ::: 當然也有可能是父母匯款 , 那就紀錄成 :::success 父母 給 我 xxxx元 ::: 這邊在分散式帳本 上面的: 我 , 父母 , 7-11 就是address 基本上 , 帳本就是這樣的東西 , 包含收款人 , 付款人 , 轉移的金額 # 帳本的計算 假設帳本如下 :::success * 我   有 1000 * 父母  有 20000 * 7-11  有 0 * 我  給 7-11   600 * 父母 給 我   13000 ::: ``` 我   有 1000 父母  有 20000 7-11  有 0 ``` 這三筆是address的初始資訊 剩下就是交易 所以目前各address的餘額 分別是 我 : $13400$($1000-600+13000$) 相關的交易: :::success * 我   有 1000 * 我  給 7-11   600 * 父母 給 我   13000 ::: 父母 : $7000$($20000-13000$) 相關交易: :::success * 父母  有 20000 * 父母 給 我   13000 ::: 7-11 : $600$($0+600$) 相關交易: :::success * 7-11  有 0 * 我  給 7-11   600 ::: 注意到 , 帳本是有時間順序的 所以每筆交易要有時間的紀錄 , 或有時間上的偏序關係(誰比誰先) # 不合理的帳本 簡單說 , 就是算出來有address , 餘額是負的 , 或有要花錢時 , 錢不夠的情況 例如: :::success * 我 有 10 * 它 有 0 * 我 給 它 6 * 我 給 它 10 ::: 來算餘額 我 : $-6$($10-6-10$) 它 : $16$($0+6+10$) 這樣是錯的 因為在 ``` 我 給 它 10 ``` 就會發現 : 我 的餘額只剩4元 根本不夠錢可以給人10元 那這在單一帳本是不會出現的 每次有新交易進來 , 都會檢查餘額是否正確 但分散式帳本就不一定了 # 帳本之前的紀錄被更改 帳本例子 : :::success * 我 有 10 * 它 有 0 * 我 給 它 6 ::: 這邊 我 , 它 的餘額都是正常的 但是 , 如果有人把第三條 ``` 我 給 它 6 ``` 改成 ``` 我 給 它 60 ``` 那就會變成不合理的帳本 所以分散式帳本 , 要有不可篡改性的理由就是這樣來的 # 衝突交易 帳本例子: :::success * 我 有 10 * 它 有 0 * 我 給 它 6 * 我 給 它 10 ::: 這邊 ``` 我 給 它 6 我 給 它 10 ``` 這兩筆就是衝突的交易 如果兩筆交易都算是合法的 , 算餘額就有address會錯(我 的餘額是負的(-6)) , 所以對帳本的程式來說 , 要選擇兩筆都不接受或接受其中一筆 # IRI的交易格式 [The Anatomy of a Transaction](https://iota.readme.io/docs/the-anatomy-of-a-transaction) 基本上 , 一筆交易只會有一個address與value 解釋為什麼 上面提到的交易紀錄 , 其中一個例子 :::success 我 給 它 6 ::: 這在IRI內稱為 $Bundle$ [Bundles](https://iota.readme.io/docs/bundles) 每個 $Bundle$ 會拆成數個 $Transaction$ 以上面例子為例 , 會拆成 :::success 我 -6 它 6 ::: 這是兩筆交易 :::success 我 -6 ::: 稱為 $Input$ :::success 它 6 ::: 稱為 $Output$ $Input$ 跟 $Outpu$ 可以多個 通常 , 一個 $Bundle$ 的錢不會一次買賣就花光 , 由於address花錢需要簽名 , 而簽名是一次性的 所以一個 $Bundle$ 通常會有兩個 $Output$ 其中一個 $Output$ 是找零的address # IRI address餘額計算 address餘額計算非常簡單 不考慮衝突的話 把所有內含address的交易拿出來 , value直接相加就是餘額了 # IRI衝突交易的可能組合 ## case 1 假設"我"這個address的餘額為10 有兩個 $bundle$ 如下情況 :::success 我 -10 它 10 ::: :::success 我 -10 他 10 ::: 這樣 , "我" 的餘額是負的 所以這兩個bundle衝突 不過IRI花錢需要簽名 , 只能簽一次 按照之前重複簽名事件的處理 , "我"的餘額會被轉移到別的address , 需要基金會的tool或人員才能拿回餘額 # case 2 $bundle$如下 假設一開始"我"的餘額是10 :::success 我   -10 它   6 餘額一 4 他   8 餘額二 2 ::: :::success 它   6 餘額一 4 ::: 與 :::success 他   8 餘額二 2 ::: 這是兩組衝突的交易 目前 $bundle \space hash$的實做 是 $Input$ 與 $Output$ 都有field是hash function的輸入 所以要製造衝突的交易有難度 , 尤其雙花的Output address是任意組合的時候 # IRI衝突交易的實驗 # 0元交易 iota是可以有0元交易的 從算帳的角度看 :::success 0元交易 , node可收也可以不收 , 可以廣播也可以不廣播 ::: 所以可推論出 :::success 攻擊者要篡改帳本 , 很大可能是發0元交易 ::: 道理很簡單 , 要發交易增加權重 , 當然是單位時間內 , 發起交易的數量越多越好 任何的address , 餘額都不是無限多的 , 所以發的交易會有上限 而且任何address最好只花一次 , 多次會有別人偽造交易的問題 , 偽造交易會破壞攻擊者增加權重的意圖 # 分散式帳本 當帳本從單一node變成多node保存相同的交易紀錄與address初始餘額時 狀況就更複雜了 由於多個node都要保存相同的交易紀錄 所以有個規則 :::success 某個node發起新的一筆交易都要廣播給其他帳本接收 , 0元交易可以不用廣播 ::: 那自然 , 在分散式系統 , 就會出現下列狀況 ## 有某些node沒收到交易 ## 接收交易的時間順序錯了 # 有惡意node的分散式帳本 再考慮有惡意 , 來亂的帳本 就更多亂七八糟的情況了 ## address偽造 ## 交易偽造 交易偽造需要靠密碼學的方法來處理 簡單說 , 就是發一筆有值交易需要簽名 而簽名用的私鑰只有擁有相關 $seed$ 的人才有 # ref [The Anatomy of a Transaction](https://iota.readme.io/docs/the-anatomy-of-a-transaction) [IOTA IRI rocksdb data storage structure](https://blog.louie.lu/2017/10/31/iota-iri-rocksdb-data-storage-structure/) ###### tags: `IOTA`