-
Notifications
You must be signed in to change notification settings - Fork 38.7k
rpc: combinerawtransaction now rejects unmergeable transactions #31298
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
base: master
Are you sure you want to change the base?
rpc: combinerawtransaction now rejects unmergeable transactions #31298
Conversation
|
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. Code Coverage & BenchmarksFor details see: https://corecheck.dev/bitcoin/bitcoin/pulls/31298. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please copy-paste ConflictsNo conflicts as of last run. |
c0d23a0 to
8515fc6
Compare
|
🚧 At least one of the CI tasks failed. HintsTry to run the tests locally, according to the documentation. However, a CI failure may still
Leave a comment here, if you need help tracking down a confusing failure. |
9b24f38 to
192a50b
Compare
192a50b to
f19a815
Compare
|
It seems like, with #31249, I should migrate these test changes as well. WIP |
This comment was marked as abuse.
This comment was marked as abuse.
This is the same functional approach and error message already. |
f19a815 to
85c2168
Compare
This comment was marked as abuse.
This comment was marked as abuse.
1440000bytes
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK 85c2168
yuvicc
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested ACK 85c216871a01aab003e1b1aba6246b4178afc929
Below is my full test setup:
Tested on Regtest mode
master@d2136d32bb4764e4035fb892d979c27f037fad93
- When checked with only 1 raw txn, returns only the txn (no error for missing txns)
- When checked for mergeability:
- returns only the first txn when unrelated txns were provided
- doesn't show descriptive error for any mergeability issue
combinerawtransaction-check@85c216871a01aab003e1b1aba6246b4178afc929
- When only 1 raw txn provided it returns missing inputs
- checking for mergeability:
- shows descriptive error for mergeability issue
for e.g.
- shows descriptive error for mergeability issue
error code: -8
error message:
Transaction 1 not compatible (different transactions)
Gives combine hex when same txns are provided
./build/src/bitcoin-cli combinerawtransaction '["0200000001a0d2e799d40d404da2daf128fc678fdd15f245bdd92c6e1ad15b45f7258a47b90000000000fdffffff01008c86470000000016001483f259c98962117d75154f35cb55cd60b88a257e00000000","0200000001a0d2e799d40d404da2daf128fc678fdd15f245bdd92c6e1ad15b45f7258a47b90000000000fdffffff01008c86470000000016001483f259c98962117d75154f35cb55cd60b88a257e00000000"]'
0200000001a0d2e799d40d404da2daf128fc678fdd15f245bdd92c6e1ad15b45f7258a47b90000000000fdffffff01008c86470000000016001483f259c98962117d75154f35cb55cd60b88a257e00000000
for inputs already spent:
error code: -25
error message:
Input not found or already spent
Note: newly created wallet and txns were used during the test using createrawtransaction rpc in regtest mode
Also, the functional test LGTM:
Temporary test directory at /var/folders/jb/wlbrz0t95vl58wzxjt75wqmh0000gn/T/test_runner_₿_🏃_20241219_004940
Remaining jobs: [rpc_createmultisig.py]
1/1 - rpc_createmultisig.py passed, Duration: 3 s
TEST | STATUS | DURATION
rpc_createmultisig.py | ✓ Passed | 3 s
ALL | ✓ Passed | 3 s (accumulated)
Runtime: 3 s
85c2168 to
85d798d
Compare
|
Concept ACK |
85d798d to
9d31e94
Compare
naiyoma
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested ACK 9d31e94
I have tested the changes on regtest and got expected output
bitcoin-cli -regtest combinerawtransaction "[\"$RAW_TX1\", \"$RAW_TX2\"]"
error code: -8
error message:
Transaction 1 not compatible (different transactions)
yuvicc
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
re-ACK 9d31e94bf584e12269683b74b1c96c7ac883a760
|
Are you still working on this? |
4e31bbe to
a26e9fd
Compare
|
@achow101 I've rebased this and updated the comment. No other changes. |
theStack
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK
rkrux
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK a26e9fd5b5908853d37b81915f5e12a5ad822f86
Thanks for adding the fix.
|
Tested ACK a26e9fd5b5908853d37b81915f5e12a5ad822f86 Built on macOS, ran
Agree with the minor nits from other reviewers (style changes, error message verbosity). |
Yes, I will produce an additional patch addressing all comments in the coming days. |
a26e9fd to
a516fe8
Compare
|
I've addressed all nits and rebased. Thank you to each of you who left thoughtful commentary. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looking quite good.
I noticed that these new cases are added within the do_multisig function that is called several times here:
bitcoin/test/functional/rpc_createmultisig.py
Lines 48 to 51 in 56ce78d
| m_of_n = [(2, 3), (3, 3), (2, 5), (3, 5), (10, 15), (15, 15)] | |
| for (sigs, keys) in m_of_n: | |
| for output_type in ["bech32", "p2sh-segwit", "legacy"]: | |
| self.do_multisig(keys, sigs, output_type) |
Given the nature of the bug regarding the un-mergeable transactions, I feel testing this once should be sufficient in which case we can consider adding these cases in a separate function that should help in avoiding testing the fix multiple times. WDYT? (I have not formed a strong opinion on this though.)
Previously, combinerawtransaction would silently return the first tx when asked to combine unrelated txs. Now, it will check tx mergeability and throws a descriptive error if tx cannot be merged.
The tx mergeability constraints are invariant across output_type and n_sig etc, it should be sufficient to test them one time explicitly and disable during all other runs. Probably not a huge runtime cost as-is but there is definitely a fan-out that would adds additional overhead to all callers of |
a516fe8 to
e3069ec
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tx mergeability constraints are invariant across output_type and n_sig etc, it should be sufficient to test them one time explicitly and disable during all other runs. Probably not a huge runtime cost as-is but there is definitely a fan-out that would adds additional overhead to all callers of do_multisig so got rid of that. Also integrated all other feedback.
Thanks for addressing all the feedback! I had a different approach in mind that creates a separate function for these checks but the latest implementation also looks fine to me.
Code is lgtm e3069ec
Shared 2 nits that could be addressed at the moment I believe.
| Txid txid{}; | ||
| for (unsigned int k{0}; k < tx_variants_copy.size(); ++k) { | ||
| // Remove all scriptSigs and scriptWitnesses from inputs | ||
| for (CTxIn& input : tx_variants_copy[k].vin) { | ||
| input.scriptSig.clear(); | ||
| input.scriptWitness.SetNull(); | ||
| } | ||
| if (k == 0) { | ||
| txid = tx_variants_copy[k].GetHash(); | ||
| } else if (txid != tx_variants_copy[k].GetHash()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit - this is set only once for the first transaction:
diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp
index 1de4d200e8..d0038f25ad 100644
--- a/src/rpc/rawtransaction.cpp
+++ b/src/rpc/rawtransaction.cpp
@@ -622,7 +622,7 @@ static RPCHelpMan combinerawtransaction()
{ // Test Tx relation for mergeability. Strip scriptSigs and scriptWitnesses to facilitate txId comparison
std::vector<CMutableTransaction> tx_variants_copy(txVariants);
- Txid txid{};
+ Txid first_txid{};
for (unsigned int k{0}; k < tx_variants_copy.size(); ++k) {
// Remove all scriptSigs and scriptWitnesses from inputs
for (CTxIn& input : tx_variants_copy[k].vin) {
@@ -630,8 +630,8 @@ static RPCHelpMan combinerawtransaction()
input.scriptWitness.SetNull();
}
if (k == 0) {
- txid = tx_variants_copy[k].GetHash();
- } else if (txid != tx_variants_copy[k].GetHash()) {
+ first_txid = tx_variants_copy[k].GetHash();
+ } else if (first_txid != tx_variants_copy[k].GetHash()) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Transaction number %d not compatible with first transaction", k+1));
}
}| out_addr2 = getnewdestination('bech32')[2] | ||
| unmergeable_transaction_args = [ | ||
| ([[{"txid": tx["txid"], "vout": tx["sent_vout"]}], [{out_addr: outval * 2}]], {}), # similar transaction but with different amount to send | ||
| ([[{"txid": tx["txid"], "vout": tx["sent_vout"]}], [{out_addr: outval}]], {"locktime": 0, "replaceable": True, "version": 1}), # similar transaction but with different version |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because non-positional arguments are used here for version, rest 2 (locktime and replaceable) are not required:
diff --git a/test/functional/rpc_createmultisig.py b/test/functional/rpc_createmultisig.py
index fa0f668922..199193cbbd 100755
--- a/test/functional/rpc_createmultisig.py
+++ b/test/functional/rpc_createmultisig.py
@@ -162,7 +162,7 @@ class RpcCreateMultiSigTest(BitcoinTestFramework):
out_addr2 = getnewdestination('bech32')[2]
unmergeable_transaction_args = [
([[{"txid": tx["txid"], "vout": tx["sent_vout"]}], [{out_addr: outval * 2}]], {}), # similar transaction but with different amount to send
- ([[{"txid": tx["txid"], "vout": tx["sent_vout"]}], [{out_addr: outval}]], {"locktime": 0, "replaceable": True, "version": 1}), # similar transaction but with different version
+ ([[{"txid": tx["txid"], "vout": tx["sent_vout"]}], [{out_addr: outval}]], {"version": 1}), # similar transaction but with different version
([[{"txid": tx["txid"], "vout": tx["sent_vout"]}], [{out_addr: outval}]], {"locktime": 1}), # similar transaction but with different locktime
([[{"txid": tx["txid"], "vout": tx["sent_vout"]}], [{out_addr2: outval}]], {}), # similar transaction but with different output address (scriptPubKey)
([[{"txid": tx["txid"], "vout": tx["sent_vout"], "sequence": 1}], [{out_addr: outval}]], {}), # similar transaction but with different sequence number
(END)
Previously, combinerawtransaction would silently return the first tx when asked to combine unrelated txs. Now, it will check tx mergeability and throws a descriptive error if tx cannot be merged.
fixes #25980