<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[twouplabs - Medium]]></title>
        <description><![CDATA[Twoup Labs - Medium]]></description>
        <link>https://medium.com/twouplabs?source=rss----d54fb7b95cd4---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>twouplabs - Medium</title>
            <link>https://medium.com/twouplabs?source=rss----d54fb7b95cd4---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Fri, 13 Nov 2026 21:23:24 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/twouplabs" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Account Abstraction]]></title>
            <link>https://medium.com/twouplabs/account-abstraction-dab7c5bd0772?source=rss----d54fb7b95cd4---4</link>
            <guid isPermaLink="false">https://medium.com/p/dab7c5bd0772</guid>
            <dc:creator><![CDATA[shinthom]]></dc:creator>
            <pubDate>Fri, 02 Dec 2022 03:47:28 GMT</pubDate>
            <atom:updated>2022-12-19T14:32:00.747Z</atom:updated>
            <content:encoded><![CDATA[<h4>진정한 디지털 데이터 소유권과 블록체인 대중화를 위한 솔루션</h4><p><em>Special thanks to </em><a href="https://medium.com/@4000d"><em>Carl Park</em></a><em> and </em><a href="https://medium.com/@zrkdehddn"><em>Andy Kang</em></a><em> for feedback and review.</em></p><p>이 글은 Account Abstraction이 무엇이고 왜 필요한지에 대해 설명합니다. 그리고 이와 관련한 주요 EIP(EIP-2938, EIP-4337)들과 유즈케이스들을 살펴 봅니다.</p><p>작성의 편의를 위해 해당 내용들은 반말로 작성되어 있습니다. 그리고 잘못된 내용이 있다면 지적 부탁드립니다.</p><h3>이더리움 어카운트 모델</h3><p>이더리움은 유저의 자산을 추적하기 위해 어카운트 모델을 사용한다. 각 어카운트는 자신만의 고유한 주소를 갖는다.</p><p>이더리움 어카운트는 두 가지 타입으로 존재한다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*9Uww9fg3wxCO8i2S" /><figcaption><a href="https://www.preethikasireddy.com/post/how-does-ethereum-work-anyway">https://www.preethikasireddy.com/post/how-does-ethereum-work-anyway</a></figcaption></figure><ul><li><strong>EOA(Externally Owned Account)</strong>: 고유한 키(private key)에 의해 주소가 결정된다.</li><li><strong>CA(Contract Account)</strong>: 스마트 컨트랙트를 배포하여 어카운트를 생성한다. 해당 어카운트의 주소는 배포자의 주소와 nonce 값에 의해 결정된다.</li></ul><p>실제로 둘의 자료구조는 동일하지만 EOA는 codeHash와 storageRoot 값을 갖지 않는다.</p><h3>이더리움 지갑</h3><p>지갑은 어카운트(EOA, CA)를 관리한다. EOA용 지갑은 private key를 관리하여 어카운트를 관리한다. 반면 CA용 지갑은 지갑의 기능을 하는 dApp으로 컨트랙트에서 자산을 관리한다. dApp이기 때문에 다양한 지갑들이 존재할 수 있는데 대표적으로 <a href="https://gnosis-safe.io/">멀티시그 지갑</a>이 존재한다.</p><p>EOA용 지갑과 CA용 지갑의 가장 큰 차이는 EOA는 직접 트랜잭션을 생성할 수 있는 반면 CA는 스스로 트랜잭션을 만들 수 없다는 점이다. 그렇기 때문에 CA가 동작하기 위해서는 EOA가 CA를 호출(트랜잭션 생성)해야만 한다. 따라서 <strong>모든 CA용 지갑은 EOA에 종속적이고 </strong>이더리움에서 EOA와 CA는 아래처럼 취급된다.</p><ul><li><strong>EOA</strong>: first-class citizen</li><li><strong>CA</strong>: second-class citizen</li></ul><h3>문제점</h3><p>오늘날 대부분의 유저가 사용하는 지갑은 EOA용 지갑이다. 그렇기 때문에 <strong>이더리움 상의 모든 dApp은 EOA용 지갑과 상호작용하는 것을 가정하고 만들어진다.</strong></p><p>하지만 EOA는 <strong>security</strong>와 <strong>UX</strong> 측면에서 한계점을 갖고 있다.</p><h4><strong>security</strong></h4><p><strong>EOA는 서명자(signer)와 결합되어 있다.</strong> 즉 EOA에 존재하는 크립토 자산은 EOA가 소유하지만 해당 자산의 사용 권한은 서명자에게 있다. 서명자는 어카운트의 개인키를 소유한다. 따라서 개인키를 잃어버리면 어카운트를 잃게 되고 심지어 recovery도 불가능하다.</p><p><strong>개인키를 관리하는 것은 매우 어렵고 힘들다.</strong> 현재까지도 많은 사람들이 개인키를 제대로 관리하지 못해 자산을 잃고 있다. 이런 점 때문에 많은 사람들이 중앙화된 커스터디 서비스<em>(e.g., Coinbase/Upbit 거래소 지갑 또는 Bitgo와 같은 솔루션)</em>를 사용하고 있다.</p><blockquote><strong>블록체인은 진정한 디지털 데이터 소유권을 가능하게 만들어준 기술이다.</strong> 우리 자신이 직접 디지털 자산을 관리(self-custody)하지 않는다면 우리는 그 자산을 진정으로 소유하고 있다고 말할 수 없다.</blockquote><p>EOA를 first-class citizen으로 사용하는 이더리움의 구조에서 self-custody를 하기는 매우 어렵다.</p><h4><strong>UX</strong></h4><p>현재 이더리움의 UX는 좋지 않다. 유저는 아래와 같은 절차와 지식을 준수해야만 dApp 서비스를 사용할 수 있게 된다.</p><blockquote><strong>EOA 생성(개인키) → ETH 구매(거래소) → 지갑 로그인(서명) → 트랜잭션 생성(가스) → 트랜잭션 처리(마이닝)</strong></blockquote><p>그리고 현재 EOA에는 어카운트 별 역할이나 지출 정책을 별도로 지정할 수 없다. 멀티시그 기능을 사용하고 싶으면 멀티시그 지갑을 별도로 사용해야 하고 EOA에 접근 제한을 별도로 설정할 수도 없다.</p><p>또한 EOA는 반드시 ETH가 있어야만 트랜잭션을 전송할 수 있다. 비용 측면에서도 한계를 가지는데 예를 들어 유니스왑에서 처음 토큰 스왑을 하게 되면 approve + transferFrom 반드시 두 개의 트랜잭션을 보내야 한다. 원하는 기능은 스왑 하나인데 두 번의 서명이 필요한 것이다.</p><blockquote><em>이제는 self-custody를 위한 방안과 UX 개선이 필요한 시점이다. 그래야만 진정한 디지털 데이터 소유권과 블록체인 대중화를 가져올 수 있다.</em></blockquote><h3>Account Abstraction</h3><p>위에서 언급한 security와 UX의 문제는 AA를 통해 해결될 수 있다. AA는 다음과 같다:</p><ol><li>CA를 first-class citizen으로 만든다(<em>현재 이더리움에서는 이를 위해 코어 변경이 필요하다</em>).</li><li>CA 지갑이 직접 트랜잭션을 생성하고 수수료를 지불한다.</li><li>유저의 필요에 따라 다양한 기능을 CA 지갑에 커스텀해서 추가할 수 있다.</li></ol><p><strong>결국 AA의 핵심은 CA를 기본 지갑으로 사용하는 것이다.</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/942/1*_yk1J8O6sKObCSFHHGpSMw.png" /><figcaption><a href="https://youtu.be/OwppworJGzs">https://youtu.be/OwppworJGzs</a></figcaption></figure><p>AA를 구현하기 위해 다양한 제안(EIP)들이 존재하는데 대표적으로 EIP-2938과 EIP-4337이 존재한다.</p><h3>EIP-2938</h3><p>EIP-2938은 이더리움 코어 변경을 통해 AA(Account Abstraction)를 도입하는 것을 목표로 한다. 이를 위해 AA 트랜잭션과 AA 어카운트를 제안한다.</p><h4><strong>AA 트랜잭션</strong></h4><p>AA 트랜잭션은 새로운 트랜잭션 타입이다<em>(EIP-2718: Typed Transaction Envelope 베를린 하드포크에 포함되면서 다양한 트랜잭션 타입이 만들어질 수 있고, 현재 EIP-1559와 EIP-2930 트랜잭션 타입이 존재한다)</em>. AA 트랜잭션의 payload는 다음과 같다:</p><p><strong><em>RLP[(</em></strong><strong><em>nonce, </em></strong><strong><em>target, </em></strong><strong><em>data])</em></strong></p><p>현재 우리가 사용하는 트랜잭션의 payload는 <strong><em>RLP([</em></strong><strong><em>nonce, </em></strong><strong><em>gas_price, </em></strong><strong><em>gas_limit, </em></strong><strong><em>to, </em></strong><strong><em>value, </em></strong><strong><em>data, </em></strong><strong><em>v, </em></strong><strong><em>r, </em></strong><strong><em>s])</em></strong>이다.</p><p>차이점을 살펴보면 다음과 같다(<strong><em>nonce</em></strong>와 <strong><em>data</em></strong>은 동일):</p><ul><li><strong>gas_limit</strong>, <strong>gas_price</strong>: AA 어카운트 내부에서 명시된다(<strong>gas_limit</strong>은 remaining gas를 사용하고 <strong>gas_price</strong>는 base_gas를 사용하게 된다).</li><li><strong>to</strong>: <strong>target</strong> 주소로 대체된다. <strong>target</strong>은 AA 어카운트 주소다.</li><li><strong>v</strong>, <strong>r</strong>, <strong>s</strong>: <strong>AA 어카운트 내부에 정의된 서명 알고리즘으로 대체된다. AA 트랜잭션은 EOA의 서명(ECDSA)을 필요로 하지 않는다.</strong> 그렇기 때문에 base_gas_cost가 21,000이 아닌 15,000이다.</li><li><strong>value</strong>: <strong>AA 트랜잭션은 내부적으로 tx.origin을 0xfff…fff (entry_point)로 변경한다.</strong> 그렇기 때문에 <strong>value</strong> 값을 사용하지 않는다.</li></ul><p>정리하면, AA 트랜잭션 payload를 구성하는 <strong>target</strong>은 AA 어카운트 주소, <strong>nonce</strong>는 target AA 어카운트의 nonce 그리고 <strong>data</strong>는 실제 실행하고자 bytecode가 된다.</p><p>핵심은 AA 트랜잭션의 target은 항상 AA 어카운트여야 하고, AA 트랜잭션은 내부적으로 tx.origin을 0xfff…fff로 변경된다는 점이다.</p><h4><strong>AA 어카운트</strong></h4><p>AA 트랜잭션은 서명되지 않기 때문에 코드 내부에 서명 알고리즘이 포함되어 있어야 하고 스스로 수수료를 지불할 수 있어야 한다.</p><p>아래는 이를 위한 예시 코드로 2-of-2 멀티시그 기능을 가진 AA 어카운트다.</p><pre>// SPDX-License-Identifier: MIT<br>pragma solidity ^0.8.0;<br><br>account contract TwoOfTwo {<br>    struct Signature {<br>        uint8 v;<br>        bytes32 r;<br>        bytes32 s;<br>    }<br><br>    address public owner0;<br>    address public owner1;<br><br>    constructor(address _owner0, address _owner1) payable {<br>        owner0 = _owner0;<br>        owner1 = _owner1;<br>    }<br><br>    function transfer(<br>        uint256 gasPrice,<br>        uint256 gasLimit,<br>        address payable to,<br>        uint256 amount,<br>        bytes calldata payload,<br>        Signature calldata sig0,<br>        Signature calldata sig1<br>    ) external {<br>        bytes32 digest = keccak256(abi.encodePacked(this, gasPrice, gasLimit, to, amount, tx.nonce, payload));<br><br>        address signer0 = recover(digest, sig0);<br>        require(owner0 == signer0);<br><br>        address signer1 = recover(digest, sig1);<br>        require(owner1 == signer1);<br><br>        paygas(gasPrice, gasLimit);<br><br>        (bool success, ) = to.call{ value: amount }(payload);<br>        require(success);<br>    }<br><br>    function recover(bytes32 digest, Signature calldata signature) private pure returns (address) {<br>        return ecrecover(digest, signature.v, signature.r, signature.s);<br>    }<br>}</pre><ul><li><strong><em>account contract TwoOfTwo</em></strong>: AA 어카운트를 나타내기 위해 새로운 <strong>account</strong> 키워드를 사용한다.</li><li><strong><em>constructor</em></strong>: 2-of-2 멀티시그 지갑기 때문에 두 명의 owner 주소들을 상태에 저장해둔다.</li><li><strong><em>function transfer(…)</em></strong>: 실제 실행 코드다. 내부적으로 서명 검증(2-of-2)을 수행하고 <strong>PAYGAS</strong> opcode를 실행하여 수수료를 지불한다.</li></ul><h4><strong>NONCE &amp; PAYGAS opcode</strong></h4><p>AA 트랜잭션과 AA 어카운트가 이더리움에서 동작하도록 하기 위해 새로운 opcode 두개가 필요하다. 즉 프로토콜의 변경이 필요하다.</p><ul><li><strong>NONCE</strong>: 유저가 보낸 nonce와 AA 컨트랙트(target)의 nonce를 비교한다. target AA 컨트랙트의 nonce를 구하기 위해 <strong>NONCE</strong> opcode가 필요하다.</li><li><strong>PAYGAS</strong>: <strong>PAYGAS</strong> opcode를 실행해 AA 어카운트가 수수료를 지불한다. 이를 위해 AA 어카운트의 잔액은 gas_price * gas_limit보다 많아야 한다. <strong>PAYGAS</strong> opcode는 실행을 위한 체크포인트로 사용되는데, 만약 <strong>PAYGAS</strong> 이후에 revert가 발생하면 일반적인 revert와 마찬가지로 모든 수수료는 지불되고 실행은 롤백된다. 간단히, <strong>PAYGAS</strong> opcode 이전은 검증 단계이고 <strong>PAYGAS</strong> opcode 이후는 실행 단계라고 볼 수 있다.</li></ul><h4><strong>AA 트랜잭션 검증</strong></h4><p>이더리움의 모든 트랜잭션은 노드에 전송되면 검증 절차를 거치게 된다. AA 트랜잭션도 검증 절차를 거치게 되는데 절차가 조금 더 복잡하다. 우선 mempool에 존재하는 AA 트랜잭션이 펜딩 중인 다른 트랜잭션의 상태에 의존성을 갖지 않도록 하기 위해서 다음의 조건이 필요하다.</p><ol><li><strong>PAYGAS </strong>opcode가 실행되기 전에 코드에서 다음의 opcode들 —<em> BLOCKHASH, COINBASE, TIMESTAMP, NUMBER, DIFFICULTY, GASLIMIT, BALANCE, CALL, CALLCODE, STATICCALL, CREATE, CREATE2, EXTCODESIZE, EXTCODEHASH, EXTCODECOPY, DELEGATECALL</em> — 이 포함되어서는 안된다. 즉 <strong>PAYGAS</strong> opcode 이전인 검증 단계에서 의존성을 갖는 opcode가 존재해서는 안된다. 만약 AA 트랜잭션이 노드에 전송되면 해당 노드는 이와 같은 룰을 위반했는지 확인한다. 즉 <strong>PAYGAS</strong> opcode 이전에 의존성을 갖는 opcode들이 존재한다면 해당 트랜잭션을 받아들이지 않는다.</li><li>AA 트랜잭션이 아닌 트랜잭션이 AA 어카운트에 영향을 주지 못하도록 막아야 한다. 이를 위해 <strong>AA 컨트랙트가 배포되면 bytecode에 AA_PREFIX를 두고 저장한다.</strong> 만약 트랜잭션의 target(또는 to) 필드의 주소가 AA 컨트랙트이면 해당 컨트랙트에는 AA_PREFIX가 존재할 것이다. AA_PREFIX가 존재하면 노드는 해당 트랜잭션의 tx.origin이 0xfff…fff인지를 확인한다. tx.origin이 0xfff…fff가 아니면 AA 트랜잭션이 아니기 때문에 AA 트랜잭션이 아닌 트랜잭션이 AA 어카운트를 실행할 수 없게 막을 수 있다.</li></ol><p>EIP-2938은 오랜 기간동안 논의된 제안이지만 이더리움 프로토콜에 반영되지 않았다. 현재 더 머지(The Merge)가 이루어지긴 했지만, 이더리움에게 있어서 AA를 구현하는 것보다 더 머지와 같은 프로토콜 변경에 더 많은 관심과 리소스가 소요되고 있었다. 또한 이더리움 프로토콜 변경은 완전한 합의가 없이는 매우 힘든 부분들이 존재한다.</p><h3>EIP-4337</h3><p>이후 비탈릭은 AA(Account Abstraction)을 위한 새로운 EIP-4337을 제안한다. 해당 제안은 EIP-2938과 달리 프로토콜 변경없이 AA를 구현할 수 있도록 한다. 이런 특성으로 현재 EIP-4337이 AA를 주도하고 있다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/811/0*kf_CXgZqYFLKHpvd" /><figcaption><a href="https://medium.com/infinitism/erc-4337-account-abstraction-without-ethereum-protocol-changes-d75c9d94dc4a">https://medium.com/infinitism/erc-4337-account-abstraction-without-ethereum-protocol-changes-d75c9d94dc4a</a></figcaption></figure><p>EIP-4337은 UserOperation을 위한 새로운 레이어를 필요로 한다. UserOperation은 트랜잭션과 유사한 것으로, 유저는 트랜잭션 대신 UserOperation을 전송한다. UserOperation은 UserOperation mempool에 쌓이게 되는데 이를 Bundler가 번들링한다. 번들링된 UserOperation들은 하나의 Bundle 트랜잭션으로 이더리움 노드에 전송되어 처리된다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cnTjVoNQU4NaiCxUpJxPVA.png" /></figure><p>UserOperation을 처리하기 위해 3개의 컨트랙트(EntryPoint, Wallet, Paymaster)가 필요하다<em>(Paymaster 컨트랙트는 조건에 따라 사용되지 않을 수도 있다)</em>.</p><ul><li><strong>EntryPoint</strong>: UserOperation을 검증하고 실행한다.</li><li><strong>Wallet</strong>: 컨트랙트 어카운트 지갑으로 UserOperation의 sender다. 수수료를 지불하고 서명 검증 로직을 담고 있다.</li><li><strong>Paymaster</strong>: UserOperation의 sender가 ETH가 아닌 ERC20 토큰으로 수수료를 지불할 수 있게 해준다. 심지어 수수료를 내지 않고도 트랜잭션을 보내도록 해줄 수 있다.</li></ul><p>번들러는 UserOperation들을 패키징하고 EntryPoint 컨트랙트의 handleOps 함수를 호출한다. handleOps 함수는 UserOperation들을 검증하고 실행하게 된다.</p><pre>function handleOps(UserOperation[] calldata ops, address payable beneficiary);</pre><p>각각의 UserOperation이 handleOps 함수 내에서 어떻게 처리되는지 <a href="https://github.com/stackup-wallet/stackup/tree/main/apps/contracts/contracts">코드</a>를 통해 단계별로 살펴보도록 한다.</p><h4>UserOperation</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/566/1*cgbEYJXvsKNsjNXAm-mRRA.png" /></figure><p>UserOperation 필드값은 위와 같다.</p><h4>1/ 번들러(bundler)는 handleOp 함수를 호출한다.</h4><p>번들러는 UserOperation을 번들링해서 하나의 번들 트랜잭션을 만든다. 번들 트랜잭션은 EntryPoint 컨트랙트의 <strong>handleOps</strong> 함수를 호출하는 트랜잭션이다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*KPzCX1pLjWDalv6SrvpaxQ.png" /></figure><p><strong>handleOps</strong> 함수 내부에서는 <strong>_verifyOp</strong> 함수와 <strong>_executeOp</strong> 함수를 호출하는데, 이곳에서 UserOperation에 대한 <strong>검증</strong>과 <strong>실행</strong>을 하게 된다.</p><h4>2/ _verifyOp</h4><p>UserOperation을 검증하는 함수다. 다음의 검증들이 이루어진다.</p><ol><li>nonce &amp; signature 검증</li><li>op.verificationGas 검증</li><li>balance 검증</li><li><em>(Paymaster 검증 (Paymaster 섹션에서 다루게 된다))</em></li></ol><h4>2–1/ nonce &amp; signature 검증</h4><p>Wallet을 검증하기 위해 UserOperation의 <strong>op.sender</strong>, <strong>op.nonce</strong> 그리고 <strong>op.signature</strong>가 사용된다<em>(Wallet 검증은 트랜잭션을 검증하기 위해 EOA의 nonce와 signature 그리고 upfront cost보다 많은 balance가 있는지 검증하는 것과 같다)</em>.</p><blockquote>op.으로 시작하는 값들은 모두 UserOperation의 필드값을 의미한다.</blockquote><p><strong>op.sender</strong>는 Wallet 주소이고, <strong>op.nonce</strong>는 Wallet의 nonce 값이다. <strong>op.signature</strong>는 requestId를 서명한 값이다. requestId는 UserOperation을 인코딩해서 해싱한 뒤, 이를 EntryPoint 컨트랙트의 주소와 chainId 3개의 값을 다시 해싱한 값이다. 이를 통해 유효한 EntryPoint 주소가 사용되었는지 확인할 수 있고, chainId를 사용함으로써 replay 공격을 막을 수 있다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-JxQpr6vpnvFLsTeeUDkBg.png" /></figure><p>중간 과정으로, 만약 Wallet이 존재하지 않으면 Wallet을 생성해 준다. 이를 위해 <strong>op.initCode</strong>를 확인한다. <strong>op.sender</strong>의 주소로 아직 Wallet 컨트랙트가 배포되지 않았고, <strong>op.initCode</strong>가 존재한다면 CREATE2 opcode를 통해 Wallet 컨트랙트를 새로 배포한다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*BKrD85SFhfeFVuZnwdzrtg.png" /></figure><p>Wallet 검증은 다음과 같이 이루어진다:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/655/1*ZYcWtJkcHugoK4Olg1mlQw@2x.png" /></figure><ol><li><em>(Wallet이 존재하지 않는 경우 Wallet을 생성)</em></li><li><strong>nonce 검증</strong> — <em>op.sender 주소를 가진 Wallet의 nonce와 op.nonce를 비교한다.</em></li><li><strong>signature 검증</strong> —<em> Wallet 컨트랙트 내부에서 op.signature의 signer가 유효한 주소인지를 확인한다. signer의 주소가 Wallet에서 허용되는 주소이면 해당 검증은 통과된다.</em></li></ol><p><strong>signature 검증 과정에서 AA의 장점이 들어난다. signature 검증이 스마트 컨트랙트 코드 내에서 일어나기 때문에 signature 검증 과정을 커스텀할 수 있다.</strong></p><p>Wallet 검증 과정에서 UserOperation의 4개의 필드값(sender, nonce, initCode, signature)의 역할에 대해서 이해할 수 있었다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/572/1*PxnOhJT9Sv-nyZci0vS5yA.png" /></figure><ul><li><strong>sender</strong>: Wallet 컨트랙트의 주소로 <strong>유저는 더이상 EOA를 사용하지 않고 CA(Wallet 컨트랙트)를 사용한다.</strong></li><li><strong>nonce</strong>: Wallet 컨트랙트의 nonce 값이다. op.nonce와 Wallet의 nonce가 같아야 한다. UserOperation이 처리되면 Wallet의 nonce는 1 증가할 것이다.</li><li><strong>initCode</strong>: sender 주소가 CA가 아니면 Wallet 컨트랙트를 새로 배포하는데 이를 위해 필요한 bytecode다.</li><li><strong>signature</strong>: Wallet 내부에서 서명 검증에 이용되는 서명값이다. signer가 Wallet이 허용하는 주소라면 서명 검증은 통과하게 된다.</li></ul><h4>2–3/ op.verifiactionGas 검증</h4><p>UserOperation 검증은 Wallet 검증과 Paymaster 검증으로 이루어진다. 검증 과정을 거치면서 가스를 소모하게 되는데 소모하게 되는 gas는 <strong>op.verifiactionGas</strong>보다 적거나 같아야 한다. 해당 조건을 충족하지 못하면 UserOperation은 처리되지 않는다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/914/1*6e4GHEDoUW-pN-C_jqy4LA@2x.png" /></figure><h4>2–3/ balance 검증</h4><p>번들 트랜잭션의 수수료는 번들러(Bundler)가 지불한다. 번들러는 UserOperation을 처리하는 대가로 UserOperation의 Wallet 주소(<strong>op.sender</strong>)로부터 수수료를 받게 된다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*xWFdGD3x7l-v0NbD" /></figure><p>Wallet은 EntryPoint 컨트랙트에 수수료를 지불하기 위해 UserOperation이 처리되기 위해 필요한 수수료만큼 ETH를 보유하고 있어야 한다. 이를 확인하는 과정을 balance 검증이라고 한다.</p><p>balance 검증을 하기 위해서는 upfront cost를 구해야 한다. 트랜잭션의 upfront cost는 gasLimit * gasPrice로 구해지는데 반해 UserOperation의 upfront cost는 totalGas(<strong>op.preValidationGas</strong> + <strong>op.validationGas</strong> + <strong>op.callGas</strong>) * gasPrice로 구해진다.</p><blockquote>validationGas는 UserOperation 검증 단계에서 소모된 가스라면 preValidationGas는 번들 트랜잭션 생성에 대한 가스를 말한다. callGas는 UserOperation을 실행할 때 소모될 gas다.</blockquote><figure><img alt="" src="https://cdn-images-1.medium.com/max/696/1*z1mJpme47KVloDaiXPNY1w@2x.png" /></figure><p>gasPrice를 구하기 위해 <strong>op.maxFeePerGas</strong>와 <strong>op.maxPriorityFeePerGas</strong>를 사용한다. 해당 로직은 EIP-1559의 스펙과 동일하다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9OCVj2DJYEQJMxdhgZt7Qw.png" /></figure><p>구한 upfront cost를 EntryPoint 컨트랙트로 보낸다. 만약 upfront cost만큼 Wallet에 ETH가 없다면 revert될 것이다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/655/1*aYftaexSTAgoqXBS5d_qcg@2x.png" /></figure><p>우리는 <strong>op.verificationGas</strong> 검증과 balance 검증을 통해 아래의 필드값이 어떻게 사용되는지 알 수 있다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/818/1*vgOIt8P8kEFS5sn_6UzLTQ.png" /><figcaption>ㄱ</figcaption></figure><h4>3/ _executeOp</h4><p>검증 단계가 끝이 났다. 이제는 UserOperation을 실행할 단계다. 실행 단계는 검증 단계보다 과정이 단순하다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*g_2FItSJDFmYa0SWAE7hhA.png" /></figure><ol><li>지갑을 실행한다. 이를 위해 <strong>op.callGas</strong>와 <strong>op.callData</strong>가 사용된다.</li><li>실행에 소모된 gas를 더해준다. 검증 단계에서 소모한 가스와 실행 단계에서 소모한 가스를 더하면 totalGasUsed가 된다. 여기에 gasPrice를 곱하면 totalGasCost가 된다.</li><li>upfront cost에서 totalGasCost를 빼준 만큼을 Wallet(<strong>op.sender</strong>)에게 환불 해준다.</li></ol><p><strong>지갑 실행</strong></p><p>Wallet 컨트랙트로 <strong>op.callGas</strong>와 <strong>op.callData</strong>를 보낸다. 실행 단계에서 <strong>op.callGas</strong>보다 많은 가스를 소모하게 되면 out-of-gas 에러가 발생할 것이다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/530/1*fHNeyGebjS-cIo0CpNz6PQ@2x.png" /></figure><p><strong>op.callData</strong>는 executeUserOp 함수를 호출하기 위한 4 bytes와 executeUserOp 함수의 인자값을 인코딩한 값으로 구성될 것이다.</p><blockquote><strong>[function_selector + encoded[to, value, data]]</strong></blockquote><p><strong>to</strong>는 Wallet이 호출하고자 하는 컨트랙트 주소이고 <strong>value</strong>는 전송할 wei가 될 것이다. <strong>data</strong>는 to 컨트랙트의 함수 호출과 관련된 calldata가 들어가게 될 것이다.</p><h3>Paymatser</h3><p>UserOperation 검증과 실행은 EntryPoint가 수행하지만 실행을 위한 수수료는 Wallet이 지불한다. 하지만 EntryPoint가 원한다면 수수료 지불을 위해 ETH가 아닌 다른 토큰을 Wallet으로부터 받을 수도 있을 것이다. 예를 들어 Wallet은 DAI를 EntryPoint로 보내고 EntryPoint는 자신의 ETH를 사용해 UserOperation을 처리해준다. 이러한 기능을 담당하는 것이 Paymaster 컨트랙트다.</p><p>ETH가 아닌 토큰을 받고 UserOperation을 처리하기 위해서는 EntryPoint 컨트랙트에 ETH가 어느정도 stake되어 있어야 한다. Staking 컨트랙트는 이러한 기능을 담당한다.</p><h4>Paymaster 검증과 실행</h4><p>Paymaster만을 위한 검증과 실행 단계가 존재한다. 이 단계들은 위에서 설명한 검증 단계와 실행 단계에 포함된다.</p><p><strong>검증 단계</strong></p><p>Paymaster를 검증하기 위해 <strong>op.paymaster</strong>와 <strong>op.paymasterData</strong> 값이 사용된다. <strong>op.paymaster</strong>는 Paymaster 컨트랙트 주소이고, <strong>op.paymatserData</strong>는 [uint256 fee, PaymasterMode mode, IERC20Metadata token, AggregatorV3Interface feed, bytes memory signature]를 인코딩한 값이다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/898/1*ENoC85ZZdtgZM6KP8TDYfQ@2x.png" /></figure><p>mode(PaymasterMode)는 4가지가 존재한다. 이러한 모드에 따른 fee 값도 다를 것이다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/200/1*wOIOvQil8wgY8vRaQq5-fw@2x.png" /></figure><p>signature는 Paymaster 사용을 하기 위해 필요한 서명값으로 해당 서명의 signer가 Paymaster로부터 허용되는 주소라면 signature 검증은 통과하게 된다.</p><p>token은 수수료로 지급할 ERC20 토큰 주소가 된다. AggregatorV3Interface 컨트랙트 주소는 Chainlink 가격 피드 시스템으로부터 ETH와 해당 토큰의 비율을 구하기 위해 사용된다. upfront cost인 ETH의 수량은 ETH &lt;&gt; 토큰의 가격 비율값을 통해 토큰 수량으로 변환된다. 해당 토큰 수량만큼 <strong>op.sender</strong>가 보유하고 있는지 확인을 하는 것으로 Paymaster 검증을 마친다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/826/1*YF8tOG9aP4imssU7l4dMLw@2x.png" /></figure><p><strong>실행 단계</strong></p><p>_executePostOp 함수는 UserOperation 실행이 모두 끝난 이후에 호출된다. 실행까지 끝났기 때문에 총 소요한 gasCost를 알 수 있다. 이 gasCost는 하나의 UserOperation의 검증과 실행에서 소모한 총 가스량이 된다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/917/1*Sdc2bWT1gcIU01YN4_HnXw@2x.png" /></figure><p>postOp 함수는 ETH &lt;&gt; 토큰 가격 비에 맞게 gasCost(wei)에 해당하는 토큰 수량을 구한다. 해당 토큰 수량만큼 Wallet에서 Paymaster 컨트랙트로 전송하는 것으로 수수료를 지급한다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/764/1*De8bQT5zYq72My9Bjv76Tg@2x.png" /></figure><p>마지막으로 실행을 모두 끝내고 남은 가스는 다시 Staking 컨트랙트에 stake된다.</p><p>하나의 UserOperation 위와 같은 과정으로 처리되고, 모든 UserOperation의 처리가 끝나면 번들 트랜잭션의 실행은 종료된다.</p><h3>Use cases</h3><p><strong>AA가 구현되면 어카운트와 서명자의 분리가 가능해진다.</strong> 이로 인해 다양한 장점과 유즈케이스가 생긴다.</p><h4>Key management</h4><p>AA는 하나의 키(key)에 의존적이지 않다. 다양한 키를 만들어서 사용할 수 있다. 예를 들어 지갑에 메인 키를 변경할 수 있는 함수나 여러 키들을 관리하는 함수를 둘 수 있다. 이에 따라 social recovery도 가능해진다. 예를 들어 메인 키를 잃어버렸을 때, 메인 키에 대한 3명의 guardian들이 존재한다고 했을 때, 이들로부터 합의를 통해 메인 키를 변경해줄 수 있을 것이다.</p><p>그리고 키별로 역할과 정책을 다르게 둘 수도 있다. 예를 들어 어떤 키는 회사 내의 C-레벨만 사용하는 것으로 두고 동시에 특정 함수만 호출 가능하도록 할 수 있다. 그 뿐만 아니라 기기 별로 키를 할당해서 사용할 수 있다. 메인 키는 하드웨어 지갑에서 관리하고 모바일 기기와 데스크탑에서 사용하는 키는 다른 것을 사용한다. 이 키들은 메인 키들로부터 승인을 받은 것이다.</p><p>오늘날 모바일 지갑은 대부분 읽기만 하고 인터랙션 용도로 잘 사용하지 않는다. 인터랙션을 하기 위해서는 모바일에 키가 존재해야 하는데 폰을 잃어버리면 자산을 잃어버릴 수도 있기 때문이다. 하지만 모바일에 할당된 키를 특정 함수만 호출할 수 있도록 설정한다면 폰을 잃어버리더라도 자산을 잃어버릴 위험은 사라진다. <strong>결국 AA를 통해 기기에 상관없이 더욱 안전하게 블록체인을 사용할 수 있게 된다.</strong></p><h4>Gas payment</h4><p>EOA는 트랜잭션을 전송하기 위해 ETH가 반드시 필요하다. 하지만 AA를 이용하면 ETH가 없어도 트랜잭션을 보낼 수 있다. ERC-4337에서 살펴본 것처럼 다른 토큰으로 수수료를 대체해도 되고 심지어 Paypal을 통해 fiat으로 지불하도록 만들 수도 있다.</p><p>또한 이를 통해 privacy 문제도 해결될 수 있다. 우리는 거래소에서 ETH를 구매하는 순간 privacy가 깨진다. 트랜잭션들은 모두 추적되기 때문이다. ETH를 구매하지 않고도 트랜잭션을 보낼 수 있다면 privacy 측면에서도 장점이 생긴다.</p><h4>Signature</h4><p>현재 트랜잭션은 ECDSA 서명 알고리즘에 의해 암호화된다. 하지만 AA는 컨트랙트 코드에 의해 서명 검증이 이루어지기 때문에 ECDSA 서명 알고리즘에 의존하지 않아도 된다. ECDSA보다 더 나은 서명 알고리즘이 있다면 그것을 사용해도 된다. 예를 들어 BLS 서명 알고리즘이나 양자 저항성을 띤 서명 알고리즘을 사용할 수 있을 것이다. 게다가 하나의 서명이 아니라 동시에 여러 개의 서명을 받아 이를 검증하는 multisig 방식을 지갑에 구현할 수 있다.</p><h4>Batch transaction</h4><p>일반적인 트랜잭션은 하나의 함수만 호출가능하다. 하지만 AA를 통해 여러 트랜잭션을 단 하나의 트랜잭션으로 처리되도록 만들 수 있다. 예를 들어 ERC20의 approve + tranfserFrom + revoke 과정이 필요하다고 했을 때 3번의 서명이 필요하다.</p><p>AA는 3개의 트랜잭션을 하나의 트랜잭션으로 처리되도록 만들 수 있다. 유저가 필요한 기능을 사용하기 위해 단 하나의 서명만을 필요로 하게 만드는 것이다. 이를 통해 유저 경험을 더욱 좋게 만든다.</p><h4>Session key</h4><p>온체인 게임은 앞으로 많이 나올 것이다. 온체인 게임에서 유저가 액션을 할 때마다 서명을 해야 한다면 이는 유저 경험을 해친다. 세션 키는 정해진 기간 내에 특정 트랜잭션에 대해 유저 서명 없이 트랜잭션이 전송되도록 만드는 것을 말한다. 세션 키에는 유효 기간은 존재하고 이 유효 기간이 끝나면 해당 키는 소멸될 것이다.</p><h4>Plugin</h4><p>위에서 언급한 모든 기능들이 AA 지갑에 플러그인 방식으로 구현될 수 있다. multisig 플러그인, session key 플러그인 그리고 BLS signature 플러그인 등등 유저가 원하는 플러그인들을 사용할 수 있다.</p><h3>마치며</h3><p>AA는 앞으로 이더리움의 미래에 가장 중요한 기술 중 하나다. 현재 AA는 이더리움에 구현되어 있지 않다. 대신 몇몇 L2 프로젝트에서 AA를 사용하고 있다. 특히 zk 계열의 L2인 StarkNet와 zkSync는 AA를 default 어카운트로 사용하고 있다. zk 계열의 L2는 execution 비용이 싸고 L2이기 때문에 L1보다 다소 코드 변경에 용이하기 때문에 AA를 적극 도입할 수 있었다.</p><p>L2에서 AA 관련해서 여러 실험들이 이루어진 뒤 L1에서도 자연스럽게 도입될 것이다. 이를 통해 우리 모두가 self-custody를 통해 진정한 디지털 데이터 소유권을 얻음과 동시에 블록체인 대중화가 급속도록 이루어지는 것을 지켜볼 수 있을 것이다.</p><h4>Reference</h4><ul><li><a href="https://medium.com/infinitism/erc-4337-account-abstraction-without-ethereum-protocol-changes-d75c9d94dc4a">https://medium.com/infinitism/erc-4337-account-abstraction-without-ethereum-protocol-changes-d75c9d94dc4a</a></li><li><a href="https://eips.ethereum.org/EIPS/eip-2938">https://eips.ethereum.org/EIPS/eip-2938</a></li><li><a href="https://eips.ethereum.org/EIPS/eip-4337">https://eips.ethereum.org/EIPS/eip-4337</a></li><li><a href="https://www.youtube.com/watch?v=WsZBymiyT-8">https://www.youtube.com/watch?v=WsZBymiyT-8</a></li><li><a href="https://www.youtube.com/watch?v=OwppworJGzs">https://www.youtube.com/watch?v=OwppworJGzs</a></li><li><a href="https://www.youtube.com/watch?v=QuYZWJj65AY">https://www.youtube.com/watch?v=QuYZWJj65AY</a></li><li><a href="https://www.argent.xyz/blog/wtf-is-account-abstraction/">https://www.argent.xyz/blog/wtf-is-account-abstraction/</a></li><li><a href="https://github.com/stackup-wallet/stackup">https://github.com/stackup-wallet/stackup</a></li><li><a href="https://hackmd.io/@s0lness/BJUb16Yo9">https://hackmd.io/@s0lness/BJUb16Yo9</a></li><li><a href="https://mirror.xyz/matchboxdao.eth/VXOvLKIvfXHP-cusKHw55zqlHpvvWwzh_fqm6j48Yek">https://mirror.xyz/matchboxdao.eth/VXOvLKIvfXHP-cusKHw55zqlHpvvWwzh_fqm6j48Yek</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=dab7c5bd0772" width="1" height="1" alt=""><hr><p><a href="https://medium.com/twouplabs/account-abstraction-dab7c5bd0772">Account Abstraction</a> was originally published in <a href="https://medium.com/twouplabs">twouplabs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[KGZ Commitment]]></title>
            <link>https://medium.com/twouplabs/kgz-commitment-969ccfe91ba4?source=rss----d54fb7b95cd4---4</link>
            <guid isPermaLink="false">https://medium.com/p/969ccfe91ba4</guid>
            <category><![CDATA[polynomial-commitment]]></category>
            <category><![CDATA[kgz-commitment]]></category>
            <category><![CDATA[verkle-tree]]></category>
            <category><![CDATA[ethereum]]></category>
            <category><![CDATA[pc]]></category>
            <dc:creator><![CDATA[4000D]]></dc:creator>
            <pubDate>Fri, 02 Dec 2022 01:57:18 GMT</pubDate>
            <atom:updated>2022-12-12T04:07:42.637Z</atom:updated>
            <content:encoded><![CDATA[<p>이 글은 Verkle Tree에서 사용되는 KGZ Commitment을 다룹니다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*T4F09XLbLjtdq9ZQ.png" /><figcaption>John Kuszmaul, Verkle Trees</figcaption></figure><h4>TLDR;</h4><ul><li>KGZ Commitment는 PCS(Polynomial Commitment Scheme)로서 “데이터에 (라그랑주) 보간법을 이용해 생성한 다항식”을 commit할 경우 Vector Commitment로서 기능한다.</li><li>다항식 P(x)에 대한 KGZ Commitment는 [P(s)]₁로 정의되며 이에 대한 proof의 사이즈는 O(1)이다. 이 때 s는 Trust Setup으로 생성된 비밀값이다.</li><li>multiopenings: 모든 점을 한번에 reveal하기 위한 multiproofs를 생성할 수 있으며 multiproofs의 사이즈는 O(1)이다.</li></ul><p>KGZ Commitment는 Polynomial Commitment로서 Merkle Tree의 Merkle Root를 만드는 과정을 대체할 수 있습니다. 이는 Proof 사이즈를 줄여 p2p 통신에 사용되는 네트워크 대역폭을 크게 줄일 수 있으며 stateless client까지의 가능성도 제공합니다.</p><p>이 글은 KGZ Commitment의 핵심 동작 방식을 설명하기 위해 디테일한 요소(엄밀한 수학적 정의와 보안 요소)는 다소 생략됨을 알립니다.</p><h3>Commitment Scheme</h3><p>Commitment Scheme은 데이터를 숨긴 후 그에대한 Commitment만 제출하고 이후에 실제 데이터를 드러내는 방식입니다. 가장 이해하기 쉬운 예시는 <em>해시 함수를 이용한 commit-reveal scheme</em>입니다.</p><ol><li>유저는 본인이 가진 데이터 input을 해시하여 commit = sha256(input)을 계산합니다.</li><li>유저는 프로토콜에 commit을 제출하며 이후 필요할 경우 input 을 드러냅니다.</li><li>프로토콜은 유저가 제출한 input이 (2)에서 제출한 commit 에 대응하는지 sha256(input) == commit 로 확인합니다. 일치하지 않을 경우 유저가 제출한 input을 거부합니다.</li><li>프로토콜은 제한된 시간 안에 유저가 input 을 드러내지 않으면 패널티를 부여합니다.</li></ol><p>(reveal이란 단어 보다 opening이란 표현을 자주 사용하지만 동일한 의미를 가집니다. 마찬가지로 proof-of-membership 또한 동일한 의미를 가지며 이 글에선 세 단어를 혼용합니다.)</p><h3>Vector Commitment</h3><p>해시 함수는 임의의 길이의 인풋을 고정된 사이즈의 아웃풋으로 변환합니다. 만약 인풋의 사이즈가 크다면 해시 함수는 여러 라운드를 반복하기에 해시 함수의 연산 시간은 인풋 사이즈에 비례합니다. 위와 같은 commit 과정 뿐만 아니라 reveal(=opening) 과정에서도 인풋 사이즈에 비례해 컴퓨팅 자원들이 필요합니다.</p><p><em>“인풋 사이즈가 크니 이를 나눠서 배열로 처리하자”</em>는 아이디어를 적용하면 위에서 언급한 문제들을 해결할 수 있습니다. 이제는 인풋의 정의역이 “하나의 값”(scalar)이 아닌 “배열”(vector)이기에 이러한 Commitment Scheme은 Vector Commitment Scheme이라고 불립니다.</p><p>가장 명확한 예시는 Merkle Tree입니다. 길이가 n인 배열에 Merkle Tree를 이용해 Commitment를 생성한다면 이 Commitment는 결국 Merkle Root가 됩니다. Binary Merkle Tree의 경우 Merkle Root를 만들기 위해 O(n)번의 해시 함수를 실행해야 하며 i번째 노드를 reveal하기 위해선 (proof-of-membership) 사이즈가 O(log(n)/log(2))인 proof가 필요합니다. 만약 모든 노드를 reveal하기 위해선 proofs의 총 사이즈는 O(n log(n)/log(2)) 가 될것입니다.</p><blockquote>Commitment Scheme을 개선하는 목적은 proof 사이즈를 줄여 네트워크 대역폭을 더 효율적으로 사용하기 위함입니다. 물론 그를 위해 관련 자료구조를 만들고 proof를 계산하는 시간(e.g., Merkle Tree 구성 및 Merkle Path 생성)을 trade-off 합니다.</blockquote><h3>Polynomial Commitment</h3><p>Vector Commitment가 인풋의 정의역이 배열(=vector)인 것이라면 Polynomial Commitment는 인풋의 정의역이 <em>다항식</em>입니다.</p><p>다항식을 아래와 같은 방식으로 구성하면 <em>Polynomial Commitment를 Vector Commitment로</em> 사용할 수 있습니다.</p><ol><li>길이가 n인 input: Array&lt;Bytes32&gt;에 대해 <strong>n개의 점</strong> (i, input[i])를 생성합니다.</li><li><strong>라그랑주 보간법</strong>을 이용해 다항식 P(x)를 생성합니다. 즉, P(i) = input(i) for 0 ≤ i &lt; n 입니다. (이 때 P(x)의 차수는 최대 n 입니다)</li><li>Polynomial Commitment를 이용해 다항식 P(x)를 commit합니다.</li><li>추후 필요할 경우 i번째 점을 reveal(=proof-of-membership)합니다.</li></ol><p>여기서 3번은 Merkle Root에 대응하고 4번에서 생성된 proof는 Merkle Path에 대응합니다.</p><p>또한 i번째 점을 reveal 한다는 것은 P(i) = input[i] 임을 보이는 것과 동일합니다.</p><p>KGZ Commitment는 다항식 P(x)를 commit하는 Polynomial Commitment 입니다.</p><p>지금까지는 다소 생소할 수 있는 Commitment 와 관련 용어들을 설명했습니다. 마지막으로 KGZ Commitment에서 사용하는 2가지 수학적 요소(Polynomial Divisibility, Elliptic Curve Pairings)를 간략하게 이해하고 나면 KGZ Commitment을 이해할 재료는 모두 갖춰집니다.</p><h3>Polynomial Divisibility: <a href="https://en.wikibooks.org/wiki/Unit_roots/Divisibility_of_polynomials">Factor Theorem</a></h3><p><strong>방적식</strong> f(x) = 0이 x=a를 해로 가질 때 <strong>다항식</strong> f(x)는 (x-a)를 인수(factor)로 가집니다. f(x) = (x-a) * Q(x) 를 만족하는 다항식 Q(x)가 존재하기 때문에 f(x)는 x-a로 나눌 수 있습니다. 그 나눗셈에서 몫 다항식은 Q(x)가 됩니다.</p><h3>EC Pairings (Elliptic Curve Pairings)</h3><p>EC 위의 점들로 할 수 있는 기존의 연산들은<br> a) 하나의 EC 위의 두 점 P, Q에 대한 덧셈 (P+Q), 뺄셈 (P-Q)<br> b) EC 위의 한 점 P와 자연수 n의 곱셈 (nP) <br>뿐이었습니다. EC Pairings이 가지는 수학적 의미는 <strong>2개의 ECs 위에 있는 각각의 점 (P in G1, Q in G2)에 대해 곱셈(</strong><strong>P*Q)</strong>과 같은 연산을 제공한다는 점입니다.</p><p>EC Pairings은 <em>두 개의 EC를 정의역으로 가지고 치역은 자연수</em>(정확히는 finite field Fₚ) 입니다. 즉, function pairing(pointA: Point_on_EC1, pointB: Point_on_EC2): Fₚ 와 같은 function signature를 가집니다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/906/1*Ul92gj6klocy-vSMMYlt4w.png" /></figure><p>또한 EC Pairing은 아래와 같은 특징(Bilinearity)을 가집니다</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1014/1*bPseOO0BIJH_HkyxM5XSFQ.png" /></figure><p>EC Pairings를 더 자세히 이해하고 싶으시다면 <a href="https://www.computer.org/csdl/magazine/co/2022/04/09755194/1CubvXcnR9m">이 글</a>을 읽는 것을 추천합니다.</p><h4>Short Notations for elements in G₁, G₂, G_T — [ ]₁,[ ]₂,[ ]_T</h4><p>앞으로 다룰 수학적 표현에서 G₁, G₂, G_T에 속하는 각 원소들을 아래와 같은 방식으로 표기합니다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1022/1*_532b3uZ4O9qi8ApHMbAjg.png" /></figure><h3>KGZ Commitment</h3><p>KGZ Commitment는 악의적인 prover가 false positive proof를 생성할 수 있기 때문에 Trust Setup이 필요합니다. 즉, 특정한 secret s를 생성한 후 이를 기반으로 [sⁱ]₁, [sⁱ]₂ 를 생성해야합니다. 이 과정은 MPC(e.g., KGZ Ceremony) 방식으로 생성하는 것이 안전하며 s는 유출되어선 안됩니다.</p><p>[sⁱ]₁, [sⁱ]₂는 퍼블릭하게 공유하며 앞으로 필요한 연산에 사용될 것입니다. 예를 들어 다항식 P(x) = ∑ᵢⁿpᵢxⁱ을 알고있는 사람(즉, pᵢ를 아는 사람)은 s 에서의 결과인 P(s)를 계산할 수 없지만, [P(s)]₁와 [P(s)]₂를 계산 할 때는 sⁱ 대신 [sⁱ]₁, [sⁱ]₂를 이용해 계산할 수 있습니다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/952/1*BaRU3TWN_801Jr5PJMM0cg.png" /><figcaption>because c[sⁱ]₁ = csⁱG = [csⁱ]₁</figcaption></figure><p>이제 Commitment Scheme의 3가지 정의(Commitment, proof, verification equation)을 다룹니다. <strong>Prover가 Commitment, proof 를 만들어 Verifier에게 전달하고 Verifier는 verification equation를 확인해 “Commitment의 유효성”을 확인합니다.</strong></p><h4>Commitment</h4><p>다항식 P(x)에 대한 Commitment C는 아래와 같이 정의합니다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/396/1*J_HszD2YKHICt7CqmRDSIw.png" /></figure><p>이는 Merkle Tree의 Merkle Root와 동일한 의미를 가집니다. Merkle Tree의 proof-of-membership에는 (1) Merkle Root, (2) Merkle Path, (3) i번째 노드의 값(해시)이 필요합니다. proof-of-membership의 재료가 되는 (1)은 C에 대응하니 (2)와 (3)이 필요합니다.</p><p>(2)는 앞으로 설명할 proof입니다.<br>(3)은 우리가 P(x)를 생성하기 위해 사용했던 점 (i, input[i])입니다. 즉, P(i) = input[i]이고 Prover는 이를 Verifier에게 점 (z, y) 형태로 전달합니다. (z = i, y = input[i])</p><h4>Proof</h4><p>다항식 P(x)는 x=z 일 때 y입니다. 즉, 다항식 “P(x)-y”는 x=z 일 때 0입니다. 따라서 다항식 “P(x)-y”는 다항식 “x-z”로 나눌 수 있습니다. 이는 곧 어떠한 “몫 다항식 Q(x)”가 아래 형태로 존재함을 의미합니다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/238/1*zbDcjVY5pxYKnhXbVNKLWg.png" /></figure><p>다항식 P(x)에 대한 Commitment C에 대한 proof π는 아래와 같이 정의합니다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/960/1*WfKqpPPwqVof_58B97TOnw.png" /></figure><p>재미있는 점은 Commitment와 Proof 모두 단순히 특정 다항식을 G₁로 옮겨놓은 것이 불가하단 것입니다. 물론 Verifier가 <strong>“</strong><strong>C의 유효성”</strong>을 올바르게 확인하기 위해서는 아래 방정식을 확인합니다.</p><h4>Verification Equation</h4><p>Prover는 Verifier에게 C, π, (z, y) 를 전달합니다. Verifier는 아래 방정식을 통해 “C의 유효성”을 확인합니다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/460/1*Y7lIEYOGxpdVi6PkyJ2YKg.png" /><figcaption>자세한 증명은 <a href="https://hackmd.io/y5IRAkbxT02ho0JxdLyGDw?view#Verification-Equation">여기</a></figcaption></figure><p>[s-z]₂ = (s-z)H = sH-zH = [s]₂-[z]₂ 이기에 Verifier는 [s]₂와 z를 이용해 모든 연산을 수행할 수 있습니다.</p><p>지금까지 다룬 Commitment Scheme은 1개의 점 (z,y)에 대해 1개의 proof가 필요합니다. proof는 𝔾₁ 위의 점이기에 사이즈가 <strong>O(1)</strong>입니다.</p><h3>KGZ Commitment — multiproofs</h3><p>우리는 하나의 다항식 P(x)에 여러 점이 지나는 것을 알고 있습니다. n개의 점이면 n개의 π가 생깁니다. 하지만 이를 1개의 π로 압축할 수 있습니다.</p><p>Commitment C 는 이전과 동일하게 [P(s)]₁를 사용합니다.</p><h4>Proof — multiproofs</h4><p>P(x)는 k개의 점을 지나고 이는 라그랑주 보간법을 이용해 생성되었습니다. 마찬가지로 라그랑주 보간법을 이용해 <strong>I(x)</strong>를 생성합니다. <br>(라그랑주 보간법을 이용해 P(x)와 I(x)를 생성한다면 P(x) = I(x) 일 수 있습니다. 따라서 이를 피하기 위해 P(x)를 생성할 때 추가적인 항 (e.g., x∏₀ᵏ(x-xᵢ))을 붙인다면 k개의 점들을 동일하게 지나면서 두 다항식이 다르게 생성할 수 있습니다.)</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/494/1*l5mCze5bekg9vx2Zmz_-fg.png" /></figure><p>다항식 P(x)와 다항식 I(x) 모두 k개의 점을 지납니다. 즉, 다항식 “P(x)-I(x)”는 x=zᵢ 일 때 항상 0입니다. 따라서 다항식 “P(x)-I(x)”는 다항식 “<strong>Z(x)</strong>=∏₀ᵏ(x-xᵢ)”로 나누어집니다. 이는 곧 “몫 다항식 <strong>Q(x)</strong>”가 아래 형태로 존재함을 의미합니다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/247/1*RHoGkCe1AXNNvX_r277BrQ.png" /></figure><p>이제 k개의 점에 대한 multiproofs π는 아래와 같이 정의됩니다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/458/1*bk8mvLk4vhN5f8dzWlFU2w.png" /></figure><h4>Verification Equation — multiproofs</h4><p>Prover는 Verifier에게 C, π, (zᵢ, yᵢ) 를 전달합니다. Verifier는 아래 방정식을 통해 “C의 유효성”을 확인합니다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/369/1*esaLNgAroQySw4ftEvx1Qg.png" /><figcaption>자세한 증명 <a href="https://hackmd.io/y5IRAkbxT02ho0JxdLyGDw?view#%EC%A6%9D%EB%AA%851">여기</a></figcaption></figure><p>Verifier는 (zᵢ, yᵢ)를 이용해 Z(x)와 I(x)를 계산할 수 있습니다.</p><p>multiproofs π 또한 𝔾₁ 위의 점이기에 사이즈가 <strong>O(1)</strong>입니다.</p><h3>Conclusion</h3><p>지금까지 Verkle Tree에서 사용될 Polynomial Commitment Scheme(PCS)인 KZG Commitment를 살펴봤습니다. 주어진 데이터 셋(input: Array&lt;Bytes32&gt;)을 2차 평면위의 점으로 표현해 라그랑주 보간법을 사용한다면 PCS를 Vector Commitment Scheme으로도 이용할 수 있습니다. Commitment Scheme이기에 기존의 Merkle Tree의 기능을 대체할 수 있습니다.</p><p>단점으로는 Trust Setup이 필요하고 연산 시간이 O(n)에서 O(n²)로 늘어납니다. 장점으로는 proof 사이즈가 O(log(n))에서 O(1)으로 줄어들고 multiproofs를 사용한다면 여러 데이터를 한번에 reveal할 수 있습니다.</p><p><em>지금 논의한 내용만으로 구성한 </em>Verkle T<strong>rie</strong>의 Proof 사이즈가 O(1)이 아닙니다. k-ary Verkle Trie에서 동일한 parent node에 속하는 여러 children nodes에 대해 크기가 O(1)인 proof를 가지는 것 뿐입니다. 즉, π 하나는 depth 하나 올라갈 때 사용되는 것으로 depth가 2이상일 경우 더 많은 π가 필요합니다.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*9MgBNaMBPkKStHG9NKJPQQ.png" /><figcaption>이 글에서 다루고 있는 Commitment Scheme은 빨간 박스에서 한 번 적용됩니다. 위 다이어그램은 depth가 2이기에 root node까지 도달하기 위해선 2개의 2개의 π가 필요합니다. 물론 k=n일 경우 depth가 1이기에 1개의 π가 필요합니다.</figcaption></figure><p>실제 Verkle Tree(Trie)에는 더 많은 최적화 요소들이 들어갑니다. 이러한 내용들은 다음 글에서 설명하도록 하겠습니다.</p><h3>References</h3><ul><li><a href="https://www.computer.org/csdl/magazine/co/2022/04/09755194/1CubvXcnR9m">https://www.computer.org/csdl/magazine/co/2022/04/09755194/1CubvXcnR9m</a></li><li><a href="https://vitalik.ca/general/2017/01/14/exploring_ecp.html">https://vitalik.ca/general/2017/01/14/exploring_ecp.html</a></li><li><a href="https://dankradfeist.de/ethereum/2020/06/16/kate-polynomial-commitments.html">https://dankradfeist.de/ethereum/2020/06/16/kate-polynomial-commitments.html</a></li></ul><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=969ccfe91ba4" width="1" height="1" alt=""><hr><p><a href="https://medium.com/twouplabs/kgz-commitment-969ccfe91ba4">KGZ Commitment</a> was originally published in <a href="https://medium.com/twouplabs">twouplabs</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>