分散式帳本與衝突交易
===
先說說什麼是帳本
帳本就是用來紀錄收入與支出用的
所以上面會有消費的明細
例如今天去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`