관리 메뉴

개발이야기

[Mastering Bitcoin] 마스터링 비트코인 내 맘대로 정리 Ch 06 - Transaction 본문

블록체인 /마스터링 비트코인

[Mastering Bitcoin] 마스터링 비트코인 내 맘대로 정리 Ch 06 - Transaction

안성주지몬 2019. 1. 21. 00:00

마스터링 비트코인 Ch6 - Transaction



Transaction

거래는 비트코인 시스템 참가자 간 가치 이전을 암호화하는 데이터 구조다. 각 거래는 세계적인 더블-엔트리 부기 원장인 비트코인 블록체인의 공개 항목이다.

Transactions in Detail

블록 탐색기 응용 프로그램은 앨리스의 "주소"에서 밥의 "주소"로의 거래를 보인다. 이것은 실제 거래에 포함된 내용보다 훨씬 적은 내용이다. 사실, 이 장에서 볼 수 있듯이, 표시된 정보의 대부분은 블록 탐색기에 의해 생성되며 실제로 트랜잭션에 포함되지 않는다.

[그림 6-1] 밥의 카페에 대한 앨리스의 거래

Transactions—Behind the Scenes

이면에는 실제 거래는 전형적인 블록 탐험가가 제공하는 거래와 매우 다르게 보인다. 실제로 다양한 비트코인 애플리케이션 사용자 인터페이스에서 볼 수 있는 고급 구조는 대부분 비트코인 시스템에 존재하지 않는다.

앨리스의 거래 디코딩

{

"version": 1,

"locktime": 0,

"vin": [

{

"txid": "7957a35fe64f80d234d76d83a2a8f1a0d8149a41d81de548f0a65a8a999f6f18",

"vout": 0,

"scriptSig" : "3045022100884d142d86652a3f47ba4746ec719bbfbd040a570b1deccbb6498c75c4ae24cb02204b9f039ff08df09cbe9f6addac960298cad530a863ea8f53982c09db8f6e3813[ALL] 0484ecc0d46f1918b30928fa0e4ed99f16a0fb4fde0735e7ade8416ab9fe423cc5412336376789d172787ec3457eee41c04f4938de5cc17b4a10fa336a8d752adf",

"sequence": 4294967295

}

],

"vout": [

{

"value": 0.01500000,

"scriptPubKey": "OP_DUP OP_HASH160 ab68025513c3dbd2f7b92a94e0581f5d50f654e7 OP_EQUALVERIFY OP_CHECKSIG"

},

{

"value": 0.08450000,

"scriptPubKey": "OP_DUP OP_HASH160 7f9b1a7fb68d60c536c2fd8aeaa53a8f3cc025a8 OP_EQUALVERIFY OP_CHECKSIG",

}

]

}

위에서 보여주고 있는 비트코인에는 동전도, 발신자도, 수신자도, 잔액도, 계좌도, 주소도 없다. 이러한 모든 것들은 사용자의 이익을 위해 더 높은 수준에서 구성되어보다 쉽게 이해할 수 있게 한다. 또한 이상하고 이해할 수 없는 필드와 16 진수 문자열을 많이 볼 수 있다.

Transaction Outputs and Inputs

비트코인 거래의 기본 구성 블록은 거래 출력이다. 거래 출력은 블록체인에 기록된 비트코인 통화의 나눌 수 없는 한 덩어리이며 전체 네트워크에서 유효한 것으로 인식된다. 비트코인 풀 노드는 사용되지 않은 거래 출력 또는 UTXO라고 하는 사용 가능하고 소비 가능한 모든 출력을 추적한다. 모든 UTXO의 컬렉션은 UTXO 세트로 알려져 있으며 현재 UTXO의 수백만에 해당한다. 새로운 UTXO가 생성되면 UTXO 세트가 커지고 UTXO가 소비되면 축소된다. 모든 거래는 UTXO 세트에서 변경(상태 전이)을 나타낸다.

사용자의 지갑이 비트코인을 받았다고 하면 지갑이 제어하는 키 중 하나를 사용하여 UTXO를 사용할 수 있다는 것을 의미한다. 따라서 사용자의 비트 코인 "잔액"은 사용자의 지갑이 소비 할 수 있는 모든 UTXO의 합계이며 수백 개의 거래와 수백 개의 블록 사이에 흩어져있을 수 있다. 지갑은 블록체인을 스캔하고 지갑이 소비하는 UTXO의 가치를 자신이 제어하는 키와 통합하여 사용자의 잔고를 계산한다. 대부분의 지갑은 데이터베이스를 유지 관리하거나 데이터베이스 서비스를 사용하여 자신이 제어하는 키로 보낼 수 있는 모든 UTXO의 빠른 참조 세트를 저장한다.

거래 출력은 satoshis의 배수로 표시된 임의의 (정수) 값을 가질 수 있다. 비트코인은 satoshis로 소수 여덟 자리로 나눌 수 있다. 출력은 임의의 값을 가질 수 있지만 일단 생성되면 분할할 수 없다. 출력은 정수 satoshis로 표시된 값의 개별적이고 분리할 수 없는 단위다. 소비되지 않은 출력은 거래에 의해서만 전체적으로 소비될 수 있다.

UTXO가 원하는 거래 값보다 큰 경우, UTXO가 전체적으로 소비되어야하고 거스름돈이 거래에서 생성되어야 한다. 즉, UTXO가 20 비트코인이고 1 비트코인만 지불하려는 경우 거래는 전체 20 비트코인 UTXO를 소비하고 두 개의 출력을 생성해야 한다. 하나는 원하는 수신자에게 1 비트코인를 지불하고 다른 하나는 19 비트코인의 거스름돈을 다시 자기 지갑에 돌려주어야 한다. 거래 출력의 나눌 수 없는 특성으로 인해 대부분의 비트코인 거래는 변경을 생성해야 한다.

사용자의 지갑 응용 프로그램은 일반적으로 사용자가 사용할 수 있는 UTXO 중에서 원하는 거래 금액보다 크거나 같은 금액을 선택한다. 비트코인 애플리케이션은 몇 가지 작은 단위를 결합하거나 정확한 거스름돈을 찾거나 거래 값보다 큰 단일 단위를 사용하여 변경하는 등 구입 금액을 충족시키는 여러 가지 전략을 사용할 수 있다. 이 복잡한 UTXO의 복잡한 어셈블리는 모두 사용자의 지갑에서 자동으로 수행되며 사용자는 볼 수 없다. UTXO에서 원시 거래를 프로그래밍 방식으로 생성하는 경우에만 관련이 있다.

트랜잭션은 이전에 기록된 미사용 트랜잭션 출력을 소비하고 향후 트랜잭션이 소비할 수 있는 새로운 트랜잭션 출력을 생성한다. 이렇게 하면 비트 코인 값의 덩어리가 UTXO를 소비하고 생성하는 트랜잭션 체인에서 소유자에서 소유자로 이동한다. 출력 및 입력 체인에 대한 예외는 각 블록의 첫 번째 트랜잭션인 코인베이스 트랜잭션이라는 특별한 유형의 트랜잭션이다. 이 거래는 "승리한" 채굴자에 의해 이루어지며 채굴에 대한 보상으로 해당 채굴자에게 지불 할 수 있는 새로운 비트코인을 생성한다. 이 특별한 코인베이스 거래는 UTXO를 소비하지 않는다. 대신에 "coinbase"라는 특별한 유형의 입력이 있다. 이것은 광산에서 보듯이 비트코인의 돈 공급이 채굴 과정에서 어떻게 생성 되는가이다.

Transaction Outputs

모든 비트코인 트랜잭션은 비트코인 장부에 기록되는 출력을 생성한다. 거의 모든 출력이 UTXO라는 비트코인 덩어리를 만들어 전체 네트워크에서 인식되고 소유자가 향후 거래에 사용할 수 있다. UTXO는 UTXO 세트의 모든 전체 노드 비트코인 클라이언트에 의해 추적된다. 새 트랜잭션은 UTXO 집합의 이러한 출력 중 하나 이상을 소비한다.

트랜잭션 출력은 두 부분으로 구성된다:

⦁satoshis에서 명명 된 비트코인의 양, 가장 작은 비트코인 단위

⦁출력을 소비하는 데 필요한 조건을 결정하는 암호화 퍼즐

암호화 퍼즐은 잠금 스크립트, 감시 스크립트 또는 scriptPubKey라고도 한다.

이제 Alice의 트랜잭션에서 살펴본 결과를 확인할 수 있는지 보겠다. JSON 인코딩에서 출력은 vout이라는 배열 (목록)에 있다.

거래에는 두 개의 출력이 포함되어 있다. 각 출력은 값과 암호 퍼즐로 정의된다. 비트코인 코어(지갑)에 표시된 인코딩에서 값은 비트코인으로 표시되지만 트랜잭션 자체에서는 satoshis로 표시된 정수로 기록된다. 각 출력의 두 번째 부분은 지출 조건을 설정하는 암호화 퍼즐이다. 비트코인 코어는 이를 scriptPubKey로 표시하고 사람이 읽을 수 있는 스크립트를 보여준다.

Transaction serialization—outputs

트랜잭션이 네트워크를 통해 전송되거나 응용 프로그램 간에 교환되면 직렬화된다. 직렬화는 데이터 구조의 내부 표현을 바이트 스트림이라고도 하는 한 번에 한 바이트 씩 전송할 수 있는 형식으로 변환하는 프로세스이다. 직렬화는 네트워크를 통한 전송 또는 파일의 저장을 위해 데이터 구조를 인코딩하는 데 가장 일반적으로 사용된다. 트랜잭션 출력의 직렬화 형식은 트랜잭션 출력 직렬화에 표시된다.

[표 6-1] 트랜잭션 출력 직렬화

편의성과 가독성을 위해 비트코인 라이브러리는 트랜잭션을 내부적으로 데이터 구조 (일반적으로 객체 지향 구조)에 저장한다. 트랜잭션의 바이트 스트림 표현에서 라이브러리의 내부 표현 데이터 구조로 변환하는 프로세스를 역 직렬화 또는 트랜잭션 구문 분석이라고 한다.

직렬화 된 16진수 형식에서 Alice의 트랜잭션을 수동으로 디코딩 할 수 있는지 확인하고 이전에 살펴본 요소 중 일부를 찾는다. 두 개의 출력이 포함 된 섹션은 Alice의 트랜잭션에서 강조 표시되며, 직렬화되어 16 진수로 표시된다:

[예시 6-1] Alice의 트랜잭션, 직렬화와 16진수 형식

힌트:

⦁강조 표시된 섹션에는 두 개의 출력이 있으며, 각 출력은 트랜잭션 출력 직렬화에 표시된 대로 직렬화된다.

⦁0.015 bitcoin 값은 1,500,000 satoshis다. 16 진수로 16 e3 60이다.

⦁직렬화 된 트랜잭션에서 값 16 e3 60은 리틀 엔디안(최하위 바이트 우선) 바이트 순서로 인코딩되므로 60 e3 16처럼 보인다.

⦁scriptPubKey 길이는 25 바이트이며 16진수는 19이다.

Transaction Inputs

트랜잭션 입력은 UTXO가 소비 될 것으로 (참조 기준으로) 확인하고 잠금 해제 스크립트를 통해 소유권 증명을 제공한다. 트랜잭션을 작성하기 위해, 요청된 비용을 지불하기에 충분한 값을 가진 UTXO가 지갑에서 선택된다. 때로는 하나의 UTXO로 충분할 수도 있고, 여러 번 필요할 수도 있다. 이 지불을 하기 위해 소비되는 각 UTXO에 대해 지갑은 UTXO를 가리키는 하나의 입력을 생성하고 잠금 해제 스크립트로 잠금을 해제한다.

트랜잭션 입력은 vin이라는 배열 (목록)이다.

Alice의 트랜잭션에서 트랜잭션 입력

목록에 하나의 입력만 있다 (하나의 UTXO에 충분한 금액이 포함되어 있기 때문에). 입력에는 네 가지 요소가 포함된다.

⦁UTXO가 사용 된 트랜잭션을 참조하는 트랜잭션 ID

⦁해당 트랜잭션의 UTXO를 참조하는 출력 인덱스 (vout) (첫 번째 인덱스는 0 임)

⦁UTXO에 배치 된 조건을 충족시키는 scriptSig가 지출을 위해 잠금 해제된다.

⦁시퀀스 번호 (후술 됨)

Alice의 트랜잭션에서 입력은 트랜잭션 ID를 가리킨다.

출력 인덱스는 0 (즉, 그 트랜잭션에 의해 생성 된 첫 번째 UTXO). 잠금 해제 스크립트는 Alice의 지갑에서 먼저 참조된 UTXO를 검색하고 잠금 스크립트를 검사한 다음 잠금 스크립트를 사용하여 이를 푸는 데 필요한 잠금 해제 스크립트를 작성한다.

입력을 보았을 때 우리는 이 UTXO를 포함하고 있는 트랜잭션에 대한 참조 이외에 이 UTXO에 대해 알지 못한다. 입력 값이 명시적으로 명시되어 있지 않으므로 이 트랜잭션에서 지불 할 수수료를 계산하기 위해 참조된 UTXO를 사용해야한다. 예를 들어 수수료로 지불한 금액을 계산하려면 입력 값과 출력 값의 합을 알아야한다. 그러나 입력에서 참조된 UTXO를 검색하지 않으면 그 값을 알 수 없다.

Alice의 트랜잭션 (getrawtransaction 및 decoderawtransaction)을 검색 할 때 사용한 것과 동일한 명령 시퀀스를 비트코인 코어와 함께 사용할 수 있다. 이를 통해 이전 입력에서 참조된 UTXO를 가져 와서 살펴볼 수 있다.

입력에서 참조된 이전 트랜잭션의 Alice의 UTXO

이 UTXO의 값은 0.1BTC이며 "OP_DUP OP_HASH160 ..."을 포함하는 잠금 스크립트 (scriptPubKey)가 있음을 알 수 있다.

Transaction serialization—inputs

네트워크상의 전송을 위해 트랜잭션이 직렬화 될 때, 그 입력은 표 6-2와 같이 바이트 스트림으로 인코딩된다.

[표 6-2] 트랜잭션 입력 직렬화

출력물과 마찬가지로 Alice의 트랜잭션으로부터 입력을 직렬화된 형식으로 찾을 수 있는지 살펴 보겠다. 첫째, 디코딩된 입력 :

이제 앨리스의 트랜잭션에서 직렬화된 16진수 인코딩의 필드를 식별할 수 있는지 알아보겠다. 이 필드는 직렬화 되어 16진수로 표시된다.

[예시 6-2] 앨리스의 트랜잭션 (16 진수로 직렬화되고 표현됨)

힌트 :

⦁트랜잭션 ID는 역순 바이트 순서로 직렬화되므로 (16진수) 18로 시작하고 79로 끝난다.

⦁출력 인덱스는 쉽게 식별할 수 있는 0의 4바이트 그룹이다.

⦁scriptSig의 길이는 139 바이트 또는 16진수의 8b이다.

⦁시퀀스 번호는 식별하기 쉬운 FFFFFFFF로 설정된다.

Transaction Fees

대부분의 거래에는 네트워크 확보를 위해 비트코인 채굴자를 보상하는 거래 수수료가 포함된다. 수수료는 공격자가 네트워크를 트랜잭션으로 넘치게 하는 것이 경제적으로 불가능하기 때문에 보안 메커니즘 역할을 한다. 대부분의 지갑은 거래 수수료를 자동으로 계산하여 포함한다. 그러나 프로그래밍 방식으로 트랜잭션을 구성하거나 명령-라인 인터페이스를 사용하는 경우 이러한 수수료를 수동으로 계산하여 포함해야한다.

거래 수수료는 트랜잭션을 다음 블록에 포함 (인센티브)하는 역할(1)을 하며 또한 모든 트랜잭션에 작은 비용을 부과함으로써 시스템 남용을 저지(2)한다. 거래 수수료는 블록체인에 거래를 기록하는 블록을 채굴하는 채굴자가 수집한다.

거래 수수료는 비트코인 거래의 가치가 아닌 킬로바이트 단위의 거래 규모를 기반으로 계산된다. 전체적으로 거래 수수료는 비트코인 네트워크 내의 시장 세력을 기반으로 설정된다. 채굴자는 비용을 포함한 다양한 기준에 따라 거래의 우선순위를 정하고 특정 상황에서 무료로 거래를 처리 할 수도 있다. 거래 수수료는 처리 우선순위에 영향을 미치므로 충분한 수수료가 있는 거래가 채굴 된 다음 블록에 포함되는 반면 수수료가 불충분하거나 없는 거래는 지연되거나 몇 블록 후에 최선의 노력으로 처리되거나 전혀 처리되지 않는다. 거래 수수료는 의무 사항은 아니며 수수료 없는 거래는 결국 처리될 수는 있다. 그러나 거래 수수료를 포함하여 우선 처리가 권장된다.

시간이 지남에 따라 거래 수수료가 계산되고 거래 우선순위에 미치는 영향이 진화되었다. 처음에는 네트워크 전체에 걸쳐 일정했으나 점차적으로 수수료 구조가 완화되면서 네트워크 용량 및 시장 거래량에 따라 시장 세력의 영향을 받았다.

비트코인 코어에서 요금 릴레이 정책은 minrelaytxfee 옵션으로 설정된다. 현재 기본 minrelaytxfee는 0.00001 비트코인 또는 킬로바이트 당 100 분의 1 밀리비트코인이다. 따라서 기본적으로 0.00001 비트코인 미만의 수수료는 무료로 처리되며 mempool(메모리풀)에 공간이 있는 경우에만 릴레이 된다. 그렇지 않으면 삭제된다. 비트코인 노드는 minrelaytxfee 값을 조정하여 기본요금 릴레이 정책을 무시할 수 있다.

수수료 산정 알고리즘은 "경쟁"거래에서 제공되는 용량 및 수수료를 기준으로 적절한 수수료를 계산한다. 이들은 트랜잭션을 선택하고 특정 수의 블록 내에 포함시킬 높은 확률을 제공하는 데에 필요한 요금 (바이트 당 satoshis)을 계산한다. 대부분의 서비스는 사용자에게 높음, 보통 또는 낮은 우선순위 요금을 선택할 수 있는 옵션을 제공한다.

수수료 산정 서비스 [그림 6-2] 차트는 각 범위의 수수료가 있는 트랜잭션의 10 satoshi / byte 단위 증가분 및 예상 확인 시간 (분 및 블록 수)에 대한 실시간 견적을 보여준다. 각 수수료 범위 (예 : 61-70 satoshi / byte)에 대해 두 개의 가로 막대는 미확인 거래의 수 (1405)와 지난 24 시간 (102,975)의 거래 총 수를 보여준다. 그래프에 따르면 이 시점에서 권장되는 우선순위 수수료는 80 satoshi / byte였으며 다음번 블록 (0 블록 지연)에서 트랜잭션을 채굴 할 가능성이 높다. 관점에서 트랜잭션 크기의 중앙값은 226 바이트이므로 권장 트랜잭션 비용은 18,080 satoshis (0.00018080 BTC)이다.

수수료 산정 데이터는 https://bitcoinfees.21.co/api/v1/fees/recommended에서 간단한 HTTP REST API를 통해 검색할 수 있다. 예를 들어, curl 명령을 사용하는 명령 행에서 다음을 수행하시오.

수수료 산정 API 사용

API는 가장 빠른 확인 (fastestFee), 3 블록 (halfHourFee) 및 6 블록 (hourFee) 이내의 확인을 위해 현재 요금 추정치를 바이트 단위로 satoshi로 JSON 객체를 반환한다.

[그림 6-2] 수수료 견적 서비스 bitcoinfees.21.co

Adding Fees to Transactions

거래의 데이터 구조에는 수수료 필드가 없다. 대신 수수료는 입력 합계와 출력 합계의 차이로 암시된다. 모든 출력이 모든 입력에서 공제된 후에 남은 초과분은 채굴자에 의해 징수된 수수료이다:

거래 수수료는 입력에서 출력을 뺀 금액으로 암시된다.

이것은 거래의 다소 혼란스러운 요소이며 이해해야 할 중요한 점이다. 왜냐하면 자신의 거래를 구성하는 경우 입력을 줄임으로써 실수로 매우 많은 수수료를 포함시키지 않아야하기 때문이다. 즉, 거스름돈을 만드는 것이 필요하다면 모든 입력을 계좌에 넣어야만 한다. 그렇지 않으면 광부에게 엄청난 팁을 제공하게 된다!

예를 들어, 20 비트코인 UTXO를 사용하여 1 비트 동전 결제를 하는 경우 19 비트코인 거스름돈 출력을 지갑에 포함시켜야한다. 그렇지 않으면 19 비트코인 잔액이 거래 수수료로 계산되며 당신의 트랜잭션이 포함된 블록을 채굴하는 채굴자가 그 수수료를 모두 가져갈 것이다. 당신이 우선처리를 하고 채굴자를 매우 행복하게 만들지만, 이것은 당신이 의도한 것이 아니다.

Alice의 커피 구매를 다시 살펴봄으로써 이것이 실제로 어떻게 작동하는지 보겠다. Alice는 커피를 지불하기 위해 0.015 비트코인을 소비하려고한다. 이 거래가 즉시 처리되도록 하려면 거래 수수료 (예 : 0.001)를 포함하기를 원할 것이다. 즉, 총 거래 비용은 0.016이 된다. 따라서 그녀의 지갑은 0.016 비트코인 이상을 추가하는 UTXO 세트를 제공해야하며, 필요한 경우 거스름돈을 생성해야 한다. 그녀의 지갑에 0.2 비트코인 UTXO가 있다고 가정해 보자. 이 UTXO를 소비하고, Bob 's Cafe에 0.015로 하나의 출력을 생성하고, 0.184 비트코인으로 자신의 지갑에 다시 출력하여 0.001 비트 동전을 할당하지 않은 상태로 트랜잭션에 대한 암시 적 수수료로 생성해야 한다.

이제 다른 시나리오를 살펴 보겠다. 필리핀의 자선 단체인 Eugenia는 아이들을 위한 교과서 구입을 위한 모금 활동을 완료했다. 그녀는 50 명의 비트코인을 합계하여 전 세계 사람들로부터 수천 건의 작은 기부금을 받았으며, 지갑에는 아주 작은 지불금 (UTXO)이 가득하다. 이제 그녀는 지역 게시자로부터 수백 개의 교과서를 구입하여 비트코인으로 지불하려고 한다.

Eugenia의 지갑 응용 프로그램은 하나의 큰 지불 거래를 생성하려고 시도하기 때문에 많은 소량으로 구성된 사용 가능한 UTXO 세트를 소스로 사용해야 한다. 즉, 최종 트랜잭션은 백개의 작은 값의 UTXO를 입력으로 사용하고 출력은 단 하나만 출력하여 책 게시자에게 지불하게 된다. 그 많은 입력을 가진 트랜잭션은 크기가 1 킬로바이트 (아마도 수 킬로바이트)를 넘을 것이다. 따라서 중간 규모 거래보다 훨씬 높은 수수료가 부과된다.

Eugenia의 지갑 응용 프로그램은 거래 규모를 측정하고 이를 킬로바이트 당 수수료로 곱하여 적절한 수수료를 계산한다. 많은 지갑은 거래가 신속하게 처리 될 수 있도록 더 큰 거래 비용을 초과 지불한다. 더 높은 수수료는 Eugenia가 더 많은 돈을 지출하고 있기 때문에가 아니라 거래가 더 복잡하고 크기가 커지기 때문에 수수료는 거래의 비트 동전 가치와 별개이다.

Transaction Scripts and Script Language

Script라고 하는 비트코인 트랜잭션 스크립트 언어는 스택 기반 실행 언어이다. UTXO에 배치 된 잠금 스크립트와 잠금 해제 스크립트는 모두 이 스크립팅 언어로 작성된다. 트랜잭션의 유효성을 검사할 때 각 입력의 잠금 해제 스크립트는 해당 잠금 스크립트와 함께 실행되어 지출 조건을 충족시키는 지 확인한다.

Turing Incompleteness

비트코인 트랜잭션 스크립트 언어에는 많은 연산자가 포함되지만 조건부 흐름 제어 이외의 루프 또는 복잡한 흐름 제어 기능이 없는 한 가지 중요한 방법으로 의도적으로 제한된다. 이렇게 하면 언어가 Turing Complete(튜링 완전)가 아니므로 스크립트의 복잡성과 예측 가능한 실행 시간이 제한된다. 이러한 제한 사항은 비트코인 네트워크에 대한 서비스 거부 공격을 유발하는 방식으로 트랜잭션에 포함될 수 있는 무한루프 또는 다른 형태의 "로직 폭탄"을 생성하는데 언어를 사용할 수 없도록 한다. 모든 트랜잭션은 비트코인 네트워크의 모든 풀 노드에 의해 유효성이 확인된다. 제한된 언어는 트랜잭션 검증 메커니즘이 취약점으로 사용되는 것을 방지한다.

Stateless Verification

비트코인 트랜잭션 스크립트 언어는 스크립트를 실행하기 전에는 상태가 없거나 스크립트 실행 후 상태가 저장된다는 점에서 stateless라고 할 수 있다. 따라서 스크립트를 실행하는 데 필요한 모든 정보는 스크립트 내에 포함된다. 시스템이 스크립트를 검증하면 비트코인 네트워크의 다른 모든 시스템에서도 스크립트를 검증하므로 유효한 트랜잭션이 모든 사람에게 유효하며 모든 사람이 이를 알고 있음을 확인할 수 있다.

Script Construction (Lock + Unlock)

비트코인의 트랜잭션 유효성 검사 엔진은 트랜잭션을 확인하는 두 가지 유형의 스크립트에 의존 한다: (1)잠금 스크립트와 (2)잠금 해제 스크립트

(1) 잠금 스크립트는 출력에 배치되는 지출 조건이다. 미래에 출력을 사용하기 위해 충족되어야하는 조건을 지정한다. 역사적으로 잠금 스크립트는 일반적으로 공개 키 또는 비트코인 주소 (공개 키 해시)가 포함되어 있기 때문에 scriptPubKey라고 한다.

(2) 잠금 해제 스크립트는 잠금 스크립트에 의해 출력에 설정된 조건을 "해결하거나" 만족시키는 스크립트로, 출력을 소비한다. 잠금 해제 스크립트는 모든 트랜잭션 입력의 일부이다. 대개의 경우 개인 키로 사용자의 지갑에서 생성된 디지털 서명이 들어 있다. 역사적으로 잠금 해제 스크립트는 일반적으로 디지털 서명이 포함되어 있기 때문에 scriptSig라고 불렸다.

모든 비트코인 유효성 검사 노드는 잠금 및 잠금 해제 스크립트를 함께 실행하여 트랜잭션의 유효성을 검사한다. 각 입력에는 잠금 해제 스크립트가 포함되어 있으며 기존의 UTXO를 참조한다. 유효성 검사 소프트웨어는 잠금 해제 스크립트를 복사하고 입력으로 참조되는 UTXO를 검색한 다음 해당 UTXO에서 잠금 스크립트를 복사한다. 잠금 해제 스크립트가 잠금 스크립트 조건을 충족하면 입력이 유효하다. 모든 입력은 트랜잭션의 전체 유효성 검사의 일부로 독립적으로 유효성이 검사된다.

UTXO는 블록체인에 영구적으로 기록되므로 새로운 트랜잭션에서 참조로 사용하려는 시도가 실패해도 UTXO는 변경되지 않고 영향을 받지 않는다. 출력 조건을 정확하게 만족시키는 유효한 트랜잭션만 출력이 "소비"된 것으로 간주되어 사용되지 않은 트랜잭션 출력 집합 (UTXO 집합)에서 제거된다.

[그림 6-3]은 가장 일반적인 유형의 비트코인 트랜잭션 (공개 키 해시로의 지불)에 대한 잠금 해제 및 잠금 스크립트의 예제로, 스크립트 유효성 검사에 앞서 잠금 해제 및 잠금 스크립트 연결의 결과로 결합된 스크립트를 보여준다.

[그림 6-3] scriptSig와 scriptPubKey를 결합하여 트랜잭션 스크립트 평가

The script execution stack

비트코인의 스크립팅 언어는 스택이라고하는 데이터 구조를 사용하기 때문에 스택 기반 언어라고 한다. 스크립팅 언어는 각 항목을 왼쪽에서 오른쪽으로 처리하여 스크립트를 실행한다. 숫자 (데이터 상수)가 스택에 푸시된다. 연산자는 스택에서 하나 이상의 매개 변수를 푸시하거나 팝하거나 실행하여 결과를 스택으로 푸시할 수 있다. 예를 들어, OP_ADD는 스택에서 두 항목을 팝하고 결과 합을 스택에 푸시한다.

조건부 연산자는 조건을 평가하여 TRUE 또는 FALSE의 부울 결과를 생성한다. 예를 들어, OP_EQUAL은 스택에서 두 항목을 팝하고 같지 않으면 TRUE (TRUE는 숫자 1로 표시) 또는 FALSE (숫자 0으로 표시)를 푸시한다. 비트코인 트랜잭션 스크립트에는 대개 조건부 연산자가 포함되어 있으므로 유효한 트랜잭션을 나타내는 TRUE 결과를 생성할 수 있다.

A simple script

[그림 6-4]에서 간단한 수학을 수행하는 비트코인의 스크립트 유효성 검사에서 스크립트 2 3 OP_ADD 5 OP_EQUAL은 산술 연산자 OP_ADD를 보여 주며 두 개의 숫자를 더하고 그 결과를 스택에 넣은 다음 결과 합이 5와 같은지 확인하는 조건 연산자 OP_EQUAL을 표시한다.

대부분의 잠금 스크립트는 공개 키 해시 (본질적으로 비트코인 주소)를 참조하기 때문에 자금을 사용하기 위해 소유권을 증명해야하므로 스크립트가 그렇게 복잡하지 않아도 된다. TRUE 값을 갖는 잠금 및 잠금 해제 스크립트의 모든 조합이 유효하다. 스크립팅 언어의 예로 사용된 간단한 산술 연산은 트랜잭션 출력을 잠그는 데 사용할 수 있는 유효한 잠금 스크립트이기도하다.

산술 예제 스크립트의 일부를 잠금 스크립트로 사용하시오:

3 OP_ADD 5 OP_EQUAL

잠금 해제 스크립트로 입력을 포함하는 트랜잭션이 만족할 수 있다:

2

유효성 검사 소프트웨어는 잠금 및 잠금 해제 스크립트를 결합하고 결과 스크립트는 다음과 같다.

2 3 OP_ADD 5 OP_EQUAL

[그림 6-4]의 단계별 예제에서 보았듯이 이 스크립트가 실행될 때 결과는 OP_TRUE이므로 트랜잭션이 유효하다. 이것은 유효한 트랜잭션 출력 잠금 스크립트 일뿐만 아니라 결과적인 UTXO는 숫자 2가 스크립트를 충족시키는지를 알기 위해 산술 스킬을 가진 사람이 소비할 수 있다.

[그림 6-4] 간단한 수학을 수행하는 비트코인의 스크립트 유효성 검사

① 왼쪽부터 실행이 시작된다. 상수 값 "2"가 스택 맨 위로 푸시된다.

② 실행은 각 단계마다 오른쪽으로 이동하면서 계속된다. 상수 값 "3"이 스택 맨 위로 푸시된다.

③ ADD 연산자가 스택에서 두 상수를 꺼내 더한다(3+2). 그 뒤 ADD 연산자가 결과 값(5)을 스택 맨 위로 푸시한다.

④ 상수 “5”를 스택 맨 위로 푸시한다.

⑤ EQUAL 연산자는 스택에서 두 항목을 팝하고 그 값들을 비교한다(5와 5). 만약 그 둘이 같으면 EQUAL은 TRUE(=1)을 스택 맨 위에 푸시한다.

Pay-to-Public-Key-Hash (P2PKH)

비트코인 네트워크에서 처리되는 트랜잭션의 대부분은 Pay-to-Public-Key-Hash 또는 "P2PKH"스크립트로 고정되어 있다. 이 출력에는 공개 키 해시로 출력을 잠그는 잠금 스크립트가 포함되어 있다. 일반적으로 비트코인 주소라고 한다. P2PKH 스크립트에 의해 잠긴 출력은 공개 키와 해당 개인 키에 의해 생성된 디지털 서명을 제시함으로써 잠금 해제 (소비) 될 수 있다.

예를 들어 Alice가 Bob 's Cafe에 다시 지불하는 것을 살펴보겠다. Alice는 카페 비트 코인 주소에 0.015 비트코인을 지불했다. 해당 트랜잭션 출력에는 다음 형식의 잠금 스크립트가 있다:

OP_DUP OP_HASH160 <Cafe Public Key Hash> OP_EQUALVERIFY OP_CHECKSIG

Cafe Public Key Hash는 Base58Check 인코딩이 없는 카페의 비트코인 주소와 같다. 대부분의 응용 프로그램에서는 공개 키 해시가 16진수 인코딩으로 표시되며 "1"로 시작하는 친숙한 비트코인 주소 Base58Check 형식이 표시되지 않는다.

이전 잠금 스크립트는 다음 형식의 잠금 해제 스크립트로 충족될 수 있다:

<Cafe Signature> <Cafe Public Key>

두 스크립트는 다음과 같이 결합된 유효성 검사 스크립트를 형성한다:

<Cafe Signature> <Cafe Public Key> OP_DUP OP_HASH160

<Cafe Public Key Hash> OP_EQUALVERIFY OP_CHECKSIG

실행될 때 잠금 해제 스크립트가 잠금 스크립트에 의해 설정된 조건과 일치하는 경우에만 이 결합된 스크립트는 TRUE로 평가된다. 즉, 잠금 해제 스크립트가 공개 키 해시에 상응하는 카페의 개인 키에서 유효한 서명을 가지면 TRUE가 된다.

[그림 6-5]와 [그림 6-6]은 두 부분으로 나뉘어져있는 단계별 실행 결과를 보여준다. 이 스크립트는 유효한 트랜잭션임을 증명한다.

[그림 6-5] P2PKH 트랜잭션에 대한 스크립트 평가 (1/2 부)

① 실행 시작, <sig>값이 스택 맨 위로 푸시된다.

② 실행은 각 단계마다 오른쪽으로 이동하면서 계속된다. <PubK>값이 <sig> 위인 스택 맨 위로 푸시된다.

③ DUP 연산자가 스택 맨 위에 있는 항목을 복사한 다음 그 결과를 스택 맨 위로 푸시한다.

[그림 6-6] P2PKH 트랜잭션에 대한 스크립트 평가 (2/2 부)

④ HASH160 연산자가 스택 맨 위 항목을 RIPEMD160(SHA256(PubK))로 해시한다. 그 결과(PubKHash)를 스택 맨 위에 푸시한다.

⑤ 스크립트로에 있는 PubKHash값을 이전에 PubK를 HASH160로 계산된 값인 PubKHash 위에 푸시한다.

⑥ EQUALVERIFY 연산자는 트랜잭션을 방해하는 PubKHash를 사용자의 PubK에서 계산 된 PubKHash와 비교한다. 일치하면 둘 다 제거되고 실행이 계속된다.

⑦ CHECKSIG 연산자는 서명 <sig>를 공개 키 <PubK>에 매치시켜 검사하고 같으면 스택 맨 위에 TRUE를 푸시한다.

Digital Signatures (ECDSA)

비트코인에 사용되는 디지털 서명 알고리즘은 ECDSA (Elliptic Curve Digital Signature Algorithm)다. ECDSA는 타원 곡선 개인 / 공개 키 쌍을 기반으로 하는 디지털 서명에 사용되는 알고리즘이다. ECDSA는 스크립트 함수 OP_CHECKSIG, OP_CHECKSIGVERIFY, OP_CHECKMULTISIG 및 OP_CHECKMULTISIGVERIFY에 의해 사용된다. 잠금 스크립트에서 해당 내용을 볼 때마다 잠금 해제 스크립트에 ECDSA 서명이 있어야한다.

디지털 서명은 비트코인에서 세 가지 용도로 사용된다.

첫째, 서명은 함축적으로 자금의 소유자인 개인 키 소유자가 자금의 지출을 승인했음을 증명한다.

둘째, 허가 증명은 부인할 수 없다 (부인 방지).

셋째, 서명은 거래 (또는 거래의 특정 부분)가 서명된 후 누구도 수정할 수 없으며 변경할 수 없다는 것을 증명한다.

각 거래 입력은 독립적으로 서명된다. 이것은 서명이나 입력 모두가 동일한 "소유자"에 속하거나 적용되어야하므로 중요하다.

How Digital Signatures Work

디지털 서명은 두 부분으로 구성된 수학적 체계이다:

첫 번째 부분은 메시지 (트랜잭션)에서 개인 키 (서명 키)를 사용하여 서명을 만드는 알고리즘이다.

두 번째 부분은 누구나 서명과 메시지 및 공개 키를 확인할 수 있는 알고리즘이다.

Creating a digital signature

비트코인의 ECDSA 알고리즘 구현에서 서명되는 "메시지"는 트랜잭션이거나 트랜잭션의 특정 데이터 서브 세트의 해시이다. 서명 키는 사용자의 개인 키다. 결과는 다음과 같다.

-dA는 서명 개인 키

-m은 거래 (또는 그 일부)

-Fhash는 해시 함수

-Fsig는 서명 알고리즘

-Sig는 결과 서명

함수 Fsig는 일반적으로 R 및 S라고 하는 두 값으로 구성된 서명 Sig를 생성:

Sig = (R, S)

이제 R과 S의 두 값이 계산되었으므로 고유한 인코딩 규칙 (DER)이라는 국제 표준 인코딩 체계를 사용하여 바이트 스트림으로 직렬화된다.

Serialization of signatures (DER)

Alice가 다시 생성한 트랜잭션을 살펴보겠다. 트랜잭션 입력에는 Alice의 지갑에서 DER로 인코딩된 다음 서명이 포함된 잠금 해제 스크립트가 있다.

이 서명은 Alice의 지갑에서 생성된 R 및 S 값의 직렬화된 바이트 스트림으로, 해당 출력을 보낼 권한이 있는 개인 키를 소유하고 있음을 증명한다. 직렬화 형식은 다음과 같은 9 개의 요소로 구성된다.

0x30 - DER 시퀀스의 시작

0x45 - 순서의 길이 (69 바이트)

0x02 - 정수 값 뒤에 온다.

0x21 - 정수의 길이 (33 바이트)

R-00884d142d86652a3f47ba4746ec719bbfbd040a570b1deccbb6498c75c4ae24cb

0x02 - 다른 정수가 온다.

0x20 - 정수의 길이 (32 바이트)

S-4b9f039ff08df09cbe9f6addac960298cad530a863ea8f53982c09db8f6e3813

사용 된 해시 유형을 나타내는 접미어 (0x01) (SIGHASH_ALL)

Verifying the Signature

서명을 확인하려면 서명(R과 S), 일련화된 트랜잭션 및 공개 키가 있어야 한다. 기본적으로 서명의 확인은 공개 키를 생성한 개인 키 소유자만 트랜잭션에 서명을 생성할 수 있다. 서명 검증 알고리즘은 메시지, 서명자의 공개 키 및 서명을 취하고 서명이 유효한 경우 TRUE를 반환한다.


Signature Hash Types (SIGHASH)

비트코인의 경우 메시지에 디지털 서명이 적용된다. 서명은 특정 거래 데이터에 대한 서명자의 약속을 의미한다. 가장 단순한 형태로 서명이 전체 트랜잭션에 적용되어 모든 입력, 출력 및 기타 트랜잭션 필드를 약속한다. 그러나 서명은 트랜잭션의 데이터 하위 집합에서만 약속할 수 있다.


비트 코인 서명은 SIGHASH플래그를 사용한 개인 키 서명에 의해 서명된 해시에 거래 데이터에 어느 부분이 포함되어 있는지를 표시하는 방법을 가지고 있다. SIGHASH플래그는 서명에 추가된 단일 바이트이다. 모든 서명에는 SIGHASH플래그가 있으며 플래그는 입력마다 다를 수 있다. 3개의 서명 입력이 있는 트랜잭션에는 각각 다른 SIGHASH플래그가 있는 3개의 서명이 있을 수 있다.


각 입력은 잠금 해제 스크립트에 서명을 포함할 수 있다. 따라서 여러 입력을 포함하는 트랜잭션에는 각 입력에 트랜잭션의 다른 부분을 약속하는 여러 SIGHASH플래그가 있는 서명이 있을 수 있다.


SIGHASH유형과 그 의미에 표시된 대로 ALL, NONE및 SINGLE의 SIGHASH플래그가 있다.


[표 6-3] SIGHASH 유형과 의미


또한 앞의 각 깃발과 결합할 수 있는 SIGHASH_ANYONECANPAY 수식어가 있다. ANYONECANPAY가 설정되면 하나의 입력만 서명되고 나머지(및 해당 시퀀스 번호)는 수정할 수 있도록 열린다. ANYONECANPAY는 0x80의 값을 가지고 있으며 비트코인에 의해 적용되며, 이로 인해 수정자와 그 의미가 있는 SIGHASH형식으로 결합된다.


[표 6-4] SIGHASH 수식어 유형과 의미


서명 및 검증하는 동안 SIGHASH플래그를 적용하는 방법은 트랜잭션 복사본이 만들어지고, 내부의 특정 필드가 잘리는 것이다(길이 0으로 설정하거나 비워 둠). 결과적으로 트랜잭션이 일련화된다. SIGHASH플래그가 일련화된 트랜잭션의 끝에 추가되고 그 결과는 해시 된다. 해시 자체는 서명된 "메시지"이다. 사용되는 SIGHASH플래그에 따라 트랜잭션의 다른 부분이 잘린다.


ECDSA Math

서명 알고리즘은 먼저 임시 개인 공개 키 쌍을 생성한다. 이 임시 키 쌍은 서명 개인 키와 트랜잭션 해시가 관련된 변환 후 R 및 S 값을 계산할 때 사용된다.

임시 키 쌍은 임시 개인 키로 사용되는 난수 k를 기반으로 한다. k에서 우리는 상응하는 임시 공개 키 P (P = k * G로 계산 됨, 비트 코인 공개 키가 파생되는 방식과 동일하게 계산 됨)를 생성한다. 디지털 서명의 R 값은 일시적인 공개 키 P의 x 좌표이다.

거기에서 알고리즘은 다음과 같이 서명의 S 값을 계산한다:

-k는 일시적인 개인 키

-R은 일시적인 공개 키의 x 좌표

-dA는 서명 개인 키

-m은 거래 데이터

-p는 타원 곡선의 소수

검증은 R, S 값 및 공개 키를 사용하여 타원 곡선 (서명 생성에 사용되는 임시 공개 키)의 한 점인 값 P를 계산하는 서명 생성 함수의 역이다:

R과 S는 서명 값

Qa는 Alice의 공개 키

m은 서명 된 트랜잭션 데이터

G는 타원 곡선 생성기 점

계산된 점 P의 x 좌표가 R과 같으면 검증자는 서명이 유효하다고 결론을 내릴 수 있다.

서명을 검증 할 때 개인 키는 알려지지도 공개되지도 않는다.


Comments