Vitalik 신작 속독: 다차원 Gas 가격 책정
편집:Karen,Foreisght News
이더리움에서 자원은 최근까지 제한적이었으며, "Gas"라는 단일 자원을 통해 가격이 책정되었습니다. Gas는 특정 거래나 블록을 처리하는 데 필요한 "계산량"(computational effort)을 측정하는 단위입니다. Gas는 여러 유형의 "계산량"을 통합하며, 그 중 가장 중요한 것은 다음과 같습니다:
- 원시 계산(Raw computation, 예: ADD, MULTIPLY);
- 이더리움 저장소의 읽기 및 쓰기(예: SSTORE, SLOAD, ETH 전송);
- 데이터 대역폭;
- 블록 생성의 ZK-SNARK 증명의 비용.
예를 들어, 제가 보낸 이 거래는 총 47,085 Gas를 소모했습니다. 여기에는 다음이 포함됩니다: (i) 기본 비용 21,000 Gas, (ii) 거래의 일부로 포함된 calldata 바이트가 소모한 1,556 Gas, (iii) 저장소 읽기 및 쓰기가 소모한 16,500 Gas, (iv) 로그 생성이 소모한 2,149 Gas, 나머지는 EVM 실행에 사용되었습니다. 사용자가 지불해야 하는 거래 수수료는 거래에서 소모된 Gas에 비례합니다. 하나의 블록은 최대 30,000,000 Gas를 포함할 수 있으며, Gas 가격은 EIP-1559 타겟팅 메커니즘을 통해 지속적으로 조정되어 각 블록이 평균적으로 15,000,000 Gas를 포함하도록 보장합니다.
이 방법은 주요 장점이 있습니다: 모든 것이 하나의 가상 자원으로 통합되기 때문에 시장 설계가 매우 간단합니다. 비용을 최소화하기 위해 거래를 최적화하는 것이 쉽고, 가능한 한 높은 수수료를 부과하기 위해 블록을 최적화하는 것도 상대적으로 쉽습니다(여기서 MEV는 제외됨). 또한 일부 거래가 다른 거래와 묶여 비용을 절감하도록 유도하는 이상한 인센티브 메커니즘이 없습니다.
그러나 이 방법은 비효율성도 존재합니다: 서로 다른 자원을 상호 변환할 수 있는 것으로 간주하지만, 실제 기본 제한은 다릅니다. 이 문제를 이해하기 위해 아래의 차트를 먼저 살펴보세요:
Gas 제한은 제약 조건을 부과합니다:
실제 기본 보안 제약은 일반적으로 다음과 더 가깝습니다:
이러한 차이는 Gas 제한이 실제 보안 블록을 무작정 배제하거나, 실제로 안전하지 않은 블록을 수용하거나, 두 가지 모두를 초래합니다.
n개의 자원이 서로 다른 보안 제한을 가진 경우, 일차원 Gas는 처리량을 최대 n배 감소시킬 수 있습니다. 따라서 오랫동안 다차원 Gas 개념에 대한 관심이 있었으며, EIP-4844를 통해 우리는 이제 이더리움에서 실제로 다차원 Gas를 구현했습니다. 본 문서는 이 방법의 장점과 향후 강화 가능성을 탐구합니다.
Blob: Dencun의 다차원 Gas
올해 초, 평균 블록 크기는 150 kB였습니다. 그 중 상당 부분은 Rollup 데이터로, Layer2 프로토콜이 체인에 데이터를 저장합니다. 이러한 데이터는 매우 비쌉니다: Rollup에서의 거래 비용은 이더리움 L1에서의 해당 거래의 5-10배에 불과하지만, 이러한 비용조차도 많은 사용 사례에 대해 너무 높습니다.
그렇다면 왜 Rollup을 더 저렴하게 만들기 위해 calldata의 Gas 비용(현재 비제로 바이트는 16 Gas, 제로 바이트는 4 Gas)을 낮추지 않을까요? 우리는 이전에 그렇게 했고, 지금도 다시 그렇게 할 수 있습니다. 그러나 여기서의 대답은: 블록의 최대 크기는 30,000,000/16=1,875,000 비제로 바이트이며, 네트워크는 이러한 크기의 블록을 간신히 처리할 수 있습니다. 비용을 4배 더 낮추면 최대값이 7.5 MB로 증가하여 보안에 큰 위험을 초래합니다.
이 문제는 각 블록에 Rollup 친화적인 독립 데이터 공간(Blob이라고 함)을 도입함으로써 해결되었습니다.
이 두 자원은 서로 다른 가격과 제한을 가지고 있습니다: Dencun 하드포크 이후, 하나의 이더리움 블록은 최대 (i) 30,000,000 Gas와 (ii) 6개의 Blob을 포함할 수 있으며, 각 Blob은 약 125 kB의 calldata를 포함할 수 있습니다. 이 두 자원은 별도의 가격을 가지고 있으며, EIP-1559와 유사한 별도의 가격 책정 메커니즘을 통해 조정되어 각 블록이 평균적으로 15,000,000 Gas와 3개의 Blob을 사용하도록 목표를 설정합니다.
결과적으로 Rollup의 비용은 100배 감소하였고, Rollup에서의 거래량은 3배 이상 증가했으며, 이론적인 최대 블록 크기는 약간 증가하여 약 1.9 MB에서 약 2.6 MB로 증가했습니다.
주: Rollup 거래 수수료는 Growthepie.xyz에서 제공. Dencun 하드포크는 2024년 3월 13일에 발생하여 다차원 가격 책정 Blob을 도입했습니다.
다차원 Gas와 무상태 클라이언트
가까운 미래에 무상태 클라이언트(stateless clients)의 저장소 증명도 유사한 문제에 직면할 것입니다. 무상태 클라이언트는 로컬에 대량의 데이터나 아무 데이터도 저장하지 않고 체인을 검증할 수 있는 새로운 유형의 클라이언트입니다. 무상태 클라이언트는 해당 블록에서 거래가 접근해야 하는 이더리움 상태의 특정 부분에 대한 증명을 수용함으로써 이를 달성합니다.
위 이미지는 무상태 클라이언트가 블록을 수신하고, 해당 블록 실행에 필요한 상태의 특정 부분(예: 계좌 잔액, 코드, 저장소)의 현재 값에 대한 증명을 보여줍니다. 이를 통해 노드는 저장소 없이 블록을 검증할 수 있습니다.
저장소 읽기 한 번에는 2,100-2,600 Gas가 소모되며, 이는 읽기 유형에 따라 다릅니다. 저장소 쓰기는 더 높은 비용이 듭니다. 평균적으로 하나의 블록은 약 1,000회의 저장소 읽기 및 쓰기 작업을 수행합니다(ETH 잔액 확인, SSTORE 및 SLOAD 호출, 계약 코드 읽기 및 기타 작업 포함). 그러나 이론적인 최대값은 30,000,000/2,100=14,285회 읽기입니다. 무상태 클라이언트의 대역폭 부하는 이 숫자에 비례합니다.
현재 계획은 이더리움의 상태 트리 설계를 Merkle Patricia 트리에서 Verkle 트리로 전환하여 무상태 클라이언트를 지원하는 것입니다. 그러나 Verkle 트리는 양자 저항성이 없으며, 최신 STARK 증명 시스템에 최적의 선택이 아닙니다. 따라서 많은 사람들이 이진 Merkle 트리와 STARK를 통해 무상태 클라이언트를 지원하는 데 관심을 가지고 있으며, Verkle를 완전히 건너뛰거나 Verkle로 몇 년 동안 전환한 후 STARK가 더 성숙해지면 업그레이드를 고려하고 있습니다.
이진 해시 트리 분기 기반의 STARK 증명은 많은 장점을 가지고 있지만, 그 핵심 약점은 증명을 생성하는 데 오랜 시간이 걸린다는 것입니다: Verkle 트리는 초당 100,000개 이상의 값을 증명할 수 있지만, 해시 기반 STARK는 일반적으로 초당 몇 천 개의 해시만 증명할 수 있으며, 각 값을 증명하려면 많은 해시의 "분기"(branch)를 포함해야 합니다.
오늘날 Binius 및 Plonky3와 같은 초최적화 증명 시스템과 Vision-Mark-32와 같은 전용 해시에서 예측된 수치를 고려할 때, 우리는 한동안 초당 1,000개의 값을 증명하는 것이 가능할 것으로 보이지만, 14,285개의 값을 증명하는 것은 불가능할 것입니다. 평균 블록은 문제 없지만, 잠재적으로 최악의 경우 블록(공격자가 발행한 블록)은 네트워크를 파괴할 것입니다.
이러한 상황을 처리하는 기본 방법은 재가격 책정입니다: 저장소 읽기 비용을 높여 각 블록의 최대값을 더 안전한 수준으로 줄이는 것입니다. 그러나 우리는 이미 여러 번 그렇게 했으며, 다시 그렇게 하면 너무 많은 애플리케이션이 너무 비싸질 것입니다. 더 나은 방법은 다차원 Gas입니다: 저장소 접근에 대해 각각 제한하고 요금을 부과하여 평균 사용량을 각 블록당 1,000회의 저장소 접근으로 유지하되, 각 블록의 상한을 설정하는 것입니다(예: 2,000회).
다차원 Gas의 보편성
고려해야 할 또 다른 자원은 상태 크기의 증가입니다: 즉, 이더리움 상태 크기를 증가시키는 작업으로, 이러한 작업 후에는 전체 노드가 이를 저장해야 합니다. 상태 크기 증가의 독특한 점은 이를 제한하는 이유가 전적으로 장기적인 지속적 사용에서 비롯된다는 것입니다.
따라서 상태 크기를 증가시키는 작업(예: zero-to-non-zero SSTORE, 계약 생성)에 대해 별도의 Gas 차원을 추가하는 것이 유용할 수 있지만, 목표는 다릅니다: 특정 평균 사용량을 목표로 하는 변동 가격을 설정할 수 있지만, 각 블록의 제한을 전혀 설정하지 않을 수 있습니다.
이는 다차원 Gas의 강력한 속성을 보여줍니다: 각 자원에 대해 (i) 이상적인 평균 사용량은 얼마인가? (ii) 각 블록의 안전한 최대 사용량은 얼마인가?를 별도로 질문할 수 있습니다. 각 블록의 최대값에 따라 Gas 가격을 설정하고 평균 사용량이 그에 따라 따라가는 것과는 달리, 우리는 2n 자유도를 가지고 2n 매개변수를 설정하여 네트워크 보안에 대한 고려에 따라 각 매개변수를 조정할 수 있습니다.
두 가지 자원의 보안 고려가 부분적으로 합산되는 더 복잡한 경우에는, 하나의 작업 코드 또는 자원이 여러 유형의 Gas를 소비하도록 하여 처리할 수 있습니다(예: zero-to-non-zero SSTORE는 5,000개의 무상태 클라이언트 증명 Gas와 20,000개의 저장소 확장 Gas를 소비할 수 있습니다).
각 거래의 Max(데이터 또는 계산 소비가 더 큰 것을 선택)
𝑥1을 데이터의 Gas 비용, 𝑥2를 계산 Gas 비용이라고 가정하면, 일차원 Gas 시스템에서 우리는 거래의 Gas 비용을 다음과 같이 쓸 수 있습니다:
이 계획에서 우리는 거래의 Gas 비용을 다음과 같이 정의합니다:
즉, 거래는 데이터와 계산의 합계가 아니라, 소비된 두 자원 중 더 많은 자원에 따라 요금이 부과됩니다. 이는 더 많은 차원을 포함하도록 쉽게 확장할 수 있습니다(예: 𝑚𝑎𝑥(…,𝑥3∗𝑠𝑡𝑜𝑟𝑎𝑔𝑒_𝑎𝑐𝑐𝑒𝑠𝑠)).
안전성을 보장하면서 처리량을 높이는 방법이 어떻게 되는지 쉽게 알 수 있습니다. 이론적으로 하나의 블록에서 최대 데이터량은 여전히 Gas LIMIT /𝑥1로, 일차원 Gas 계획과 완전히 동일합니다. 유사하게, 이론적인 최대 계산량은 Gas LIMIT /𝑥2로, 역시 일차원 Gas 계획과 완전히 동일합니다. 그러나 데이터와 계산을 소비하는 거래의 Gas 비용은 감소합니다.
이는 제안된 EIP-7623에서 채택된 계획으로, 최대 블록 크기를 줄이면서 Blob 수를 추가로 증가시키는 것입니다. EIP-7623의 정확한 메커니즘은 약간 복잡하지만, 현재 calldata 가격을 바이트당 16 Gas로 유지하면서 바이트당 48 Gas의 바닥 가격을 추가합니다; 거래는 (16 * bytes + execution_Gas)와 (48 * bytes) 중 더 높은 금액을 지불합니다. 따라서 EIP-7623는 블록 내 이론 최대 거래 호출 데이터를 약 1.9 MB에서 약 0.6 MB로 줄이면서 대부분의 애플리케이션의 비용은 변하지 않도록 합니다. 이 방법의 장점은 현재의 일차원 Gas 계획과 비교할 때 변화가 매우 적어 구현이 매우 용이하다는 것입니다.
그러나 이 방법에는 두 가지 단점이 있습니다:
- 블록 내의 다른 모든 거래가 이 자원을 거의 사용하지 않더라도, 많은 자원을 차지하는 거래는 여전히 불필요하게 많은 비용을 부과받습니다;
- 데이터 집약적이고 계산 집약적인 거래가 비용을 절감하기 위해 하나의 번들로 결합되도록 유도합니다.
저는 EIP-7623와 같은 규칙이 거래 calldata나 다른 자원에 대해 충분한 이점을 가져올 수 있다고 생각하며, 이러한 단점이 있더라도 그만한 가치가 있다고 믿습니다.
그러나 우리가 (상당히 더 높은) 개발 노력을 기울일 의향이 있다면, 더 이상적인 방법이 나타날 수 있습니다.
다차원 EIP-1559: 더 어렵지만 이상적인 전략
먼저 일반 EIP-1559의 작동 방식을 살펴보겠습니다. 우리는 EIP-4844에서 Blob에 대해 도입된 버전에 초점을 맞출 것입니다. 이는 수학적으로 더욱 우아합니다.
우리는 하나의 매개변수 excess_blobs를 추적합니다. 각 블록 동안 우리는 다음과 같이 설정합니다:
excessblobs \<-- max(excessblobs + len(block.blobs) - TARGET, 0)
여기서 TARGET = 3입니다. 즉, 특정 블록의 Blob 수가 목표보다 많으면 excessblobs가 증가하고, 특정 블록의 Blob 수가 목표보다 적으면 excessblobs가 감소합니다. 그런 다음 우리는 blobbasefee = exp(excessblobs / 25.47)로 설정합니다. 여기서 exp는 지수 함수 𝑒𝑥𝑝(𝑥)=2.71828\^𝑥의 근사값입니다.
즉, excessblobs가 약 25 증가할 때마다 blob 기본 비용이 약 2.7배 증가합니다. Blob이 너무 비싸지면 평균 사용량이 감소하고, excessblobs가 감소하기 시작하여 자동으로 가격이 다시 낮아집니다. Blob의 가격은 지속적으로 조정되어 평균적으로 블록이 반쯤 차도록 보장합니다. 즉, 각 블록은 평균적으로 3개의 Blob을 포함합니다.
사용량에 단기적인 피크가 발생하면 제한이 생깁니다: 각 블록은 최대 6개의 Blob만 포함할 수 있으며, 이 경우 거래는 우선 수수료를 높여 서로 경쟁할 수 있습니다. 그러나 정상적인 경우, 각 Blob은 blob_basefee와 함께 소량의 추가 우선 수수료만 지불하면 됩니다.
이러한 Gas 가격 책정은 이더리움에서 수년간 존재해왔습니다: 2020년 초, EIP-1559는 매우 유사한 메커니즘을 도입했습니다. EIP-4844를 통해 우리는 Gas와 Blob에 대해 두 개의 독립적인 변동 가격을 설정했습니다.
주: 2024년 5월 8일 한 시간 동안의 Gas 기본 비용, 단위는 gwei입니다. 출처: ultrasound.money
원칙적으로 우리는 저장소 읽기 및 기타 유형의 작업에 대해 더 많은 독립 변동 비용을 추가할 수 있지만, 다음 섹션에서 주의해야 할 문제를 자세히 설명하겠습니다.
사용자에게는 이러한 경험이 오늘날과 매우 유사합니다: 기본 비용(basefee)을 더 이상 지불하지 않고 두 가지 기본 비용을 지불하지만, 지갑은 이를 사용자로부터 추상화하여 예상 지불 비용과 최대 비용만 표시할 수 있습니다.
블록 생성자에게는 대부분의 경우 최상의 전략이 오늘과 동일합니다: 유효한 내용을 포함합니다. 대부분의 블록은 Gas나 Blob 모두 가득 차지 않습니다. 도전적인 상황은 충분한 Gas 또는 충분한 Blob이 블록 제한을 초과할 때 발생하며, 생성자는 잠재적으로 다차원 배낭 문제를 해결하여 이익을 극대화해야 합니다. 그러나 상당히 좋은 근사 알고리즘이 존재하더라도, 이 경우 독점 알고리즘을 통해 이익을 최적화하여 얻는 수익은 MEV를 사용하여 동일한 작업을 수행하여 얻는 수익보다 훨씬 적습니다.
개발자에게 주요 도전 과제는 현재 단일 가격과 단일 제한 설계를 기반으로 하는 EVM 및 관련 인프라 기능을 재설계해야 한다는 것입니다. 이제는 여러 가격과 여러 제한에 적응할 수 있는 설계로 변경해야 합니다.
응용 프로그램 개발자가 직면하는 문제는 최적화가 약간 어려워진다는 것입니다: 특정 경우에 A가 B보다 더 효율적이라고 명확하게 말할 수 없기 때문입니다. A가 더 많은 calldata를 사용하고 B가 더 많은 실행을 사용하는 경우, calldata가 저렴할 때는 A가 더 저렴할 수 있지만, calldata가 비쌀 때는 A가 더 비쌀 수 있습니다.
그러나 개발자는 여전히 장기적인 역사적 평균 가격을 기반으로 최적화를 통해 상당히 좋은 결과를 얻을 수 있습니다.
다차원 가격 책정, EVM 및 서브 호출
Blob에서는 발생하지 않는 문제가 있으며, EIP-7623 또는 심지어 calldata에 대한 완전한 다차원 가격 책정 구현에서도 발생하지 않지만, 상태 접근이나 기타 자원에 대해 개별 가격 책정을 시도할 경우 이 문제가 발생합니다: 즉, 서브 호출(sub-calls) 내의 Gas 제한입니다.
EVM의 Gas 제한은 두 곳에 존재합니다. 첫째, 각 거래는 Gas 제한(Gas Limit)을 설정하여 해당 거래에서 사용할 수 있는 Gas의 총량을 제한합니다. 둘째, 계약이 다른 계약을 호출할 때, 해당 호출은 자체 Gas 제한을 설정할 수 있습니다. 이를 통해 계약은 신뢰하지 않는 다른 계약을 호출할 수 있으며, 호출 후에도 다른 계산을 수행하기 위해 남은 Gas를 보장받을 수 있습니다.
주: 계좌 추상화 거래의 흔적, 한 계좌가 다른 계좌를 호출하고, 호출된 계좌에 한정된 수의 Gas만 제공하여 호출된 계좌가 할당된 모든 Gas를 소모하더라도 외부 호출이 계속 실행될 수 있도록 보장합니다.
도전 과제는: 서로 다른 유형의 실행 간에 다차원 Gas를 구현하려면 서브 호출이 각 유형의 Gas에 대해 여러 제한을 제공해야 할 것 같습니다. 이는 EVM에 매우 깊은 변경을 요구하며, 기존 애플리케이션과 호환되지 않을 것입니다.
이것이 다차원 Gas 제안이 일반적으로 두 가지 차원, 즉 데이터와 실행에 머무르는 이유 중 하나입니다: 데이터(거래 calldata 또는 Blob)는 EVM 외부에서만 할당되므로 EVM 내부에서 아무것도 변경하지 않고도 calldata 또는 Blob을 개별적으로 가격 책정할 수 있습니다.
우리는 이 문제를 해결하기 위한 "EIP-7623 스타일의 해결책"을 생각해낼 수 있습니다. 이는 간단한 구현입니다: 실행 중에 저장소 작업에 대해 4배의 비용을 부과합니다; 분석을 단순화하기 위해 각 저장소 작업에 10,000 Gas가 소모된다고 가정합니다. 거래가 끝날 때, 환불은 min(7,500 * storageoperations, executionGas)입니다. 결과적으로 환불을 차감한 후 사용자가 지불해야 하는 비용은 다음과 같습니다:
executionGas + 10,000 * storageoperations - min(7,500 * storageoperations, executionGas)
이는 다음과 같습니다:
max(executionGas + 2,500 * storageoperations, 10,000 * storage_operations)
이는 EIP-7623의 구조를 반영합니다. 또 다른 방법은 storageoperations와 executionGas를 실시간으로 추적하고, 당시 max(executionGas + 2,500 * storageoperations, 10,000 * storage_operations)가 얼마나 상승하는지에 따라 2,500 또는 10,000을 부과하는 것입니다. 작업 코드가 호출됩니다. 이는 거래가 Gas를 과도하게 할당할 필요가 없도록 하며, 이러한 Gas는 주로 환불을 통해 회수됩니다.
우리는 서브 호출에 대한 세밀한 허가를 얻지 못했습니다: 서브 호출은 거래의 모든 할당량을 소모하여 저렴한 저장소 작업을 수행할 수 있습니다.
그러나 우리는 서브 호출을 수행하는 계약이 제한을 설정하고, 서브 호출이 완료된 후에도 주 호출이 필요한 후처리를 수행할 수 있는 충분한 Gas를 보장할 수 있다는 점에서 충분히 좋은 것을 얻었습니다(post-processing).
제가 생각할 수 있는 가장 간단한 "완전한 다차원 가격 책정 솔루션"은 서브 호출 Gas 제한을 비례적으로 간주하는 것입니다. 즉, 𝑘개의 서로 다른 실행 유형이 있다고 가정하고 각 거래가 다차원 제한 𝐿1…𝐿𝑘을 설정합니다. 현재 실행 지점에서 남은 Gas를 𝑔1…𝑔𝑘이라고 가정합니다. CALL 작업 코드를 호출하고 서브 호출 Gas 제한을 𝑆로 사용합니다. 그러면 𝑠1=𝑆, 𝑠2=𝑠1/𝑔1∗𝑔2, 𝑠3=𝑠1/𝑔1∗𝑔3, 이렇게 계속됩니다.
즉, 우리는 첫 번째 유형의 Gas(실제로는 VM 실행)를 특별한 "계좌 단위"로 간주하고, 다른 유형의 Gas를 할당하여 서브 호출이 각 유형의 Gas에서 동일한 비율의 사용 가능한 Gas를 얻도록 합니다. 이 방법은 다소 보기 흉하지만(ugly), 최대한의 하위 호환성을 보장합니다.
우리가 하위 호환성을 희생하지 않고 이 계획을 서로 다른 유형의 Gas 간에 더 "중립적"으로 만들고 싶다면, 서브 호출의 Gas 제한 매개변수를 현재 컨텍스트에서 남은 Gas의 일부로 단순히 표현할 수 있습니다(예: [1…63]/64).
그러나 어떤 경우든, 다차원 실행 Gas를 도입하기 시작하면 내재적인 복잡성(ugliness)이 증가한다는 점을 강조할 가치가 있습니다. 이는 피할 수 없는 것처럼 보입니다.
따라서 우리의 과제는 복잡한 균형을 이루는 것입니다: EVM 수준에서 어떤 정도의 복잡성(ugliness) 증가를 수용하여 안전하게 상당한 L1 확장성 이득을 잠금 해제할 것인지, 그렇다면 어떤 구체적인 제안이 프로토콜 경제와 애플리케이션 개발자에게 가장 효과적일 것인지입니다. 제가 위에서 언급한 두 가지 제안이 최선이 아닐 가능성이 높지만, 여전히 더 우아하고 나은 제안을 제시할 여지가 있습니다.
특별히 Ansgar Dietrichs, Barnabe Monnot, Davide Crapis의 피드백과 검토에 감사드립니다.