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

[RPC] Add bumpfee command. #7865

Closed

Conversation

jonasschnelli
Copy link
Contributor

Refactor

CreateTransaction() now accepts a input-value over the nFee parameter (currently only used to return the calculated fee). This "base fee" will be the delta to the calculated fee. This allows to create transaction replacements with respecting the previous fee of the replaced transaction.

bumpfee RPC command

Syntax: bumpfee <txid>

Bumpfee will directly sign&send the new transaction and reports the old/new fee and the new <txid>.

How it works: the Bumpfee command removes all previous signatures, removes change outputs and re-funds the transaction (if necessary).

Currently, bumpfee will increase the fees by using the <old transaction fee> + <new transaction fee estimate>.
Increasing the fees can involve adding n inputs (which can again increase the require minimum fee).

sendtoaddress / sandmany

Added another parameter to sendtoaddress and sendmany. The boolean parameter defines if the transaction will signal opt-in-RBF over the nSequence number after BIP125.

Bitcoin-Tx / CreateRawTransaction

  • Extended bitcoin-tx to accept a sequence number when adding inputs
  • Extended createrawtransaction to accept a sequence number when defining inputs

Possible next steps

  • Add a bumprawtransaction command
  • Refactor transaction signing
  • Optimize the fee-estimation for replacements

@@ -533,6 +533,11 @@ class CAccountingEntry
std::vector<char> _ssExtra;
};

enum CreateTransactionFlags {
CREATE_TX_DEFAULT = 0,
Copy link
Member

Choose a reason for hiding this comment

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

It seems to me default is simply "not bip125". Not sure the name "default" really fits, especially longer-term.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think the CREATE_TX_DEFAULT is okay. Passing just a 0(int) would require casting. "not bip125" is also not true because in future you could combine flags (Don't SIGN & RBF)?

@jonasschnelli
Copy link
Contributor Author

Force push fixed @instagibbs nits.

@instagibbs
Copy link
Member

utACK post-nits

Although it might make sense to split this into ~3 PRs to get through a couple faster, and each of which would still be useful on their own:

  1. bitcoin-tx stuff
  2. createrawtransaction stuff
  3. rest of stuff

CReserveKey reservekey(pwalletMain);
if(!pwalletMain->FundTransaction(tx, reservekey, nFee, nChangePos, strFailReason, false))
throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);

Copy link
Contributor

Choose a reason for hiding this comment

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

Why not ensuring (nFee - nOldFee) > minTxRelayFee, and if not, exit early with a descriptive JSONRpcError which say the fees are high enough and can't be bumped ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. I have though about that. But you also would like to have a check that makes sure, it would be accepted as replacement.
This would require to factor out the RBF check from main.cpp to rbf.cpp (which probably would sense in a follow up PR).

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, but CommitTransaction later is already doing that under the hood if I understand.
The most likely problem is that the fees can't be bumped, for the 0.0001% chance that it still get rejected for whatever other issue during the CommitTransaction, a generic error message would be enough.

@paveljanik
Copy link
Contributor

@jonasschnelli Can you please separate "Bitcoin-Tx / CreateRawTransaction" changes into new PR, so this can get merged?

@NicolasDorier
Copy link
Contributor

NicolasDorier commented Apr 26, 2016

@jonasschnelli maybe unrelated to this PR, or I should bring that up in a meeting (sadly it is 4am in japan when there is core meeting), but I think a better (or alternative) bumpfee would be one which take the number of block to confirm. As a developer using the RPC API, I'd like my backend to bump fees periodically to reach confirmation target in case of fee increase. So that bumpfee 3 would mean "put whatever fee at current rate that can confirm into 3 blocks". If the calculated fee are smaller than current one, then it would do be a no op.

It might not belong to this PR though.

It would also be used if I initially said "confirm into 20 blocks", then changed my mind and say "now I want to confirm in the next block".

@jonasschnelli
Copy link
Contributor Author

@NicolasDorier: I agree that a confirm target for the bumpfee command would make sense.
The variable confirm target for CreateTransaction would require some refactoring.

This PR is already relatively large, we should probably add this feature in another PR.

@NicolasDorier
Copy link
Contributor

right, utACK

@jonasschnelli
Copy link
Contributor Author

Rebased (non trivial after #7518).

@jonasschnelli jonasschnelli force-pushed the 2016/04/rbf_combined branch 2 times, most recently from 7dc957d to 395571b Compare April 28, 2016 08:41
@jonasschnelli
Copy link
Contributor Author

Removed createrawtransaction and bitcoin-tx commits because they are now in #7957.

@jonasschnelli
Copy link
Contributor Author

Needed rebase.

@@ -0,0 +1,85 @@
#!/usr/bin/env python2
Copy link
Member

Choose a reason for hiding this comment

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

Mind to change this to py3?

replacedTx= self.nodes[1].getrawtransaction(rbftx)
assert(False)
except JSONRPCException as e:
assert_equal(len(replacedTx), 0)
Copy link
Member

Choose a reason for hiding this comment

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

Is this doing anything different that assert_raises(JSONRPCException, ...?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Right. Fixed.

@jonasschnelli
Copy link
Contributor Author

Rebased. Fixed nit reported by @MarcoFalke.

@@ -745,8 +749,13 @@ class CWallet : public CCryptoKeyStore, public CValidationInterface
* selected by SelectCoins(); Also create the change output, when needed
* @note passing nChangePosInOut as -1 will result in setting a random position
*/
<<<<<<< 08b37c5e06bf1698c1d0e5905806382cbfa8cefd
Copy link
Member

Choose a reason for hiding this comment

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

Unresolved conflict

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh. Messed up the rebase. Will fix.
Wait: you commented and old commit.

Copy link
Member

Choose a reason for hiding this comment

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

@jonasschnelli This commit is still in the history.

You didn't solve the conflict in this commit but in a later one. Looks weird if someone digs through it.

Copy link
Member

@sipa sipa Jun 20, 2016 via email

Choose a reason for hiding this comment

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

@jonasschnelli
Copy link
Contributor Author

Rebased and improved.
Made usage of the new feeRate option in fundrawtransaction.

Now the bumpfee command takes an existing wtx (identified by txid), increases the fee by using at the estimating mempool feeRate for the default confirmation target. If the new estimate feeRate is < old feeRate , it will use oldFeeRate+minRelayTxFee instead.

nonrbftx = self.nodes[0].sendtoaddress(self.nodes[2].getnewaddress(), 1, "", "", True, False)

try:
bumpedrawtx = self.nodes[0].bumpfee(nonrbftx)
Copy link
Member

Choose a reason for hiding this comment

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

Replace by

assert_raises(JSONRPCException, self.nodes[0].bumpfee, nonrbftx)

@maflcko
Copy link
Member

maflcko commented Jun 9, 2016

Mind to squash the history to aid review?

@rubensayshi
Copy link
Contributor

rubensayshi commented Jun 14, 2016

hmm, "Currently, bumpfee will increase the fees by using the <old transaction fee> + <new transaction fee estimate>."

not sure if I'm missing something but when newFeeRate.GetFeePerK() >= oldFeeRate.GetFeePerK()+::minRelayTxFee.GetFeePerK() it just uses newFeeRate no?

I think I read the code right and you just need to update your initial description of the PR, in which case; utACK
if I'm wrong then it doesn't make sense to me to bump the fee past the , asuming nTxConfirmTarget is set to my desired target and we trust the fee estimation, why would I want to bump the fee higher than what the estimate is?

as said before by others, I think estimateFoundTarget should just be a param (default to 1),
it would make more sense that my configured nTxConfirmTarget when doing the initial TX wasn't 1 and instead I know want to bump it to 1, so you'd specify estimateFoundTarget (default to 1).
though even without that this PR is already very useful!

also nits; remove //CFeeRate newFeeRate = CFeeRate(oldFeeRate.GetFeePerK()*2); and // double fee rate ;-)

it = tx.vout.erase(it);
}
else {
++it;
Copy link
Member

Choose a reason for hiding this comment

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

I think this increment needs to happen always, even if the condition above is true.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

doesn't tx.vout.erase(it); result in pointing to the next element in the iteration?

Copy link
Member

Choose a reason for hiding this comment

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

erase returns the new position of the next element after the one that is erased, so it = tx.vout.erase(it) does the right thing

@gmaxwell
Copy link
Contributor

Concept ACK (for future reference, I think this would have potentially been better as two PRs, with the bumpfee separate-- built on top of the first), will review.

@fanquake
Copy link
Member

Is this still going into 0.13.0 ?

@laanwj laanwj removed this from the 0.13.0 milestone Jun 22, 2016
@laanwj
Copy link
Member

laanwj commented Jun 22, 2016

@fanquake No, not as-is. Unfortunately this missed the feature freeze. At last Thursday's meeting @jonasschnelli mentioned working on much simplified minimum RPC functionality for 0.13 to serve as a stop-gap.

@jonasschnelli
Copy link
Contributor Author

superseded by #8456. Closing.

@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

10 participants