[블록체인] Lightning Network(2) - Invocies
Alice가 Dina의 팬이어서 donation이 하고 싶다.
이건 계속해서 하는 거래가 아니라 일회성이다.
이럴때 Lightning Network을 사용할 수 있는 방법이 있다.
Announcing the Channel
Alice가 Dina에게 돈을 보내기 위해 최소한 Bob, Chan의 존재를 알고 있어야 하고
그러기 위해 Bob, Chan이 channel을 announce 하는 것이다.
즉 Dina에게 가는 경로를 제공하고 수수료를 받는다.
단, unAnnounced channel이 있을 수 있다.
이러면 존재를 알고 있는 node만 이용할 수 있을 것이다.
이때 announce 하는 방법으로 gossip protocol을 사용한다.
(모든 node가 서로의 정보를 공유하는 방법)
단, 경로는 Alice가 찾아야 한다 (source based path finding)
Fairness Protocol
-
Trustless operation
-
Atomicity
-
Multihop
Invoices
쉽게 말해 견적서다.
전달 될때는 atomic way로 전달된다. 즉 중간에 실패하는 일은 없고 보내지거나/안보내지거나 둘중 하나로 보장된다.
보장 되어야 중간에 있는 node가 참여 할것이다.
Bitcoin (on-chain) vs LN (off-chain)
Bitcoin | LN |
---|---|
address | invoice |
sender(Alice)가 receiver(Bob)의 address를 찾는다 | receiver(Bob)가 sender(Alice)에게 invoice를 보내준다 |
adddress로 sender가 돈을 보낸다 | sender가 invoice에 payment에 하면 routing된다. |
어떤 miner가 block에 포함 시키는지 관심 없음 (on-chain에 등록 되기만 하면 된다) | 어떤 경로로 Bob에게 가야하는지 sender가 정해서 보내야 한다. |
-> 마지막 문장이 가장 큰 차이점이다.
sender가 경로를 정해야 한다는 점에서 확장성 측면에서 한계가 존재한다.
어떤 알고리즘으로 경로를 정할 수 있는게 아니다.
Payment Hash
Dina는 random number(preimage / payment secret)를 고른다.
그리고 random number를 hash 한다.
그리고 hash(r) 값을 payment hash라고 한다.
의미
r 값을 Dina가 돈을 받았다는 proof로 사용한다.
Dina가 Invoice에 payment hash를 포함해서 보낸다.
Hash는 일방향성을 가지고 있으니, payment hash로부터 payment secret을 알 수 없다.
정확히는 Alice와 Bob이 약속을 하고 (약간의 수수료와 함께)
Bob과 Chan이 약속을 하고 (약간의 수수료와 함께)
Chan과 Dina가 약속을 한다.
돈을 전달 받았는지 proof로 제공하는 증거가 r 값이다.
그리고 실제로 동작하는 방식은 거꾸로이다.
Dina가 Chan의 local balance로 돈을 받고 r 값을 제시 한다.
Chan이 Bob의 local balance로 돈을 받고 r 값을 제시 한다.
Bob이 Alice에게 돈을 받고 r 값을 제시 한다.
전달 과정 구체적인 예시
Alice가 Dina에게 50,000 sat를 보내고 싶다.
R값을 알고 있는 사람은 Dina만 존재한다.
1, 2, 3 이후에
Alice는 H를 포함한 HTLC를 만들어서 Bob에게 보낸다.
이것부터 순서대로 살펴본다.
4. Alice -> Bob
HTLC는 이렇게 생겼다 (locking script)
OP_SHA256 0575...f6b3 OP_EQUAL <목적지 생략>
unlocking script는 이렇게 생겨야 한다.
<R>
execute 할 unloking + locking은 다음과 같다.
<R> OP_SHA256 <H> OP_EQUAL
복습해보면 스택의 모습이
스택 | 스크립트 |
---|---|
R | R |
h(R) | SHA256 |
h(R) H | H |
TRUE | EQUAL |
-> 이 script를 쓰려면 올바른 R값을 알아야만 한다.
즉 Bob은 이 transaction을 사용할 수 없다.
Dina에게 보내고 싶은 금액은 50,000 sat.
수수료를 Bob과 Chan에게 100sat씩 주는 것으로 설정한 것이다.
Alice의 balance는 70,000 -> 19,800
Bob의 balance는 70,000 -> 120,200
여기서 Bob이 수수료 100sat을 챙기고 Chan에게 50,100 HTLC를 제시한다.
5. Bob -> Chan
Bob의 balance는 120,200 -> 70,100
Chan의 balance는 4,000.000 -> 4,050,100
이제 Chan이 100sat을 수수료로 챙기고 Dina에게 50,000 sat을 보낸다.
6. Chan -> Dina
Chan의 balance는 200,000 -> 150,000
Dina의 balance는 50,000 -> 100,000
7. Dina -> Chan -> Bob -> Alice
Dina에게 입금이 완료되고 r 값을 Chan에게 제시한다.
Chan이 Bob에게 r 값을 제시한다.
Bob이 Alice에게 r 값을 제시한다.
최종적으로 Alice가 받은 r 값은 영수증 역할을 한다.
- 만약 누군가 r 값을 넘기지 않고 redeem해서 쓴다면?
어차피 LN을 종료하고 redeem 한다는 것은 bitcoin network에 breoadcast 해야한다.
그러면 나머지 참여자들도 r 값을 알게 된다.
최종 모습은 이렇게 된다.
Signature Bindng
위에서 살펴본 HTLC script는 미완성이었다. (unlocking + locking)
<R> OP_SHA256 <H> OP_EQUAL <목적지 생략>
이걸 안성시켜보자.
Alice -> Bob 상황이었으니까 Bob의 public key가 목적지일 것이다.
그럼 locking
OP_SHA256 <H> OP_EQUALVERIFY <Bob's Pub> OP_CHECKSIG
unlocking
<Bob Sig> <R>
unlocking + locking
<Bob Sig> <R> OP_SHA256 <H> OP_EQUALVERIFY <Bob's Pub> OP_CHECKSIG
stack을 살펴보면 (append right, pop right 했다고 가정)
스택 | 스크립트 |
---|---|
BobSig | BobSig |
BobSig, R | R |
BobSig, h(R) | SHA256 |
BobSig, h(R), H | H |
BobSig | OP_EQUALVERIFY |
BobSig, BobPub | Bob’s Pub |
TRUE | OP_CHECKSIG |
HTLC timelock refund
r 값을 제시해서 transaction을 사용할 수 있도록 하는 방법과
time lock이 지나면 서명을 제시해서 transaction을 사용할 수 있도록 하는 방법을 추가한다.
-> 이건 누구의 서명일까? : Alice의 서명.
즉 Alice -> Bob 상황에서 Bob이 r 값을 제시하지 않으면(응답이 없거나 협조하지 않는다면) Alice가 refund 할 수 있다.
OP_DROP <cltv_expiry> OP_CHECKLOCKTIMEVERIFY OP_DROP OP_CHECKSIG
OP_DROP은 이전에 stack에 있는 내용을 다 지우는 것이다.
cltv_expiry는 설정된 time out 값이다.
만약 cltv_expirty = 100 이면 100 block 이후에 사용할 수 있다.
그리고 Bob이 100 block 내에 r 값을 제시하지 않으면 Alice가 refund 할 수 있다.
lock time은 block height로 설정한다. (절대 시간, 예를 들어 3일 후의 block height로 지정)
OP_CHECKLOCKTIMEVERIFY는 현재 transaction에도 lock time이 걸려 있어야 한다는 말이다.
그리고 transaction의 lock time이 cltv_expiry보다 커야 한다. (더 나중이여야 한다.)
더 먼저 걸려있다면 invalid 하게 된다.
정리하면 현재 transaction의 time lock이 cltv_expiry보다 크거나 같게 설정 되어 있어야 한다.
-
Alice->Bob
현재 + 500 block으로 설정했다.
그럼 Bob은 현재 + 450 block.
Chan은 현재 + 400 block. -
cltv_expirty는 decrement해야 한다 time lock은 Alice, Bob, Chan 순으로 decrement 해야 한다.
제공을 Chan Bob Alice 순이기 때문에
이렇게 하지 않으면 Bob은 pay 하고 Alice는 refund 할 수 있게 된다.
그러므로 회수도 Chan Bob Alice 순으로 해야 한다.
r 값이 탈취된 경우
Alice -> Dina 10,000 sat
Chan이 Bob에게 돈을 요구해 (Dina에게 받은 처럼) 돈을 전달한 척 한다.
- Chan -> Dina
Dina의 실수로 Chan이 r 값을 알게 되었다.
Chan이 실제로 Dina에게 돈을 전달하지 않는다. - Bob -> Chan
Chan이 Bob에게 돈을 요구한다.
Bob이 Chan에게 돈을 전달한다 (10,000 sat)
Bob에게 r 값을 제시한다. - Alice -> Bob
Bob이 Alice에게 돈을 요구한다.
Alice가 Bob에게 돈을 전달한다 (10,000 sat)
Alice에게 r 값을 제시한다.
-> 결과적으로 Chan은 r(payment secret) 값을 알아내서 10,000 sat 이득을 봤다.
Additional Metadata
3가지 추가 정보를 가질 수 있다.
-
additional metadata (text description)
text로 된 짧은 설명 -
additional metadata (routing hints)
경로상에 있는 node에 대한 정보.
unannounced channel을 사용할 수 있다. (추천해주는 느낌) -
exprity date
invoice가 만료되는 날짜
(invoice를 발행한)Dina 입장에서 각각의 비밀값 r을 가지고 있어야 한다.
만약 만료된 invoice가 있다면 r 값을 지워도 된다.
경로 찾기 (Path Finding)
경로를 찾을때 송금 금액이 channel의 capacity를 넘으면 당연히 안된다.
하지만 capacity를 넘지 않더라도 channel의 balance를 넘어서는 경우도 있다.
-> 결론은 경로를 찾는 문제가 쉽지 않다.. 로 마무리 지으셨다.
현재 Optimal한 경로를 찾는 방법은 없다.
Optimal한 경로란 최소 node를 거치며 최소 수수료를 지불하는 경로를 말한다.
즉 시행착오를 거치며 찾은 경로를 우선으로 시도해 본다.
추가적으로 privacy를 위해서 Onion Routing을 사용한다.
P2P Gossip Protocol
경로 찾기를 위해 channel 정보를 알기 위해 필요한 protocol.
그리고 이 경로를 Alice (sender)가 찾아야 한다.
이를 source based path finding이라고 한다.
channel 검증
각 Peer가 announce 하기 전에 channel이 존재하는 지 검증한다.
즉 Funding transaction이 bitcoin block chain onchain에 존재하는 지 확인한다.
이때 과도한 전파를 막기 위해 이미 알고 있는 channel 정보는 전파하지 않는다.
channel 정보 update
channel끼리 balance는 얼마든지 redistribute 될 수 있다. 그러면 다른 node가 가지고 있는 channel balance는 정확하지 않다.
이를 해결하기 위해 하루에 4번 정도 channel 정보를 업데이트 한다 (광고한다)
-> 실제 channel local balance가 몇대 몇인지 실질적으로 알 수 있는 방법은 없다. 그러므로 시행착오를 거치며 경로를 탐색할 수 밖에 없다.
Onion Routing
privacy를 위해 사용한다.
자세한 내용은 생략.