본문 바로가기
BlockChain/Ethereum

[Ethereum] 계좌와 트랜잭션

by 손정빈 2019. 4. 23.
728x90
반응형

이더리움 플랫폼 구성 중 데이터 계층에 대해서 알아보도록 하겠습니다.

 

이더리움 플랫폼에서 account는 모든 트랜잭션의 실행 주체이자 기본 단위로서 모든 것은 account에서 실행된다고 생각할 수 있습니다. 이러한 account는 2가지 타입을 갖는데요.

 

외부 소유 어카운트 (EOA, Extenally owned Account)

일반적으로 말하는 Account가 외부 소유 어카운트입니다. 사람이 직접 개인키를 관리하며, 스마트 컨트랙트 실행 코드는 가지고 있지 않습니다. EOA는 개인 키를 사용하여 전자 서명된 트랜잭션을 생성하고 실행함으로써 다른 EOA나 컨트랙트 어카운트에 메세지를 보낼 수 있습니다. 보통은 EOA간의 메세지는 이더를 보내지만, EOA는 컨트랙트 어카운트에 메세지를 보내 해당 코드를 실행 시킬 수 도 있습니다.

 

컨트랙트 어카운트 (CA, Contract Account)

일반적으로 사용되는 스마트 컨트랙트의 정식 용어가 바로 컨트랙트 어카운트입니다. 컨트랙트 어카운트는 EOA나 다른 CA의 메세지를 받은 후 내부의 스마트 컨트랙트 코드를 실행한 후, 새로운 컨트랙트를 생성하거나 다른 메세지를 읽거나 보내게 됩니다. 또한 필요하면 내부 저장 공간에 데이터를 저장 할 수도 있습니다. 그러나 랜덤 넘버를 생성하거나 직접 운영체제를 조작하는 API를 호출하는 작업등은 할수 없으며, 오직 EOA나 다른 컨트랙트 코드에 의해서만 작동되는 것입니다. 즉, 자기 자신이 직접 새로운 트랜잭션을 실행할 수는 없습니다.

 

 

외부 소유 어카운트, 컨트랙트 어카운트 모두 어카운트이며, 둘의 주소 아래와 같은 형태의 값을 가지고 있습니다.

0x064C998923E7170D698dB010ca9F53479fff6BF6

 

실제 어카운트 주소와 어카운트 정보는 다음과 같은 Account 구조체에 저장되어 처리됩니다.

Account 구조체에서 Address 필드는 20바이트의 고정 배열이고, URL은 해당 주소의 위치를 나타내며 옵션 사항입니다.

//Account Address

type Account strcut{

    Address common.Address 

    URL URL

}

 

const AddressLength = 20

type Address[AdressLenght]byte

 

// Account info

type Account struct {

    Nonce uint64

    Balance *big.Int

    Root common.Hash

    CodeHash []byte

}

어카운트 정보는 4개의 필드로 구성되어 있는데

 

- 넌스(Nonce)는 해당 어카운트로부터 보내진 트랜잭션의 수를 의미하며, 0으로 시작합니다. 트랙잰션이 무제한 실행될 때는 의미가 없으나 트랜잭션을 오직 한번만 실행되게 할 때 사용할 수 있는 카운터 입니다. CA의 경우 넌스는 어카운트에 의해 생성된 컨트랙트 수를 의미합니다.

 

- 잔액(Balance)는 해당 어카운트의 이더 잔고를 의미합니다.

 

- 루트(Root)는 해당 어카운트가 저장될 머클 패트리시아 트리의 루트 노드를 의미합니다.

 

- 코드해시(CodeHash)는 해당 어카운트의 스마트 컨트랙트 바이트 코드의 해시를 의미합니다.

코드해시값이 비어(nil)있으면 해당 어카운트는 일반 EOA라는 뜻입니다.

 

 

 

어카운트 생성

모든 이더리움 어카운트는 개인키와 공개키의 쌍으로 정의가 됩니다. 보통 개인키와 공개키를 비대칭 키라고하는데, 서명을 위해 비대칭 암호화키를 생성할 때는 RSA, ECDSA, DSA 등 다양한 비대칭 암호화 알고리즘을 사용 할 수 있습니다.

 

이더리움에서는 256bit ECDSA를 사용하는데 C언어로 작성된 비트코인의 ECDSA 라이브러리인 secp256k1를 Go언어로 래핑하여 사용합니다. ECDSA 서명 암호화를 통해 얻은 256bit 공개키를 다시 암호 해시 알고리즘 Keccak256을 사용하여 암호화하여 32바이트의 고정값을 생성해 낸 후 이중 20byte를 절삭하여 어카운트 주소값으로 사용합니다.

 

개인키 ---(ECDSA/sepc256k1)---> 공개키 ---(Keccak256/20byte 절삭)---> 주소

 

어카운트의 상태

어카운트들이 모인 것을 이더리움에서는 상태라고 하고 이를 stateObject 구조체로 표현하고 있다. 어카운트에 접근하여 상태를 변경하기 위해서는 stateObject를 통해 접근 후 상태를 변경할 수 있습니다. 변경된 어카운드는 CommitTrie() 함수를 호출하여 변경된 Trie를 levelDB에 업데이트하게 됩니다.

 

type stateObject struct {

    address common.Address

    addrHash common.Hash

    data Account

    db *StateDB

...

}

 

 

트랜잭션

이더리움에서 트랜잭션은 다른 어카운트나 컨트랙트에 보낼 데이터 구조체로써, 전자 서명을 통해 암호화가 이루어집니다. 아래는 이더리움에서 사용되는 트랜잭션 구조체입니다.

type Transaction struct {
	data txdata
    hash atomic.Value
    Size atomic.Value
    from atomic.Value
}

type txdata struct{
	AccountNaonce uint64
    Price *big.Int
    GasLimit *big.Int
    Recipient *common.Address
    Amount *big.Int
    Payload []byte
    
    V *big.Int
    R *big.Int
    S *big.Int
}

트랜잭션 구조체에 포함된 필드는 다음과 같습니다.

- AccountNonce : 발신자에 의해 보내진 트랜잭션의 갯수를 의미하며, 0으로 시작

- Price : 트랜잭션의 밠니자가 각 실행 단계에서 지급하는 비용인 가스 가격을 의미

- GasLimit : 트랜잭션 수행 시 지급 가능한 최대 범위

- Recipient : 메시지 주신처의 주소를 의미

- Amount : 발신자로부터 수신자에게 전송할 이더의 양

- Payload : 옵션 필드로서 메시지 호출 시 매개변수 등을 전달

- V, R, S : 트랜잭션의 발신자를 식별하기 위한 ECDSA 서명을 만드는데 사용되는 값

V는 1바이트로 ECDSA가 복원한 공개키 4개중 어떤 키를 사용할지 지정한 값

R과 S는 각각 32바이트로 서명 데이터입니다.

 

실제 트랜잭션의 실행 비용은 Price * GasLimit로 계산되며, Recipient의 값이 수신자가 지정되지 않은 nil일 경우 해당 수신자가 컨트랙트임을 의미합니다.

 

또한 트랜잭션에 대한 처리 수수료를 채굴자에게 지급해야하는데, 사용된 가스와 가스 비용의 곱으로 트랜잭션의 수수료를 계산합니다.

반응형

댓글