출처 : 위키링크
비트코인에서는 "스크립트"라는 스크립트 언어를 사용해서 UTXO를 이용해 거래를 하고 이것을 컴퓨터가 이해할 수 있게 합니다.
이 스크립트를 비트코인 스크립트라고 부릅니다. 스크립트에서 사용하는 연산들은 Opcode라고 부르는데요.
Opcode: Operation code의 약자로 컴퓨팅에서 수행할 작업을 지정하는 기계어 명령의 일종입니다. Low-Level 기계언어로 약 140종류의 연산이 존재합니다.
다음은 Opcode 예시입니다.
A. 비트코인은 Stack-based 언어다.
Stack은 후입선출의 구조로 나중에 들어간 것이 먼저 나오는 구조다. 자료구조에서 Stack을 구글링해보면 알 수 있다.
다음과 같이 스택에 [1, 2, 3, 4, 5]가 있을 때 여기서 원소를 빼려고 하면 5부터 빠진다. 반대 자료구조로는 큐가 있는데 큐의 경우에는 1부터 빠진다.
다음 위키링크에서 알 수 있다.
B. Forth-Like
스크립트와 Forth는 닮은 언어다. forth는 1970년대에 처음 등장한 프로그래밍 언어로 오픈 펌웨어 부트로더, 우주선 및 하드웨어와의 상호작용과 관련된 다양한 기타 임베디드 시스템에서 사용되던 언어다.
C. 역폴란드 표기법(RPN, reverse Polish notation)
접두사 표기법이라고도 하는 RPN은 후위 표기법(postfix notation) 이라고도 불린다. 연산자를 연산 대상 뒤에 쓰는 연산표기법이다.
중위 표기법에서 "1 + 2"와 같은 역폴란드 표기법은 " 1 2 + "이다.
중위 표기법에서 "(2 + 3) * 4"는 역폴란드 표기법으로 "2 3 + 4 *" 이다.
따라서 연산대상과 연산자를 분리해서 연산자를 뒤에 쓰는 것이라고 간단히 이해하면 될 것 같다.
역폴란드 표기법에 대한 참고링크다.
D. 불완전한 튜링
튜링완전성이 없다는 의미는 무한 루프를 허용하지 않는다는 것이다. 장점은 악의적 공격이나 의도하지 않은 프로그래밍 오류에 관계없이 잘못된 스크립트는 실행할 수 없다는 것입니다. 단점은 기능의 활용에 있어서 제한이 많다는 것이 단점입니다.
비트코인 스크립트에서 새 트랜잭션이 추가되면 참조된 UTXO(TX-ID 및 TX-Index)와 일치하는 잠금해제 스크립트를 제공해야함
출력잠금 스크립트는 향후 다른 사람들의 출력을 사용하기 위해 기대하는 것
이 두 스크립트 필드에는 비트코인 스크립트가 포함되어 있음 예시는 하단에 있습니다.
입력 :
TX-ID(이전 트랜잭션 아이디값) : 해제하고자 하는 이전의 출력을 가리키는 포인터
TxIndex(이전 트랜잭션 인덱스값) : 해제하고자 하는 이전의 출력을 가리키는 포인터
ScriptSig : 이전의 출력을 해제하는 키
(위 사진을 참고하면 unlock script length와 unlock script인 것 같습니다만 장담은 못하겠습니다. )
출력 :
ScriptPubkey : 잠금, ScriptPubkey의 소유자(해당 공개키의 소유자)만이 ScriptSig를 만들 수 있음
Amount: 잠긴 비트코인의 양(단위:사토시)
다음 사진은 트랜잭션 포맷의 raw json 데이터입니다.
Ver : 버전은 트랜잭션 포맷의 버전입니다.
Block height : 현재 블록체인의 블록 번호이고 BIP34에서 추가됐다. BIP34에 대해서는 다음 링크를 참조하자. > 참고링크
Relayed by : 작업증명을 해결한 마이닝 풀 다음 링크에서 "Relayed by" 를 참고하자. > 링크
Weight : Segwit에서 처음 본 개념, 가중치는 거래규모와 유사함. 다음 링크를 참고하자 > 링크
스크립트는 빈 스택에서 시작하며 이 스택에서 데이터가 들어오거나(Push) 나가게 된다.(Pop)
스크립트 프로그램은 두 종류의 객체를 가지고 있다.
Opcode : 덧셈, 뺄셈, 곱셈과 같은 연산작업을 가지고 있음
데이터 : Opcode가 아닌 데이터는 모두 원시데이터로 해석되고 스택에 들어감
스택 조작 연산 : POP, PUSH, DUP, SWAP
산술/비교/비트연산 : ADD, SUB, GT, LT, OR
환경 연산: CALLER, CALLVE, NUMBER
메모리 조작 연산 : MLOAD, MSTORE, MSTORE8, MSIZE
스토리지 조작 연산 : SLOAD, SSTORE
작업 중지 연산 : STOP, RETURN, REVERT, INVALID, SELFDESTRUCT
스크립트는 이 Opcode와 DATA를 일렬로 늘어놓은 것 여기서 포인터(Pointer)는 일렬로 늘어진 Opcode와 데이터를 순서대로 하나씩 가리킴, 만약 포인터가 데이터를 가리키면 데이터를 스택에 넣고, Opcode를 가리키면 스택에서 가장 나중에 들어온 데이터를 꺼내옴
스크립트 성공시 : 스택 최상단은 1이되고 ScriptSig와 ScriptPubkey 형태의 스크립트를 얻음, 이 경우는 트랜잭션이 유효하다고 판단하고 노드는 트랜잭션을 주변노드에 전파함
스크립트 실패시 : 스택 최상단이 1이 아닐경우 트랜잭션이 유효하지 않다고 판단하고 주변노드들한테 전파되지 않음
대략 이런 뜻
if 1 in top stack : ValidTx >> Execute(ScriptSig, ScriptPubkey)
else Invalid Tx
다음 트랜잭션을 보고 비트코인 코어의 디코드 스크립트를 이용해 구조를 파악해봅시다.~
{
"version_number": 1,
"marker": null,
"flag": null,
"tx_ins": [
{
"tx_id": "00f645c7443e367330410e526b152fc799c71dafd4971d8ed6ee37babbd581bb",
"tx_index": 10,
"script": "483045022100b7393ff959120e3ccb5284e3cf2eaa200235643a1549a4e6faaa911619089e2b02207b677827c7beeb53503e016a8dd29164d07cb79f0f1e058df9b8dfa3568d0290014104c4b7a7f7bb2c899f4aeab75b41567c040ae79506d43ee72f650c95b6319e47402f0ba88d1c5a294d075885442679dc24882ea37c31e0dbc82cfd51ed185d7e94",
"sequence": 4294967295
}
],
"tx_outs": [
{
"satoshi": 16939,
"script": "a914c29b367fe...bd1b29ef47a687"
},
"... more outs..."
],
"witness": {
"stack_items": [
[]
]
},
"locktime": 0
}
흥미로운 부분은 이진 잠금 해제 스크립트가 첫 번째(그리고 유일한) 입력에 대해 16진수 표기로 제공된다는 것이다. 위 블록에 굵은 글씨로 표시했다. 잘 보이지 않을 것 같아서 나는 이것을 다음과 같이 추출했다.
"script": "483045022100b7393ff959120e3ccb5284e3cf2eaa200235643a1549a4e6faaa911619089e2b02207b677827c7beeb53503e016a8dd29164d07cb79f0f1e058df9b8dfa3568d0290014104c4b7a7f7bb2c899f4aeab75b41567c040ae79506d43ee72f650c95b6319e47402f0ba88d1c5a294d075885442679d"
키-밸류 형태로 보인다.
다음 스크립트(Ubuntu 20.04의 경우)를 사용하여 이진 비트코인 스크립트를 ASM(어셈블리 언어)로 디코딩할 수 있다:
먼저 스크립트를 다운받고 tar 압축해제를 해서 실행할 수 있다. 그리고 위에 있던 "script"의 밸류값을 인자로 넣는다.
비트코인 코어 스크립트 다운 및 실행 (디코드 옵션과 script의 밸류값을 넣어줘야한다.)
# Download and extract bitcoin-core
$ wget https://bitcoin.org/bin/bitcoin-core-0.20.0/bitcoin-0.20.0-x86_64-linux-gnu.tar.gz
$ tar -xvf bitcoin-0.20.0-x86_64-linux-gnu.tar.gz
$ cd bitcoin-0.20.0/bin/
# Run the daemon, but do not download blocks
$ ./bitcoind -daemon -connect=0.0.0.0
# Finally! Decode a Bitcoin Script hex-encoded program
$ ./bitcoin-cli decodescript "483045022100b7393ff959120e3ccb5284e3cf2eaa200235643a1549a4e6faaa911619089e2b02207b677827c7beeb53503e016a8dd29164d07cb79f0f1e058df9b8dfa3568d0290014104c4b7a7f7bb2c899f4aeab75b41567c040ae79506d43ee72f650c95b6319e47402f0ba88d1c5a294d075885442679dc24882ea37c31e0dbc82cfd51ed185d7e94"
실행 결과
{
"asm": "3045022100b7393ff959120e3ccb5284e3cf2eaa200235643a1549a4e6faaa911619089e2b02207b677827c7beeb53503e016a8dd29164d07cb79f0f1e058df9b8dfa3568d029001 04c4b7a7f7bb2c899f4aeab75b41567c040ae79506d43ee72f650c95b6319e47402f0ba88d1c5a294d075885442679dc24882ea37c31e0dbc82cfd51ed185d7e94",
"type": "nonstandard",
"p2sh": "3QEAyVJgyTXivsKQopPiGngaPwFWmzdHLL",
"segwit": {
"asm": "0 64c118d91f54d62936c29915c5cb61d39dc3353b005aca55528a714b607800de",
"hex": "002064c118d91f54d62936c29915c5cb61d39dc3353b005aca55528a714b607800de",
"reqSigs": 1,
"type": "witness_v0_scripthash",
"addresses": [
"bc1qvnq33kgl2ntzjdkzny2utjmp6wwuxdfmqpdv542j3fc5kcrcqr0qxaa2gw"
],
"p2sh-segwit": "3EVPaAaNmZtuP4acv63USoRkSXPez4dX4z"
}
}
여기서 asm은 다음과 같이 구성되어있다.
"asm": 일반적인 잠금 해제 스크립트
"스크립트서명" :
"3045022100b7393ff959120e3ccb5284e3cf2eaa200235643a1549a4e6faaa911619089e2b02207b677827c7beeb53503e016a8dd29164d07cb79f0f1e058df9b8dfa3568d029001
"공개 키"
04c4b7a7f7bb2c899f4aeab75b41567c040ae79506d43ee72f650c95b6319e47402f0ba88d1c5a294d075885442679dc24882ea37c31e0dbc82cfd51ed185d7e94",
그렇다면 이 트랜잭션에서 이번에는 잠금 스크립트를 가져와서 테스트해보자~
1. blockchain.com 사이트 링크로 가서 Overview 옆에 "JSON" 버튼을 클릭하면 다음과 같은 값이 있다. "76a9147ddb236e7877d5040e2a59e4be544c65934e573a88ac" 이 값을 가져온 뒤
2. 다음 커맨드를 입력하면 결과를 볼 수 있다.
입력 커맨드
bitcoin-cli decodescript "76a9147ddb236e7877d5040e2a59e4be544c65934e573a88ac"
실행 결과
{
"asm": "OP_DUP OP_HASH160 7ddb236e7877d5040e2a59e4be544c65934e573a OP_EQUALVERIFY OP_CHECKSIG",
"reqSigs": 1,
"type": "pubkeyhash",
"addresses": [
"1CUTyyxgbKvtCdoYmceQJCZLXCde5akiX2"
],
"p2sh": "3Jp8er9Srb9LMkJqk8jPeWafjDztYGLyLn",
"segwit": {
"asm": "0 7ddb236e7877d5040e2a59e4be544c65934e573a",
"hex": "00147ddb236e7877d5040e2a59e4be544c65934e573a",
"reqSigs": 1,
"type": "witness_v0_keyhash",
"addresses": [
"bc1q0hdjxmncwl2sgr32t8jtu4zvvkf5u4e64ucrwj"
],
"p2sh-segwit": "37e78P9jyHEZ7dp2as7w817BUPgEEUQDD2"
}
}
여기서 ASM 키 값은 매우 일반적인 잠금 스크립트입니다.
너무 색깔이 흑백이라서 캡처본도 같이 올려봤다. 참고하시면 된다.
여기서 잠금스크립트 값과 잠금스크립트 해제 값에 대해 살펴봤다. ~
대략적인 이해는 됐으나 정말 이 아이디어를 생각해낸 사람들은 대단한 것 같다.
참고 링크:
4. 비트코인 메트릭(지표데이터?정도로 이해하면된다.)
스탠다드 비트코인 스크립트(Standard Bitcoin Script) (0) | 2023.02.06 |
---|---|
Ubuntu 20.04에 bitcoin-cli 설치후 계정 생성 및 월렛 생성 테스트하기 (테스트용) (0) | 2023.02.04 |