無知

갈 길이 먼 공부 일기

기술 공부/블록체인

스마트 컨트랙트 (3) | P2SH, OP_RETURN

moozii 2022. 4. 12. 18:41

 

01. P2SH, Pay-to-Script-Hash

 

 

스마트 컨트랙트 (2) | Bitcoin Scripts

0. Testnet 실습 >>> from bitcoin import * >>> priv = sha256('****************') >>> pub = privtopub(priv) >>> addr = pubtoaddr(pub) >>> addr '1L8zP6iitxPx3YKXfJQSJpifhNgwZnUszM' >>> addr = pubtoaddr..

moozii-study.tistory.com

위의 지난 글에서 살펴보았듯이, 기존 P2PKH 기반의 Multisignature Transaction은 아래와 같은 문제가 존재했다. 

다중서명 트랜잭션은 현재 몇가지 한계가 있다. 
1. 스크립트 상 참여자의 공개 키를 모두 포함해야 하므로 그 코드의 크기가 매우 커지게 된다. 
2. 참여자 중 필수 서명 수에 따라 서로 다른 스크립트가 완성된다. 
3. 길어진 스크립트는 UTXO 포함 과정까지 시스템에 지속적인 부담을 제공한다. 
4. 스크립트 작성 과정에서 pybitcointools로는 구현이 되지 않아 수동적으로 스크립트를 수정해야 한다.

즉, 정리하면 공개키가 locking script에 포함되어 스크립트 길이가 너무 길어진다는 문제가 존재한다. 나아가, 다중서명 트랜잭션을 위해 m, n 값도 명시해줘야 하기도 한다. 이런 문제는 P2SH를 통해 해결한다. 

 

 

P2SH란, Pay-to-Script-Hash, 즉 스크립트 해시에 지불하는 방법이다. 

P2PKH, Pay-to-Public-Key-Hash, 퍼블릭 키로 지불하는 해시 방식과 달리 locking script에 해당 스크립트의 해시 값만 넣어, 복잡한 스크립트를 단순하게 만들어주는 효과를 가진다. 즉, 송금을 보내는 사람 입장에서는 송금 대상 전체의 공개 키를 알 필요 없이, 그 공개 키를 포함한 스크립트의 해시값 20바이트만 UTXO로 포함해주면 된다. 

 

스크립트 대신 스크립트 해시 값으로 locking script를 사용한다는 의미는, 송금 과정에서는 그 편의성이 증대되지만, 그에 대한 trade-off로 송금을 받은 사람이 해당 UTXO로 지불을 하려 할 때 복잡성이 늘어난다. 

 

 

구체적으로, 스크립트 해시를 통해 송금받은 P2SH 대상의 코인 사용 메커니즘은 다음과 같다. 

트랜잭션 검증 메커니즘 = Unlocking Script + Redeem Script + Locking Script 순이다. 

기존 공개 키 및 m, n 정보를 담은 locking script를 redeem script라는 이름으로 unlocking script 뒤에 붙인다. 

Unlocking Script = 0 <Payer_Signature_1> ... <Payer Signature_N>  OP_PUSHDATA1 

Redeem Script = M <Public_Key_1> ... <Public_Key_N> N OP_CHECKMULTISIG

Locking Script =  Hash160 <Redeem_Script_Hash> OP_EQUAL

 

https://wikidocs.net/14507

 

 

1. Input의 Unlocking Script (scriptSig) + Redeem Script를 실행한다.

즉, 실행 대상은 아래와 같다.

0 <Payer_Signature_1> ... <Payer Signature_N>  OP_PUSHDATA1 M <Public_Key_1> ... <Public_Key_N> N OP_CHECKMULTISIG

 

1.1. 0 <Payer_Signature_1> ... <Payer Signature_N> 부분은 데이터로 스택에 쌓인다. 

1.2. OP_PUSHDATA1는 뒤에 이어지는 Redeem Script를 하나의 데이터로 보고 스택에 쌓는다. 

즉, 현재 스택 상태는 아래 코드 블럭과 같다. 

M <Public_Key_1> ... <Public_Key_N> N OP_CHECKMULTISIG <Payer_Signature_N> ... <Payer Signature_1> 0

 


2. Locking Script Hash160 <Script_Hash> OP_EQUAL를 실행한다. 
2-1. Locking Script가 P2SH 기반인지를 검증한다. 

2-1-1. 검증 방법은 HASH 연산자, 20바이트 스크립트 해시값, EQUAL 연산자의 형태를 갖추었는지를 확인한다. 

2-2. Hash160 : P2SH 기반임이 확인되면 스택에서 데이터로 저장한 Redeem Script(=Unlocking Script)를 꺼내와 스크립트의 해시 값을 연산한다. 

2-3. <새롭게 구한 해시 값> <기존에 Locking Script에 있던 해시 값> OP_EQUAL : 해시 값이 동일한지 비교한다. 

2-4. 비교 결과 동일하면, Redeem Script를 Locking Script처럼 실행한다. 

 

 

3. Redeem Script를 실행한다. 
3-1. Redeem Script의 값 M <Public_Key_1> ... <Public_Key_N> N 를 차례로 읽어 스택에 넣는다.

3-2. OP_CHECKMULTISIG 연산자로 값을 읽어 조건에 맞는지 확인한다.
3-3. 조건에 부합하면 스택에 1이 결과값으로 남아 스크립트가 유효하다고 검증하여 UTXO 내 코인 사용이 가능하다. 
 

[P2SH 방법의 문제점]

P2SH 기반으로 코인을 지불할 때는 스크립트 해시만 사용하고, UTXO 코인을 사용할 때 스크립트가 비로소 제시되기 때문에 지불 시점이 아닌 사용 시점에 스크립트가 블록체인에 기록되는 '검증 시점 지연'이 발생한다. 즉, 검증 시점이 지연되면서 스크립트 내 오류가 지불 시점에 확인되지 않고 지불은 정상 처리되므로, 사용 시점에 오류가 발생해서 사용하지 못하는 경우가 있을 수 있다.

 

http://wiki.hash.kr/index.php/P2SH

 

P2SH - 해시넷

P2SH(Pay To Script Hash)란 공개키가 아닌 스크립트 해시에 지불하는 개념으로, 하나의 공개키를 해싱하는 것이 아닌 여러 공개키가 함께 해싱하여 출력하는 개념이다. P2SH는 BIP16에서 표준화되었고,

wiki.hash.kr

https://wikidocs.net/14507

 

2-02 P2SH 스크립트(P2SH Scripts)

Pubkey 스크립트는 스크립트가하는 일에별로 관심이없는 사람들이 만듭니다. 수신자는 스크립트 조건에주의를 기울이고 원하는 경우 지출 자에게 특정 pubkey 스크립트 사용 ...

wikidocs.net

 

# 2 of 3 transaction -> from A to B,C,D

from bitcoin import *

priv_A = sha256('password of A')
pub_A = privtopub(priv_A)
addr_A = pubtoaddr(pub_A)
blockinfo_unspent(addr_A) >>> check UTXO

priv_B = sha256('password of B')
priv_C = sha256('password of C')
priv_D = sha256('password of D')
pub_B = privtopub(priv_B)
pub_C = privtopub(priv_C)
pub_D = privtopub(priv_D)

redeem_script = mk_multisig_script(pub_B, pub_C, pub_D, 2, 3)

script_hash = scriptaddr(redeem_script, 196)
# input 196 is a prefix which indicates that the script hash is for testnet

input = blockinfo_unspent(addr_A)
output = {'value':1000000, 'address':script_hash}
# send 1000000 from UTO to script_hash address

tx = mksend(input, [output], addrA, 100000)
# addr_A = address to send change, 100000 = transaction fee

tx2 = sign(tx, 0, priv_A)
testnet_pushtx(tx2)

 

# 2 of 3 transaction -> from B,C,D to E

from bitcoin import *

priv_B = sha256('password of B')
priv_C = sha256('password of C')
priv_D = sha256('password of D')
pub_B = privtopub(priv_B)
pub_C = privtopub(priv_C)
pub_D = privtopub(priv_D)

priv_E= sha256('password of E)
pub_E= privtopub(priv_E
addr_E = pubtoaddr(pub_E, 111)

blockinfo_unspent(addr_A) 
>>> [{'output': 'transactionid****:1, 'value':2890000}]
# :1 means an index for change
# so :0 is an index for the previous transaction

input = [{'output': 'transactionid****:0 'value':1000000}]
output = {'value':995000, 'address':addr_E} 
# deducts transaction fee

tx = mksend(input, [output])
sig_B = multisign(tx, 0, redeem_script, priv_B)
sig_D = multisign(tx, 0, redeem_script, priv_D)
tx2 = apply_multisignatures(tx, 0, redeem_script, sig_B, sig_D)
testnet_pushtx(tx2)

 

 

[BITCOIN MULTISIG WALLET: THE FUTURE OF BITCOIN]

The technology that I am calling Bitcoin 1.5 is a concept that was first pioneered and formalized into the standard Bitcoin protocol in 2011 and 2012: multisignature transactions
. In a traditional Bitcoin account, as described above, you have Bitcoin addresses, where each address has one associated private key that grants the keyholder full control over the funds. With bitcoin multisignature addresses, you can have a Bitcoin address with three associated private keys, such that you need any two of them to spend the funds. Theoretically, you can have one-of-three, five-of-five, or six-of-eleven addresses too; it just happens that two-of-three is the most useful combination. With bitcoin multisignature addresses, you can have a Bitcoin address with three associated private keys, such that you need any two of them to spend the funds. Theoretically, you can have one-of-three, five-of-five, or six-of-eleven addresses too; it just happens that two-of-three is the most useful combination.

So how can multisig be used in practice? The first major use case of the protocol is consumer protection. When you make a payment with a credit card, if later on you do not get the product that you paid for you can request a "chargeback". The merchant can either accept the chargeback, sending the funds back (this is what happens by default), or contest it, starting an arbitration process where the credit card company determines whether you or the merchant have the better case. With Bitcoin (or rather, Bitcoin 1.0), transactions are final. As soon as you pay for a product, your funds are gone. And in Bitcoin 1.0, we saw this as a good thing; although it harms consumers to not have chargebacks, we would argue, it helps merchants more, and in the long term this would lead to merchants lowering their prices and benefitting everyone. In some industries, this argument is very correct; in others, however, it's not. And in Bitcoin 1.5 we recognize that, instead providing a real solution to the problem: escrow

So all in all, given that this multisig approach does require intermediaries who will charge fees, how is it better than Paypal? First of all, it's voluntary. In certain circumstances, such as when you are buying from a large reputable corporation or when you're sending money to an employee or contractor you have an established relationship with and trust, intermediaries are unnecessary; plain old A to B sends work just fine.

Second, the system is modular. Sometimes, the ideal arbitrator for a particular transaction is a specialized entity that can do that particular job much better; for example, if you're seling virtual goods the ideal arbitrator would be the operator of the platform the virtual goods are on, since they can very quickly determine whether a given virtual good has been sent.

Although multisignature escrow is a very interesting application in its own right, there is another, much larger issue that multisignature transactions can solve, and one that has been responsible for perhaps the largest share of Bitcoin's negative associations in the media, dwarfing even Silk Road, in the last three years. That issue is the concern of security and trust. 

Source : https://bitcoinmagazine.com/technical/multisig-future-bitcoin-1394686504 
 

Bitcoin Multisig Wallet: The Future of Bitcoin

Bitcoin multisig wallets have tremendous potential for increasing the security of funds and giving technology tools to enforce corporate governance. Over the

bitcoinmagazine.com

https://en.bitcoin.it/wiki/Contract#Theory

 

Contract - Bitcoin Wiki

A distributed contract is a method of using Bitcoin to form agreements with people via the block chain. Contracts don't make anything possible that was previously impossible, but rather, they allow you to solve common problems in a way that minimizes trust

en.bitcoin.it

 

 

 

 

 

2. Escrow Contracts

다중 서명 트랜잭션의 구현을 통해, 우리는 거래의 신뢰를 보장할 수 있는 중재자의 개입을 구현할 수 있다. 이때 거래 중재자, 중재 서비스를 에스크로라 부른다. 비트코인 스크립트를 통핸 트랜잭션에서도 에스크로 서비스 제공이 다중 서명을 통해 가능해진 것이다. 판매자가 에스크로 계좌로 대금을 지급받고도 그에 상응하는 상품을 지급하지 않는 경우 에스크로 중재자의 서명을 통해 지급된 대금을 반환해줄 수 있다. 

에스크로(escrow)는 상거래 시에, 판매자와 구매자의 사이에 신뢰할 수 있는 중립적인 제삼자가 중개하여 금전 또는 물품을 거래를 하도록 하는 것, 또는 그러한 서비스를 말한다. 거래의 안전성을 확보하기 위해 이용된다. (출처 : 위키백과)

 

과거 에스크로 서비스는 실제 중재자의 계좌로 대금이 송금된 뒤, 검증 작업을 거쳐 판매자에게 최종 지급되는 방식으로, 밸류체인 중도에 중재자의 완전한 통제 하에 들어간다는 위험이 존재한다. 이에 반해 다중서명 트랜잭션 기반으로 에스크로를 구현하면 공동 명의의 계좌를 통해 중재를 시행하는 것과 같기 때문에 상대적으로 권력이 분산되어 보다 안전한 서비스 구현이 가능하다는 효익이 있다. 

 

 

2-of-3 transaction 코드 구현을 보면서 실제 에스크로 서비스 구현을 확인해보자. 

# Scenario 1: Transaction Normal Flow with Escrow

from bitcoin import *

priv_customer = sha256('password of buyer')
priv_seller = sha256('password of seller')
priv_arbitrator = sha256('password of arbitrator')

pub_customer = privtopub(priv_customer)
pub_seller = privtopub(priv_seller)
pub_arbitrator = privtopub(priv_arbitrator)

redeem_script = mk_multisig_script(pub_customer, pub_seller, pub_arbitrator, 2, 3)

script_hash = scriptaddr(redeem_script, 196)
# 196 is a prefix for testnet
# customer sends coin to this co-owned address hash

# Customer Sending Coin
addr_customer = pubtoaddr(pub_customer, 111)
blockinfo_unspent(addr_customer, "testnet") >>> check UTXO
input = blockinfo_unspent(addr_customer, "testnet")
output = [{'address':script_hash, 'value':500000}]
tx_fee = 5000
tx = mksend(input, output, addr_customer, tx_fee)
tx_customer = sign(tx, 0, priv_customer)
testnet_pushtx(tx_customer)

# Seller Getting Coin
addr_seller = pubtoaddr(pub_seller, 111)
input = [{'output': 'tx_customer_id:0', 'value':495000}]
output = [{'address':addr_seller, 'value':490000}]
tx = mktx(input, output)
sig_seller = multisign(tx, 0, redeem_script, priv_seller)
>>> Send [tx, sig_seller] to Buyer

# Transaction was successful and Customer Allows Seller to Get Coin
sig_customer = multisign(tx, 0, redeem_script, priv_customer)
tx_both_signed = apply_multisignatures(tx, 0, redeem_script, sig_customer, sig_seller)
# signature order must be same as the order of public key in redeem script 
testnet_pushtx(tx_both_signed)

 

 

 

 

 

3. Return Transactions

리턴 트랜잭션은, 트랜잭션 내에 송금과 상관없이 일정 길이의 데이터를 추가해서 함께 전달하는 트랜잭션이다. 예를 들어, 우리가 송금을 할 때 송금 메시지를 첨부하는 것과 같다. 이번에 살펴본 바로는 비트코인 스크립트 내에 83바이트 정도 길이의 데이터를 OP_RETURN이라는 연산을 통해 추가할 수 있다. 거래와 무관한 별도의 데이터를 블록체인에 기록하기 위해 거짓된 UTXO를 만들 필요 없이, UTXO set에는 포함하지 않는 리턴 트랜잭션으로 데이터만 기록하는 것이다. 

 

구체적으로는, OP_RETURN 연산으로 표현되고, Locking Script 내 Output에 위치하며, 80바이트 정도의 데이터를 트랜잭션 output에 넣는 특별 유형 트랜잭션이다. 

from bitcoin import *

priv_sender = sha256('password for sender')
priv_receiver = sha256('password for receiver')

pub_sender = privtopub(priv_sender)
pub_receiver = privtopub(priv_receiver)

addr_sender = pubtoaddr(pub_sender, 111)
addr_receiver = pubtoaddr(pub_receiver, 111)

input = blockinfo_unspent(addr_sender)
output = [{'value': 100000, 'address':addr_receiver}]
tx_fee = 5000
tx = mksend(input, output, addr_sender, tx_fee)

tx_with_data = mk_opreturn('message data included', tx)
tx_with_data_signed = sign(tx_with_data, 0, priv_sender)
testnet_pushtx(tx_with_data_signed)

 

 

 

 

 

4. Blockchain Applications (based on Bitcoin)

비트코인 생태계 위에 설계된 블록체인 애플리케이션 구축 시도들에 대해 알아보자. 

 

(1) 비트코인 블록체인에 OP_RETURN으로 저작권 정보 담기

Music Copyrights Stored On The Bitcoin BlockChain: Rock Band 22HERTZ Leads The Way

Toronto’s industrial rock band 22HERTZ, created by Ralf Muller, is set to encode a copyright of the band’s new single into the Bitcoin blockchain. The overly charged copyright turned out to be a certificate with a title of the song, without any information regarding the lyrics or the melody. Muller continued to search for alternative ways to issue a copyright for the song until he thought of encoding it in the Bitcoin blockchain.

"I don’t know much about that method and wouldn’t want to burden the blockchain with a few megabytes of song data if that were even possible. I’m going the hashing route with the OP_RETURN feature. Less bloat and as effective in proving a file existed in time."


Q. The Bitcoin blockchain’s OP_RETURN limits data storage to 80 bytes. Other databases are far more efficient to store non-currency data. Why did the band still decide to encode it to the Bitcoin blockchain?

"Other databases might be more efficient to store non-currency data but are not as secure as the Bitcoin blockchain with all the petahash of power the network has. Once you encode a hash in the OP_RETURN and block upon blocks get written on top, it is basically impossible to go back and change anything, this to me is incredible."

Joseph Young, 2015-05-06, Cointelegraph
https://cointelegraph.com/news/music-copyrights-stored-on-the-bitcoin-blockchain-rock-band-22hertz-leads-the-way 
 

Music Copyrights Stored On The Bitcoin BlockChain: Rock Band 22HERTZ Leads The Way

Toronto’s industrial rock band 22HERTZ, created by Ralf Muller, is set to encode a copyright of the band’s new single into the Bitcoin blockchain.

cointelegraph.com

 

 

(2) 소유권 증명하기

파일을 업로드하면 그 해시값을 구해주고, 비트코인 사용료를 지불하면 비트코인 네트워크에 그 파일의 해시 값을 저장해주어, 본인의 소유권을 증명할 수 있는 서비스. 파일의 해시 값을 OP_RETURN 데이터에 넣어 저장하고, 파일 자체가 네트워크에 저장되지는 않으므로 파일의 내용 공개는 피한 채 소유권만 증명이 가능하다. 

 

 

(3) Colored Coin

비트코인 트랜잭션 내 다른 데이터를 포함시켜 비트코인 거래 이외 정보를 네트워크에 포함시키는 방법이다. 추가 데이터를 넣는 것을 코인을 색칠한다는 표현으로 대체한 신조어이다. 블록체인에 추가 정보를 담아 자산의 소유권을 주장하거나, 소유권을 이전하는 등의 거래가 가능하다. 

 

(3-1) Open Assets Protocol by CoinPrism

비트코인 트랜잭션을 생성하는 데, 해당 컬러 코인 프로토콜의 트랜잭션은 3가지 Output을 가진다는 특징이 있다. 이를 통해 메타데이터로 표현한 자산의 소유권 증명 혹은 이전이 가능하다. 

 

1. P2PKH 방식의 Output으로, 자산의 발행을 표현한다.

 

2. RETURN 트랜잭션으로 Marker Output이라 한다. 

2-1. OP_RETURN으로 푸시하는 데이터는 다음의 구성을 따른다. 

2-1-1. 4f 41, OA의 아스키코드 값으로 시작한다. 오픈 애셋 프로토콜임을 의미한다.

2-1-2. 그 뒤 프로토콜의 버전 정보를 담는다.

2-1-3. 그 뒤 메타데이터가 표현하는 자산 정보를 담는다. 

2-1-4. 그 뒤 메타데이터가 표현하는 자산으로의 링크 정보를 담는다. 

 

3. P2PKH 방식의 Output으로, 자산의 소유권 이전을 표현한다.

 

 

(3-2) Mastercoin

비트코인 네트워크 위에서 작동하는 새로운 코인의 작동 방법을 제안한 프로젝트이다. 별도의 블록체인 네트워크를 만드는 것이 아니라, 비트코인을 하부 구조로 삼아 새로운 코인을 개발하는 방식이다. 그리고 이 시스템을 만들기 위해 ICO도 최초로 시도한 프로젝트이다. 

 

마스터코인을 위한 비트코인 트랜잭션은 4가지 Output으로 구성된다. 

 

1. Exodus Address라는 특정 주소로 6000 사토시를 보내 해당 트랜잭션이 마스터코인 트랜잭션임을 선언한다.

2. 트랜잭션을 통해 마스터코인을 수령하는 주소를 표현한다. 

3. input UTXO를 사용한 뒤의 나머지를 표현한다. 

4. 어떤 코인을 얼마나 전달할지의 정보를 인코딩한다. 

 

즉, 비트코인 스크립트가 아닌 독자적인 인코딩 방식을 통해 비트코인 트랜잭션으로 거래를 만드는 방식이다. 이를 통해 비트코인 스크립트에 대한 의존성을 감소시킬 수 있었다. 하지만 OP_RETURN이 추가되면서 인코딩이 아닌 메타데이터 저장 방식으로 마스터코인 프로젝트도 작동 방식을 변화하게 된다. 어찌 되었든, 비트코인을 하부 구조로 삼아 보다 복잡한 서비스 및 애플리케이션을 제공하고자 한 시도이다. 

 

https://github.com/OmniLayer/spec/blob/master/OmniSpecification-v0.6.adoc

 

Omni Protocol Specification v0.6

We claim that the existing bitcoin network can be used as a protocol layer, on top of which new currency layers with new rules can be built without changing the foundation

The term “Mastercoins” applies to the digital tokens that access the features of the “Omni Protocol” clients.

https://github.com/OmniLayer/spec/blob/master/OmniSpecification-v0.6.adoc 
 

GitHub - OmniLayer/spec: Omni Protocol Specification (formerly Mastercoin)

Omni Protocol Specification (formerly Mastercoin). Contribute to OmniLayer/spec development by creating an account on GitHub.

github.com

 

MASTERCOIN: A SECOND-GENERATION PROTOCOL ON THE BITCOIN BLOCKCHAIN

Alternative currencies have become a popular topic in the Bitcoin space. We have Litecoin and Primecoin introducing alternative mining algorithms with novel properties, PPCoin replacing mining entirely with a non-costly alternative, Ripple creating a cryptocurrency network that can store credit relationships and user-defined currencies, and over seventy more up and running with new ones being created every week. One particularly interesting project that has received a large amount of attention over recent months, however, is Mastercoin. The key difference in Mastercoin is this: rather than trying to bootstrap an entirely new blockchain, as every other cryptocurrency does, Mastercoin seeks to create an entirely new network of currencies, commodities and securities on top of Bitcoin itself.

The concept of an alternative currently relying on Bitcoin to take advantage of its powerful and secure network backed by petahashes of mining power is not a new idea. The general concept first appeared in a much weaker form as “merged mining”, a mechanism in which alternative currency miners publish pointers to their blocks in the Bitcoin blockchain to mitigate the threat of 51 attacks. Mastercoin, however, takes this principle a step further. Rather than simply using the Bitcoin blockchain as a secure timestamping system to store its own blocks, Mastercoin uses the Bitcoin blockchain to store every transaction. Philosophically, the best way to think of Mastercoin is as an alternative way of making sense of Bitcoin transactions; just like the Bitcoin protocol takes a series of transactions and parses them to determine how many bitcoins are in every address at any particular moment, the Mastercoin protocol also takes the available Bitcoin transactions and parses them to extract data relevant to the Mastercoin network.

VITALIK BUTERIN 2013-11-04 Bitcoin Magazine
https://bitcoinmagazine.com/technical/mastercoin-a-second-generation-protocol-on-the-bitcoin-blockchain-1383603310 
 

Mastercoin: A Second-Generation Protocol on the Bitcoin Blockchain

Alternative currencies have become a popular topic in the Bitcoin space. We have Litecoin and Primecoin introducing alternative mining algorithms with novel

bitcoinmagazine.com