Add P2SH-P2WSH support to listunspent RPC #14481

pull meshcollider wants to merge 3 commits into bitcoin:master from meshcollider:201810_listunspent_wsh changing 4 files +81 −10
  1. meshcollider commented at 5:49 am on October 15, 2018: contributor

    This is a reworked version of #11708 after #12427 and the signrawtransaction split.

    For a P2WSH address, listunspent should return the witness script, and for a P2SH-P2WSH address, it should also return the inner witness script (because SignTransaction will automatically wrap it in P2SH if required).

    Includes a test which also tests the behaviour of #12427, and release note.

  2. meshcollider added the label Wallet on Oct 15, 2018
  3. meshcollider added the label RPC/REST/ZMQ on Oct 15, 2018
  4. in src/wallet/rpcwallet.cpp:2712 in c789fef8ca outdated
    2708@@ -2709,7 +2709,7 @@ static UniValue listunspent(const JSONRPCRequest& request)
    2709             "    \"scriptPubKey\" : \"key\",   (string) the script key\n"
    2710             "    \"amount\" : x.xxx,         (numeric) the transaction output amount in " + CURRENCY_UNIT + "\n"
    2711             "    \"confirmations\" : n,      (numeric) The number of confirmations\n"
    2712-            "    \"redeemScript\" : n        (string) The redeemScript if scriptPubKey is P2SH\n"
    2713+            "    \"redeemScript\" : n        (string) The redeemScript if scriptPubKey is P2SH, or witnessScript if the scriptPubKey is P2WSH or P2SH-P2WSH\n"
    


    Sjors commented at 8:40 am on October 17, 2018:
    Why not a separate witnessScript field like in #14454?

    meshcollider commented at 12:05 pm on October 17, 2018:
    @Sjors because this has to be compatible with how signrawtransaction works, so it can be passed directly in. signrawtransaction only accepts the witness script as “redeemScript” and automatically wraps it

    Sjors commented at 12:42 pm on October 17, 2018:
    Would it be super involved to add support for witnessScript to signrawtransactionwithkey and signrawtransactionwithwallet? The terminology is already quite confusing, so consistency can really help.

    instagibbs commented at 2:32 pm on October 17, 2018:
    Agreed with @Sjors I’d much rather we fix terminology instead of compounding confusion.

    ryanofsky commented at 4:03 pm on November 14, 2018:

    re: #14481 (review)

    Being consistent with terminology from https://bitcoincore.org/en/segwit_wallet_dev/#creation-of-p2sh-p2wsh-address and importmulti seems good. Making it possible to call signrawtransaction directly also seems good. Can’t we do both by updating signrawtransaction to accept a witnessScript field?

    If we did this, I guess there would still be question of whether signrawtransaction should remain backwards compatible and continue accepting overloaded redeemScript’s introduced in #12427, or if that feature should be deprecated. I’d probably opt not to deprecate. Nicolas made decent usability arguments in #11708 (comment), #11708 (comment) that overloading redeemScript can make calling signraw less painful, and that it doesn’t introduce ambiguities that would let callers shoot themselves in the foot (which I guess would not be the case with importmulti).

  5. DrahtBot commented at 9:57 am on October 20, 2018: member

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #12677 (RPC: Add ancestor{count,size,fees} to listunspent output by luke-jr)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  6. fanquake added this to the "In progress" column in a project

  7. in src/wallet/rpcwallet.cpp:2824 in c789fef8ca outdated
    2818@@ -2819,7 +2819,29 @@ static UniValue listunspent(const JSONRPCRequest& request)
    2819                 const CScriptID& hash = boost::get<CScriptID>(address);
    2820                 CScript redeemScript;
    2821                 if (pwallet->GetCScript(hash, redeemScript)) {
    2822-                    entry.pushKV("redeemScript", HexStr(redeemScript.begin(), redeemScript.end()));
    2823+                    // First check if the redeemScript is actually a P2WSH script
    2824+                    CTxDestination witness_destination;
    2825+                    if (redeemScript.IsPayToWitnessScriptHash() && ExtractDestination(redeemScript, witness_destination)) {
    


    ryanofsky commented at 4:56 pm on November 14, 2018:
    IsPayToWitnessScriptHash succeeding and ExtractDestination failing should never happen, right? I think it would be better to trigger an actual error in this case than to silently fall back to the non-witness case.
  8. ryanofsky approved
  9. ryanofsky commented at 5:06 pm on November 14, 2018: member
    Code utACK c789fef8ca4739e2fb3c930bacad77543650b781, but I agree with others about not wanting to overload redeemScript in listunspent #14481 (review). It seems like it should be possible to be compatible with signraw without overloading.
  10. sipa commented at 11:48 pm on November 14, 2018: member
    I wonder if it isn’t just easier to support passing in a descriptor in signrawtransactionwithkey and using #14477 to get to get descriptors from listunspent etc? The various ways of passing around scripts in different RPCs looks like hard to solve mess.
  11. ryanofsky commented at 8:32 pm on December 4, 2018: member

    @MeshCollider is there an update on the status of this PR?

    c789fef8ca4739e2fb3c930bacad77543650b781 seems like an improvement to me, and has my ACK. But I do think it would be an easy win to replace “redeemScript” with “witnessScript” there, and tweak signrawtransaction to accept “witnessScript”, so all RPCs could use these terms consistently.

    Or if we want to abandon this approach and jump to descriptors instead as suggested in #14481 (comment), this seems like another good option. Do you have thoughts on it? Does it require more work? Is it blocked on anything now that #14477 is merged?

  12. meshcollider commented at 8:01 pm on December 6, 2018: contributor
    @ryanofsky I plan on modifying this for terminology as above for now, and then I think we should look at RPC descriptor support as a whole after that. But I will come back to this PR in the next few days
  13. meshcollider commented at 8:35 pm on February 5, 2019: contributor
    I’ve rebased this and addressed the terminology comments above, moving to a new witnessScript field with backwards compatibility
  14. meshcollider added this to the milestone 0.18.0 on Feb 8, 2019
  15. Sjors commented at 12:05 pm on February 11, 2019: member

    bd2b1f65e949a1768c6f989677ea24b746384ca6 looks OK, but…

    I have my doubt if backwards compatibility with something that was already buggy is worth the confusion of overloading redeemScript for listunspent. I’d rather have it null if signrawtransaction can infer it anyway, or even just the P2SH wrapper redeem script.

    It might be better to squash the first and last commit.

    I think addmultisigaddress should also return both redeemScript and witnessScript in the correct manner, so you you can just test:

    0assert_equal(unspent_output["witnessScript"], p2sh_p2wsh_address["witnessScript"])
    1assert_equal(unspent_output["redeemScript"], p2sh_p2wsh_address["redeemScript"])
    2assert_equal(unspent_output["redeemScript"], CScript([OP_0, sha256(hex_str_to_bytes(unspent_output["witnessScript"])))
    
  16. meshcollider commented at 7:48 pm on February 11, 2019: contributor

    Forgot to update the release notes, listunspent doesn’t overload redeemScript anymore

    Agree about addmultisigaddress, and about squashing :+1:

  17. meshcollider commented at 11:09 pm on February 11, 2019: contributor
    I’ve squashed and updated the release notes, but modifying addmultisigaddress to return a witnessScript as well as redeemScript would be a breaking change, because currently the witnessScript is returned as “redeemScript”. It would be more confusing to use different terminology so unless a breaking change is worth it here, which I don’t think it is, I’ll leave it as is
  18. in doc/release-notes-14481.md:8 in 77c0c8e246 outdated
    0@@ -0,0 +1,9 @@
    1+Low-level RPC changes
    2+----------------------
    3+
    4+The `listunspent` RPC has been modified so that it also returns `witnessScript`,
    5+the witness script in the case of a P2WSH or P2SH-P2WSH output.
    6+
    7+The `signrawtransactionwithkey` and `signrawtransactionwithwallet` RPCs have been
    8+modified so that they also accept a `witnessScript`, the witness script in the
    


    laanwj commented at 9:20 am on February 12, 2019:
    maybe optionally instead of also
  19. in test/functional/rpc_signrawtransaction.py:165 in 77c0c8e246 outdated
    160+        unspent_output = self.nodes[1].listunspent(0, 999999, [p2sh_p2wsh_address["address"]])[0]
    161+        assert_equal(unspent_output["witnessScript"], p2sh_p2wsh_address["redeemScript"])
    162+        p2sh_redeemScript = CScript([OP_0, sha256(hex_str_to_bytes(p2sh_p2wsh_address["redeemScript"]))])
    163+        assert_equal(unspent_output["redeemScript"], bytes_to_hex_str(p2sh_redeemScript))
    164+        # Now create and sign a transaction spending that output on node[0], which doesn't know the scripts or keys
    165+        spending_tx = self.nodes[0].createrawtransaction([unspent_output], {self.nodes[1].getnewaddress(): 49.998})
    


    laanwj commented at 9:24 am on February 12, 2019:
    Please pass fractional amounts as a Decimal
  20. in src/rpc/rawtransaction.cpp:867 in 77c0c8e246 outdated
    862+                if (!rs.isNull()) {
    863+                    std::vector<unsigned char> rsData(ParseHexV(rs, "redeemScript"));
    864                     CScript redeemScript(rsData.begin(), rsData.end());
    865                     keystore->AddCScript(redeemScript);
    866                     // Automatically also add the P2WSH wrapped version of the script (to deal with P2SH-P2WSH).
    867+                    // This is only for compatibility, it is encouraged to use the explicit witnessScript field instead.
    


    Sjors commented at 10:08 am on February 12, 2019:
    I was also referring to this overloading.
  21. Sjors commented at 10:13 am on February 12, 2019: member

    to return a witnessScript as well as redeemScript would be a breaking change, because currently the witnessScript is returned as “redeemScript”

    I could be wrong, but I suspect very few people use addmultisigaddress with SegWit in an automated setup (maybe @alecalve has stats on how much SegWit multisig is used in general). So it might still be early enough for a breaking change to use redeemScript and witnessScript accurately and consistently throughout the RPC.

    (I can live with not doing it though)

  22. in src/rpc/rawtransaction.cpp:958 in 0b665ab577 outdated
    954@@ -945,7 +955,8 @@ static UniValue signrawtransactionwithkey(const JSONRPCRequest& request)
    955                                     {"txid", RPCArg::Type::STR_HEX, /* opt */ false, /* default_val */ "", "The transaction id"},
    956                                     {"vout", RPCArg::Type::NUM, /* opt */ false, /* default_val */ "", "The output number"},
    957                                     {"scriptPubKey", RPCArg::Type::STR_HEX, /* opt */ false, /* default_val */ "", "script key"},
    958-                                    {"redeemScript", RPCArg::Type::STR_HEX, /* opt */ true, /* default_val */ "omitted", "(required for P2SH or P2WSH) redeem script"},
    959+                                    {"redeemScript", RPCArg::Type::STR_HEX, /* opt */ true, /* default_val */ "omitted", "(required for P2SH) redeem script"},
    


    ryanofsky commented at 10:01 pm on February 12, 2019:

    In commit “Make listunspent return witness script for P2WSH or P2SH-P2WSH” (0b665ab577ab41e3b7b12d9b7d83c151cf90fdaf)

    Could update commit message to mention change to signrawtransactionwithkey

  23. in src/wallet/rpcwallet.cpp:2883 in 0b665ab577 outdated
    2876@@ -2876,6 +2877,27 @@ static UniValue listunspent(const JSONRPCRequest& request)
    2877                 CScript redeemScript;
    2878                 if (pwallet->GetCScript(hash, redeemScript)) {
    2879                     entry.pushKV("redeemScript", HexStr(redeemScript.begin(), redeemScript.end()));
    2880+                    // Now check if the redeemScript is actually a P2WSH script
    2881+                    CTxDestination witness_destination;
    2882+                    if (redeemScript.IsPayToWitnessScriptHash()) {
    2883+                        assert(ExtractDestination(redeemScript, witness_destination));
    


    ryanofsky commented at 10:11 pm on February 12, 2019:

    In commit “Make listunspent return witness script for P2WSH or P2SH-P2WSH” (0b665ab577ab41e3b7b12d9b7d83c151cf90fdaf)

    This would be broken if compiled with NDEBUG, which even though we don’t support it, isn’t really great for readability because you don’t expect to see code with side effects inside an assert. Would be a little better to write something like:

    0bool extracted = ExtractDestitionation...;
    1assert(extracted);
    
  24. ryanofsky approved
  25. ryanofsky commented at 10:21 pm on February 12, 2019: member

    utACK 77c0c8e246e1a7f8c403c19d13c8bb699dba8cf4. Left some comments but I think this is good to merge as-is. Only changes since last review are rebase and following up on previous suggestions (main one being to switch from redeemScript to witnessScript). Thanks for adopting these!

    change to use redeemScript and witnessScript accurately and consistently throughout the RPC

    Would agree with Sjors in preferring to use these terms consistently, and breaking backwards compatibility in what seems to be a minor edge case. This could be done in a followup PR, and would be easy thing to explain in release notes.

  26. MarcoFalke added the label Needs rebase on Feb 12, 2019
  27. MarcoFalke commented at 11:54 pm on February 12, 2019: member
    Needs rebase (blame me)
  28. Make listunspent and signrawtransaction RPCs support witnessScript 314784a60f
  29. meshcollider commented at 1:27 am on February 13, 2019: contributor

    Rebased and addressed comments above. @MarcoFalke I expect a review from you then ;)

    addmultisigaddress change can be done in a followup PR to avoid adding extra review burden here so close to merge-readiness

  30. Add test for P2SH-P2WSH in signrawtransactionwithkey and listunspent 928beae007
  31. Add release note for listunspent P2WSH change 6ca836ab3a
  32. ryanofsky approved
  33. ryanofsky commented at 1:38 am on February 13, 2019: member
    utACK 6ca836ab3abef5a90df0c3c4e4983f328b1afe00. Changes since last review: rebase due to #14918 and making various requested changes (updating release notes and first commit message, removing assert side-effect, using python Decimal).
  34. DrahtBot removed the label Needs rebase on Feb 13, 2019
  35. MarcoFalke commented at 8:36 pm on February 14, 2019: member
    utACK 6ca836ab3abef5a90df0c3c4e4983f328b1afe00
  36. laanwj merged this on Feb 14, 2019
  37. laanwj closed this on Feb 14, 2019

  38. laanwj referenced this in commit 3facd9fdc4 on Feb 14, 2019
  39. meshcollider deleted the branch on Feb 15, 2019
  40. meshcollider moved this from the "In progress" to the "Done" column in a project

  41. MarcoFalke locked this on Dec 16, 2021

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2024-10-04 22:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me