Introduction


2.相關研究

iota:->主打scalability的分散式帳本(略)

ethereum:->有著智能合約的分散式帳本平台(略)

babble:

因為設計的目標是想盡可能的減少對於evm的更改,並且讓ethereum現有支援盡可能的可以support(如web3,solc之類的),所以除了研究ethereum smartcontract本身之外,我們還研究了babble的專案,babble是一個基於hash graph共識的拜占庭容錯系統,它提供了一個模組話的情境,去除掉ethereum有關於pow共識的部份改為使用hash graph來達成共識,它的共識保證了全部的節點會以一樣的順序處理相同的交易(透過hashgraph).
以下為其架構圖:


                =============================================
============    =  ===============         ===============  =
=          =    =  = Service     =         = State App   =  =
=  Client  <-----> =             = <------ =             =  =
=          =    =  = -API        =         = -EVM        =  =
============    =  = -Keystore   =         = -Trie       =  =
                =  =             =         = -Database   =  =
                =  ===============         ===============  =
                =         |                       |         =
                =  =======================================  =
                =  = Babble Proxy                        =  =
                =  =                                     =  =
                =  =======================================  =
                =         |                       ^         =
                ==========|=======================|==========
                          |Txs                    |Blocks
                ==========|=======================|==========
                = Babble  v                       |         =
                =                                           =
                =                   ^                       =
                ====================|========================
                                    |
                                    |
                                    v
                                Consensus


動機

我們想解決的是在於物連網上的邏輯運算和微型支付會遇上的問題

我們知道iot可以收集資料,可以有簡單的邏輯運算
但是沒辦法追蹤資料的走向,來源,(可以中央式的解決這個問題),買賣資料(手續費成本的問題).

  • 首先,微型支付手續費必須低,如果手續費高過資料本身的價值這就沒意義了,所以我們選則在iota的平台上來實作,零手續費的分散式帳本
  • 第二人力成本,中心化程度如果我們要實作買賣iot裝置資料買賣的平台,以充電站為例子,充電站即是一個簡單的iot裝置,他收集了使用者何時觸發,充了多少電等資料,但是管理整個充電站系統仍然要一定的人力中心化的管理,電價隨時段調整,付費上的管理等
    智能合約提供了我們一個更大的空間,首先邏輯運算移到了鏈上,提供了更好的安全性,支付上的管理也可以簡化為一個合約,更可以提供其他的邏輯,透過合約改變電價等
    可以以solck.it在ethereum平台上做的充電站為例子
    • slock.it的使用合約充電站的案例

綜合以上兩點,我們希望能讓iot裝置處理支付時手續費低廉,又希望能提供一定的邏輯運算因此我們決定
採用tangle帳本上零手續費的特性,和選擇現階段比較成熟的ethereum smart contract為我們研究的目標


IOTA transaction order

  • 我們要解決的就是iota順序問題,對於合約,交易的順序是最為重要的合約的指令順序都是基於此,但是在iota的架構上,現階段並不強調交易的順序.

    • Come-from-Beyond曾經描述過:"It's worth emphasizing that in IOTA we don't care about the order of transactions. For ledger validation we can traverse the transactions in any order. This boosts performance and helps to scale to much higher TPS than a ledger with ordering would allow."
    • 所以我們得訂出一個方法,讓全部的節點可以共識著一組順序.

交易順序

上一個章結題到iota本身並不在意交易的先後順序,但是我們要提供出一個方法可以讓各個節點之間共識一組順序,在開始介紹我們的架構之前,需要了解iota的milestone是如何運作的.
相關研究:iota的timestamp->無法使用在這邊

milestone

iota現階段為了保護網路的健康狀態(ledger revert),使用了milestone來幫助帳本的finality,透過全部的節點紀錄著coordinator(hosted by iota fundation)的address(ISS+merkle root signature),持續追綜該地址所發出來的交易,此交易稱為milestone,節點們以milestone直接或者間接reference到的交易為帳本finality的基準.
節點間同步milestone的問題,每個節點都會記載著兩個變數lastmilestone_index和last_sub_tangle_milestone_index,分別代表著該節點最近接到最新的milestone,跟節點除了有這筆milestone之外還有他直接或間接reference到的交易,當這節點兩個數值不同時,便會開始同步(跟鄰居request他所欠缺的交易),讓last_sub_tangle_milestone_index追上lastmilestone_index.這是一個重構帳本的動作

algorith

我們的目的是讓節點們可以透過milestone算出一組順序,因為milestone是大家有共識的東西,所以這組順序也是有共識的.
1.首先在我們這個研究裡,coordinator是由我們所控制的,我們必須定義好coordinator在執行mcmc(markov chain monte carlo iota用來挑選驗證tip的演算法)時的起點必須是上一個index的milestone.並且必須是設在其trunktransaction的位置.
2.接下來看到節點同步的部分,當節點開始同步時,透過我們的算法,我們就可以訂出last_sub_tangle_milestone_index和lastmilestone_index之間的交易.
3.我們先沿著milestone的trunktransaction(優先)建立出樹的左子樹,其他的branchtransaction放在右子樹,接下來在透過dfs來經歷這棵樹,我們就可以得到一組順序,這邊有考慮到一個情境,就是每個節點的同步index並不一定,下面舉個例子來說明.

下圖是模擬出來的tangle網路狀況,綠色的交易是milestone,其他的為普通交易,我們假設交易0的milestone index是0,交易4的index是1,交易8的index是2,因為網路的狀況不穩定,可能會掉包,導致以下的情境,nodeA跟nodeB的last_sub_tangle_milestone_index都是index0,因為網路的關係,nodeA先接到index1,nodeB先接到index2,在這個情況下他們算出來的順序交集的部分必須是一樣,這個例子的交集就是(0,1,4)三筆交易,就是因為這個需求我們才制定了第二點關於coordinator的行為,因為milestone交易都是coordinator發出的,他本身並不存在掉包的問題,所以我們沿著trunktransaction一定能走回上一個index的milestone,所以即使節點們在同步時並沒有照著順序我們也可以保證結果的正確性.

  • nodeA:order:0-1-4
    Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →
  • nodeB:order:0-1-4-3-6-2-5-8
    Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →

iota address

  • iota address的問題,因為iota使用winternitz one-time signature的簽章,地址如果過於頻繁的重複使用會有洩漏私鑰的可能,但是對於合約一比交易從哪個account發出的是很重要的事情(iota的交易封包裡面,無法辨別出這個封包是從哪個seed(帳戶)所發出的).

iota地址問題

iota的地址因為不能重用,所以很難紀錄著一個身份,所以我們設計了一個可以給地址另一個別名的系統架構,來達到我們的目的.

提供alias

這個概念就是在iota的地址上面附加上一個可以辨別身份的別名:
1.首先這個別名在iota的系統上必須是獨一無二的,在系統裡不該有重複的別名.
2.這個別名要跟seed或address沒有關係.別名不能是seed或者address做任何運算的產物,因為都會有洩漏私鑰的風險
3.不能透過第三方來處理,我們不會希望在加入一個centralized的機制在我們的架構裡
所以我們是透過交易來附加別名上去的,每個節點在db會有新的欄位來儲存相關資訊,為了第一點交易必須有明確的順序(才可以辨別出誰先提出申請的),可以透過我們上面提到的方法來取得交易順序.

講一下iota state 不同步的問題

各節點執行完合約之後會有一vm state,如何保證vm state的finality會是一個問題


要跟別人比對自己執行完的hash很困難

iota的節點狀態,沒有辦法跟其他大多數的節點溝通

為了速度才這樣設計的,是他的優勢,允許subtangle的存在
在這個架構裡面,各節點的block大小是不一致的,取決於他收到哪個milestone和同步到哪個milestone

要如何保證我們的執行結果是對的
輸入evm的tx是被iota的consensus保證的

我們是一個非同步的網路,因此節點並不會看到一樣的交易集合
但是透過milestone各節點承認的交易集合是唯一的
問題在於根據這些交易為輸入,節點執行完的合約狀態是否要比較

先討論會在同樣的輸入同樣的環境之下合約執行狀態會不一致的情況,
惡意節點,改變了合約狀態,但是他無法說服正常節點跟他一樣就沒意義
自己的節點出錯,確保evm真的是沙盒,這部分不討論


規定coordinator的行為,發初milestone時必須附上執行到該輪的vmstate hash
其他node接收到milestone時會去跟這個結果做比對
分兩種情形做討論
一致
不一致

雖然會有太依賴coo的問題,但是現在的系統是會work的,其他潛在風險不在這邊討論


  • 該如合跟evm嫁接溝通,系統架構設計,基於合約執行可能會產生internal transaction,該如合對應到iota的帳本.

流程

  • 註冊alias:發一筆交易到要註冊的地址,並附加上別名,要記錄下該地址對應自己私鑰的位置,以便後面要製作簽名時使用
  • 轉移alias:要轉移的地址,然後從full node紀錄的地址發出附上簽章來表明對該別名的擁有權
  • 使用alias:要在交易裡面附上該地址的簽章來表明別名的擁有權

系統架構

在節點同步的過程中我們會得到交易的順序,把跟contract有關的交易挑出來打包成區塊,再丟進去evm,詳細的架構圖如下:

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

流程說明

  • client透過full node發起交易,當full node接到milestone時,會給transaction排出一組順序
  • package block,挑出跟contract有關的transaction,包成以太坊的區塊,送入ethereum執行
  • 在package bolck之前需要先同步ethereum state的帳本,go-ethereum在這裡辦演的只是提供執行合約的環境,沒辦法跟外部溝通,所以在使用前要先將帳本狀態跟外部同步,ethereum裡面的地址對應到的是上面提到的alias,需要確保alias裡面的balance足夠負擔gas的消耗,和transfer的value,因此帳本的狀態並不需要跟外界的真實狀況一樣,只要能提出有足夠負擔gas跟transfer value的證明即可,一搬來說msg call的tx所轉出的錢就可以證明這一點
  • evm執行完後如果有internal transaction的產生,會再把他包裝成iota的transaction格式送回iri紀錄,透過設定snapshot index讓該筆transaction直接confirm

evm更改部分

保留ethereum大部分的原行,抽換掉了原本依靠pow出塊的部分,根據iota的milestone來給予區塊,ethereum角色為執行合約的環境,所以裡面的帳本狀態跟iota不會一致

問題討論

  • iota好的節點只要做好自己的事,就能得到跟大家有共識的結果,壞的節點沒辦法說服好的節點,所以合約的結果並不需要比較,這是跟ethereum本質上的不同

  • ethereum internal transaction的分析方式,有可以透過分析process block之後的狀態來訂出來,比較直接的方式是在evm裡面加入紀錄點,監控以下幾個op code來構建internal transaction
    CREATE
    CALL
    CALLCODE
    DELAGATECALL
    SUICIDE

5.實驗評估

demo:

pragma solidity ^0.4.11; contract CrowdFunding { // Defines a new type with two fields. struct Funder { address addr; uint amount; } struct Campaign { address beneficiary; uint fundingGoal; uint numFunders; uint amount; } Campaign campaign; event NewContribution( address beneficiary, address funder, uint amount ); event Settlement( bool ok ); function CrowdFunding(uint goal) { // Creates new struct and saves in storage. campaign = Campaign({ beneficiary: msg.sender, fundingGoal: goal, numFunders: 0, amount:0}); } function contribute() payable { campaign.amount += msg.value; NewContribution(campaign.beneficiary, msg.sender, msg.value); } function checkGoalReached() constant returns (bool reached, address beneficiary, uint goal, uint amount) { if (campaign.amount < campaign.fundingGoal) return (false, campaign.beneficiary, campaign.fundingGoal , campaign.amount); else return (true, campaign.beneficiary, campaign.fundingGoal , campaign.amount); } function settle() { if (campaign.amount >= campaign.fundingGoal) { uint am = campaign.amount; campaign.amount = 0; campaign.beneficiary.transfer(am); Settlement(true); } else { Settlement(false); } } }

部屬合約
1.deploy contract for 100000wei

{"from":"0xdfbecb1949f0ae50dd542f1b6185af48c831ddad",
"gas":1000000,
"gasPrice":0,
"data":"0x608060405234801561001057600080fd5b5060405160208061031983398101604081815291516080820183523380835260208301829052600093830184905260609092018390528254600160a060020a031916909117825560015560028190556003556102a8806100716000396000f3006080604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166301cb3b20811461005b57806311da60b4146100ad578063d7bb99ba146100c4575b600080fd5b34801561006757600080fd5b506100706100cc565b60408051941515855273ffffffffffffffffffffffffffffffffffffffff9093166020850152838301919091526060830152519081900360800190f35b3480156100b957600080fd5b506100c2610143565b005b6100c2610215565b60008060008060006001015460006003015410156101135750506000805460015460035492945073ffffffffffffffffffffffffffffffffffffffff90911692509061013d565b50506000546001805460035491945073ffffffffffffffffffffffffffffffffffffffff90921692505b90919293565b600154600354600091116101dd5750600380546000918290558154604051919273ffffffffffffffffffffffffffffffffffffffff9091169183156108fc0291849190818181858888f193505050501580156101a3573d6000803e3d6000fd5b50604080516001815290517f09af12d5b97e0b3db4b2467182ec45bb12cae9cf8942cf8cf4a34b0fbb2cb3789181900360200190a1610212565b604080516000815290517f09af12d5b97e0b3db4b2467182ec45bb12cae9cf8942cf8cf4a34b0fbb2cb3789181900360200190a15b50565b60038054349081019091556000546040805173ffffffffffffffffffffffffffffffffffffffff90921682523360208301528181019290925290517f567b97209529fbb11a50c435abb5bfdae05a969880bb35a24afc52d1f383af809181900360600190a15600a165627a7a7230582081ff803b8ddec6489cbef1a4ebbadf90535c51143736b3cb3199ef7b8794b64200290000000000000000000000000000000000000000000000000000000000000001"}

觸發合約

2.Contribute 499 wei from

Sending Contract-Method Tx: {"from":"0xaa5a69fa1ff5c282ca808f145941c2da90c39525",
"to":"0xaa5a69fa1ff5c282ca808f145941c2da90c39515",
"gas":1000000,"gasPrice":0,
"value":1,
"data":"0xd7bb99ba"}

3.檢查結果

Calling Contract Method: {"from":"0x97e1838cbBc449206bFEef90755c5b0bF5A0f735",
"value":0,
"to":"0x850652c56c498386dbfcd05f1a53d5cf62b3e3fb",
"data":"0x01cb3b20"}

curl -H "Content-Type:application/json" -X POST http://127.0.0.1:8080/call -d '{"from":"0xea95c7dce6c1362ccbdd959077fb60e17282b117","value":0,"to":"0xaa5a69fa1ff5c282ca808f145941c2da90c39526","data":"0x01cb3b20"}'

取錢

Sending Contract-Method Tx: {"from":"0xdfbecb1949f0ae50dd542f1b6185af48c831ddad",
"to":"0xaa5a69fa1ff5c282ca808f145941c2da90c39515",
"gaz":1000000,
"gazPrice":0,
"value":0,
"data":"0x11da60b4"}

6.問題討論,future work

當以後iota的網路沒有coodinator之後,
可以留著當作輔助這套系統運作的基準
如何產生internal transaction
為何不需要比對
講一下snapshotindex的事情


更動作業紀錄

  1. 提案設計考量這章應該還有更多議題,像是出塊的行為、EVM 有哪些特徵要採用,哪些又將被捨棄等

關於EVM保留的行為
關於contract creation:
因為創造合約地址的交易是iota共識時就已定下來
所以使用一個新的boolean值來表明contractcreation的意願


Created with Raphaël 2.2.0UUAACCmapping alias on addresssend create contract tx Xprepare milestonemilestone reference the Xget transaction orderexcute contract bytecodefill state hash into milestonereceive milestonesync ledgerget transaction orderexcute contract bytecodecompare state hash with milestone

note


{  
"hash":"not important", 
"signatureMessageFragment":
"{“method”:”contractcreation”,”gas”:”10000”,”alias”:”u”,”data”:”bytecode”}", 
"address":"contract_address",
"value":0,
"tag":"999999999999999999999999999",
"timestamp":1482522289,
"currentIndex":0,
"lastIndex":4, 
"bundle":"ABCD…",
}

{  
"hash":"not important", 
"signatureMessageFragment":"99999….(it mean empty)", 
"address":"reward_address",
"value":10000,
"tag":"999999999999999999999999999",
"timestamp":1482522289,
"currentIndex":1,
"lastIndex":4, 
"bundle":"ABCD…",
}
{  
"hash":"not important",
"signatureMessageFragment":"signature for index1 partA", 
"address":"index1",
"value":-20000,
"tag":"999999999999999999999999999",
"timestamp":1482522289,
"currentIndex":2,
"lastIndex":4, 
"bundle":"ABCD…",
}
{  
"hash":"not important",
"signatureMessageFragment":"signature for index1 partB", 
"address":"index1",
"value":0,
"tag":"999999999999999999999999999",
"timestamp":1482522289,
"currentIndex":3,
"lastIndex":4, 
"bundle":"ABCD…",
}

{  
"hash":"not important",
"signatureMessageFragment":"99999….(it mean empty)", 
"address":"unspent address",
"value":0,
"tag":"999999999999999999999999999",
"timestamp":1482522289,
"currentIndex":4,
"lastIndex":4, 
"bundle":"ABCD…",
}

{  
"hash":"not important",  "signatureMessageFragment":"{“method”:”invokecontract”,”gas”:”1000”,”alias”:”u”,”data”:”method_hash”}", 
"address":"contract_address",
"value":0,
"tag":"999999999999999999999999999",
"timestamp":1482522289,
"currentIndex":0,
"lastIndex":3, 
"bundle":"BCDE…",
}

{  
"hash":"not important",
"signatureMessageFragment":"99999….(it mean empty)", 
"address":"reward_address",
"value":1000,
"tag":"999999999999999999999999999",
"timestamp":1482522289,
"currentIndex":1,
"lastIndex":3, 
"bundle":"BCDE…",
}

{  
"hash":"not important",
"signatureMessageFragment":"signature for index1 partA", 
"address":"index1",
"value":-1000,
"tag":"999999999999999999999999999",
"timestamp":1482522289,
"currentIndex":2,
"lastIndex":3, 
"bundle":"BCDE…",
}

{  
"hash":"not important",
"signatureMessageFragment":"signature for index1 partB", 
"address":"index1",
"value":0,
"tag":"999999999999999999999999999",
"timestamp":1482522289,
"currentIndex":3,
"lastIndex":3, 
"bundle":"BCDE…",
}

{  
"hash":"not important",
"signatureMessageFragment":"99999….(it mean empty)", 
"address":"index1",
"value":1000,
"tag":"999999999999999999999999999",
"timestamp":1482522289,
"currentIndex":0,
"lastIndex":1, 
"bundle":"CDEF…",
}

{  
"hash":"not important",
"signatureMessageFragment":"99999….(it mean empty)", 
"address":"contract_address",
"value":-1000,
"tag":"999999999999999999999999999",
"timestamp":1482522289,
"currentIndex":1,
"lastIndex":1, 
"bundle":"CDEF…",
}

doi:10.6342/NTU201802130