91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Plasma Cash 合約解讀

發布時間:2020-07-31 18:35:42 來源:網絡 閱讀:460 作者:蟲洞社區 欄目:開發技術

作者介紹

蟲洞社區·簽約作者 steven bai

Plasma Cash 合約解讀

  • Plasma Cash 合約解讀
    • 1. 合約代碼
    • 2. 合約文件簡單介紹
    • 3. Plasma Cash 的基礎數據結構
      • 3.1 Plasma Cash 中的資產
      • 3.2 Plasma Cash中的交易
      • 3.3 Plasma Cash 中的 Block
      • 3.4 Plasma Cash 中資產的回歸主鏈以太坊
        • 3.4.1 資產擁有證明
        • 3.4.2 等待其他人來挑戰我
        • 3.4.3 挑戰期過了, Bob 拿回資產 uid
    • 4. Plasma Cash 中的退出示例
    • 5. 其他問題

此文來自 SmartMesh 團隊,轉載請聯系作者。

Plasma 由 V 神在2017年8月提出,希望通過鏈下交易來大幅提高以太坊的 TPS.

每條 Plasma 鏈都會將有關交易順序的消息換算成一個哈希值存儲在根鏈上。比特幣和以太坊都屬于根鏈——這兩條區塊鏈具有很高的安全性,并且通過去中心化保證了(安全性和活性)。

Plasma 設計模型有兩個主要的分支:Plasma MVP 和 Plasma Cash 。這里我們來研究 SmartPlasma 實現的 Plasma Cash 合約,并通過合約分析來回答大家關于 Plasma Cash 的一系列疑問.

1. 合約代碼

SmartPlasma的合約代碼肯定會不斷升級,我針對他們在今天(2018-09-14)最新版本進行分析,這份代碼目前保存在我的 github 上 plasma cash.

2. 合約文件簡單介紹

文件夾中有不少與 Plasma Cash 無關的合約,這里只關注直接與 Plasma Cash 相關合約,像 ERC20Token 相關合約就忽略,自行查看.

  • Mediator.sol 是 Plasma Cash 鏈中資產的進出口
  • RootChain.sol 處理 Plasma Cash 子鏈(相對于以太坊而言)中的交易以及打包等
  • libraries/MerkleProof.sol 是子鏈中交易用到的默克爾樹,用于子鏈參與方進行欺詐證明 fraud proof.
  • libraris/RLP.sol RLP編碼支持,可以暫時忽略,子鏈中所有的交易都是用RLP 編碼的.
  • libraries/PlasmaLib.sol 生成 uid 的輔助函數
  • ECRecovery.sol 簽名驗證
  • datastructures/Transaction.sol 描述交易的數據結構

3. Plasma Cash 的基礎數據結構

Plasma Cash 是一種子鏈結構,可以認為 Plasma Cash 是以太坊的一個是基于 =一種簡化的UTXO模型的子鏈.

3.1 Plasma Cash 中的資產

Plasma Cash 中的資產都來自于以太坊,但是一旦進入 Plasma Cash 就會擁有唯一的 ID,并且不可分割.
可以參考 Mediator.sol的deposit函數. Mediator就是 Plasma Cash 資產存放的地方.

        /** @dev Adds deposits on Smart Plasma.
     *  @param currency Currency address.
     *  @param amount Amount amount of currency.
     */
    function deposit(address currency, uint amount) public {
        require(amount > 0);

        Token token = Token(currency);
        token.transferFrom(msg.sender, this, amount); /// deposit test1

        bytes32 uid = rootChain.deposit(msg.sender, currency, amount); /// deposit test2
        cash[uid] = entry({
            currency: currency,
            amount: amount
        });
    }

通過合約可以看出進入 Plasma Cash 的資產必須是 ERC20 Token,這些資產實際上是存在 Mediator 這個合約上,然后由 RootChain 為其分配一個唯一的 ID, 也就是 uid. 這個 uid 代表著什么 token, 有多少個.

3.2 Plasma Cash中的交易

關鍵代碼在 Transaction.sol中.

    struct Tx {
        uint prevBlock;
        uint uid;
        uint amount;
        address newOwner;
        uint nonce;
        address signer;
        bytes32 hash;
    }

這里可能不太明顯,需要解釋才能看出來這是一個 UTXO 交易的模型. 這里面的amount 和 hash 實際上都有點啰唆,可以忽略. 那么剩下的成員需要來解釋.

prevBlock就是 UTXO 中的輸入,來自于哪塊. 至于為什么沒有像比特幣一樣的OutPoint 結構,也就是 TxHash+Index, 后續會講到.
uid 就是交易的資產 ID
newOwner 交易輸出給誰, 這里也不支持像 比特幣一樣的腳本.
nonce 是這筆資產的第多少次交易,在雙花證明中有重要作用.
signer必須由資產原擁有者的簽名.

amount 不重要,是因為資產不可分割,導致這里的 Amount 不會隨交易發生而發生變化. 而 hash 則是可以直接計算出來.

3.3 Plasma Cash 中的 Block

如果一般區塊鏈中的 Block 一樣,他是交易的集合.但是不同于一般鏈的是,這里面的礦工(不一定是 Operator)不僅需要維護好子鏈,還需要周期性的將每一個 Block 對應的默克爾樹根保存到以太坊中,這個工作只能有 Operator 來完成.
具體代碼可見 RootChain.sol的.

    function newBlock(bytes32 hash) public onlyOperator {
        blockNumber = blockNumber.add(uint256(1));
        childChain[blockNumber] = hash;

        NewBlock(hash);
    }

交易證據提交者只能是 Operator, 也就是合約的創建者. 這個 Operator 既可以是普通賬戶,這時他就是這個子鏈的管理員.也可以是一份合約,那么就可以通過合約來規定子鏈的出塊規則.

3.4 Plasma Cash 中資產的回歸主鏈以太坊

當資產在 Plasma 中交易一段時間以后,持有者Bob如果想退出Plasma Cash 子鏈,那么就需要向以太坊合約也就是 RootChain證明,他確實擁有這一筆資產.

3.4.1 資產擁有證明

這個思路和 UTXO 的思路是一樣的,Bob能證明這筆資產是從哪里轉給我的即可.具體見[RootChain.sol]()中的startExit函數. 其思路非常簡單,證明

  • 這筆資產來自哪里(在哪 M塊中轉移到了 Alice 手中)
  • 經過 Alice 簽名轉移給了Bob(在N塊中 Alice 做了簽名給我)
    具體看代碼 startExit

    /** @dev Starts the procedure for withdrawal of the deposit from the system.
     *  @param previousTx Penultimate deposit transaction.
     *  @param previousTxProof Proof of inclusion of a penultimate transaction in a Smart Plasma block.
     *  @param previousTxBlockNum The number of the block in which the penultimate transaction is included.
     *  @param lastTx Last deposit transaction.
     *  @param lastTxProof Proof of inclusion of a last transaction in a Smart Plasma block.
     *  @param lastTxBlockNum The number of the block in which the last transaction is included.
     */
    function startExit(
        bytes previousTx,
        bytes previousTxProof,
        uint256 previousTxBlockNum,
        bytes lastTx,
        bytes lastTxProof,
        uint256 lastTxBlockNum
    )
        public
    {
        Transaction.Tx memory prevDecodedTx = previousTx.createTx();
        Transaction.Tx memory decodedTx = lastTx.createTx();
        // 證明在 prevBlock的時候 Alice 擁有資產 uid
        require(previousTxBlockNum == decodedTx.prevBlock);
        require(prevDecodedTx.uid == decodedTx.uid);
        //amount 不變,證明資產不可分割
        require(prevDecodedTx.amount == decodedTx.amount);
        //Alice 確實簽名轉移給了我,并且交易是相鄰的兩筆交易
        require(prevDecodedTx.newOwner == decodedTx.signer);
        require(decodedTx.nonce == prevDecodedTx.nonce.add(uint256(1))); //緊挨著的兩筆交易
        //我是 Bob, 我要來拿走這筆資產
        require(msg.sender == decodedTx.newOwner);
        require(wallet[bytes32(decodedTx.uid)] != 0);
    
        bytes32 prevTxHash = prevDecodedTx.hash;
        bytes32 prevBlockRoot = childChain[previousTxBlockNum];
        bytes32 txHash = decodedTx.hash;
        bytes32 blockRoot = childChain[lastTxBlockNum];
    
        require(
            prevTxHash.verifyProof(
                prevDecodedTx.uid,
                prevBlockRoot,
                previousTxProof
            )
        );
        require(
            txHash.verifyProof(
                decodedTx.uid,
                blockRoot,
                lastTxProof
            )
        );
    
        /// Record the exit tx.
        require(exits[decodedTx.uid].state == 0);
        require(challengesLength(decodedTx.uid) == 0);
    
        exits[decodedTx.uid] = exit({
            state: 2,
            exitTime: now.add(challengePeriod),
            exitTxBlkNum: lastTxBlockNum,
            exitTx: lastTx,
            txBeforeExitTxBlkNum: previousTxBlockNum,
            txBeforeExitTx: previousTx
        });
    
        StartExit(prevDecodedTx.uid, previousTxBlockNum, lastTxBlockNum);
    }

    代碼的前一半都是在用來證明在lastTxBlockNum的時候,資產 uid 歸Bob所有.
    然后后一半就是提出來,Bob想把資產 uid 提走. 我的這個想法會暫時保存在合約中,等待別人來挑戰.

3.4.2 等待其他人來挑戰我

有了以上信息, 就可以證明在 N 塊時,這筆資產歸Bob所用.但是這肯定不夠,無法證明現在資產仍然屬于Bob,也無法證明Alice 沒有在 M 塊以后再給別人.
更加不能證明在 M 塊的時候 Alice 真的是 uid 的擁有者?
這些問題,看起來很難回答,其實思路也很簡單.
這個思路和雷電網絡中解決問題的辦法是一樣的, 讓這筆資產的利益攸關者站出來舉證.
比如: 如果 Carol能夠舉證這筆資產Bob 后來又轉移給了 Carol, 那么實際上 Bob 就是在雙花.
具體的挑戰以及迎戰代碼比較復雜,但是這也是 Plasma Cash 的核心安全性所在.如果沒有這些,所有的參與者都將無法保證自己的權益.

//challengeExit 挑戰資產uid 其實不屬于 Bob
  /** @dev Challenges a exit.
     *  @param uid Unique identifier of a deposit.
     *  @param challengeTx Transaction that disputes an exit.
     *  @param proof Proof of inclusion of the transaction in a Smart Plasma block.
     *  @param challengeBlockNum The number of the block in which the transaction is included.
     */
    function challengeExit(
        uint256 uid,
        bytes challengeTx,
        bytes proof,
        uint256 challengeBlockNum
    )
        public
    {
        require(exits[uid].state == 2);

        Transaction.Tx memory exitDecodedTx = (exits[uid].exitTx).createTx();
        Transaction.Tx memory beforeExitDecodedTx = (exits[uid].txBeforeExitTx).createTx();
        Transaction.Tx memory challengeDecodedTx = challengeTx.createTx();

        require(exitDecodedTx.uid == challengeDecodedTx.uid);
        require(exitDecodedTx.amount == challengeDecodedTx.amount);

        bytes32 txHash = challengeDecodedTx.hash;
        bytes32 blockRoot = childChain[challengeBlockNum];

        require(txHash.verifyProof(uid, blockRoot, proof));

        // test challenge #1 & test challenge #2 最后一筆交易后面又進行了其他交易, Bob 在進行雙花
        if (exitDecodedTx.newOwner == challengeDecodedTx.signer &&
        exitDecodedTx.nonce < challengeDecodedTx.nonce) {
            delete exits[uid];
            return;
        }

        // test challenge #3, 雙花了,  Alice 給了兩個人,并且挑戰者 Carol的BlockNumer 更小,也就是發生的更早.
        if (challengeBlockNum < exits[uid].exitTxBlkNum &&
            (beforeExitDecodedTx.newOwner == challengeDecodedTx.signer &&
            challengeDecodedTx.nonce > beforeExitDecodedTx.nonce)) {
            delete exits[uid];
            return;
        }

        // test challenge #4   在 M塊之前,還有一筆交易,Alice 需要證明自己在 M 塊確實擁有 uid
        if (challengeBlockNum < exits[uid].txBeforeExitTxBlkNum ) {
            exits[uid].state = 1;
            addChallenge(uid, challengeTx, challengeBlockNum);
        }

        require(exits[uid].state == 1);

        ChallengeExit(uid);
    }

//Bob應戰,再次舉證,實際上這個過程就是要不斷的追加證據,將所有的交易連起來,最終證明 Alice 在 M塊確實擁有 uid
 /** @dev Answers a challenge exit.
     *  @param uid Unique identifier of a deposit.
     *  @param challengeTx Transaction that disputes an exit.
     *  @param respondTx Transaction that answers to a dispute transaction.
     *  @param proof Proof of inclusion of the respond transaction in a Smart Plasma block.
     *  @param blockNum The number of the block in which the respond transaction is included.
     */
    function respondChallengeExit(
        uint256 uid,
        bytes challengeTx,
        bytes respondTx,
        bytes proof,
        uint blockNum
    )
        public
    {
        require(challengeExists(uid, challengeTx));
        require(exits[uid].state == 1);

        Transaction.Tx memory challengeDecodedTx = challengeTx.createTx();
        Transaction.Tx memory respondDecodedTx = respondTx.createTx();

        require(challengeDecodedTx.uid == respondDecodedTx.uid);
        require(challengeDecodedTx.amount == respondDecodedTx.amount);
        require(challengeDecodedTx.newOwner == respondDecodedTx.signer);
        require(challengeDecodedTx.nonce.add(uint256(1)) == respondDecodedTx.nonce);
        require(blockNum < exits[uid].txBeforeExitTxBlkNum);

        bytes32 txHash = respondDecodedTx.hash;
        bytes32 blockRoot = childChain[blockNum];

        require(txHash.verifyProof(uid, blockRoot, proof));

        removeChallenge(uid, challengeTx);

        if (challengesLength(uid) == 0) {
            exits[uid].state = 2;
        }

        RespondChallengeExit(uid);
    }
3.4.3 挑戰期過了, Bob 拿回資產 uid

挑戰期過后,Bob 在Mediator.sol 中提出將資產退回到以太坊中

 /** @dev withdraws deposit from Smart Plasma.
     *  @param prevTx Penultimate deposit transaction.
     *  @param prevTxProof Proof of inclusion of a penultimate transaction in a Smart Plasma block.
     *  @param prevTxBlkNum The number of the block in which the penultimate transaction is included.
     *  @param txRaw lastTx Last deposit transaction.
     *  @param txProof Proof of inclusion of a last transaction in a Smart Plasma block.
     *  @param txBlkNum The number of the block in which the last transaction is included.
     */
    function withdraw(
        bytes prevTx,
        bytes prevTxProof,
        uint prevTxBlkNum,
        bytes txRaw,
        bytes txProof,
        uint txBlkNum
    )
        public
    {
        bytes32 uid = rootChain.finishExit(
            msg.sender,
            prevTx,
            prevTxProof,
            prevTxBlkNum,
            txRaw,
            txProof,
            txBlkNum
        );

        entry invoice = cash[uid];

        Token token = Token(invoice.currency);
        token.transfer(msg.sender, invoice.amount); /// 真正的資產轉移

        delete(cash[uid]); 
    }

RootChain 再次驗證

 /** @dev Finishes the procedure for withdrawal of the deposit from the system.
     *       Can only call the owner. Usually the owner is the mediator contract.
     *  @param account Account that initialized the deposit withdrawal.
     *  @param previousTx Penultimate deposit transaction.
     *  @param previousTxProof Proof of inclusion of a penultimate transaction in a Smart Plasma block.
     *  @param previousTxBlockNum The number of the block in which the penultimate transaction is included.
     *  @param lastTx Last deposit transaction.
     *  @param lastTxProof Proof of inclusion of a last transaction in a Smart Plasma block.
     *  @param lastTxBlockNum The number of the block in which the last transaction is included.
     */
    function finishExit(
        address account,
        bytes previousTx,
        bytes previousTxProof,
        uint256 previousTxBlockNum,
        bytes lastTx,
        bytes lastTxProof,
        uint256 lastTxBlockNum
    )
        public
        onlyOwner
        returns (bytes32)
    {
        Transaction.Tx memory prevDecodedTx = previousTx.createTx();
        Transaction.Tx memory decodedTx = lastTx.createTx();

        require(previousTxBlockNum == decodedTx.prevBlock);
        require(prevDecodedTx.uid == decodedTx.uid);
        require(prevDecodedTx.amount == decodedTx.amount);
        require(prevDecodedTx.newOwner == decodedTx.signer);
        require(account == decodedTx.newOwner);

        bytes32 prevTxHash = prevDecodedTx.hash;
        bytes32 prevBlockRoot = childChain[previousTxBlockNum];
        bytes32 txHash = decodedTx.hash;
        bytes32 blockRoot = childChain[lastTxBlockNum];

        require(
            prevTxHash.verifyProof(
                prevDecodedTx.uid,
                prevBlockRoot,
                previousTxProof
            )
        );

        require(
            txHash.verifyProof(
                decodedTx.uid,
                blockRoot,
                lastTxProof
            )
        );

        require(exits[decodedTx.uid].exitTime < now); //挑戰期過了
        require(exits[decodedTx.uid].state == 2); //并且沒有人挑戰或者我都給出了合適的證據
        require(challengesLength(decodedTx.uid) == 0);

        exits[decodedTx.uid].state = 3;

        delete(wallet[bytes32(decodedTx.uid)]);

        FinishExit(decodedTx.uid);

        return bytes32(decodedTx.uid);
    }

4. Plasma Cash 中的退出示例

Plasma Cash 合約解讀

5. 其他問題

    1. 為什么 Plasma Cash 中的資產是不可分割的?
      進入 rootchain 的資產類似于比特幣的 UTXO 模型,但是是不可分割的,這個可以通過交易驗證時每次都要求 amount 不變可以得出.
    1. operator 的作用是什么
      operator 負責將子鏈中的交易證據(默克爾樹)提交證明到以太坊主鏈中.
    1. operator 是否必須可信任的?
      是的. 雖然 operator 不能將他人資產隨意轉移,但是卻可以阻止他人資產轉移.也就是說無法從 Plasma 子鏈中退回到以太坊中.
      當然這部分是可以改進,降低 operator 作惡帶來的風險.
    1. operator 是否可以是一個合約呢?
      是的. 如果 operator 是一個 Pos 共識合約,那么可以降低問題3中的風險
添加微信(cdong1024),加入區塊鏈開發者技術交流群
蟲洞社區:https://www.uzanapp.com/

Plasma Cash 合約解讀

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

安图县| 安泽县| 海阳市| 长丰县| 怀化市| 桐柏县| 安达市| 柯坪县| 芒康县| 瑞昌市| 贵南县| 仙桃市| 大兴区| 万载县| 华容县| 玉树县| 凤城市| 宜都市| 新田县| 浪卡子县| 衡东县| 大足县| 临西县| 滨州市| 岑溪市| 荔浦县| 叙永县| 奉新县| 沁水县| 西城区| 水城县| 三门峡市| 济宁市| 台东市| 绥江县| 通许县| 札达县| 罗江县| 家居| 应城市| 仁寿县|