utxonursery: add additional comments to new sections
This commit is contained in:
parent
c9dbaa1403
commit
ccb12ab0a8
@ -61,7 +61,8 @@ const (
|
|||||||
// witness for a particular public key script. This function acts as an
|
// witness for a particular public key script. This function acts as an
|
||||||
// abstraction layer, hiding the details of the underlying script from the
|
// abstraction layer, hiding the details of the underlying script from the
|
||||||
// utxoNursery.
|
// utxoNursery.
|
||||||
type witnessGenerator func(tx *wire.MsgTx, hc *txscript.TxSigHashes, inputIndex int) ([][]byte, error)
|
type witnessGenerator func(tx *wire.MsgTx, hc *txscript.TxSigHashes,
|
||||||
|
inputIndex int) ([][]byte, error)
|
||||||
|
|
||||||
// generateFunc will return the witnessGenerator function that a kidOutput uses
|
// generateFunc will return the witnessGenerator function that a kidOutput uses
|
||||||
// to generate the witness for a sweep transaction. Currently there is only one
|
// to generate the witness for a sweep transaction. Currently there is only one
|
||||||
@ -71,7 +72,9 @@ func (wt witnessType) generateFunc(signer *lnwallet.Signer,
|
|||||||
|
|
||||||
switch wt {
|
switch wt {
|
||||||
case commitmentTimeLock:
|
case commitmentTimeLock:
|
||||||
return func(tx *wire.MsgTx, hc *txscript.TxSigHashes, inputIndex int) ([][]byte, error) {
|
return func(tx *wire.MsgTx, hc *txscript.TxSigHashes,
|
||||||
|
inputIndex int) ([][]byte, error) {
|
||||||
|
|
||||||
desc := descriptor
|
desc := descriptor
|
||||||
desc.SigHashes = hc
|
desc.SigHashes = hc
|
||||||
desc.InputIndex = inputIndex
|
desc.InputIndex = inputIndex
|
||||||
@ -344,8 +347,14 @@ out:
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := u.graduateKindergarten(uint32(epoch.Height)); err != nil {
|
// A new block has just been connected to the main
|
||||||
utxnLog.Errorf("error while graduating kindergarten outputs: %v", err)
|
// chain which means we might be able to graduate some
|
||||||
|
// outputs out of the kindergarten bucket. Graduation
|
||||||
|
// entails successfully sweeping a time-locked output.
|
||||||
|
height := uint32(epoch.Height)
|
||||||
|
if err := u.graduateKindergarten(height); err != nil {
|
||||||
|
utxnLog.Errorf("error while graduating "+
|
||||||
|
"kindergarten outputs: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
case <-u.quit:
|
case <-u.quit:
|
||||||
@ -430,11 +439,14 @@ func (k *kidOutput) waitForPromotion(db *channeldb.DB, confChan *chainntnfs.Conf
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
maturityHeight := k.confHeight +
|
maturityHeight := k.confHeight + k.blocksToMaturity
|
||||||
k.blocksToMaturity
|
|
||||||
heightBytes := make([]byte, 4)
|
heightBytes := make([]byte, 4)
|
||||||
byteOrder.PutUint32(heightBytes, uint32(maturityHeight))
|
byteOrder.PutUint32(heightBytes, uint32(maturityHeight))
|
||||||
|
|
||||||
|
// If there're any existing outputs for this particular block
|
||||||
|
// height target, then we'll append this new output to the
|
||||||
|
// serialized list of outputs.
|
||||||
var existingOutputs []byte
|
var existingOutputs []byte
|
||||||
if results := kgtnBucket.Get(heightBytes); results != nil {
|
if results := kgtnBucket.Get(heightBytes); results != nil {
|
||||||
existingOutputs = results
|
existingOutputs = results
|
||||||
@ -444,7 +456,6 @@ func (k *kidOutput) waitForPromotion(db *channeldb.DB, confChan *chainntnfs.Conf
|
|||||||
if err := serializeKidOutput(b, k); err != nil {
|
if err := serializeKidOutput(b, k); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := kgtnBucket.Put(heightBytes, b.Bytes()); err != nil {
|
if err := kgtnBucket.Put(heightBytes, b.Bytes()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -467,22 +478,31 @@ func (k *kidOutput) waitForPromotion(db *channeldb.DB, confChan *chainntnfs.Conf
|
|||||||
// startup in order to process graduations from blocks missed while the UTXO
|
// startup in order to process graduations from blocks missed while the UTXO
|
||||||
// nursery was offline.
|
// nursery was offline.
|
||||||
func (u *utxoNursery) graduateKindergarten(blockHeight uint32) error {
|
func (u *utxoNursery) graduateKindergarten(blockHeight uint32) error {
|
||||||
|
// First fetch the set of outputs that we can "graduate" at this
|
||||||
|
// particular block height. We can graduate an output once we've
|
||||||
|
// reached its height maturity.
|
||||||
kgtnOutputs, err := fetchGraduatingOutputs(u.db, u.wallet, blockHeight)
|
kgtnOutputs, err := fetchGraduatingOutputs(u.db, u.wallet, blockHeight)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we're able to graduate any outputs, then create a single
|
||||||
|
// transaction which sweeps them all into the wallet.
|
||||||
if len(kgtnOutputs) > 0 {
|
if len(kgtnOutputs) > 0 {
|
||||||
if err := sweepGraduatingOutputs(u.wallet, kgtnOutputs); err != nil {
|
if err := sweepGraduatingOutputs(u.wallet, kgtnOutputs); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Using a re-org safety margin of 6-blocks, delete any outputs which
|
||||||
|
// have graduated 6 blocks ago.
|
||||||
deleteHeight := blockHeight - 6
|
deleteHeight := blockHeight - 6
|
||||||
if err := deleteGraduatedOutputs(u.db, deleteHeight); err != nil {
|
if err := deleteGraduatedOutputs(u.db, deleteHeight); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finally, record the last height at which we graduated outputs so we
|
||||||
|
// can reconcile our state with that of the main-chain during restarts.
|
||||||
return putLastHeightGraduated(u.db, blockHeight)
|
return putLastHeightGraduated(u.db, blockHeight)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -495,7 +515,6 @@ func fetchGraduatingOutputs(db *channeldb.DB, wallet *lnwallet.LightningWallet,
|
|||||||
blockHeight uint32) ([]*kidOutput, error) {
|
blockHeight uint32) ([]*kidOutput, error) {
|
||||||
|
|
||||||
var results []byte
|
var results []byte
|
||||||
|
|
||||||
if err := db.View(func(tx *bolt.Tx) error {
|
if err := db.View(func(tx *bolt.Tx) error {
|
||||||
// A new block has just been connected, check to see if we have
|
// A new block has just been connected, check to see if we have
|
||||||
// any new outputs that can be swept into the wallet.
|
// any new outputs that can be swept into the wallet.
|
||||||
@ -508,21 +527,28 @@ func fetchGraduatingOutputs(db *channeldb.DB, wallet *lnwallet.LightningWallet,
|
|||||||
byteOrder.PutUint32(heightBytes, blockHeight)
|
byteOrder.PutUint32(heightBytes, blockHeight)
|
||||||
|
|
||||||
results = kgtnBucket.Get(heightBytes)
|
results = kgtnBucket.Get(heightBytes)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If no time-locked outputs can be sweeped at this point, ten we can
|
||||||
|
// exit early.
|
||||||
if len(results) == 0 {
|
if len(results) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Otherwise, we deserialize the list of kid outputs into their full
|
||||||
|
// forms.
|
||||||
kgtnOutputs, err := deserializeKidList(bytes.NewReader(results))
|
kgtnOutputs, err := deserializeKidList(bytes.NewReader(results))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utxnLog.Errorf("error while deserializing list of kidOutputs: %v", err)
|
utxnLog.Errorf("error while deserializing list of kidOutputs: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For each of the outputs, we also generate its proper witness
|
||||||
|
// function based on its witness type. This varies if the output is on
|
||||||
|
// our commitment transaction or theirs, and also if it's an HTLC
|
||||||
|
// output or not.
|
||||||
for _, kgtnOutput := range kgtnOutputs {
|
for _, kgtnOutput := range kgtnOutputs {
|
||||||
kgtnOutput.witnessFunc = kgtnOutput.witnessType.generateFunc(
|
kgtnOutput.witnessFunc = kgtnOutput.witnessType.generateFunc(
|
||||||
&wallet.Signer, kgtnOutput.signDescriptor,
|
&wallet.Signer, kgtnOutput.signDescriptor,
|
||||||
@ -562,6 +588,7 @@ func sweepGraduatingOutputs(wallet *lnwallet.LightningWallet, kgtnOutputs []*kid
|
|||||||
if err := wallet.PublishTransaction(sweepTx); err != nil {
|
if err := wallet.PublishTransaction(sweepTx); err != nil {
|
||||||
utxnLog.Errorf("unable to broadcast sweep tx: %v, %v",
|
utxnLog.Errorf("unable to broadcast sweep tx: %v, %v",
|
||||||
err, spew.Sdump(sweepTx))
|
err, spew.Sdump(sweepTx))
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -570,7 +597,9 @@ func sweepGraduatingOutputs(wallet *lnwallet.LightningWallet, kgtnOutputs []*kid
|
|||||||
// createSweepTx creates a final sweeping transaction with all witnesses in
|
// createSweepTx creates a final sweeping transaction with all witnesses in
|
||||||
// place for all inputs. The created transaction has a single output sending
|
// place for all inputs. The created transaction has a single output sending
|
||||||
// all the funds back to the source wallet.
|
// all the funds back to the source wallet.
|
||||||
func createSweepTx(wallet *lnwallet.LightningWallet, matureOutputs []*kidOutput) (*wire.MsgTx, error) {
|
func createSweepTx(wallet *lnwallet.LightningWallet,
|
||||||
|
matureOutputs []*kidOutput) (*wire.MsgTx, error) {
|
||||||
|
|
||||||
pkScript, err := newSweepPkScript(wallet)
|
pkScript, err := newSweepPkScript(wallet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -608,6 +637,7 @@ func createSweepTx(wallet *lnwallet.LightningWallet, matureOutputs []*kidOutput)
|
|||||||
|
|
||||||
txIn.Witness = witness
|
txIn.Witness = witness
|
||||||
}
|
}
|
||||||
|
|
||||||
return sweepTx, nil
|
return sweepTx, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user