상세 컨텐츠

본문 제목

비트코인 스크립트(Bitcoin Script)

Blockchain/Bitcoin

by Yongari 2023. 2. 6. 16:58

본문

출처 : https://en.bitcoin.it/wiki/Script#Script_examples

출처 : 위키링크 

 

Script - Bitcoin Wiki

Bitcoin uses a scripting system for transactions. Forth-like, Script is simple, stack-based, and processed from left to right. It is intentionally not Turing-complete, with no loops. A script is essentially a list of instructions recorded with each transac

en.bitcoin.it

 

 

비트코인 스크립트란?

비트코인에서는 "스크립트"라는 스크립트 언어를 사용해서 UTXO를 이용해 거래를 하고 이것을 컴퓨터가 이해할 수 있게 합니다.

이 스크립트를 비트코인 스크립트라고 부릅니다. 스크립트에서 사용하는 연산들은 Opcode라고 부르는데요.

 

Opcode: Operation code의 약자로 컴퓨팅에서 수행할 작업을 지정하는 기계어 명령의 일종입니다. Low-Level 기계언어로 약 140종류의 연산이 존재합니다.

다음은 Opcode 예시입니다.

상수

  • OP_0, OP_FALSE : 빈 바이트 배열이 스택으로 푸시된다.
  • N/A : 다음 옵코드 바이트는 스택에 푸시 할 데이터이다.
  • OP_PUSHDATA1 : 다음 바이트는 스택으로 푸시 될 바이트 수를 포함한다.
  • OP_PUSHDATA2 : 다음 2 바이트에는 리틀 엔디안 순서로 스택에 푸시 할 바이트 수가 포함된다.
  • OP_PUSHDATA4 : 다음 4 바이트에는 리틀 엔디안 순서로 스택에 푸시 할 바이트 수가 포함된다.
  • OP_1NEGATE : 숫자 -1이 스택으로 푸시된다. 코드 숫자로는 79로 나타내고,
  • OP_1, OP_TRUE : 숫자 1이 스택으로 푸시된다.
  • OP_2-OP_16 : 단어 이름(2-16)의 숫자가 스택으로 푸시된다.

참고 링크

 

A. 비트코인은 Stack-based 언어다.

Stack은 후입선출의 구조로 나중에 들어간 것이 먼저 나오는 구조다. 자료구조에서 Stack을 구글링해보면 알 수 있다.

다음과 같이 스택에 [1, 2, 3, 4, 5]가 있을 때 여기서 원소를 빼려고 하면 5부터 빠진다. 반대 자료구조로는 큐가 있는데 큐의 경우에는 1부터 빠진다. 

 

 

다음 위키링크에서 알 수 있다.

스택위키

 

스택(자료구조) - 나무위키

이 저작물은 CC BY-NC-SA 2.0 KR에 따라 이용할 수 있습니다. (단, 라이선스가 명시된 일부 문서 및 삽화 제외) 기여하신 문서의 저작권은 각 기여자에게 있으며, 각 기여자는 기여하신 부분의 저작권

namu.wiki

 


B. Forth-Like
스크립트와 Forth는 닮은 언어다.  forth는 1970년대에 처음 등장한 프로그래밍 언어로 오픈 펌웨어 부트로더, 우주선 및 하드웨어와의 상호작용과 관련된 다양한 기타 임베디드 시스템에서 사용되던 언어다. 

 

 

C. 역폴란드 표기법(RPN, reverse Polish notation)

접두사 표기법이라고도 하는 RPN은 후위 표기법(postfix notation) 이라고도 불린다.  연산자를 연산 대상 뒤에 쓰는 연산표기법이다.

중위 표기법에서 "1 + 2"와 같은 역폴란드 표기법은 " 1 2 + "이다. 

중위 표기법에서 "(2 + 3) * 4"는 역폴란드 표기법으로 "2 3 + 4 *" 이다. 

따라서 연산대상과 연산자를 분리해서 연산자를 뒤에 쓰는 것이라고 간단히 이해하면 될 것 같다.

 

역폴란드 표기법에 대한 참고링크다. 

 

역폴란드 표기법 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. 역폴란드 표기법(RPN, reverse Polish notation) 또는 후위 표기법(후치 표기법)(後位 -, postfix notation)은 연산자를 연산 대상의 뒤에 쓰는 연산 표기법이다. 예를 들어,

ko.wikipedia.org

 

D. 불완전한 튜링 

튜링완전성이 없다는 의미는 무한 루프를 허용하지 않는다는 것이다. 장점은 악의적 공격이나 의도하지 않은 프로그래밍 오류에 관계없이 잘못된 스크립트는 실행할 수 없다는 것입니다. 단점은 기능의 활용에 있어서 제한이 많다는 것이 단점입니다.

 

 

 

 

입력과 출력

출처 : https://betterprogramming.pub/the-bitcoin-script-language-e4379908448f

 

 

 

비트코인 스크립트에서 새 트랜잭션이 추가되면 참조된 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 키 값은 매우 일반적인 잠금 스크립트입니다.

 

너무 색깔이 흑백이라서 캡처본도 같이 올려봤다. 참고하시면 된다. 

 

 

여기서 잠금스크립트 값과 잠금스크립트 해제 값에 대해 살펴봤다. ~ 

대략적인 이해는 됐으나 정말 이 아이디어를 생각해낸 사람들은 대단한 것 같다. 

 

 

 

참고 링크:

 

1. 비트코인 스크립트

 

The Bitcoin Script Language

An elegant solution to change management

betterprogramming.pub

 

2. 트랜잭션정보 링크 

3. UTXO 모델 

 

The UTXO model

A technical cornerstone of Bitcoin

medium.com

4. 비트코인 메트릭(지표데이터?정도로 이해하면된다.)

 

Understanding some Bitcoin metrics

Are you tired of hearing only about Bitcoin’s price? Yeah me too! The fact is, the price of Bitcoin (or the price of any crypto for that…

medium.com

5. 세그윗 데이터 설명

6. BIP34 링크

 

BIP 0034 - Bitcoin Wiki

This page describes a BIP (Bitcoin Improvement Proposal).Please see BIP 2 for more information about BIPs and creating them. Please do not just create a wiki page. Please do not modify this page. This is a mirror of the BIP from the source Git repository h

en.bitcoin.it

 

7. 비트코인 스크립트에 대하여 링크

 

Bitcoin Script: An Introduction For Beginners

Bitcoin Script is a simple, stack-based programming language that enables the processing of transactions on the Bitcoin blockchain. To understand more about Bitcoin Script, we’ll first look at its characteristics and a basic example of how this programmi

komodoplatform.com

 

관련글 더보기