라이트닝 네트워크는 Fairness Protocol 이다.
따라서 다음과 같은 특성을 갖는다.
- Trustless operation
LN에 존재하는 노드는 서로 믿을 필요가 없다.
프로토콜 자체가 수학을 이용하여 치팅을 막아주는 것을 신뢰할 수 있기 때문이다.
- Atomicity
여러 payment channel 을 이어서 돈을 주고 받는 경우, 내가 보낸 돈은 상대방에게 전송되거나 전송되지 않거나, 둘 중 하나의 결과만 발생하는 원자성이 보장된다.
중간에 보낸 돈이 멈춰서 안간다거나 하는 일은 발생하지 않는다.
(만약 중간에 사기를 치는 사람이 있다면 돈을 돌려받을 방법이 있다.)
- Multihop
LN은 기본적으로 P2P 네트워크에서 시작했지만, 그 보안성이 end-to-end 로 확장되어 나와 직접 연결되지 않은 상대방과의 거래에 있어서도 신뢰성있는 결제 시스템을 갖출 수 있다.
이제 라이트닝 네트워크에서 채널을 통해 서로 직접 연결되지 않은 상대방에게 돈을 보내는 구체적인 과정을 살펴보자.
먼저 앨리스가 다이나에게 10 gold coin을 보내고자 하는데, 직접적으로 연결이 설정된 페이먼트 채널이 없는 상황이라고 해보자.
그러면 먼저 다이나는 앨리스에게 이 주소로 자신에게 돈을 보내라는 주소값을 보내준다.
이 주소값은 다이나가 생성한 랜덤 넘버 값을 해싱해서 만든 값이다.
앨리스는 이 주소로 돈을 보내기 위해 먼저 밥에게 12 골드코인을 지불한다.
이때 10이 아니라 12 골드코인이 되는 이유는 밥과 챈이 수수료를 챙겨야 하기 때문이다.
밥은 여기에서 1골드코인을 자신이 챙기고 11골드 코인을 챈에게 보낸다.
챈은 마찬가지로 1골드코인을 자신이 챙기고 10골드 코인을 다이나에게 보낸다.
이를 코인이 아니라 '사토시' 단위로도 생각해보면
먼저 앨리스는 다이나에게 5만 사토시를 전송할 invoice를 웹사이트를 통해 요청한다.
다이나는 웹사이트를 통해 앨리스에게 invoice를 제공한다.
이 invoice가 방금 위에서 본 시크릿 값을 해시해서 만든 해시값이다.
다이나가 정상적으로 5만 사토시를 수신하면, 올바르게 수신했다는 영수증으로서 시크릿 값을 응답하고,
나머지 관계자들이 이 영수증을 서로 응답하면서 정산과정을 거치게 된다.
이 정산과정에서 HTLC (Hash Time-Locked Contract) 가 사용된다.
LN은 비트코인 위에서 동작하므로, HTLC는 비트코인의 스크립트를 이용해서 만든다.
먼저 다이나가 랜덤 넘버 제너레이터를 돌려서 랜덤 숫자 R을 생성한다.
그리고 SHA256 과 같은 크립토 해시 함수를 사용해서 H(R)을 계산한다.
이 값으로부터 R 값을 역으로 알아내는 것은 불가능하다.
(만약 가능하다면 챈과 같은 중간 노드가 마치 나는 돈을 지불하고 이제 정산하려는 것처럼 속일 수 있게 된다.)
H(R) 값은 페이먼트 트랜잭션이 다이나를 찾아가는데 사용된다.
그리고 이 R값 (Hash Preimage, LN에서는 Payment Preimage 라고 부름)은 페이먼트 트랜잭션이 정상적으로 수신되었을 때, 그 영수증처럼 사용된다.
그래서 이 과정을 다시 더 구체적으로 들어가보면
앨리스는 다이나에게 인보이스를 요청하면, 다이나는 R (Payment preimage, Secret) 을 생성한 뒤, 이 값을 해싱해서 Payment Hashf를 만들고 인보이스에 담아서 응답한다.
앨리스는 이제 source-based routing을 해야 하므로, 자신으로부터 다이나까지 갈 수 있는 경로를 찾는다.
그리고 5만 사토시를 보낼 수 있는, 잔액이 충분한 경로를 찾았다고 해보자.
(중간 경로 중에서 송금하는 사람의 잔액이 5만 사토시가 안되는 노드가 있다면 전송할 수 없다.)
그러면 앨리스는 이렇게 5만 200 사토시를 담아서 밥에게 전송하게 된다.
이 중 100사토시는 수수료로써 밥이 가지게 되고, Alice-Bob 사이 채널의 잔액이 재조정된다.
밥은 다시 챈에게 이 둘 사이 채널에 대해 잔액을 조정하여 50100 사토시를 보낸다.
챈은 마지막으로 100 사토시를 수수료로 챙기고 5만 사토시를 다이나에게 보낸다.
애때 전송하는 트랜잭션 스크립트에는 HTLC가 들어있다.
이는 0575.. 로 시작하는, 다이나가 앨리스에게 보내줬던 그 페이먼트 해시값이 포함된 스크립트이다.
이 스크립트가 True가 되는 값은 다이나가 가지고 있는 R 값 (페이먼트 프리이미지) 이다.
다이나는 여기에 대해 R값을 제시하면 5만 사토시를 가져올 수 있다.
이때, 여기에는 타임락이 걸려있어서 정해진 시간 안에 나의 상대방이 비밀값을 알려주지 않으면 계약이 무효가 되고, 내가 주기로 한 돈을 다시 가져올 수 있다.
만약 위 그림과 같은 상황에서 챈이 R 값을 받고나서 잠수를 탔다고 해보자.
그러면 밥 입장에서는 50100을 보낸 뒤에 특정 시간동안 R 값을 받지 못하면 50100을 그대로 돌려받을 수 있기 때문에 손해보지 않는다.
(챈은 대신 쌩으로 자신의 5만 사토시를 날린 셈이 된다.)
만약 다이나가 챈이 보낸 돈을 받고 R을 응답하지 않은채로 나는 R을 갖고 있으니까 이 트랜잭션을 비트코인 온체인에 뿌린다고 하면 어떻게 될까?
그때는 비트코인 온체인에 뿌리는 순간 R값을 알 수 있게 되어, 챈도 R값을 알게 된다.
비트코인에서 기존의 해시로부터 redeem 하는 트랜잭션 자체는 공개되어 있으므로, 챈이 다이나가 5만을 가져오기 위해서 제시한 input script의 내용을 보고 r값을 알아낼 수 있다.
따라서 다이나 입장에서도 굳이 R값을 응답하지 않을 이유가 없다.
어차피 내가 5만을 쓰기 위해서 온체인에 트랜잭션을 뿌리면 그 순간 챈도 R값을 알게 되기 때문이다.
그러면 챈은 이 R값을 밥에게 제시하여 5만 100사토시를 가져올 수 있게 된다.
밥은 챈이 준 R값을 앨리스에게 제시하여 5만 200 사토시를 챙김으로써 정산을 완료한다.
이제 HTLC에 대해 구체적으로 파고들어보자.
먼저 앨리스는 밥에게 50200 사토시를 지불하며, 그때의 locking script 는 이렇게 다이나가 제공한 payment hash 값을 포함하는 스크립트로 제시한다.
밥은 챈으로부터 R값을 받기 전까지는 unlocking script를 만들 수 없으므로 50200 사토시를 얻을 수 없다.
밥은 동일한 locking script를 갖지만 50100 사토시를 전송하는 commitment transaction을 만들어 챈에게 보낸다.
챈 역시 R값을 받기 전에는 unlocking script를 만들 수 없으므로 50100 사토시를 얻을 수 없다.
챈은 다이나에게 50000 사토시를 전송하는 commitment transacction을 만들고, 다이나는 R 값을 응답한다.
챈은 R 값을 밥에게 응답하고, 50100 사토시를 R을 사용하여 가져온다.
밥은 R 값을 앨리스에게 응답하고, 50200 사토시를 R을 사용하여 가져온다.
따라서 동일한 R 이라는 시크릿을 통해 모든 관계자의 돈이 이동하므로,
모두의 돈이 이동하거나, 이동하지 않거나 라는 atomicity 가 성립하게 된다.
(중간에 끊어지면, 그 끊어진 쪽에서 돈을 대신 손해보고 내는 셈이 되기 때문이다.)
이제 여기에 각 노드의 서명까지 연결하면 더 안전해진다.
기존에는 <H> 만 존재했으나, 이제는 그 뒤에 밥의 public key 까지 함께 존재한다.
앨리스가 밥에게 50200을 보낼 때 이렇게 locking script를 작성해서 보내면 이 트랜잭션을 나중에 on chain에 뿌렸을 때, 오직 밥만 이 트랜잭션을 redeem해서 사용할 수 있을 것이다.
(기존 방법대로라면, 이 트랜잭션을 뿌린 이후에 챈이 이 트랜잭션에서 리딤해올 수도 있다.
원래는 밥이 50200을 받고, 챈이 50100을 밥에게 받아오는 것이었는데, 밥에게 50100을 받고, 앨리스가 밥에게 보낸 50200까지 추가로 챙겨오는 것이다!)
그리고 밥이 redeem할 때는 unlocking script로 위와 같이 작성하면 된다.
이제 마지막으로 아까 잠깐 언급했던 Timelock 을 스크립트에 포함해보자.
상대방이 그냥 잠수를 타는 경우를 대비해서 안전장치가 필요하기 때문이다.
앨리스 입장에서는 내가 보낸 트랜잭션이 중간에 밥이나 챈이 협조하지 않아서 거기서 멈춰있다면 불안할 것이다.
그래서 앨리스는 최선은 다이나에게 정상적으로 보내지는 것, 차선은 최소한 실패하더라도 자신에게 돈이 돌아오는 것까지는 보장이 되어야 안심할 수 있다. (이를 failure gracefully 라고 표현한다.)
이때 failure gracefully 가 진행될 때는 크게 2가지 상황이 발생할 수 있다.
첫 번째는 다이나가 그냥 돈을 받지 않겠다고 할 수도 있다.
이 경우에는 다이나-챈 사이의 컨트랙트(트랜잭션)를 지우고, 챈-밥, 밥-앨리스도 컨트랙트를 지우면 아무 일도 없어진다.
두 번째는 중간에서 누군가 협조하지 않는 경우가 있을 수 있다.
이 경우에는 타임아웃을 걸어서, 이 기간동안 R값을 제시하지 않으면 내 돈을 다시 찾아오겠다고 명시한다.
그래서 다음과 같이 타임 락을 걸어서 스크립트를 작성한다.
OP_DROP 은 스택에 있는 내용을 버린다는 뜻이다.
다음으로 <cltv_expiry>는 내가 지정한 lock time 데이터로 스택에 들어가고 OP_CHECKLOCKTIMEVERIFY (OP_CLTV) 는 트랜잭션의 마지막 필드에 들어있는 Lock Time 필드를 확인해서 현재 시간이 기준 시간보다 크거나 같은지 확인한다. 만약 락타임이 블록을 기준으로 설정이 되었다고 할 때, 현재 블록의 높이가 락타임 필드에 설정된 값에 도달하지 않았다면 이 스크립트의 검증이 실패하면서 트랜잭션이 무효한 것으로 판명된다.
따라서 특정 기간동안 이 트랜잭션이 무효하도록 만들 수 있다.
즉, 너가 만약에 내가 락타임으로 지정한 기간까지 R값을 보내지 않으면 이 트랜잭션은 그 이후부터는 VERIFY를 통과해서 OP_DROP이 실행되어 cltv_expiry 값을 버리고 서명을 검증한다. (아마 여기서 검증하는 서명은 '나의 서명' 일 것 같다. locktime이 지나기 전에는 이 스크립트가 무효화 되므로 이 스크립트를 통해서 내가 대신 돈을 빼갈 수 없지만 시간이 지나면 그때부터는 OP_CHECKSIG가 동작하므로 돈을 빼갈 수 있는 것이다. 마치 3일의 락을 걸어서 3일 동안 치팅을 확인하지 못했다면 내가 가져갈 수 있도록 하는 스크립트와 비슷하게)
챈이 다이나에게 R을 받았는데, 무슨 이유에서인지 밥에게 R을 락타임 시간 내에 응답하지 않는다면 밥은 HTLC를 무효화하고 트랜잭션을 회수할 수 있게 된다.
HTLC에서 락타임은 다음과 같이 점점 감소하도록 설정한다.
1. 앨리스가 밥에게 보내는 HTLC에는 현재 높이 + 500블록의 락타임을 설정한다. (밥에서 다이나까지 갈 때까지는 시간이 좀 더 걸릴 수 있다.)
2. 밥이 챈에게 보내는 HTLC에는 현재 높이 + 450 블록의 락타임을 설정한다. (챈에서 다이나까지는 거리가 가까워졌으므로 시간을 줄인다.)
3. 챈이 다이나에게 보내는 HTLC에는 현재 높이 + 400 블록의 락타임을 설정한다.
이렇게 감소하지 않도록 설정하면, 내가 refund를 받기도 전에 밥이 먼저 refund를 가져갈 가능성이 생기기 때문에 감소하로고 설정하는 것이다.
예를 들어 내가 밥과 동일하게 450 블록으로 락타임을 걸었는데, 450블락이 되는 순간에 R을 받았다고 해보자.
그래서 이제 응답을 하려고 했더니 밥이 450블록이 지나서 refund를 해버린다면 챈은 곤란해질 것이다.
따라서 refund를 판단하고 처리할 때까지 걸리는 시간을 고려해서 그 여유시간만큼 감소한 락타임을 설정한다.
비트코인 vs LN
주소 및 결제 체계
- 비트코인 : address / transaction
- LN : invoice / payment
비트코인은 한번 만들어둔 주소를 통해 수신자로부터 돈을 받을 수 있지만,
LN은 내가 돈을 받기 위해서 직접 invoice를 만들어 보내야 한다.
(그래서 메타 마스크와 같은 LN 전용 월렛을 사용하여 invoice를 만들고 돈을 받는 과정을 관리한다.)
즉, 비트코인의 주소는 영구적이라 reusable하지만,
invoice에는 유효기간이 정해져있어서 유효기간이 지난 뒤에는 폐기하며, 특정한 센더, 특정한 페이먼트에만 사용되는, 일회성이라는 차이점이 있다. (따라서 같은 센더가 같은 금액을 보낸다고 하더라도 새로운 인보이스를 만들어서 거기에 페이먼트 해야 한다.)
비트코인 주소는 그 주소가 지금 online 인지 offline 인지 상관없다.
일단 보내놓고 나중에 online이 된 후에도 돈을 꺼내 쓸 수 있으며, 보내는 입장에서는 online 여부를 신경쓰지 않아도 된다.
반면 LN은 online이어야 하며 특정 시간 내로 영수증에 해당하는 시크릿 키를 받아와야 하므로 동기적으로 동적한다. (비동기 x)
수수료
- 비트코인 : 트랜잭션 크기에 비례 (금액과 무관)
- LN : 전송 금액에 비례
LN에서는 각 노드의 balnace가 충분해야 payment 를 전달해줄 수 있는데, 전송 금액이 클 수록 나의 잔액이 많이 감소하고, 그 만큼 다른 페이먼트를 받을 수 없게 되므로 수수료가 증가한다.
(보통은 기본요금 + 금액에 따른 추가요금으로 구성된다.)
따라서 LN은 소액결제가 빈번히 일어날 때 쓰는 것이 좋고, 큰 금액의 결제는 비트코인 온체인에 즉각 쓰는 것이 낫다.
이때 비트코인과 LN 모두 시장 경제에 따라서 수수료가 결정될 수 있다.
비트코인은 블록에 트랜잭션을 포함시킬 때 높은 수수료가 걸린 트랜잭션부터 넣고자 할 것이므로 시장경제에 따르고,
LN에서는 특정 노드에서 특정 노드로 보낼 때 반드시 나의 채널을 거쳐야만 한다면 그 채널의 수수료가 높아지겠지만, 그런 채널이 여러개가 생기는 순간 다시 수수료가 감소하면서 시장 경제가 형성된다.
공개적인 트랜잭션 vs 사적인 payment
- 비트코인 : 공개 트랜잭션 (슈도니머스, 거의 익명, address 까지는 공개되어있지만, address의 실 소유주는 알 수 없다.)
- LN : 비공개 payment
confirmation 대기 vs 즉각 지불
2100만 코인 지불 vs local balnce 내에서 지불
- 비트코인 : 지불할 amount 값은 이론적으로 2100만 코인까지 지불할 수 있다.
- LN : 내 현재 잔고 금액 내에서 지불할 수 있고, 여러 채널을 경유하면 각 채널의 balance 최소 금액보다 작은 금액 한도에서 보낼 수 있다.
거래 단위
- 비트코인 : 사토시
- LN : 밀리 사토시 (1/1000 사토시)
LN은 소액 결제를 위한 용도이기 때문에 단위가 더 작다.
이때 최종 정산금액은 결국 비트코인 네트워크에 쓰여야 하므로, 반올림 등을 통해 사토시 단위로 맞춰서 뿌린다.
'CS > 블록체인' 카테고리의 다른 글
[블록체인] 19. 이더리움 - Account, Transaction, Block (0) | 2024.12.13 |
---|---|
[블록체인] 18. 이더리움 개요 (0) | 2024.12.13 |
[블록체인] 16. Lightning Network (2) : Commitment Sign & Payment Channel (0) | 2024.12.04 |
[블록체인] 15. Lightning Network (1) : 개요 (0) | 2024.12.01 |
[블록체인] 14. 비트코인 Consensus (2) | 2024.11.30 |