EVM === 사전 지식 --- - 가상머신이란? 1. 물리적 하드웨어 시스템에 구축되어 자체 CPU, 메모리, 네트워크 인터페이스 및 스토리지를 갖추고 가상 컴퓨터 시스템으로 작동하는 가상 환경 [1] - ex) Virtual Box, 하이퍼바이저, Vmware 3. 운영체제에 관계없이 바이트 코드가 구동되는 환경 [2] - ex) Chrome, Node.js V8, Java Virtual Machine [3] ![](https://i.imgur.com/cCERXMN.png) <center><i>Java가 JVM 통해서 동작하는 과정</i></center> ![](https://i.imgur.com/bjeo0j5.png) <center><i>Javascript가 Node.js V8 통해서 동작하는 과정</i></center> ``` 왜 인터프리터와 JIT (Just in Time) 컴파일러를 둘 다 사용할까? 반복되지 않는 코드 같은 경우에는 인터프리터로 수행하는게 빠를 수 있음. 이러한 기법을 adaptive compilation 이라고 부름. ``` 특징 --- - EVM 에서 구동되는 코드는 네트워크, 파일시스템, 다른 프로세스에 대한 접근 권한이 없음. 따라서, 안전하게 고립된 상황에서, 고립된 상황에서 동작을 함. 수행 결과에 대한 무결성을 입증할 수 있음. 데이터 저장 공간 --- - 메모리, 스택 - ```메모리와 스택의 차이점은?``` - world state, 스토리지: 여기 저장되는 정보는 영구히 저장되기 때문에 영원히 기록된다고 볼 수 있다. 그렇기 때문에 비밀번호와 같은 민감한 정보들은 들어갈 수 없다. 또한, 블록체인의 공간을 영구히 사용하는 것이기 때문에 가스비가 많이 들 수 있으므로 꼭 저장해야되는 정보가 아니라면 스택이나 메모리를 이용하는 것이 좋다. - ```world state 는 정확히 무엇일까? message call 을 통해 접근?``` - 가스: 매 코드가 진행될 때마다 수행되는 연산량이 있는데 여기서 가스가 소모되는데, 수행한 사람의 수수료에서 소모될 수 있으면 소모하고, 아닌 경우 수행을 취소한다. - message call 이라고 하는 것은 smart contract 외부에 있는 기능을 호출할 때, 사용하는데 이 또한 가스비가 소모가 된다. - Virtual ROM 을 관리하는데, 여기서는 smart contract 코드가 존재한다. 무결성을 위해서 Immutable 하다. 구성요소 --- - 연산 - EVM 은 최소한의 instruction set 을 통해서 수행되도록 만들어졌다. 합의 문제가 생길 수 있는 정확하지 않거나 모순된 구현을 피하기 위해서 - 기본적인 대수/비트/논리/비교 연산자 지원 - 조건부, 무조건부 jump 기능 지원 - 블록넘버, 타임스탬프 등 블록/블록체인 정보 접근 지원 - 스토리지: 전역변수의 사용은 스토리지를 사용한다고 볼 수 있다. - 영구히 보존 - key-value 저장 방식: 256 bits word to 256 bits word (32 byte) - 상대적으로 비쌈: 최소한으로 사용해라 - 자기 자신의 smart contract 가 아니면 스토리지를 읽고 쓰기가 불가능 - 하지만 public 함수로 getter / setter 를 통해서 읽고 쓰기가 가능함. (public 으로 변수 선언을 하면 컴파일러가 자동으로 getter 를 만들어준다) - 메모리 - Smart contract 가 message call 마다 freshly cleared 인스턴스임. - 선형적이고 바이트 수준임 - 메모리는 256 bit 단위로 확장, 확장을 할 때마다 가스비가 청구됨 - 더 많이 청구할수록 비싸짐 (쿼드라틱하게) - 메모리 절감 기법에 대한 고민이 필요함. (필요없는 메모리는 할당 해제해주고 그 다음을 진행하도록 한다) - 대표적으로 uniswap 이 이러한 메모리 절감 기법을 잘하고, 그들만의 패턴이 있다 [참고 - line 166 ~ line 179](https://github.com/Uniswap/v2-core/blob/master/contracts/UniswapV2Pair.sol) - C++ 의 속성 중 scope 라는 것을 활용한 것인데, 중괄호 내부에 선언된 변수들은 그 안에서만 유효하기 때문에 메모리를 그 때만 사용하고 중괄호 밖으로 나가면 선언된 변수들은 메모리를 해제해준다. - 중괄호를 쓰는 것과 function call 을 하는 것의 차이는? function 을 따로 두어서 function call 을 하게되면 stack 을 더 잡아먹기 때문에 가스비가 더 소모된다. 따라서 중괄호를 중간에 넣는 것이 더 이득이다. - 스택 - EVM 은 레지스터 머신이 아니라 스택 머신임 (스택이라는 구조에서 연산을 하고 결과를 다시 스택에 넣는 구조로 일반적으로 연산을 할 때 레지스터를 사용하는 레지스터 머신과 다름). - 모든 연산은 스택에서 이뤄짐. - 최대 스택 크기는 1024 element - 스택 최대 깊이에 도달하지 않도록 주의해야함. (재귀 함수 보다는 반복문을 사용하자) - Message Call - 컨트랙트를 호출하거나 일반 계좌 (EOA, Externally Owned Account) 에 이더를 전송할 때 호출함. - Message Call 이 트랜잭션이라고 불러도 큰 무리는 없음. - 호출된 contract 는 freshly cleared instance 를 메모리 공간에 새로 생성하게 된다 - call payload 에 접근할 수 있다. - calldata 라는 또 하나의 분리된 영역에 사용할 수 있다 - 데이터를 반환하면 caller 의 메모리에 저장된다 - caller 가 미리 할당을 해둠. - message call 또한 스택을 사용하기 때문에 스택의 크기를 고려하여 재귀함수보다 반복문을 사용하는게 더 나을 수 있다. - Delegate Call - 메시지 콜의 특별한 콜 - 잘못된 설명: msg.sender 를 유지하는 호출이라고 하는데, 이는 잘못된 설명이고, (즉, EOA 가 contract 1 을 수행하고 contract 2 를 수행할 때, contract 1 의 데이터를 contract 2에서 유지하고 싶을 경우 사용하는 경우) - 올바른 설명은, contract 1 의 context 에서 contract 2를 호출하는 것으로 볼 수 있음. 그렇기 때문에 msg.sender 와 msg.value 는 변하지 않는다. - 장점은, 컨트랙트가 서로 다른 주소의 컨트랙트를 호출할 수 있다는 의미이다. - 스토리지, 주소, 잔액은 여전히 호출 컨트랙트를 참조하고 있고, 오직 코드 (새로운 로직)만 호출된 주소에서 가져온다. 라이브러리와 업그레이드 가능한 스마트 컨트랙트의 기본 개념. - Logs - 데이터를 블록체인의 블록에 저장할 수 있는 방법 - events 로 구현할 수 있음 - contract 에 로그가 생기면 로그 데이터에는 접근 불가하다. 즉, contract 내부에서는 볼 수 없고 외부에서만 볼 수 있다. - 블록체인 밖에서 접근하기 효율적이다 - 블룸필터라는 자료구조에 저장됨. - 암호학적으로 안전한 방법을 통해 전체 블록체인을 다운로드하지 않은 클라이언트들도 로그를 찾을 수 있도록 하게 한다. - Selfdestruct - 코드를 블록체인 상에서 지울 수 있다 - 남은 이더를 전송하고, 스토리지와 코드가 상태에서 제거된다. - 데이터를 지우는 것과 별개인것이, 아카이브 노드에서 과거 블록들을 통해서 데이터를 불러올 수 있다. - Selfdestruct 를 대신하는 코딩 기법 - Deactivate/Disable: 내부 상태 flag 를 하나 두고, false 인 경우 모든 함수 수행을 거절하도록 함 (예제. [multisig parity 해킹 사건](https://www.parity.io/blog/a-postmortem-on-the-parity-multi-sig-library-self-destruct/)) ``` * unix timestamp 를 사용하지 않은 이유? (애매함) 이더리움은 약 13 ~ 15초 간격으로 블록이 생성되고, 시간 분절 (?) 이 발생하기 때문에 block number 가 더 정확할 수 있다. 하지만, 블록 생성 시간이 불안정한 경우 13.5 초 15.12 초 이렇게 애매하게 블록이 생성되는 경우에는 block number 보다 unix timestamp 를 쓰는 것이 더 좋을 수 있다. 즉, 상황에 따라 시간 개념을 timestamp 에 둘지 block number 에 둘지 결정할 수 있다 ``` ``` 블룸필터 자료구조란 ```