Getting started with ethereum
Kinds of accounts
이더리움에는 두가지 종류의 account 가 있는데, External Account 와 Contract Account 가 그것이다.
먼저 External Account 는 공개키 방식의 계정이며, address 역할을 하는 public key 와 nonce 로 구성이 되며, Contract Account 는 일반적인 smart contract 이다.
여기서 account 와 account 사이에 자금이 이동하면 그것을 transaction 이라고 말한다.
Transaction
이더리움에서 transaction 이란 하나의 EOA 로부터 다른 account 로 전송되는 message 를 포함한 signed data packet 을 의미하며 다음과 같은 정보들을 담고 있으며, EOA 로 부터 EOA 로 가는 경우는 이더를 송금하는 것을 내포하고, 만약 수신자가 Contract Account 라면 해당 contract 가 어떤 코드를 실행하도록 trigger 하는 것이 된다.
- receipient
- signature
- value
- data: which can contain the message sent to a contract
여기서 data 는 contract 가 실행에 필요한 정보를 들고 있으며 Contract ABI(Application Binary Interface) 에 따라 컨트랙트와 소통한다. 이 ABI 는 외부 와컨트랙트 간의 상호작용에 필요할 뿐만 아니라 contract 간의 상호작용에도 적용된다.
따라서 data 는 다음의 규약에 따라 인코딩 되어 사용되며 ABI(Application Binary Interface 에 따라 정의된다.
함수 선택자
data 의 함수 시그니처의 Keccak-256 (SHA-3) hash 의 첫 4바이트는 어떤 함수를 호출할지를 나타내며 function 시그니처로 부터 도출된다.
1 | pragma solidity >=0.4.16 <0.6.0; |
위의 예제에서 baz 함수를 호출하고자 하는 transaction 의 data의 함수선택자는 0xcdcd77c0
인데 이는 method 의 id 로 ASCII format 으로 작성된 function signature 인 baz(uint32,bool
의 Keccak hash(sha3) 의 첫번째 4 바이트이다.
함수 Parameter
또한 해당 함수의 parameter 로 69와 true 를 제공한다면 69를 32바이트 로 패딩한 0x0000000000000000000000000000000000000000000000000000000000000045
가 값이 된다. 0x0000000000000000000000000000000000000000000000000000000000000001
ABI(Application Binary Interface)
컴퓨터 과학에서 흔히 말하는 ABI 는 두가지 종류의 binary 프로그램 모듈 사이의 인터페이스이다. 쉬운 예로는 library 와 operating 시스템의 경우가 있는데, 하나의 라이브러리는 여러 시스템 상에서 동작해야 하므로 해당 소스코드가 다양한 운영체제에서 동작하기 위해서는 약속된 인터페이스가 필요하다. 또 한 예로는 유저에 의해 실행되는 프로그램의 예가 있는데 가령 여러 운영체제에서 해당 프로그램을 실행하여도 동작하기 위해서는 이러한 ABI 가 정의되어 있어야 한다.
이와 같은 맥락에서 이더리움 에서의 ABI 란 특정 함수가 이더리움에서 실행되기 위한 포맷팅의 규약으로써 이해될 수 있다.
아래는 스마트 컨트랙트 내에서 특정 데이터를 ABI 인코딩 하는 것을 보여준다.
1 | abi.encode("AAAA") |
위 코드는 아래와 같이 3단어로 구성된 96(32byte *3) 사이즈의 바이트 문자열을 리턴한다.
1 | 0x0000000000000000000000000000000000000000000000000000000000000020 |
한 줄씩 살펴보면 먼저 첫번째 라인은 해당 문자열의 starting offset(32 in decimal) 를 32byte 문자열에 padding 한 것이며, 두번째 문자열은 인코딩 하는 데이터의 길이인 4를 32바이트 문자열에 padding 하여 나타낸다. 마지막으로 세번째 문자열은 실제 우리의 데이터인 “AAAA” 를 UTF-8 인코딩하여 32 바이트 문자열에 padding 하여 나타내어 준다.
위의 encoding 방식보다 다소 간편하게 인코딩을 하고 싶다면 abi.encodePacked("AAAA")
라는 함수를 사용할 수 있다. 이 함수는 32바이트보다 작은 문자는 그냥 해당 문자열을 바이트로 출력하고 32바이트에 padding 하지도 않는다.
한가지 흥미로운 사실이 있는데, keccak256
을 사용하여 hashing 을 할때 복수개의 인자를 전달하면 이것을 내부적으로 abi.encodePacked
함수로 인코딩 하여 해싱을 한다는 것이다. 현재는 복수개의 인자를 전달하면 warning 을 출력하기는 하지만, 알아두도록 하자.
다음은 Keccak256 에서 abi.encodePacked
를 사용하는 예이다. 아래의 두 hashing 은 정확히 동일한 역할을 수행한다.
1 | keccak256("AAAA", "BBBB", 42); |
1 | keccak256(abi.encodePacked("AAAA", "BBBB", 42)); |
Comments