트랜잭션 가변성 (Transaction Malleability)

고급블록체인수정일

트랜잭션 가변성은 트랜잭션의 효력(누가 누구에게 얼마를 보내는지)은 바꾸지 않으면서 데이터 일부를 바꿔 트랜잭션 ID(TXID)만 달라지게 할 수 있는 성질입니다. 원래 TXID를 참조하던 자식 트랜잭션이 무효가 되는 문제가 생깁니다.

자세히 알아보기

비트코인의 기존(레거시) 트랜잭션에서 TXID는 서명을 포함한 전체 트랜잭션의 해시입니다. 그런데 서명 자체는 TXID 계산 대상 데이터를 완전히 고정하지 못합니다. 예를 들어 ECDSA 서명 (r, s)는 (r, n−s)로 바꿔도 유효하고, 서명 스크립트에 불필요한 데이터를 끼워 넣을 수도 있었습니다. 제3자가 미확인 트랜잭션을 이렇게 살짝 바꿔 다시 퍼뜨리면, 송금 내용은 같지만 TXID가 다른 트랜잭션이 블록에 들어갈 수 있습니다.

돈을 훔칠 수는 없지만 문제는 생깁니다.

  • TXID로 입출금을 추적하는 거래소나 지갑이 "출금이 실패했다"고 잘못 판단해 다시 보낼 수 있습니다.
  • 아직 확정되지 않은 트랜잭션의 TXID를 미리 참조해 만든 자식 트랜잭션(예: 결제 채널의 환불 트랜잭션)이 무효가 됩니다.

블록체인·암호화폐에서는

비트코인은 BIP66(엄격한 DER 서명 인코딩) 소프트 포크와 low-S 정책 규칙 같은 조치로 일부 경로를 막았고, 2017년 활성화된 세그윗(SegWit)이 서명 데이터(위트니스)를 TXID 계산에서 제외해 서명으로 인한 가변성을 근본적으로 해결했습니다. 덕분에 미확인 트랜잭션에 의존하는 라이트닝 네트워크가 안전하게 동작할 수 있게 되었습니다. 2014년 Mt.Gox는 출금 문제의 원인으로 트랜잭션 가변성을 지목했지만, 이후 분석에서 손실의 주된 원인으로 보기 어렵다는 의견이 많았습니다.

어떻게 바뀌었나: 예시

레거시 트랜잭션 A가 네트워크에 퍼졌다고 해 봅시다. 중계 노드 하나가 A의 서명 s 값을 n−s로 바꾼 A′를 만들어 퍼뜨립니다. 두 트랜잭션은 같은 입력을 같은 출력으로 보내므로 하나만 블록에 들어갈 수 있습니다. A′가 먼저 채굴되면 A는 이중 지불로 거부되고, TXID(A)를 기다리던 지갑은 "트랜잭션이 사라졌다"고 표시합니다. 하지만 자금은 실제로 목적지에 도착했습니다.

세그윗이 해결한 방식

세그윗 트랜잭션에서는 서명이 위트니스라는 별도 영역에 들어가고, TXID는 위트니스를 뺀 데이터로 계산합니다. 서명 인코딩을 아무리 바꿔도 TXID는 그대로입니다(위트니스까지 포함한 해시는 wtxid라고 따로 부릅니다). 다만 이 보호는 세그윗 입력에만 적용되므로, 레거시 입력이 섞인 트랜잭션은 여전히 가변성이 있을 수 있습니다.

서비스 운영 시 교훈

입출금 시스템은 TXID 하나만으로 상태를 판단하지 말고, 실제로 어떤 출력(주소와 금액)이 확정되었는지 확인해야 합니다. 이는 가변성뿐 아니라 수수료 대체(RBF)로 트랜잭션이 교체되는 경우에도 똑같이 필요한 원칙입니다.

쉽게 말하면

수표 금액과 받는 사람은 그대로인데 일련번호만 바뀌어서, 번호로 관리하던 장부가 엉키는 문제입니다.

이 글은 학습을 위한 일반 정보이며 투자 권유나 법률 자문이 아닙니다. 가상자산은 가격 변동이 크고 원금 손실 위험이 있습니다.