이더리움은 어떻게 작동합니까? (2)
Last updated
Last updated
이더리움에서 매우 중요한 개념은 수수료의 개념입니다. 이더리움 네트워크에서 거래에 사용되는 계산에는 수수료가 발생합니다. 속담에 따르면 세상에 공짜 점심은 없습니다. 지불된 요금은 "가스"로 계산됩니다.
가스는 특정 계산의 비용을 측정하는 데 사용되는 단위입니다. 가스 가격은 "gwei"로 측정한 가스 단위당 지출할 의향이 있는 Ether의 총량입니다. "Wei"는 Ether의 가장 작은 단위이며 1^018 Wei는 1 Ether를 나타냅니다. 1gwei는 1,000,000,000Wei입니다.
각 거래에 대해 거래 발신자(송신기)가 가스 한도와 가스 가격을 설정합니다. 가스 가격과 가스 한도는 송금인이 거래에 대해 지불할 의향이 있는 최대 Wei 금액을 나타냅니다. 예를 들어 발신자가 가스 한도를 50,000으로 설정하고 가스 가격을 20gwei로 설정했다고 가정해 보겠습니다. 이는 트랜잭션 발신자가 최대 50,000*20gwei=1,000,000,000,000,000Wei를 지불할 용의가 있음을 의미하며 이는 트랜잭션을 실행하는 데 0.001Ether입니다.
가스 한도는 거래를 보낸 사람이 지불할 의사가 있는 최대 수수료를 나타냅니다. 계정 잔액이 이 최대 금액을 충당할 수 있다면 문제가 없습니다. 거래가 끝나면 보낸 사람은 사용하지 않은 가스 자금을 환불 받고 원래 가격으로 거래합니다.
트랜잭션 발신자가 트랜잭션을 실행하기에 충분한 가스를 제공하지 않으면 트랜잭션에 가스가 부족하여 트랜잭션이 무효화됩니다. 이 경우 트랜잭션 프로세스가 중단되고 발생한 모든 상태 변경이 취소되어 트랜잭션이 종료되고 트랜잭션 이전의 이더리움 상태가 반환됩니다. 또한 트랜잭션 실패가 기록되어 시작하려고 시도한 트랜잭션과 실패한 위치를 보여줍니다. 동시에 기계는 가스가 다 떨어지기 전에 계산을 수행하기 위해 노력을 기울였기 때문에 논리적으로 이러한 소비된 가스는 거래를 보낸 사람에게 환불되지 않습니다.
가스 자금은 어디로 갔습니까? 거래 발신자가 사용한 모든 가스 자금은 일반적으로 광부의 주소인 "수혜자" 주소로 전송됩니다. 채굴자들은 거래를 계산하고 검증하기 위해 노력을 기울이기 때문에 채굴자들은 보상으로 가스 요금을 부과합니다.
일반적으로 거래 발신자가 지불하려는 가스 가격이 높을수록 채굴자가 거래에서 더 많은 가치를 얻습니다. 따라서 광부도 높은 가격의 거래를 선택합니다. 이러한 방식으로 광부는 검증하려는 거래를 자유롭게 선택할 수 있습니다. 가스 가격을 설정하는 거래 발신자를 안내하기 위해 광부는 거래를 실행할 최저 가스 가격을 광고하도록 선택할 수 있습니다.
보관료도 있습니다.
가스는 계산 단계 비용을 지불할 뿐만 아니라 저장 비용을 지불하는 데에도 사용됩니다. 전체 스토리지 비용은 사용된 32바이트의 최소 배수에 비례합니다.
저장 비용에는 약간의 뉘앙스가 있습니다. 예를 들어, 스토리지를 늘리면 모든 노드에 대한 이더리움 상태 데이터베이스의 크기가 증가하므로 데이터 스토리지를 작게 유지하려는 인센티브가 있습니다. 따라서 트랜잭션에 저장 항목을 지울 수 있는 단계가 있는 경우 해당 작업에 대한 수수료가 면제되고 저장 공간을 확보하기 위해 수수료를 환불받을 수 있습니다.
이더리움 운영의 중요한 측면은 네트워크에서 수행되는 모든 작업이 모든 전체 노드에 의해 동시에 영향을 받는다는 것입니다. 그러나 이더리움 가상 머신의 계산 단계는 매우 비쌉니다.
따라서 이더리움 스마트 계약은 네트워크에 스트레스를 주는 파일 저장, 이메일, 머신 러닝 등과 같은 복잡한 용도보다는 단순한 비즈니스 로직을 실행하거나 서명 및 기타 암호화된 객체를 확인하는 것과 같은 간단한 작업에 가장 적합합니다. 수수료를 부과하면 사용자가 네트워크를 과도하게 사용하는 것을 방지할 수 있습니다.
이더리움은 튜링 완전 언어입니다. 간단히 말해서 튜링 기계는 모든 컴퓨터 알고리즘을 시뮬레이션할 수 있는 기계입니다. 이것은 루핑을 허용하고 이더리움을 지연 문제에 취약하게 만들어 프로그램이 무기한 실행되는지 여부를 확신할 수 없게 만듭니다. 수수료 없이 악의적인 행위자는 비용에 대한 걱정 없이 트랜잭션에서 무한 루프를 실행하여 네트워크를 쉽게 교란시키려고 시도할 수 있습니다. 따라서 수수료는 악의적인 공격으로부터 네트워크를 보호합니다. "왜 우리는 여전히 스토리지 비용을 지불해야 합니까?"라고 생각할 수도 있습니다. 글쎄요, 컴퓨팅과 마찬가지로 이더리움 네트워크의 스토리지에는 비용이 있으며 전체 네트워크가 부담해야 합니다.
Ethereum은 트랜잭션 기반 상태 머신입니다. 다시 말해, 서로 다른 계정 간에 발생하는 트랜잭션은 이더리움의 글로벌 상태를 한 상태에서 다른 상태로 푸시합니다.
가장 기본적인 의미에서 트랜잭션은 외부 계정에 의해 생성되고 직렬화된 다음 블록체인에 커밋되는 암호로 서명된 명령입니다. 트랜잭션에는 메시지 호출과 계약 생성(즉, 새로운 이더리움 계약을 생성하는 트랜잭션)의 두 가지 유형이 있습니다.
모든 트랜잭션에는 유형에 관계없이 다음 부분이 포함됩니다.
Nonce: 트랜잭션을 보낸 사람이 보낸 트랜잭션 수입니다.
Gasprice: 거래를 실행하는 데 필요한 각 가스 단위에 대해 거래 발신자가 지불할 의향이 있는 Wei의 양.
Gaslimit: 트랜잭션을 보낸 사람이 트랜잭션을 실행하기 위해 지불할 용의가 있는 최대 가스 양입니다. 수량은 계산이 완료되기 전에 설정되고 선불되며 결정됩니다.
받는 사람: 받는 사람의 주소입니다. 컨트랙트를 생성하기 위한 트랜잭션이라면 컨트랙트 계정 주소가 아직 존재하지 않으므로 null 값을 사용한다.
값: 발신자에서 수신자에게 전송된 Wei의 총량. 계약 생성 트랜잭션에서 이 값은 새로 생성된 계약 계정의 초기 잔액으로 사용됩니다.
V,r,s: 트랜잭션의 발신자를 식별하는 서명을 생성하는 데 사용됩니다.
Init: 계약 생성에만 사용되는 트랜잭션입니다. 새 계약 계정을 초기화하는 데 사용할 수 있는 EVM 코드 스니펫입니다. 초기화는 한 번만 허용되고 폐기됩니다. init가 처음 실행되면 계약 계정과 영구적으로 연결된 계정 코드의 본문을 반환합니다.
데이터: 메시지 호출 전용 선택적 필드입니다. 메시지 호출의 입력 데이터(즉, 매개변수)를 나타냅니다. 예를 들어 스마트 계약이 도메인 이름 등록 서비스 역할을 하는 경우 계약을 호출할 때 도메인 이름 또는 IP 주소와 같은 입력 필드가 필요할 수 있습니다.
계정에 관한 장에서 우리는 메시지 호출이나 계약을 생성하는 트랜잭션과 같은 트랜잭션이 항상 외부 계정에 의해 시작되고 블록체인에 커밋된다는 것을 배웠습니다. 그것에 대해 생각하는 또 다른 방법은 이러한 트랜잭션이 외부 세계와 내부 이더리움 사이의 다리 역할을 한다는 것입니다.
그러나 이것이 이러한 계약이 다른 계약과 통신할 수 없다는 것을 의미하지는 않습니다. Ethereum 상태의 범위에 존재하는 계약은 동일한 범위의 다른 계약과 통신할 수 있습니다. 그들이 통신하는 방법은 "메시지" 또는 "내부 거래"를 통한 것입니다. 메시지나 내부 트랜잭션을 트랜잭션과 유사하게 생각할 수 있지만 주요 차이점은 외부 계정에서 생성되지 않는다는 것입니다. 대신 계약에 의해 생성됩니다. 가상 객체이며 트랜잭션과 달리 직렬화되지 않고 이더리움 실행 환경에만 존재합니다.
컨트랙트가 내부 트랜잭션을 다른 컨트랙트로 보낼 때 수신자의 컨트랙트 계정과 연결된 코드가 실행됩니다.
내부 트랜잭션이나 메시지에는 gaslimit가 포함되어 있지 않습니다. 가스 한도는 원래 계약의 외부 작성자, 즉 일부 외부 계정에 의해 결정되기 때문입니다. 외부 계정에 의해 설정된 gaslimit는 트랜잭션으로 인해 발생하는 하위 실행을 포함하는 트랜잭션을 실행할 수 있을 만큼 충분히 높아야 합니다. 예를 들어 계약 간 메시지.
트랜잭션 및 메시지 체인에서 특정 메시지 실행에 가스가 부족하면 실행에 의해 트리거된 후속 메시지를 포함하여 메시지 실행이 복원됩니다. 그러나 상위 실행은 복원할 필요가 없습니다.
모든 트랜잭션은 블록으로 함께 그룹화됩니다. 블록체인은 서로 연결된 일련의 블록으로 구성됩니다. 이더리움에서 블록에는 다음이 포함됩니다.
블록 헤더
블록에 포함된 일련의 트랜잭션에 대한 정보
현재 블록의 ommers에 대한 다른 블록 헤더 세트
옴머가 도대체 뭔가요? ommer는 상위 블록이 현재 블록의 상위 블록의 상위 블록과 동일한 블록입니다. ommer의 용도와 블록에 ommer용 블록 헤더가 포함된 이유에 대해 간략히 살펴보겠습니다.
이더리움이 구축되는 방식으로 인해 블록 시간은 블록당 약 15초인 반면 비트코인의 블록 시간은 블록당 10분으로 다른 블록체인보다 짧습니다. 이를 통해 더 빠른 트랜잭션 속도를 가질 수 있습니다. 그러나 짧은 블록 시간의 한 가지 단점은 채굴자가 더 많은 경쟁 블록을 찾을 수 있다는 것입니다. 이러한 경쟁 블록은 "고아 블록"(즉, 메인 체인에 포함되지 않는 채굴 블록)이라고도 합니다.
ommers의 목적은 이러한 고아 블록을 포함하는 광부에게 보상을 제공하는 것입니다. 광부가 포함하는 ommers는 "유효"해야 합니다. 즉, 현재 블록의 6세대 이내 또는 그 미만이어야 합니다. 6세대가 지나면 오래된 트랜잭션을 포함하는 것이 복잡해지기 때문에 오래된 고아 블록은 더 이상 참조되지 않습니다. Ommer 블록은 전체 블록보다 적은 보상을 받습니다. 그럼에도 불구하고 채굴자들이 이러한 고아 블록을 포함하고 보상을 받을 인센티브가 있습니다.
블록으로 돌아가자. 모든 블록에는 블록 헤더가 있다고 이전에 언급했는데 정확히 무엇입니까?
블록 헤더는 블록의 일부이며 다음을 포함합니다.
parentHash: 상위 블록 헤더의 해시 값(블록을 체인으로 만드는 것)
ommersHash: 현재 블록의 ommers 목록의 해시 값
수취인 : 마이닝 수수료를 받는 계좌 주소
stateRoot: 상태 트라이의 루트 노드의 해시 값(상태 트라이는 블록 헤더에 저장되고 업데이트됩니다. 라이트 클라이언트가 상태를 확인하는 데 편리한 모든 정보)
transactionRoot: 블록에 나열된 모든 트랜잭션을 포함하는 트리의 루트 노드 해시
ReceiptsRoot: 블록에 나열된 모든 트랜잭션 영수증을 포함하는 트리의 루트 노드 해시
logsBloom: 로그 정보를 포함하는 블룸 필터(데이터 구조)
난이도: 블록의 난이도
number: 현재 블록의 개수(제네시스 블록의 블록 번호는 0이고 그 이후의 각 블록은 순서대로 증가합니다)
gasLimit: 블록당 현재 가스리민트
timestamp: 블록 시작의 유닉스 타임스탬프
extraData: 블록과 관련된 추가 데이터
mixHash: nonce와 결합될 때 블록에 대해 충분한 계산이 수행되었음을 증명하는 해시 값이기도 합니다.
nonce: 또한 mixHash와 결합될 때 블록에 대해 충분한 계산이 수행되었음을 증명하는 해시 값입니다.
각 블록 헤더에 세 가지 trie 구조가 어떻게 포함되어 있는지 주목하십시오.
상태(stateRoot)
트랜잭션(transactionRoot)
영수증(receiptsRoot)
이러한 트라이 구조는 앞서 언급한 Merkle Patricia 시도일 뿐입니다. 또한, 위의 설명에서 일부 용어를 명확히 할 필요가 있습니다.
이더리움은 로그를 통해 다양한 트랜잭션과 메시지를 쉽게 추적할 수 있습니다. 계약은 "이벤트"를 정의하여 로그를 명확하게 생성할 수 있습니다. 여기서 "이벤트"는 로그를 기록하기 위한 것입니다.
log 항목에는 다음이 포함됩니다.
로거의 계정 주소
이 트랜잭션에 의해 수행된 다양한 이벤트를 나타내는 일련의 테마
이러한 이벤트와 관련된 모든 데이터
로그는 효율적인 방식으로 끝없는 로그 데이터를 저장하는 블룸 필터에 저장됩니다.
블록 헤더에 저장된 로그는 트랜잭션 영수증에 포함된 로그 정보에서 파생됩니다. 상점에서 구매 영수증을 받는 것처럼 이더리움은 모든 거래에 대해 영수증을 생성합니다. 예상대로 각 영수증에는 거래에 대한 몇 가지 정보가 포함되어 있습니다. 영수증에는 다음이 포함됩니다.
블록 번호
블록 해시
트랜잭션 해시
현재 거래에서 사용한 가스
현재 트랜잭션이 실행된 후 현재 블록이 사용하는 누적 가스
현재 트랜잭션을 실행할 때 생성되는 로그
......그리고 더 많은
블록의 "난이도"는 일관성을 달성하는 데 사용되며, 이를 통해 블록을 검증하는 데 걸리는 시간이 거의 동일합니다. 제네시스 블록 난이도는 131,072이며, 이후 각 블록의 채굴 난이도를 계산하기 위해 특별한 공식이 사용됩니다. 이더리움 프로토콜은 블록이 이전 블록보다 빠르게 검증되면 블록 난이도를 높입니다.
블록 난이도는 채굴자가 블록을 채굴할 때 PoW 알고리즘을 사용하여 계산해야 하는 해시 값인 nonce에 영향을 줍니다. 블록 난이도와 논스 사이의 관계는 수학적으로 다음과 같이 공식화될 수 있습니다.
여기서 Hd는 난이도입니다.
난이도 임계값을 충족하는 nonce를 찾는 유일한 방법은 PoW 알고리즘을 사용하여 모든 가능성을 소진하는 것입니다. 솔루션을 찾는 데 예상되는 시간은 난이도에 비례합니다. 난이도가 높을수록 nonce를 찾기가 더 어렵고 블록을 검증하기가 더 어려워 새로운 블록을 검증하는 데 더 오래 걸립니다. 따라서 블록의 난이도를 조정함으로써 프로토콜은 블록을 검증하는 데 걸리는 시간을 제어할 수 있습니다.
반면, 검증 시간이 길어지면 프로토콜이 덜 어려워집니다. 이러한 방식으로 검증 시간은 일정한 비율을 유지하기 위해 자체 조정됩니다. 평균적으로 15초마다 블록이 생성됩니다.
우리는 이더리움 프로토콜의 가장 복잡한 부분 중 하나인 트랜잭션 실행에 도달했습니다. 처리를 위해 이더리움 네트워크에 트랜잭션을 보낸다고 가정합니다. 이더리움 상태가 트랜잭션을 포함하도록 변환되면 어떻게 됩니까?
첫째, 모든 트랜잭션은 실행을 위해 초기 설정 요구 사항을 충족해야 합니다. 여기에는 다음이 포함됩니다.
트랜잭션은 잘 구성된 RLP여야 합니다. "RLP"는 "재귀 길이 접두사"를 나타내며 이진 데이터의 중첩 배열을 인코딩하는 데이터 형식입니다. RLP는 Ethereum이 개체를 직렬화하는 데 사용하는 형식입니다.
유효한 거래 서명
유효한 트랜잭션 nonce. 계정의 nonce는 해당 계정에서 전송된 트랜잭션 수입니다. 유효하려면 트랜잭션 nonce가 보낸 사람 계정의 nonce와 같아야 합니다.
트랜잭션의 가스 한도는 트랜잭션에서 사용하는 고유 가스 이상이어야 합니다. 고유 가스에는 다음이 포함됩니다.
트랜잭션 실행을 위한 사전 정의된 21,000 가스 비용
트랜잭션과 함께 전송된 데이터의 가스 비용(0과 동일한 데이터 또는 코드 바이트당 가스 비용 4, 데이터 또는 코드의 0이 아닌 바이트당 가스 비용 68)
거래가 계약을 생성하는 거래인 경우 32,000 가스 추가
발신자의 계정 잔액에는 발신자가 지불해야 하는 "미리 결정된" 가스 비용을 충당할 수 있는 충분한 이더가 있어야 합니다. "예정된" 가스 비용의 계산은 간단합니다. 먼저 트랜잭션의 가스 한도에 트랜잭션의 가스 가격을 곱하여 최대 가스 비용을 구합니다. 둘째, 발신자에서 수신자에게 전달된 총 가치인 총 가치에 가장 큰 비용이 추가됩니다.
거래가 위의 모든 유효성 요구 사항을 충족하면 다음 단계로 진행합니다.
먼저 송금인의 잔액에서 미리 정해진 실행 비용을 차감하고 송금인 계정의 nonce를 1 증가시켜 현재 거래를 설명합니다. 이 시점에서 트랜잭션의 총 가스 한도에서 고유한 사용 가스를 뺀 나머지 가스를 계산할 수 있습니다.
다음으로 트랜잭션이 실행되기 시작합니다. 트랜잭션을 실행하는 동안 이더리움은 "하위 상태"를 추적합니다. 이 하위 상태는 트랜잭션이 완료된 직후에 필요한 트랜잭션 중에 생성된 정보를 기록하는 방법입니다. 구체적으로 다음을 포함합니다.
자체 파괴 세트: 거래가 완료된 후 폐기되는 계정 세트(있는 경우)
로그 시리즈: 가상 머신 코드 실행의 아카이브 및 인덱싱 가능한 체크포인트.
환불 잔액: 거래 후 송금인의 계좌로 환불된 금액입니다. 이더리움 저장 비용과 보낸 사람이 저장 공간을 비우기 위해 환불을 발행할 것이라고 언급한 것을 기억하십니까? 이더리움은 이를 추적하기 위해 차지백 카운터를 사용합니다. 환불 카운터는 0에서 시작하여 계약이 스토리지를 지울 때마다 증가합니다.
다음으로 트랜잭션에 필요한 다양한 계산을 처리합니다.
트랜잭션에 필요한 모든 단계가 처리되면 잘못된 상태가 없다고 가정하고 보낸 사람에게 환불할 미사용 가스의 양을 결정하여 최종 상태에 도달합니다. 사용하지 않은 가스 외에도 발신자는 위에서 언급한 "환불 잔액"에서 일부 보조금을 받을 수 있습니다.
보낸 사람이 환불을 받으면 다음 단계를 따르세요.
가스의 에테르가 광부에게 주어졌습니다.
트랜잭션에 사용된 가스는 블록 가스 카운터에 추가됩니다(블록의 모든 트랜잭션이 사용하는 총 가스를 추적하고 블록을 검증할 때 유용합니다).
자폭 세트의 모든 계정이 삭제됩니다(있는 경우).
마지막으로 새로운 상태와 생성된 트랜잭션 집합의 로그가 남습니다. 이제 트랜잭션 실행의 기본 사항을 다루었으므로 트랜잭션과 계약을 생성하는 메시지 호출 간의 차이점을 살펴보겠습니다.