카테고리 없음

비트코인 주소로 지불하기(2) - P2MS, P2SH

3min⚡️bitcoin 2025. 8. 17. 22:00

 

P2MS (Pay-to-Multi-Sig)

비트코인 지불 방법중 다중 서명이라는게 있다.

이는 개빈 안드레센이 2011년 BIP-0011에서 제시했다.

https://github.com/bitcoin/bips/blob/master/bip-0011.mediawiki

 

bips/bip-0011.mediawiki at master · bitcoin/bips

Bitcoin Improvement Proposals. Contribute to bitcoin/bips development by creating an account on GitHub.

github.com

N개의 서명중 M개가 제시되면 비트코인을 지불할 수 있는 방법이다.

 

비트코인을 지불받고, 지불하는 것, 그리고 이 검증은 스크립트로 이루어진다.

비트코인을 사용하기 위해서는 서명을 제시해야 하고, 지불 받는 쪽에는 공개키가 있어야 한다.

따라서 비트코인의 input의 scriptSig는 해제 스크립트로 불린다. 그리고 Output의 scriptPubKey는 잠금 스크립트로 불린다.

왜냐하면 utxo는 미사용 비트코인이고, 이를 사용하기 위해서는 개인키로 서명을 하여 잠겨있는 비트코인을 해제해야 하기 때문이다.

출처: https://learnmeabitcoin.com/technical/script/p2ms/

 

P2MS는 Pay-to-Multi-Sig로 Sig, 즉 서명이 여러개 필요하도록 잠그는 방법이다.

P2MS의 잠금 스크립트는 다음과 같다.

OP_M <PubKey1> <PubKey2> ... <PubKeyN> OP_N OP_CHECKMULTISIG
OP_2 <PubKey1> <PubKey2> <PubKey3> OP_3 OP_CHECKMULTISIG

 

이는 N개중 M개가 제시되면 된다는 코드이다. 2-of-3은 2번째 예시와 같다.

 

이와같이 잠겨있는 비트코인을 사용하기 위한 해제스크립트는 다음과 같다.용ㄹ

OP_0 <Sig1> <Sig2>

 

이를 풀노드들이 유효한 트랜잭션으로 검증하기 위해서는 해제-잠금 스크립트 순으로 나열하여 확인한다.

OP_0 <Sig1> <Sig2> OP_2 <PubKey1> <PubKey2> <PubKey3> OP_3 OP_CHECKMULTISIG

 

순서대로 스택에 OP_3까지 다 쌓고, OP_CHECKMULTISIG를 통해 공개키, 서명을 임시메모리에 두고 검증한다.

서명 개수가 부족하거나 맞지 않으면 false, 검증에 성공하면 true 반환.

 

P2SH (Pay-to-Script-Hash)

P2MS의 단점을 보완하기 위해 P2SH가 bip-0016을 통해 제안된다.

P2MS의 단점은 크게 2가지이다.

  • 잠금 스크립트에 P2PK처럼 공개키가 담겨있다. 공개키는 기왕이면 지불할때 공개하는게 안전하다. P2PKH처럼
  • 잠금 스크립트가 너무 길다. 풀노드는 모든 블록데이터와 UTXO set을 저장하게 되는데, 검증의 주체인 풀노더들에게 용량 문제를 겪게 한다.

https://github.com/bitcoin/bips/blob/master/bip-0016.mediawiki

 

bips/bip-0016.mediawiki at master · bitcoin/bips

Bitcoin Improvement Proposals. Contribute to bitcoin/bips development by creating an account on GitHub.

github.com

 

P2SH는 Pay-to-Script-Hash 로, P2MS의 긴 잠금 스크립트를 해싱을 한 주소로 지불하는 방법이다.

이를 통해, 비트코인을 지급받는 입장에서는 공개키들을 숨기고 해시만 제공할 수 있다. 이는 나중에 서명할 때 서명과 공개키를 제공함으로써 사용할 수 있다.

그래서 위 bip의 motivation 파트를 보면, 자금을 사용하는 사람이 그 거래를 상환(redeem)하기 위한 조건을 제공하도록 책임을 옮기는 데 있다.

P2MS의 원본 잠금스크립트를 P2SH에서는 redeem script라고 부른다.

 

P2SH의 잠금스크립트는 다음과 같다.

OP_HASH160 <hash160(redeemScript)> OP_EQUAL

 

해제스크립트는 다음과 같다.

OP_0 <Sig1> <Sig2> <redeemScript>

출처: https://learnmeabitcoin.com/technical/script/p2sh/

풀노드는 해제스크립트에 있던 "리딤 스크립트"의 해시값과, 잠금 스크립트의 "리딤 스크립트 해시값"을 비교하여 검증한다.

 

레거시 P2SH 주소

리딤 스크립트는 ripemd160, sha256으로 해싱한다.

기존 공개키 -> 주소를 구하는 로직과 아예 동일한 로직이다.

그래서 리딤 스크립트의 해시값은 주소처럼 사용할 수 있다.

이 또한 개빈 안드레센이 bip-0013에서 제안했다.

 

https://github.com/bitcoin/bips/blob/master/bip-0013.mediawiki

 

bips/bip-0013.mediawiki at master · bitcoin/bips

Bitcoin Improvement Proposals. Contribute to bitcoin/bips development by creating an account on GitHub.

github.com

 

그래서 이 주소를 어떻게 만드는지 한 번 알아보자

2-of-3이라고 가정해보자

  1. 공개키 3개를 준비하여 리딤스크립트(잠금스크립트)를 만든다.
  2. 잠금스크립트를 SHA256으로 먼저 해싱하고, 그 결과를 RIPEMD160으로 해싱하여 160bit를 만든다.
  3. 접두사 0x05를 붙힌다.
  4. 접두사 붙힌 값을 SHA256 으로 두 번 해싱한다. 그리고 앞 4바이트를 맨 뒤에 붙힌다.
  5. 접두사 || 해싱된 리딤스크립트 || 체크섬 이 최종 주소를 Base58인코딩

pubkey1 = 02a1633caf07d1e0e3ae5c3f4c07d7a8f7ba6b9e3f5f3b32b8d0e4d3edb0c5f3a4
pubkey2 = 03b287e5bc6d1afcb63f4a1dcd71cf62e0a4d0c7e81c9d0bfe5a87b23d8f7c9d2e
pubkey3 = 024d5f6e9f58c8c7adf7f7f8c9e1a7a8b8c6d9f0f2e4b1d9e8c7f0a6b5c4d3e2f1

redeemScript522102a1633caf07d1e0e3ae5c3f4c07d7a8f7ba6b9e3f5f3b32b8d0e4d3edb0c5f3a42103b287e5bc6d1afcb63f4a1dcd71cf62e0a4d0c7e81c9d0bfe5a87b23d8f7c9d2e21024d5f6e9f58c8c7adf7f7f8c9e1a7a8b8c6d9f0f2e4b1d9e8c7f0a6b5c4d3e2f153ae

(52 = OP_2, 53 = OP_3, 21 = 33바이트 길이 나타냄. 16진수임, ae = OP_CHECKMULTISIG)

SHA256(redeemScript) = e5f9a2c3d1b7e4a1f8c6d9f0a3b2c1d0e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9
RIPEMD160(SHA256) = 3f1a8b9c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2a

prefix || RIPEMD160(SHA256) = 053f1a8b9c7d6e5f4a3b2c1d0e9f8a7b6c5d4e3f2a

checksum(doubleSHA256, 4byte) = ee641125

최종주소 = 37SgJ2rXfRWoem7tp4akzUxf2me7yUs1ja

 

접두사로 0x05를 붙여서 인코딩 했기 때문에 레거시 p2sh 주소는 항상 3으로 시작하는게 특징이다.

p2pkh = 1, p2sh = 3