Основная концепция Lightning Network проста. Для дальнейшего понимания представьте потоки транзакций сети Lightning как код javascript, ссылаясь на белую книгу.

Если я объясню все потоки транзакций в одном сообщении в блоге, его будет трудно читать. Итак, я делю на несколько сообщений в блоге. Целью этого сообщения в блоге является использование отменяемой доставки выполнения HTLC, что соответствует рисунку 12 официального документа.

Код на Github: lightning-network-tx-flow

Pre Post: Упрощенный код Bitcoin Lightning Network, часть 2 - Средство защиты от утечек

Следующее сообщение: Упрощенный код сети Bitcoin Lightning, часть 4 - Устранение нарушения HTLC

14 шагов, чтобы провести отзывную доставку выполнения HTLC

Я пропускаю шаги до 4 из-за повторяющегося объяснения. Так что, пожалуйста, обратитесь к предыдущему сообщению в блоге, если хотите узнать.

  1. Финансирование с несколькими подписями
  2. Сборка C1a и C1b (без знака)
  3. Сборка RD1a и RD1b
  4. Обмен подписью C1a и C1b
  5. Сборка C2a и C2b (без признаков)
  6. Сборка RD2a и RD2b
  7. Сборка HTD1b
  8. Сборка HE1b
  9. Сборка HERD1b
  10. Обмен подписью C2a и C2b
  11. Сборка BR1a и BR1b
  12. Потратьте C2b
  13. Израсходовать HE1b
  14. Потратьте HERD1b

5. Постройте C2a и C2b (без признаков)

Сначала Алиса создает прообраз R, а также соответствующий хэш H. Алиса хочет заплатить 0,1 BTC Бобу только тогда, когда Боб знает прообраз R. Для Боба он должен ответить R, чтобы получить 0,1 BTC, когда Алиса предоставила H. В это время Алиса использует закрытый ключ как R и открытый ключ как H.

// Use private key as preimage R
const preimageR = generatePrivateKey();
// Preimage H is public key
const preimageH = getPubKey(preimageR);
let C2a = new Transaction(
  [
    new TxIn( // This is same as C1a
      fTxAH, 
      0, 
      { 
        type: 'MULTI',
        sig: [ 
          redeemScript.pubKeyHashs[0], 
          redeemScript.pubKeyHashs[1] 
        ],
        redeemScript
      }
    ),
    new TxIn( // This is same as C1a
      fTxBH, 
      0, 
      { 
        type: 'MULTI',
        sig: [ 
          redeemScript.pubKeyHashs[0], 
          redeemScript.pubKeyHashs[1] 
        ],
        redeemScript
      }
    )
  ],
  [
    new TxOut(
      40000000, 
      { 
        type: 'RSMS',
        pubKeyHash: [ 
          getPubKeyHash(AliceKeys[4]), 
          getPubKeyHash(BobKeys[4]) 
        ]
      }
    ),
    new TxOut(
      50000000, 
      { 
        type: 'NORMAL',
        pubKeyHash: getPubKeyHash(BobKeys[4])
      }
    ),
    new TxOut(
      10000000, 
      { 
        type: 'HTLC',
        pubKeyHash: [
          getPubKeyHash(AliceKeys[4]),
          getPubKeyHash(BobKeys[4])
        ],
        preimageH // Alice provide H, Bob need to know R
      }
    )
  ]
)

Формат Json scriptPubKey выглядит следующим образом.

scriptPubKey = { 
  type: 'HTLC',
  pubKeyHash: [
    pubKeyHash1,
    pubKeyHash2
  ],
  preimageH: preimageH
}

Таким же образом Боб строит C2b.

6. Соберите RD2a и RD2b.

Пропустите повторяющееся объяснение. См. Предыдущий пост в разделе Сборка RD1a и RD1b.

7. Соберите HTD1b.

Только Алиса может транслировать эту транзакцию, чтобы вернуть 0,1 BTC после 3-х подтверждений временной блокировки, если Боб не может ответить R. Для Боба лучше ответить R до истечения этого времени блокировки.

let HTD1b = new Transaction(
  [
    new TxIn(
      '', 
      2, 
      { 
        type: 'HTLCT',
        sig: [ 
          getPubKeyHash(AliceKeys[4]), 
          getPubKeyHash(BobKeys[4])
        ],
        sequence: 3
      }
    )
  ],
  [
    new TxOut(
      10000000, 
      { 
        type: 'NORMAL',
        pubKeyHash: getPubKeyHash(AliceKeys[5])
      }
    )
  ]
)
// Alice hand over HTD1b to Bob and let him sign
HTD1b = signTx(HTD1b, BobKeys[4]);

Формат Json scriptSig выглядит следующим образом.

scriptSig = { 
  type: 'HTLCT',
  sig: [ 
    {
     signature: signature, 
     pubKey: pubKey1 
    },
    {
     signature: signature, 
     pubKey: pubKey2
    }
  ],
  sequence: 3
}

Обратите внимание, что HT1a немного отличается от HTD1b, поэтому обратитесь к Gitbub.

8. Соберите HE1b

Боб может транслировать эту транзакцию в любое время, если он знает R. К сожалению, он не получает 0,1 BTC от этой транзакции.

let HE1b = new Transaction(
  [
    new TxIn(
      '', 
      2, 
      { 
        type: 'HTLCE',
        sig: [ 
          getPubKeyHash(AliceKeys[4]), 
          getPubKeyHash(BobKeys[4])
        ],
        preimageR // Bob answer required R
      }
    )
  ],
  [
    new TxOut(
      10000000, 
      { 
        type: 'RSMS',
        pubKeyHash: [ 
          getPubKeyHash(AliceKeys[5]), 
          getPubKeyHash(BobKeys[5]) 
        ]
      }
    )
  ]
)
// Bob hand over HE1b to Alice and let her sign
HE1b = signTx(HE1b, AliceKeys[4]);

Формат Json scriptSig выглядит следующим образом.

scriptSig = { 
  type: 'HTLCE',
  sig: [ 
    {
      signature: signature, 
      pubKey: pubKey1 
    },
    {
      signature: signature, 
      pubKey: pubKey2
    }
  ],
  preimageR: preimageR  
}

Обратите внимание, что HED1a немного отличается от HE1b, поэтому обратитесь к Gitbub.

9. Соберите HERD1b.

Боб может транслировать эту транзакцию только после 10 подтверждений блокировки по времени. Наконец, Боб получает от этой транзакции 0,1 BTC.

let HERD1b = new Transaction(
  [
    new TxIn(
      '', 
      0, 
      { 
        type: 'RD',
        sig: [ 
          getPubKeyHash(AliceKeys[5]), 
          getPubKeyHash(BobKeys[5])
        ],
        sequence: 10 // 10 block confirmation time lock
      }
    )
  ],
  [
    new TxOut(
      10000000, 
      { 
        type: 'NORMAL',
        pubKeyHash: getPubKeyHash(BobKeys[6])
      }
    )
  ]
)
// Bob hand over HERD1b to Alice and let her sign
HERD1b = signTx(HERD1b, AliceKeys[5]);

Обратите внимание, что HTRD1a немного отличается от HERD1b, поэтому обратитесь к Gitbub.

10. Обмен подписью C2a и C2b

Алиса позволила Бобу подписать C2a. Теперь Алиса может транслировать эту транзакцию в любое время.

// Alice hand over C2a to Bob, and let him sign
C2a = signTx(C2a, BobKeys[1]);

Таким же образом Боб позволил Алисе подписать C2b.

11. Соберите BR1a и BR1b.

Пропустите повторяющееся объяснение. См. Предыдущий пост в разделе Сборка BR1a и BR1b.

12. Потратьте C2b.

Боб проводит C2b. Даже если он знает R, он не может сразу получить 0,1 BTC Алисы из-за временной блокировки HERD1b.

Но, если Алиса потратит C2a, Боб может получить его немедленно, если он знает R.

// Sign by himself(Bob)
C2b = signTx(C2b, BobKeys[1]);
// Validate transaction
validateTx(C2b, Blocks);
// Mine block as adding transactions
Blocks = mineBlock(Blocks, createNewBlock([C2b], Blocks));

13. Проведите HTD1b.

Боб потратит эту транзакцию, чтобы ответить R.

// Set C2b transaction hash
HE1b.txIns[0].txPrev = calculateTxHash(C2b);
HE1b = signTx(HE1b, BobKeys[4]);
validateTx(HE1b, Blocks);
Blocks.push( createNewBlock([HE1b], Blocks) );

14. Потратьте HERD1b

Боб потратит эту транзакцию, чтобы получить 0,1 BTC после 10 временной блокировки.

// Set HE1b transaction hash
HERD1b.txIns[0].txPrev = calculateTxHash(HE1b);
HERD1b = signTx(HERD1b, BobKeys[5]);
// Wait 10 confirmations for time lock
Blocks = mineBlock(Blocks, createNewBlock([], Blocks));
Blocks = mineBlock(Blocks, createNewBlock([], Blocks));
Blocks = mineBlock(Blocks, createNewBlock([], Blocks));
Blocks = mineBlock(Blocks, createNewBlock([], Blocks));
Blocks = mineBlock(Blocks, createNewBlock([], Blocks));
Blocks = mineBlock(Blocks, createNewBlock([], Blocks));
Blocks = mineBlock(Blocks, createNewBlock([], Blocks));
Blocks = mineBlock(Blocks, createNewBlock([], Blocks));
Blocks = mineBlock(Blocks, createNewBlock([], Blocks));
Blocks = mineBlock(Blocks, createNewBlock([], Blocks));
validateTx(HERD1b, Blocks);
Blocks.push( createNewBlock([HERD1b], Blocks) );