我們現在基本都知道以太坊是一個區塊鏈應用開發平臺,基於以太坊構建的網路和智慧合約語言,我們可以實現各種各樣的與現實世界接近的分散式應用(DApp)。這種基於智慧合約實現去中心化的分散式應用固然是一種創新,但不覺又引發了市場對資訊保安的擔憂。目前透過以太坊區塊瀏覽器很容易就能追溯一個賬號的所有交易情況,以及該賬戶資金情況等,這基本上沒有任何門檻,只要你能上網就能分析一個賬號的資金流向,以及持幣等情況,這對個人來說毫無隱私可言。
SERO:世界上首個支援智慧合約的匿名公鏈
目前門羅幣(Monero),達世幣(DASH)以及大零幣(Zcash)等熱門的匿名區塊鏈技術。雖然都能匿名起到隱私保護的作用,但是它們都不支援智慧合約,無法用來開發DApp。超零協議(SERO)[白皮書]的公鏈,是個支援圖靈完備智慧合約的匿名公鏈,採用零知識證明實現隱私保護技術,並且已經發布beta版本。SERO似乎是隱私保護的一個完美方案,並且可以在其上開發匿名的DAPP。
以太坊上的以太貓程式概述
以太貓應該是以太坊迄今為止最成熟,最成功的Dapp。它在很短的時間內造成了以太坊的交易擁堵。以太貓是按照ERC721開發的,智慧合約程式碼大約兩千行,原始碼在github上有開源,並且也可以在以太坊區塊瀏覽器中找到。
以太貓程式包括了七個主程式:
1、KittyAccessControl,這個合約管理只能由特定角色執行操作的各種地址和約束。這些角色叫CEO, CFO and COO;
2、KittyBase,這個合約定義在整個核心功能中共享的最基本程式碼的地方。這包括我們的主要資料儲存,常量和資料型別,以及用於管理這些資料的內部函式;
3、KittyOwnership,這提供了遵循ERC-721規範草案的基本不可互換令牌交易所需的方法;
4、KittyBreeding,這個檔案包含了將貓一起繁殖所必需的方法,包括跟蹤繁殖提供者,並依靠外部基因組合合約;
5、KittyAuctions,在這裡,有公開的方法來拍賣貓或招標貓或繁殖貓。實際的拍賣功能是在兩個兄弟合約(一個用於買賣,一個用於繁殖)中處理的,而拍賣的建立和投標主要是透過核心合約;
6、KittyMinting,該合約包含用來建立新的gen0貓的功能;
7、KittyCore,這是主要的CryptoKitties合約,編譯和執行在以太坊區塊鏈上。這份合約把所有東西聯絡在一起。
匿名版以太貓實現
按照SERO的DApp程式設計規範,可以實現一款匿名版以太貓的DApp。目前SERO支援"發行匿名票據"的功能已經發布,這個功能對應的就是以太坊ERC721協議,是實現以太貓的基礎。
票據(Ticket)相關介面定義
SERO團隊部署了一個Remix-ide的站點,其中有一個名為SeroInterface.sol的例子,主要是提供釋出匿名token和ticket的介面,這些應該是系統介面,只要是想實行匿名就必須繼承的。根據SERO團隊提供的例子,在生成、轉移Ticket的介面中必須包含系統定義好的日誌Topic
/** * the follow topics is system topics,can not be changed at will */ bytes32 private topic_sero_send = 0x868bd6629e7c2e3d2ccf7b9968fad79b448e7a2bfb3ee20ed1acbc695c3c8b23; bytes32 private topic_sero_allotTicket = 0xa6a366f1a72e1aef5d8d52ee240a476f619d15be7bc62d3df37496025b83459f; bytes32 private topic_sero_category = 0xf1964f6690a0536daa42e5c575091297d2479edcc96f721ad85b95358644d276; bytes32 private topic_sero_ticket = 0x9ab0d7c07029f006485cf3468ce7811aa8743b5a108599f6bec9367c50ac6aad; |
/** * @dev generate a tickeId and allot to the receiver address * @param _receiver receiving address of tickeId * @param _value the seq of tickeId,can be zero. if zero the system ,the system randomly generates * @param _category the category of the ticket */ function sero_allotTicket(address _receiver, bytes32 _value, string memory _category) internal returns (bytes32 ticket){ bytes memory temp = new bytes(96); assembly { let start := temp mstore(start, _value) mstore(add(start, 0x20), _receiver) mstore(add(start, 0x40), _category) log1(start, 0x60, sload(topic_sero_allotTicket_slot)) ticket := mload(add(start, 0x40)) } return; } |
2.獲取交易引數中的category
/** * @dev the get category from the tx params */ function sero_msg_category() internal returns (string) { bytes memory tmp = new bytes(32); bytes32 b32; assembly { log1(tmp, 0x20, sload(topic_sero_category_slot)) b32 := mload(tmp) } return bytes32ToString(b32); } |
/** * @dev the get ticketId from the tx params */ function sero_msg_ticket() internal returns (bytes32 value) { bytes memory tmp = new bytes(32); assembly { log1(tmp, 0x20, sload(topic_sero_ticket_slot)) value := mload(tmp) } return; } |
4.將交易中的ticketId存入到接收方的個人賬號
/** * @dev transfer the tickeId to the receiver * @param _receiver the address of receiver * @param _category the category of ticket * @param _ticket the tickeId */ function sero_send_ticket(address _receiver, string memory _category, bytes32 _ticket)internal returns (bool success){ return sero_send(_receiver,"",0,_category,_ticket); } /** * @dev transfer the token or ticket to the receiver * @param _receiver the address of receiver * @param _currency the currency of token * @param _amount the amount of token * @param _category the category of the ticket * @param _ticket the Id of the ticket */ function sero_send(address _receiver, string memory _currency, uint256 _amount, string memory _category, bytes32 _ticket) internal returns (bool success){ bytes memory temp = new bytes(160); assembly { mstore(temp, _receiver) mstore(add(temp, 0x20), _currency) mstore(add(temp, 0x40), _amount) mstore(add(temp, 0x60), _category) mstore(add(temp, 0x80), _ticket) log1(temp, 0xa0, sload(topic_sero_send_slot)) success := mload(add(temp, 0x80)) } return; } |
struct Kitty { bytes32 kittyId; uint256 genes; uint64 birthTime; uint64 cooldownEndBlock; bytes32 matronId; bytes32 sireId; bytes32 siringWithId; uint16 cooldownIndex; uint16 generation; address owner; } |
function approveSiring(bytes32 _matronId) external whenNotPaused { //get _sireId A Kitty that you own from the tx param bytes32 _sireId = sero_msg_ticket(); sireAllowedToKittyId[_sireId] = _matronId; //Re-save _sireId to your personal account after approval sero_send_ticket(msg.sender,symbol,_sireId); } |
SERO實現匿名的第一步就是對地址作文章,無論是交易中的地址還是傳入到智慧合約中地址都將轉換成一次性地址,最終只有擁有該地址私有的人才能查詢到自己的資產情況並且使用這些資產,這無形當中弱化了地址的功效。在以太貓中存在將kittyId授信給一個地址的情況,在SERO中顯然這一點無法做到這一點,因為每次傳入到智慧合約中的地址可能都不一樣了,即使是同一個地址。雖然無法實現對一個地址直接授信,但SERO同樣可以實現類似的功能,只需要我們轉換下思路就可以了。因為SERO的所有資產都儲存到個人賬戶中去了,因此對於擁有非同質代幣的人,在某種情況下一個tickeId就能證明一個地址的身份,因此以太貓中類似將kittyId授信給一個地址的時候,都可以替換為將一個kittyId授信給另外一個kiettyId這樣的方式來實現,授信方的kittyId必須透過交易引數傳遞到智慧合約中。搞清楚以上一些主要的變化後,在不變動以太貓的業務邏輯的情況下,就能很容易將其匿名化。對比原版程式碼量會更少,而且資產的管理邏輯也會減少,實現起來主要的重心就在業務邏輯上了。
透過SERO,不但可以實現以太貓匿名化,而且SERO之於智慧合約,在支援匿名的基礎上還簡化了資產管理邏輯,使所有的DApp開發者可以將重心放到業務邏輯開發上來。某種情況下SERO降低了透過智慧合約釋出代幣的門檻,使傳統App開發者可以更加容易上手開發自己的DApp。
匿名版以太貓的Github原始碼:
https://github.com/kusun/Sero-CryptoKitties