Chapter 13. 세그윗

iworkist
Programming Bitcoin
23 min readMay 31, 2020

아래 글에서는 “밑바닥부터 시작하는 비트코인(Programming Bitcoin) -한빛미디어(2019)”의 Chapter 13.세그윗에 대한 내용을 다룬다. 본 문서에서는 세그윗 업그레이드의 배경과 주요 내용을 설명한다.

Writer.박재홍

Reviewed by @

Programming Bitcoin Series

Chapter 1. 유한체
Chapter 2. 타원곡선
Chapter 3. 타원곡선 암호
Chapter 4. 직렬화
Chapter 5. 트랜잭션
Chapter 6. 스크립트
Chapter 7. 트랜잭션 검증과 생성
Chapter 8. p2sh 스크립트
Chapter 9. 블록
Chapter 10. 네트워킹
Chapter 11. 단순 지급 검증
Chapter 12. 블룸 필터
Chapter 13. 세그윗

세그윗(segwit, segregated witness, 분리된 증인)

요약

세그윗은 다음 문제들을 해결하거나 보완하기 위한 비트코인 소프트포크 업그레이드다. 이는 2017–08–24(481,822 블록)에 완료되었으며 주요 내용은 다음과 같다.

  • 트랜잭션 가변성 문제를 분리된 증인(Segregated Witness)방법으로 해결
  • 블록 크기를 1MB에서 4MB Weight로 변경함으로써 확장성 문제 보완
  • 세그윗 버전 식별 방식 도입으로 향후 스크립트 업그레이드 체계 수립
  • 이차 해싱 문제 해결
  • 오프라인 지갑 수수료 계산 보안 강화

본 장에서는 다음의 내용을 설명한다.

  • 트랜잭션 가변성(tx malleability) 문제
  • 세그윗 업그레이드 배경
  • 세그윗 트랜잭션 데이터 구조 및 파싱 방법
  • 세그윗 sighash
  • 세그윗 표준 스크립트

트랜잭션 가변성(transaction malleability) 문제

비트코인 트랜잭션 가변성이란 트랜잭션의 의미는 같아도 그 내용은 다를 수 있다는 것이다.

다음의 예를 보자.

비트코인 트랜잭션의 스크립트 s가 있다고 하자.

s: 1 + 1

그런데, 누군가 이 스크립트를 다음과 같이 변경했다.

s*: 1 + 1 + 0

s와 s*의 스크립트 내용은 다르다.

s ≠ s*
hash(s) ≠ hash(s*)

하지만 처리 결과는 같다.

run(s) = run(s*) = 2

다음은 실제 비트코인 트랜잭션의 예를 들어 가변성과 이로 인해 발생 할 수 있는 문제를 설명한다.

비트코인 트랜잭션 스크립트의 첫 한 바이트에는 다음과 같은 명령어 코드가 올 수 있다.

명령어 코드의 예)

0x01~0x4b (1~75): 이 길이만큼 읽어서 스택에 올린다.0x4c (76): op_pushdata1, 다음 1 바이트 길이만큼 읽어서 스택에 올린다.0x4d (77): op_pushdata2, 다음 2 바이트 길이만큼 읽어서 스택에 올린다.

참고로 전체 명령어 세트는 다음 링크에서 확인할 수 있다.

https://en.bitcoin.it/wiki/Script

다음 트랜잭션을 보자.

txid:683f45578328242a06bc5c54acbcbe6e70a5435b4561fc8b0570a59ab09f8bfa

링크: https://blockstream.info/tx/683f45578328242a06bc5c54acbcbe6e70a5435b4561fc8b0570a59ab09f8bfa?expand

입력 #0이 사용하는 PREVIOUS OUTPUT SCRIPT가 p2pkh로 잠겨있는 것을 볼 수 있다.

그리고 p2pkh 스크립트의 SCRIPTSIG에는 소유자의 서명과 공개키가 들어있다.

위의 SCRIPTSIG (HEX)는 다음과 같다.

위 스크립트는 0x4d로 시작한다. 0x4d는 op_pushdata2 이므로, 이후 2바이트를 읽어서 스택에 올리라는 의미다. 다음 2바이트는 0x4900이다. 비트코인에서는 정수를 리틀엔디안으로 처리한다. 그래서 0x4900은 10진수로 73이다.

그런데 위의 스크립트는 0x4d4900을 0x49로, 0x434100을 0x41로 변경해도 같은 의미를 갖는다. 아래는 변경된 스크립트의 내용이다. 잘 보면 빨간색으로 되어 있는 명령어만 바뀌었을뿐 스크립트의 실제 내용은 바뀌지 않았다. (참고로 비트코인 트랜잭션 스크립트는 명령어 규칙만 맞으면 정상적으로 처리된다.)

트랜잭션 가변성이란 위의 예에서 처럼 트랜잭션의 의미는 동일하지만 스크립트가 다른 두 개 이상의 트랜잭션이 존재 할 수 있는것을 말한다.

위의 경우외에도 트랜잭션 가변성을 일으키는 원인은 다양하다. 자세한 내용은 다음 문서를 참고한다.

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

다음은 트랜잭션 가변성으로 발생할 수 있는 문제를 설명한다.

Alice가 tx1을 생성했다. 그리고, 아직 tx1이 블록에 포함되지 않은 시점에서 Hacker가 tx1을 tx1’이라고 변조해서 브로드캐스팅한다. 그러면 어떤 마이너들은 tx1을 블록에 포함하고 다른 마이너들은 tx1’을 블록에 포함할 것이다. 그리고, 결국에는 tx1이나 tx’중 하나만이 블록체인에 포함될 것이다.

case1: Alice -> tx1 -> Block[tx1 …]case2: Alice -> tx1 -> Hacker -> tx1’ -> Block[tx1’…]

tx1이 아닌 tx1’이 블록에 포함되는 경우, Alice는 자신이 생성한 tx1을 블록에서 찾을 수 없게 된다. 물론 A는 tx1과 의미가 동일한 tx1’을 찾을 가능성도 있다. 하지만 혼란과 불필요한 처리 비용을 발생시킨다. 만약 어떤 공격자가 트랜잭션 가변성 공격을 지속적으로 시도한다면 수 많은 사용자와 거래소들은 큰 혼란을 겪게 될 것이다.

세그윗(segwit) 업그레이드 배경

트랜잭션 가변성 문제 해결을 위한 아이디어로 BIP-64(Pieter Wuille, 2014–03–12)가 있었다. 이는 Unlock Script로 인한 트랜잭션 가변성 문제를 해결하기 위해 7가지 제약을 제안했다. 그 중에 하나로는 op_push* 명령시 실제 데이터보다 큰 사이즈를 사용하지 않아야 하며, 그렇지 않은 스크립트는 에러처리를 하자는 것이다. 앞의 트랜잭션 가변성 문제에서 예로 든것 처럼, 1바이트로 사용하면 되는것을 op_pushdata2로 사용하는 것은 에러로 처리하자는 것이다. 하지만, 이 제안은 결국 철회되었다. 왜냐하면, 제약을 추가하는 방식으로는 가변성 문제를 근본적으로 해결하지 못하기 때문이다. 예를들어 multisig를 해제하는 스크립트인 경우, 다수중 한명이 서명을 변경해서 트랜잭션을 배포하는 경우 malleability 문제가 발생한다. 결국 서명을 포함하는한 트랜잭션 가변성 문제는 해결되지 않는것을 알았다.

참고: BIP (Bitcoin Improvement Proposal)

이후, 트랜잭션 가변성 문제를 해결 및 확장성을 개선하기 위한 제안이 나왔다.

  • BIP141: Segregated Witness (Consensus layer)
  • BIP143: Transaction Signature Verification for Version 0 Witness Program
  • BIP144: Segregated Witness (Peer Services)
  • BIP145: getblocktemplate Updates for Segregated Witness
  • BIP147: Dealing with dummy stack element malleability
  • BIP148: Mandatory activation of segwit deployment
  • BIP173: Base32 address format for native v0–16 witness outputs

이 제안의 기본 아이디어는 트랜잭션 id 생성시 트랜잭션 가변성의 문제 원인인 Unlock_Script를 제외함으로써, 근본적으로 트랜잭션 가변성 문제를 해결하자는 것이다. 해결방식은 단순해 보인다. 하지만, 비트코인 생태계는 수 많은 이익집단이 협업을 통해 유지되고 있다. 그래서 비트코인의 처리 방식이 변경되면 관련된 많은 소프트웨어의 업그레이드가 필요하다.

은행의 전산시스템을 업그레이드 하는 경우, 명절등의 긴 연휴기간을 빌어 며칠간 전체 시스템을 업그레이드 하고 관련 웹, 앱들을 업그레드하면 되지만, 365일 24시간 끊임없이 동작하는 비트코인 네트워크는 중단할 수가 없다. 또한 네트워크 참여자들은 각각 다른 조직이며, 다양한 이해관계가 얽혀있다.

그렇기 때문에 비트코인 네트워크에서 기능을 업그레이드 하는 것은 쉬운일이 아니다. 또한, 자칫 잘못하면 비트코인 네트워크의 체인이 분리될 수도 있는 위험도 있다.

이러한 이유로, 세그윗 업그레이드는 하위 호환성을 보장하면서, 트랜잭션 가변성 문제와 확장성 문제를 해결하기위한 (어쩔 수 없이) 다소 복잡한 업그레이드 방안을 제안했다. 그리고, 세그윗 업그레이드는 이후 진행하기로 합의가 됐고, 481824블록(2017.8.24)부터 적용되었다. 현재(2020.5)는 전체 트랜잭션의 60% 정도가 세그윗 트랜잭션으로 처리되고 있다.

참고: https://transactionfee.info/charts/payments-spending-segwit/

세그윗 업그레이드가 해결하는 주요 문제는 다음과 같다

  • 트랜잭션 가변성 문제를 해결함과 더불어 다음의 문제들을 해결한다.
  • 블록 크기 확대로 확장성 문제 보완 (블록크기를 1MB에서 4MB Weight로 변경)
  • 세그윗 버전 식별 방식 도입으로 향후 스크립트 업그레이드 체계 수립
  • 이차 해싱 문제 해결
  • 오프라인 지갑 수수료 계산 보안 강화

그리고 세그윗을 통한 주요 소스코드 업그레이드 내용은 다음과 같다.

  • 트랜잭션 데이터 구조 변경
  • 표준 스크립트 추가
  • sig_hash 생성방법 변경
  • 블록 merkel root 계산 방법 변경
  • 트랜잭션 및 블록 전송 방법 변경
  • bech32 주소 추가

세그윗 트랜잭션 데이터 구조 및 파싱 방법

세그윗 업그레이드에서는 트랜잭션 데이터 구조를 변경했다. 변경 이유는 unlock_script로 인한 트랜잭션 가변성 문제를 제거하기 위해서다.

이 장에서는 세그윗 트랜잭션의 구조(Structure) 및 이를 파싱(Parsing)하고 직렬화(Serialization)하는 방법을 설명한다.

세그윗 트랜잭션의 구조를 기존 레거시 트랜잭션과 비교해서 설명한다.

레거시 트랜잭션은 legacy.tx, 세그윗 업그레이드 이후의 트랜잭션 구조는 segwit.tx로 지칭한다.

legacy.tx의 구조는 다음과 같다. (size:내용)

# legacy.tx04: versionvi: input_count*: input(s)vi: output_count*: output(s)4: locktime# legacy.tx.input32: prev.txid04: prev.tx.indexvi: unlock_script_length*: unlock_script04: sequence_number# legacy.tx.output08: amountvi: lock_script_length*: lock_script

참고로 vi(variable integer)는 다음과 같이 수를 인코딩한다. 저장공간을 적게 사용하기 위한 방법이다.

x < 0xFD: uint8 (0xFD=253)0xFD < x <= 0xFFFF: 0xFD + uint16 (little endian)0xFFFF < x <= 0xFFFFFFFF: 0xFE + uint32 (little endian)0xFFFFFFFF < x <= 0xFFFFFFFFFFFFFFFF: 0xFF + uint64 (little endian)

segwit.tx 구조는 다음과 같다.

# segwit.tx04: version01: marker // 0x0001: flag // 0x01vi: input_count*: input(s) // legacy.tx.inputvi: output_count*: output(s) // legacy.tx.output*: witness(s) //4: locktime# legacy.tx.input32: prev.txid04: prev.tx.indexvi: unlock_script_length*: unlock_script04: sequence_number# legacy.tx.output08: amountvi: lock_script_length*: lock_script# segwit.tx.witnessinput_count: witness(s)

legacy.tx 기준으로 세그윗에서는 (빨간색으로 표시된) marker, flag, witness 부분이 추가되었다.

marker와 flag는 무엇인가?

bip 141에서는 marker와 flag 값을 규정하고 있다.

marker는 legacy 노드에서 세그윗 트랜잭션을 비정상으로 취급할 수 있도록 해준다.

legacy 노드에서는 세그윗 트랜잭션을 파싱하면, version 다음에 오는 input_count값으로 marker(0x00) 값을 읽게 된다. 그러면 input_count이 항상 0이 되며, input_count가 0이면 비정상 트랜잭션이다. 그래서 legacy 노드는 이 트랜잭션을 폐기한다.

그러면 flag값은 왜 필요하고 어떤 의미를 갖는가? bip 문서만으로는 이해가 안되서 검색해보니,

세그윗을 제안한 PeterWuille가 이 질문에 대한 답을 해놨다. 그의 말에 따르면, 미래에 다른 witness 타입이 추가될 것을 대비해서 그렇게 한것이라는 것이다. 이는 향후에 다른 타입의 witness 처리 방식이 추가될 수 있다는 것을 암시한다.

segwit.tx.witness 내용은 세그윗 표준 스크립트에 따라 그 내용이 달라진다. 이에 대한 설명은 Chapter 6. 스크립트를 참고한다.

세그윗 트랜잭션을 파싱 과정을 파이썬 코드로 설명한다.

코드 설명을 위해 사용할 세그윗 트랜잭션의 16진수 바이트 시퀀스의 예는 다음과 같다.

tx="02000000000101fb745ed7da899f898954ae4b9d53e2f5733dc66ee9f53f437febc3dd1001f15e00000000171600145bbcf04653f3f782a060168801fd0687b3672ce2feffffff02100b3a8b0100000017a914eb4b7c2b71ae0f6850cc2a58a92d53c9ab294d8c8779b61a00000000001976a914e4c8b088f49dbc6a2248400e5002d2a29aed695388ac0247304402204f3934b856ee128dc25d2c5b825dd7d035911162bd8bf9f0a3dec1496c3cd32c0220324a0a2f9572573786ac5013e0db7fdeb92ee853ae1429901fe7cfd6242a98f2012102bace1110a291ccaad9a3fdd14ce705a92336024e4f9e29b9e6014fa3afd3c7776a671900"

다음은 위 세그윗 트랜잭션을 파싱하는 과정을 코드로 설명한다.

세그윗 sighash

signature hash는 트랜잭션의 어느 부분에 대해 서명했는지를 나타내는 플래그 값이다. 기본은 SIGHASH_ALL이다.

플래그 종류에는 SIGHASH_[ALL, ANYONECANPAY, NONE, SINGLE]이 있다. 이에 대한 내용은 다른장의 SIGHASH를 참고한다.

본 장에서는 세그윗에서 SIGHASH_ALL을 어떻게 처리하는지 설명한다.

우선 레거시 트랜잭션에서의 서명 방법을 설명한다.

위의 코드에서 보는 바와 같이 sighash 생성시에는 tx의 입력 스크립트가 제거된다.

트랜잭션에 생성시에는 입력스크립트에 서명을 추가해야 하고, 서명은 sighash값이 있어야 한다. 그래서 sighash에 서명을 포함할 방법은 없다. 이런 이유로 인해 입력 스크립트의 내용에 대해 서명할 방법이 없었다. 그리고 이것이 트랜잭션 가변성을 일으키는 주 원인이다.

세그윗에서는 이 트랜잭션 가변성 문제를 해결하기 위해 새로운 서명 방법을 추가했다.

이에 대한 내용은 (BIP143, https://en.bitcoin.it/wiki/BIP_0143)에 있다.

본 장에서는 이 내용을 파이썬으로 구현한 코드로 설명한다.

세그윗 표준 스크립트

세그윗에서는 다음의 4개의 표준 스크립트를 추가했다.

  • p2wpkh
  • p2sh-p2wpkh
  • p2wsh
  • p2sh-p2wsh

본 장에서는 위 스크립트의 처리 방식을 설명한다.

p2wpkh (pay to witness pubkey hash)

p2wpkh는 p2pkh의 세그윗 버전이다. p2pkh와 큰 차이는 unlock_script에 포함하던 [서명, 공개키]를 witness로 옮긴것이다.

이는 p2wpkh에서는 트랜잭션 가변성의 원인이었던 unlock_script를 제거함으로써 트랜잭션 가변성 문제를 해결한다.

p2pkh와 p2wpkh의 처리 방식을 비교하면 다음과 같다.

p2pkh 처리 방식은 트랜잭션 장의 설명을 참고한다.

p2wpkh는 unlock_script의 내용이 없다. 그래서 스크립트를 처리시 prev.tx.lock_script만을 실행한다.

세그윗을 업그레이드 하지 않은 레거시 노드에서 스크립트를 실행한 결과는 결과는 다음과 같다.

처리 결과를 보면 스택의 맨 위 원소가 0이 아닌 <pubkey_hash:20>가 남는다. 그래서 레거시 노드에서는 이 트랜잭션을 옳은것으로 판단한다.

여기서 한가지 의문이 들 수 있다.

“레거시 노드에서는 p2wpkh 형식의 트랜잭션을 비밀 키 없이 소비할 수 있는것인가?”

만약 비트코인 네트워크가 세그윗 체인과 레거시 체인으로 분리되었다면 그렇다고 할 수 있다. 하지만, 세그윗 업그레이드는 체인 분리없이 진행되었다. 결과적으로 비밀키 없이는 세그윗 트랜잭션을 소비할 수 없다.

세그윗 노드에서는 다음의 스크립트 명령어 패턴이 있으면 특별한 방식으로 스크립트를 치환해서 처리한다.

p2wpkh: [op_0, <pubkey.hash:20>]
p2wsh: [op_0, <witness_script.hash:32>]

다음은 세그윗 노드에서는 위 스크립트를 처리하는 모습은 다음과 같다.

세그윗 노드의 스크립트 실행기는 스크립트 실행시 특별한 스크립트 패턴이 있는지 확인한다. 위의 경우, p2wpkh 패턴[op_0, <pubkey.hash:20>]이 있는 것을 알았다. 스크립트 실행시 이 패턴을 만나면 witness 정보의 [<signanture>, <pubkey>]와 <pubkey.hash:20>를 가져와서 기존 스크립트 명령어 집합인 [op_0, <pubkey.hash:20>]를 다음과 같이 치환한다.

스크립트가 치환된 결과를 보면 p2pkh의 스크립트와 동일한 것을 알 수 있다.

p2pkh 처리 방식은 Chapter 5. 트랜잭션을 참고한다.

결론적으로 p2wpkh는 unlock_script에 들어갈 [<signanture>, <pubkey>] 정보를 witness에 넣어서 처리함으로써, 트랜잭션 가변성을 일으키는 unlock_script을 제거하는 효과를 준다.

p2sh-p2wpkh (pay to witness pubkey hash)

세그윗 이전의 레거시 지갑에서는 앞에서 설명한 p2wpkh로 송금할 수 없다. 왜냐하면 p2wpkh는 bech32(bip173) 주소를 사용하기 때문이다. 이런 이유로, 세그윗 업그레이드에서는 bech32 주소를 사용하지 않고도 p2sh형식으로 세그윗 트랜잭션을 생성할 수 있는 방법을 추가했다.

p2sh와 p2sh-p2wpkh를 비교하면 다음과 같다.

위에서 p2sh-p2wpkh를 보면 p2wpkh 스크립트 패턴[op_0, <pubkey.hash:20>]이 리딤(redeem) 스크립트 안에 포함되어 있다. 그래서 이를 nested 세그윗이라고 한다.

다음은 스크립트의 실행과정을 설명한다.

lock_script와 unlock_script를 결합해서 스크립트 실행을 준비한다.

이 스크립트에는 p2sh 특별패턴이 있다. p2sh에 대한 설명은 Chapter 8. p2sh 스크립트를 참고한다.

p2sh 특별패턴: [<redeem_script>, op_hash160, <hash:20>, op_equal]

p2sh 특별패턴이란, 스크립트 패턴의 실행 결과가 유효하면 <redeem_script>의 내용을 스크립트에 추가하는 것이다.

p2sh 특별패턴을 실행하는 과정은 다음과 같다.

<redeem_script>를 스택에 push한다.

op_hash160 명령어는 <redeem_script>를 pop하고 해시해서 스택에 push한다.

<redeem_script.hash:20>를 스택에 push한다.

op_equal 명령어는 스택에서 두번 pop해서 두 값이 일치하는지 비교한다. 두 값이 일치하는 경우 <redeem_script>의 내용을 파싱해서 스크립트에 추가한다.

위는 op_equal의 결과가 정상이라서 <redeem_script>의 내용을 파싱해서 스크립트에 추가한 모습이다.

이때 다음 명령을 실행하려고 보니 p2wpkh 패턴[op_0, <pubkey.hash:20>]이 있다. 그래서, 스크립트 실행기는 아래와 같이 스크립트를 치환한다.

이후 처리과정은 p2pkh와 동일하다. p2pkh에 대한 설명은 Chapter 5. 트랜잭션을 참고한다.

p2wsh (pay to witness script hash)

p2wpkh는 공개키를 해시한 주소로 보내는 방식으로써 가장 많이 사용되는 방식이다. 하지만, 다중서명과 같은 복잡한 처리를 위해서는 더 유연한 방식이 필요하다. 이때 사용하는 것이 p2wsh다. p2wsh는 p2sh와 비슷하다. 아래 표에서 차이점을 살펴본다.

세그윗 노드에서는 위 스크립트를 처리하는 모습은 다음과 같다.

p2wpkh에서 설명한 바와 같이 세그윗 노드에서는 다음의 스크립트 명령어 패턴이 있으면 특별한 방식으로 스크립트를 치환해서 처리한다.

p2wpkh: [op_0, <pubkey.hash:20>]
p2wsh: [op_0, <witness_script.hash:32>]

위의 경우 p2wsh 패턴에 해당된다.

세그윗 노드는 p2wsh 패턴을 만나면 witness 필드의 <winess_script>의 해시값(sha256)을 구해서 <witness_script.hash:32>값과 일치하는지 검증한다. (참고로 이때의 해시는 hash256이 아닌 sha256다.) 그리고 나서 해시값이 일치하면 witness의 내용을 스크립트에 추가한다. 이때 <witness_script>도 파싱해서 스크립트에 추가한다.

스크립트가 추가된 모습은 다음과 같다.

위 스크립트는 p2sh와 동일하다.

p2sh에 대한 설명은 Chapter 8. p2sh 스크립트를 참고한다.

p2sh-p2wsh (pay to witness script hash)

p2sh-p2wpkh 처럼 레거시 지갑에서 p2wsh를 지원할 수 있는 방법을 제공한다.

다음은 p2sh와 p2sh-p2wsh 차이를 비교한다.

lock_script와 unlock_script를 결합해서 스크립트 실행을 준비한다.

(참고로, 이후 처리과정은 p2sh-p2wpkh의 설명과 대부분 동일하지만 편의를 위해 중복 설명을 한다.)

이 스크립트에는 p2sh 특별패턴이 있다. p2sh에 대한 자세한 설명은 Chapter 8. p2sh 스크립트를 참고한다.

p2sh 특별패턴: [<redeem_script>, op_hash160, <hash:20>, op_equal]

p2sh 특별패턴이란, 스크립트 패턴의 실행 결과가 유효하면 <redeem_script>의 내용을 스크립트에 추가하는 것이다.

p2sh 특별패턴을 실행하는 과정은 다음과 같다.

<redeem_script>를 스택에 push한다.

op_hash160 명령어는 <redeem_script>를 pop하고 해시해서 스택에 push한다.

<redeem_script.hash:20>를 스택에 push한다.

op_equal 명령어는 스택에서 두번 pop해서 두 값이 일치하는지 비교한다. 두 값이 일치하는 경우 <redeem_script>의 내용을 파싱해서 스크립트에 추가한다.

<redeem_script>를 파싱해서 스크립트에 올린 결과는 다음과 같다.

위 스크립트는 p2wsh와 동일하다. 위 처리 과정은 p2wsh 설명을 참고한다.

이상으로 세그윗 업그레이드의 주요 내용을 설명했다.

하지만, 세그윗 업그레이드를 설명하기에는 부족하다. 그래서 본 설명에서 다루지 못했던 내용들을 점진적으로 추가 및 보완해 나갈 예정이다.

추가 예정인 내용은 다음과 같다.

  • 세그윗 트랜잭션 ID
  • 세그윗 블록 구조
  • 세그윗 블록 사이즈
  • 세그윗 bech32 주소
  • 세그윗 네트워크 메시지 변경 내용
  • 세그윗 소프트포크 방법
  • 세그윗 이후 비트코인의 발전 방향

--

--