Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(submitter): remove dumpPrivKey #15

Merged
merged 14 commits into from
Aug 20, 2024
Merged

Conversation

Lazar955
Copy link
Member

@Lazar955 Lazar955 commented Aug 15, 2024

This pull request removes the usage of the dumpPrivKey RPC method from the submitter and end-to-end (E2E) tests. The dumpPrivKey method is specific to legacy wallets and is no longer supported in the latest versions of bitcoind. Eliminating its usage is a necessary step for upgrading to newer versions of bitcoind, as its deprecation would otherwise hinder the upgrade process.

Updates the version of bitcoind to v27.0

References issue.

submitter/relayer/utils.go Outdated Show resolved Hide resolved
// on app level. Descriptor wallets do not allow dumping private keys.
buff, _, err := h.m.ExecBitcoindCliCmd(h.t, []string{"createwallet", walletName, "false", "false", passphrase, "false", "false"})
// last arg is true which indicates we are using descriptor wallets they do not allow dumping private keys.
buff, _, err := h.m.ExecBitcoindCliCmd(h.t, []string{"createwallet", walletName, "false", "false", passphrase, "false", "true"})
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Legacy wallets were "false", true for descriptor wallets

e2etest/test_manager.go Outdated Show resolved Hide resolved
@Lazar955 Lazar955 marked this pull request as ready for review August 16, 2024 09:55
submitter/relayer/relayer.go Outdated Show resolved Hide resolved
submitter/relayer/relayer.go Show resolved Hide resolved
e2etest/test_manager.go Outdated Show resolved Hide resolved
submitter/relayer/relayer.go Outdated Show resolved Hide resolved
@@ -386,44 +386,54 @@ func (rl *Relayer) buildTxWithData(
rl.logger.Debugf("Building a BTC tx using %v with data %x", utxo.TxID.String(), data)
tx := wire.NewMsgTx(wire.TxVersion)

outPoint := wire.NewOutPoint(utxo.TxID, utxo.Vout)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the utxo *types.UTXO argument to the function is probably not needed now as all intput to the transaction as selected by rl.BTCWallet.FundRawTransaction function.

Given that we probably need two versions of this function:

  1. first version for the first transaction, in which we allow wallet to chose inputs automatically
  2. second version for the second transaction, in which we are able to specifiy input manually to use the transaction chaining

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how FundRawTransaction would simplify things as we cannot control the inputs used by FundRawTransaction. As such, for (1), how do we know the value of the output is sufficient to fund the second tx for chaining?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand our chaining mechanism correctly, want we want to do is:

  1. send first transaction with pretty low fee rate, lets call it Tx1
  2. then send the second transaction (Tx2)with higher fee rate and with input that is Tx1 change output (this is necessary to achieve the chaining)

Imo FundRawTransaction can help here a lot and simplify stuff as:

  1. For the Tx1 we can just create unsigned and unfunded transaction with one output, and send it to FundRawTransaction, it will automatically choses inputs and add one change output which will have correct value to obey specified fee rate.
  2. Then we can create Tx2 with one input (change output from Tx1 ) and one output and send it to FundRawTransaction. Now based on specified fee rate, endpoint will attach or not other inputs and will attach one change output to Tx2 . This way chaining will be preserved, and second tx will obey specified fee rate

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I didn't realize in (2) we can inject one input from the change output of tx1. If the case, then it indeed improves a lot. Sounds good to me!

e2etest/test_manager.go Outdated Show resolved Hide resolved
Copy link
Contributor

@RafilxTenfen RafilxTenfen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR looks good, but what about dumpPrivKeyAndSignTx at the processCheckpoints case

My bad, tested the wrong branch locally

@@ -10,7 +10,7 @@ type ImageConfig struct {
//nolint:deadcode
const (
dockerBitcoindRepository = "lncm/bitcoind"
dockerBitcoindVersionTag = "v24.0.1"
dockerBitcoindVersionTag = "v26.1"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

Copy link
Contributor

@RafilxTenfen RafilxTenfen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code changes looks good to me ^^

Copy link
Member

@gitferry gitferry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Signing part lgtm! As per off-line discussion, my major concern is whether FundRawTransaction can handle the chaining without introducing much complexity. Maybe this part can be improved in a separate pr to not block here

// add unlocking script into the input of the tx
tx, err = completeTxIn(tx, segwit, wif.PrivKey, utxo)

signedTx, _, err := rl.BTCWallet.SignRawTransactionWithWallet(tx)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to check the second output is true?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep we should check this flag and retrun error if it is false.

This flags indicate whether all inputs were signed, from caller perspective it means that if it is false transaction cannot be sent to the BTC.

@@ -386,44 +386,54 @@ func (rl *Relayer) buildTxWithData(
rl.logger.Debugf("Building a BTC tx using %v with data %x", utxo.TxID.String(), data)
tx := wire.NewMsgTx(wire.TxVersion)

outPoint := wire.NewOutPoint(utxo.TxID, utxo.Vout)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how FundRawTransaction would simplify things as we cannot control the inputs used by FundRawTransaction. As such, for (1), how do we know the value of the output is sufficient to fund the second tx for chaining?

Copy link
Collaborator

@KonradStaniec KonradStaniec left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We minor nits. Before merging lets wait for @gitferry approval as he is most familiar with this logic.

rl.logger.Debugf("Got a change address %v", changeAddr.String())
changeScript, err := txscript.PayToAddrScript(changeAddr)
feeRate := btcutil.Amount(rl.getFeeRate()).ToBTC()
changePosition := 1
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would make this a constant and the top of the file and use it to refer to change outputs wherever necessary, because now we have a lot magic numbers in the file e.g Transaction.TxOut[1]

// add unlocking script into the input of the tx
tx, err = completeTxIn(tx, segwit, wif.PrivKey, utxo)

signedTx, _, err := rl.BTCWallet.SignRawTransactionWithWallet(tx)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep we should check this flag and retrun error if it is false.

This flags indicate whether all inputs were signed, from caller perspective it means that if it is false transaction cannot be sent to the BTC.

}
change := utxo.Amount - txFee
tx.AddTxOut(wire.NewTxOut(int64(change), changeScript))
change := changeAmount - txFee
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imo this is not needed and you can use changeAmount instead

return 0, err
}

btcTx, err := btcutil.NewTxFromBytes(txBytes.Bytes())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here instead of first serializing transaction, you can use btcutil.NewTx(tx) constructor, and remove serialization step

}

// resendSecondTxOfCheckpointToBTC resends the second tx of the checkpoint with bumpedFee
func (rl *Relayer) resendSecondTxOfCheckpointToBTC(tx2 *types.BtcTxInfo, bumpedFee btcutil.Amount) (*types.BtcTxInfo, error) {
// set output value of the second tx to be the balance minus the bumped fee
// if the bumped fee is higher than the balance, then set the bumped fee to
// be equal to the balance to ensure the output value is not negative
balance := tx2.Utxo.Amount
balance := btcutil.Amount(tx2.Tx.TxOut[1].Value)

if bumpedFee > balance {
rl.logger.Debugf("the bumped fee %v Satoshis for the second tx is more than UTXO amount %v Satoshis",
bumpedFee, balance)
bumpedFee = balance
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a bit debatable, as if we set bumpedFee = balance and later have tx2.Tx.TxOut[1].Value = int64(balance - bumpedFee) this means we will end up with output with value 0 that will be rejected by bitcoind as dust output.
This probably not for this pr, but some todo here for future fix would be good.

@Lazar955 Lazar955 requested a review from gitferry August 20, 2024 09:02
Copy link
Member

@gitferry gitferry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the delay. Some quick comments:

Comment on lines 283 to 284
// ChainTwoTxAndSend consumes one utxo and build two chaining txs:
// the second tx consumes the output of the first tx
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// ChainTwoTxAndSend consumes one utxo and build two chaining txs:
// the second tx consumes the output of the first tx
// ChainTwoTxAndSend builds two chaining txs with the given data
// the second tx consumes the output of the first tx

bumpedFee := newTx1Fee + newTx2Fee - ckptInfo.Tx1.Fee

return bumpedFee.MulF64(float64(rl.config.ResubmitFeeMultiplier))
return ckptInfo.Tx2.Fee.MulF64(rl.config.ResubmitFeeMultiplier)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why we don't want to estimate the fee here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've changed how we estimate fee, by using the fee value from the response of FundRawTransaction. This produces a different value (a bit higher fee) than we used to, which means when we estimate the fee here it wouldn't be the same way as we did, and in local tests resulting in a lower calculated bumpedFee needing a higher ResubmitFeeMultiplier. So I see it either as estimating fee ourselves or using the response from FundRawTransaction. Open to any other inputs, I might be missing something

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes sense. Thanks for the explanation!

Comment on lines 167 to 169
// set output value of the second tx to be the balance minus the bumped fee
// if the bumped fee is higher than the balance, then set the bumped fee to
// be equal to the balance to ensure the output value is not negative
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems outdated

balance := tx2.Utxo.Amount
balance := btcutil.Amount(tx2.Tx.TxOut[changePosition].Value)

// todo: revise this as this means we will end up with output with value 0 that will be rejected by bitcoind as dust output.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we make it an issue for reminder?

Comment on lines 324 to 327
// buildTxWithData builds a tx with data inserted as OP_RETURN
// note that OP_RETURN is set as the first output of the tx (index 0)
// and the rest of the balance is sent to a new change address
// as the second output with index 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doc string needs update

tx.AddTxIn(txIn)
if firstTx != nil {
txID := firstTx.TxHash()
outPoint := wire.NewOutPoint(&txID, 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we make 1 a self-explained constant?

return nil, err
}

change := changeAmount - txFee
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we also check the change is higher than dust?

return nil, err
}

change := changeAmount - txFee

rl.logger.Debugf("Successfully composed a BTC tx with balance of input: %v, "+
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably need to remove the balance of input as we don't specify it anymore. And we need to make it a single line as otherwise the values are not well translated

Copy link
Member

@gitferry gitferry left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! LGTM other than comments above

@Lazar955 Lazar955 merged commit e9a1e24 into dev Aug 20, 2024
8 checks passed
@Lazar955 Lazar955 deleted the lazar/remove-dump-privkey branch August 20, 2024 14:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants