트랜잭션 출력 (Transaction Output)

트랜잭션 출력 (Transaction Output)

트랜잭션 출력

비트코인에서 코인을 타인에게 지급하기 위해서는 먼저 자신의 계좌에 코인이 있어야 한다. 자신의 계좌에 코인이 있다는 것은 개인키를 가진 자신의 비트코인 주소로 어떤 사람이 코인을 보냈다는 것을 의미한다. 이 부분을 표시하는 것이 트랜잭션인데, 특히 누구에게 보냈는가를 표시하는 것이 트랜잭션 출력(transaction output)에 표시되게 된다.

비트코인 네트워크가 처음 생성되었을 때, 아무도 코인을 가지고 있는 않은 상태인데, 그러면 어떻게 코인을 전달할 수 있을까? 이는 블럭체인을 마이닝하는 마이너들이 한 블럭을 생성할 때마다, 자동으로 비트코인을 생성해서 그 마이너에게 주기 때문에, 이 마이너가 최초의 코인 소유자가 된다. 이 마이너는 다른 사람들에게 코인을 나누어 줄 수 있고, 코인을 받은 사람은 계속해서 타인에게 코인을 보낼 수 있다. 따라서, 비트코인 블럭체인에 있어 채굴(Mining)은 새로운 블럭을 생성하는 역활을 할 뿐만 아니라, 네트워크에 지속적으로 통화를 공급하는 역활을 하게 된다.

마이너들에게 지급하는 코인은 처음에는 50 비트코인, 4년 뒤에는 25 코인, 8년 뒤에는 12.5 코인 등으로 약 4년마다 계속 반감해서 지급된다. 마이너들에 지급되는 코인에 대한 트랜잭션 역시 블럭체인의 블럭에 넣게 되는데, 이 트랜잭션을 특별히 코인베이스 트랜잭션(coinbase transaction)이라 부르고, 항상 블럭바디(block body)의 첫번째에 위치하게 된다.

트랜잭션 출력의 구조

트랜잭션 출력은 3개의 데이타 필드를 갖는데, 아래 코드에서와 같이 타인에게 보내는 코인수(Amount), 출력 스크립트의 크기(ScriptPubKeySize), 출력 스크립트(ScriptPubKey) 와 같은 데이타를 갖는다. 누구에게 보내는가는 출력 스크립트(ScriptPubKey) 안에 지정되는데, ScriptPubKey에는 코인을 받는 사람에 대한 정보(public key 정보)가 들어가 있다. 출력 스크립트(ScriptPubKey)는 코인을 다른 사람들이 함부로 사용하지 못하게 잠근다는 의미에서 "locking script"라고도 불리운다.

    public class TransactionOutput
    {
        public ulong Amount { get; set; } // in Satoshi
        public VarInt ScriptPubKeySize { get; set; }
        public byte[] ScriptPubKey { get; set; }

        //...생략...
    }

위 필드들에서, 얼마만큼을 보내는지는 비트코인의 최소단위인 사토시(Satoshi) 단위로 지정한다. 누구한테 보내는지를 지정하는 방법은 일반적인 은행 트랜잭션과 다른 방식을 사용한다. 은행 트랜잭션의 경우, 개인의 계좌 번호를 지정해서 돈을 보내게 되지만, 비트코인에서는 비트코인 고유의 스크립트(script)를 사용하여 이를 표현한다.

트랜잭션 스크립트

비트코인에서 스크립트(script)는 스택 기반의 아주 단순한 프로그래밍 언어이다. 비트코인은 스크립트로 작성된 코드를 읽어 이를 실행하면서 코인 트랜잭션을 수행한다. 비트코인 스크립트 언어는 루프(loop)를 허용하지 않는 제한된 언어인데, 이 스크립트 부분을 확장하여 다양한 코드를 쓸 수 있게 하면서 스마트 계약(smart contract)을 수행할 수 있게 한 것이 이더리움(Ethereum)이다.

비트코인의 트랜잭션 스크립트는 프로그래밍 언어이므로 트랜잭션에 다양한 스크립트를 넣을 수 있게 되어 있지만, 일반적으로 사용되는 표준 스크립트(standard script)로는 P2PKH (pay to pubkey hash), P2SH (pay to script hash), P2PK (pay to pubkey), P2MS (pay to multisig) 등이 있다. 현재 가장 많이 사용되는 것은 P2PKH와 P2SH 스크립트이다.

비트코인에서 가장 전형적인 트랜잭션 스크립트인 P2PKH 는 다음과 같은 구조로 되어 있다.

    OP_DUP OP_HASH160 {publicKeyHash} OP_EQUALVERIFY OP_CHECKSIG

여기서 OP_ 로 시작되는 것들은 OPCode라고 불리우는 것으로, 스크립트의 명령어에 해당된다. 예를 들어, OP_DUP (0x76)은 스택(stack)의 가장 위에 있는 데이타를 복제해서 스택에 넣으라는 명령이고, OP_HASH160 (0xa9)은 스택의 가장 위에 있는 데이타를 RIPEMD160 해시로 해싱하라는 명령어이다.

{publicKeyHash} 에는 코인을 받는 사람의 공개키(public key)를 RIPEMD160 으로 해싱한 해시값이 들어간다. 예를 들어, 20 바이트의 RIPEMD160 해시값인 513b8dc588ca9d5787dde7eb29569da63c3b1434 과 같은 값이 여기에 들어간다.

OP_EQUALVERIFY (0x88)는 스택 상의 두개의 값이 같은지를 비교하는 것이고, OP_CHECKSIG (0xac)는 서명이 올바른 서명인지를 체크하는 명령어이다.

일반적으로 트랜잭션 출력의 스크립트(ScriptPubKey)는 단독으로 실행되지 않으며, 트랜잭션 출력에 표시된 코인 수급자가 코인을 다른 사람에게 보내려고 할 때 작성하는 입력 트랜잭션과 맞물려 실행된다. 즉, 트랜잭션 출력에 지정된 공개키(public key)에 상응하는 개인키(private key)를 가진 사람이 트랜잭션 입력(transaction input)에서 그 트랜잭션 출력(transaction output)을 사용하도록 서명을 하면, 이때의 "{트랜잭션 입력} + {이전의 트랜잭션 출력}" 을 합친 스크립트를 실행하게 된다. 스크립트의 마지막 코드인 OP_CHECKSIG 에서 서명이 맞는지 체크하게 되는데, 이것이 맞으면 개인키를 가진 올바른 사용자가 이 트랜잭션을 서명하였음을 인정하게 된다.

트랜잭션 출력에서의 출력 스크립트의 크기(ScriptPubKeySize)는 가변길이로 이루어진 정수로 지정하는데, 이 가변 길이 정수(Variable length integer)는 숫자 범위에 따라 1 ~ 9 바이트까지 가변적인 길이를 갖는다.