Add option to return non-segwit serialization via rpc
#9194

pull instagibbs wants to merge 2 commits into bitcoin:master from instagibbs:nonswserialrpc changing 11 files +45 −13
  1. instagibbs commented at 9:02 pm on November 20, 2016: member

    Libraries may not be upgraded in time to handle the new serialization when segwit blocks and transactions come into the mainchain. This flag would allow people to use the RPC interface uninterrupted and intentionally upgrade as needed.

    It’s affecting users today.

    update: I have added a command line flag instead. See below.

  2. instagibbs commented at 9:04 pm on November 20, 2016: member
    I also think this is a PR worthy of backport.
  3. gmaxwell commented at 9:05 pm on November 20, 2016: contributor
    Concept ACK, and I also think it would be worth considering for backport.
  4. sipa commented at 9:06 pm on November 20, 2016: member
    Sigh, please no extra boolean arguments everywhere :(
  5. instagibbs commented at 9:08 pm on November 20, 2016: member
    @sipa Version argument? I’m willing to put in more work if there are better ideas.
  6. luke-jr commented at 9:10 pm on November 20, 2016: member

    I don’t see a use case to exclude only segwit signatures. Instead, it should strip all signatures, whether segwit or otherwise…

    (Also note this cannot affect users today, since segwit is not active today…)

  7. gmaxwell commented at 9:13 pm on November 20, 2016: contributor
    Turn the existing boolean argument into something else instead? true/false/stripped
  8. instagibbs commented at 9:17 pm on November 20, 2016: member
    @luke-jr (may be misunderstanding you) older libraries/nodes expect older serialization, not witness serialization minus signatures?
  9. sipa commented at 9:21 pm on November 20, 2016: member
    @luke-jr For compatibility reasons, I think that’s a bad idea. scriptSigs aren’t strippable in any useful way. @instagibbs What about a command-line argument to say whether RPC clients support witnesses?
  10. luke-jr commented at 9:32 pm on November 20, 2016: member
    @instagibbs “Older serialization” is what you get when you strip signatures… And if they don’t care about the signatures, then they don’t care about any of the signatures. @sipa scriptSigs are no more or less useful to strip than segwit signatures.
  11. sipa commented at 9:44 pm on November 20, 2016: member
    @luke-jr They are, they determine the txid. You can’t strip scriptSigs for any clients that expect to be able to compute the txid. Or expect to be able to see the signatures for whatever other purpose, but don’t know about segwit.
  12. sdaftuar commented at 9:49 pm on November 20, 2016: member

    scriptSigs are no more or less useful to strip than segwit signatures.

    Of course they are, because they are included in the txid calculation.

    I understand there’s a user who is complaining, but I thought our view on this issue was that people just shouldn’t upgrade their software until their rpc clients, zmq clients, REST clients etc were ready for segwit serialization. I haven’t looked but I assume there are a lot of places in the code where this issue (of not knowing whether the consumer wants witnesses or not) would come up?

    I suppose we could try to do something like what @sipa suggests: a command line flag indicating the serialization to use (with/without witness) for all downstream consumers; it just seems tedious to get right. Might it not be better to just add a python script to contrib that takes a witness-serialized tx and returns a serialization without witness? I guess that would still require downstream library changes, so maybe that doesn’t help.

  13. luke-jr commented at 9:54 pm on November 20, 2016: member
    @sipa If they want the txids, they should be using the verbose mode in the first place, no? And if they actually need the signatures, they should need the segwit signatures as well…
  14. instagibbs commented at 9:55 pm on November 20, 2016: member
    @sdaftuar in the interest of doing a command line level argument I’m going to audit how many RPC points would need to know about a flag. This exercise also may come in handy when it comes to switching over wallet functionality to segwit by default, which I’m imagining will be a similar mechanism. I also think that any time we have to change serialization in the future, we can ratchet whatever argument we have, and deprecate older versions if we can’t trivially support them.
  15. sipa commented at 9:56 pm on November 20, 2016: member

    @luke-jr Yes, in an ideal world everybody would use everything the way it is designed. But in an ideal world, we’d also have segwit from the start, and we’d never have any compatibility issue at all.

    Stripping scriptSigs will break software.

  16. instagibbs commented at 7:03 pm on November 21, 2016: member

    I agree that adding another boolean for legacy purposes to the rpc api was suboptimal, so I have added a command line argument at startup to offer the same functionality called -rpcserialversion with a default value of 1. If set to 0 the NO_WITNESS flag is included in the same places as before. I believe this covers the major use-cases, which is passing along serializations of transactions understood by legacy libraries and the like(which is the activity the p2p layer takes great care to abide by).

    I can squash if this is deemed superior.

  17. instagibbs force-pushed on Nov 21, 2016
  18. instagibbs force-pushed on Nov 21, 2016
  19. in src/core_write.cpp: in 165dd28bbd outdated
    115@@ -116,9 +116,9 @@ string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode)
    116     return str;
    117 }
    118 
    119-string EncodeHexTx(const CTransaction& tx)
    120+string EncodeHexTx(const CTransaction& tx, const bool fNonWitnessTx)
    


    instagibbs commented at 7:08 pm on November 21, 2016:
    Perhaps a serialize flag directly here is more appropriate and would effortlessly extend if we have additional serialization flags.

    gmaxwell commented at 4:29 am on November 22, 2016:
    Yes, I think thats a good idea– and consistent with how things are done for p2p.
  20. instagibbs force-pushed on Nov 22, 2016
  21. instagibbs renamed this:
    Add flags to getrawtransaction and getblock to return non-segwit seri…
    Add option to return non-segwit serialization via rpc
    on Nov 22, 2016
  22. instagibbs force-pushed on Nov 22, 2016
  23. instagibbs force-pushed on Nov 22, 2016
  24. instagibbs commented at 2:52 pm on November 22, 2016: member
    Updated EncodeHexTx to take serialization flag directly, gettransaction[“hex”] is now affected, and added more testing.
  25. sdaftuar commented at 6:23 pm on November 22, 2016: member
    As mentioned before and on IRC, I think if we’re adding a command line argument to change the serialization for RPC calls, then for consistency’s sake we ought to do the same for REST and ZMQ. Looks to me like just a couple additional call sites would be affected.
  26. instagibbs force-pushed on Nov 22, 2016
  27. instagibbs force-pushed on Nov 22, 2016
  28. instagibbs force-pushed on Nov 22, 2016
  29. instagibbs force-pushed on Nov 22, 2016
  30. instagibbs commented at 9:57 pm on November 22, 2016: member
    updated as per @sdaftuar’s reasonable request
  31. in src/rest.cpp: in 742f1ac515 outdated
    227@@ -228,7 +228,7 @@ static bool rest_block(HTTPRequest* req,
    228             return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
    229     }
    230 
    231-    CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
    232+    CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION | (GetArg("-rpcserialversion", DEFAULT_RPC_SERIALIZE_VERSION) == 0) ? SERIALIZE_TRANSACTION_NO_WITNESS : 0);
    


    sipa commented at 10:24 pm on November 22, 2016:
    Can you extract out this conditional expression into a utility function?

    instagibbs commented at 2:42 am on November 23, 2016:
    done
  32. instagibbs force-pushed on Nov 23, 2016
  33. in src/main.cpp: in cfeb4c94a3 outdated
    3558@@ -3559,6 +3559,14 @@ std::vector<unsigned char> GenerateCoinbaseCommitment(CBlock& block, const CBloc
    3559     return commitment;
    3560 }
    3561 
    3562+int RPCSerializationFlags()
    


    sipa commented at 5:57 am on November 23, 2016:
    Unsure this belongs in main. Maybe in util?

    jonasschnelli commented at 7:37 am on November 23, 2016:
    This should be move from main.cpp to server.cpp or core_write.cpp.

    instagibbs commented at 2:40 pm on November 23, 2016:
    moved to server.cpp
  34. in src/rpc/blockchain.cpp: in cfeb4c94a3 outdated
    696@@ -697,6 +697,7 @@ UniValue getblock(const JSONRPCRequest& request)
    697             "\nArguments:\n"
    698             "1. \"hash\"          (string, required) The block hash\n"
    699             "2. verbose           (boolean, optional, default=true) true for a json object, false for the hex encoded data\n"
    700+            "3. nonwit            (boolean, optional, default=false) whether to return a non-witness block in non-verbose mode\n"
    


    jonasschnelli commented at 7:35 am on November 23, 2016:
    This should go away because it seems to be no longer in use.

    instagibbs commented at 2:40 pm on November 23, 2016:
    fixed thanks
  35. instagibbs force-pushed on Nov 23, 2016
  36. instagibbs force-pushed on Nov 23, 2016
  37. instagibbs force-pushed on Nov 23, 2016
  38. instagibbs force-pushed on Nov 23, 2016
  39. instagibbs force-pushed on Nov 23, 2016
  40. fanquake added the label RPC/REST/ZMQ on Nov 24, 2016
  41. in qa/rpc-tests/segwit.py: in fd955b98ab outdated
    218+        print("Verify block and transaction serialization rpcs return differing serializations depending on rpc serialization flag")
    219+        # Note: node1 has version 2, which is simply >0 and will catch future upgrades in tests
    220+        assert(self.nodes[2].getblock(block[0], False) !=  self.nodes[0].getblock(block[0], False))
    221+        assert(self.nodes[1].getblock(block[0], False) ==  self.nodes[2].getblock(block[0], False))
    222+        for i in range(len(segwit_tx_list)):
    223+            #Coinbase can not be a segwit transcation
    


    sdaftuar commented at 8:50 pm on November 28, 2016:
    I’m confused by this comment – after segwit activates, the coinbase transaction will generally have a witness, namely the nonce (assuming there’s a witness commitment).
  42. in qa/rpc-tests/segwit.py: in fd955b98ab outdated
    219+        # Note: node1 has version 2, which is simply >0 and will catch future upgrades in tests
    220+        assert(self.nodes[2].getblock(block[0], False) !=  self.nodes[0].getblock(block[0], False))
    221+        assert(self.nodes[1].getblock(block[0], False) ==  self.nodes[2].getblock(block[0], False))
    222+        for i in range(len(segwit_tx_list)):
    223+            #Coinbase can not be a segwit transcation
    224+            if "coinbase" in segwit_tx_list[i]:
    


    sdaftuar commented at 8:59 pm on November 28, 2016:
    Isn’t segwit_tx_list a list of txids?
  43. instagibbs force-pushed on Nov 28, 2016
  44. instagibbs force-pushed on Dec 1, 2016
  45. instagibbs commented at 7:08 pm on December 1, 2016: member
    rebased.
  46. in src/core_io.h: in 1c067e2e87 outdated
    24@@ -25,7 +25,7 @@ std::vector<unsigned char> ParseHexUV(const UniValue& v, const std::string& strN
    25 
    26 // core_write.cpp
    27 std::string FormatScript(const CScript& script);
    28-std::string EncodeHexTx(const CTransaction& tx);
    29+std::string EncodeHexTx(const CTransaction& tx, const int serializeFlags = 0);std::string EncodeHexTx(const CTransaction& tx, const int serializeFlags = 0);
    


    sdaftuar commented at 7:14 pm on December 1, 2016:
    extra text?

    instagibbs commented at 7:15 pm on December 1, 2016:
    argh, kdiff. fixing
  47. instagibbs force-pushed on Dec 1, 2016
  48. jonasschnelli added this to the milestone 0.14.0 on Dec 1, 2016
  49. instagibbs commented at 7:22 pm on December 1, 2016: member

    Cribbing from IRC for historical reasons @petertodd :

    re: luke-jr’s point on “stripped sigs”, lots of code gets written that calculates its own txids and isn’t using the RPC for that, e.g. python-bitcoinlib RPC code would likely do that, so stripped sigs mode isn’t useful there; 100% backwards compatibility is

  50. instagibbs commented at 7:26 pm on December 1, 2016: member
    backport tag @fanquake ?
  51. jonasschnelli added the label Needs backport on Dec 1, 2016
  52. jtimon commented at 8:43 pm on December 1, 2016: contributor
    utACK ebe6c30
  53. sipa commented at 8:59 pm on December 1, 2016: member
    utACK ebe6c30a2763a281425de35fd7b2f5dc87f48199
  54. in qa/rpc-tests/segwit.py: in ebe6c30a27 outdated
    221+        assert(self.nodes[1].getblock(block[0], False) ==  self.nodes[2].getblock(block[0], False))
    222+        for i in range(len(segwit_tx_list)):
    223+            assert(self.nodes[2].getrawtransaction(segwit_tx_list[i]) != self.nodes[0].getrawtransaction(segwit_tx_list[i]))
    224+            assert(self.nodes[1].getrawtransaction(segwit_tx_list[i], 0) == self.nodes[2].getrawtransaction(segwit_tx_list[i]))
    225+            assert(self.nodes[0].getrawtransaction(segwit_tx_list[i]) != self.nodes[2].gettransaction(segwit_tx_list[i])["hex"])
    226+            assert(self.nodes[1].getrawtransaction(segwit_tx_list[i]) == self.nodes[2].gettransaction(segwit_tx_list[i])["hex"])
    


    sdaftuar commented at 9:13 pm on December 1, 2016:
    Perhaps the test should explicitly test the correctness of the serializations, rather than just comparing output against each other? (Maybe just the node0/legacy-serialization case, since I presume something would break if the rpcserializationversion=1 handling were busted.)

    sdaftuar commented at 9:28 pm on December 1, 2016:

    FYI this did the trick for me:

     0diff --git a/qa/rpc-tests/segwit.py b/qa/rpc-tests/segwit.py
     1index a618aec..e8a5512 100755
     2--- a/qa/rpc-tests/segwit.py
     3+++ b/qa/rpc-tests/segwit.py
     4@@ -219,10 +219,13 @@ class SegWitTest(BitcoinTestFramework):
     5         assert(self.nodes[2].getblock(block[0], False) !=  self.nodes[0].getblock(block[0], False))
     6         assert(self.nodes[1].getblock(block[0], False) ==  self.nodes[2].getblock(block[0], False))
     7         for i in range(len(segwit_tx_list)):
     8+            from test_framework.mininode import FromHex
     9+            tx = FromHex(CTransaction(), self.nodes[2].gettransaction(segwit_tx_list[i])["hex"])
    10             assert(self.nodes[2].getrawtransaction(segwit_tx_list[i]) != self.nodes[0].getrawtransaction(segwit_tx_list[i]))
    11             assert(self.nodes[1].getrawtransaction(segwit_tx_list[i], 0) == self.nodes[2].getrawtransaction(segwit_tx_list[i]))
    12             assert(self.nodes[0].getrawtransaction(segwit_tx_list[i]) != self.nodes[2].gettransaction(segwit_tx_list[i])["hex"])
    13             assert(self.nodes[1].getrawtransaction(segwit_tx_list[i]) == self.nodes[2].gettransaction(segwit_tx_list[i])["hex"])
    14+            assert(self.nodes[0].getrawtransaction(segwit_tx_list[i]) == bytes_to_hex_str(tx.serialize_without_witness()))
    15 
    16         print("Verify witness txs without witness data are invalid after the fork")
    17         self.fail_mine(self.nodes[2], wit_ids[NODE_2][WIT_V0][2], False)
    

    instagibbs commented at 1:15 am on December 2, 2016:
    thanks, included!
  55. sdaftuar commented at 9:32 pm on December 1, 2016: member

    “no objection” utACK ebe6c30a2763a281425de35fd7b2f5dc87f48199

    It’s good that the RPC handling is tested with the segwit.py test; it’d be nice to update the zmq and rest python tests as well, but I think that can be done later.

  56. instagibbs force-pushed on Dec 2, 2016
  57. laanwj added this to the milestone 0.13.2 on Dec 2, 2016
  58. laanwj removed this from the milestone 0.14.0 on Dec 2, 2016
  59. MarcoFalke commented at 3:51 pm on December 2, 2016: member
    Note: Needs release notes for 0.13.2 after merge.
  60. MarcoFalke added the label Needs release notes on Dec 2, 2016
  61. laanwj commented at 7:12 am on December 5, 2016: member
    Needs rebase.
  62. Add option to return non-segwit serialization via rpc bc7ff8db99
  63. Adapt ZMQ/rest serialization to take rpcserialversion arg 412bab22b2
  64. instagibbs force-pushed on Dec 5, 2016
  65. instagibbs commented at 1:24 pm on December 5, 2016: member
    rebased
  66. gmaxwell commented at 4:29 am on December 6, 2016: contributor
    ACK (however I did not test rest/ZMQ).
  67. in src/init.cpp: in bc7ff8db99 outdated
    379@@ -380,6 +380,7 @@ std::string HelpMessage(HelpMessageMode mode)
    380     strUsage += HelpMessageOpt("-port=<port>", strprintf(_("Listen for connections on <port> (default: %u or testnet: %u)"), Params(CBaseChainParams::MAIN).GetDefaultPort(), Params(CBaseChainParams::TESTNET).GetDefaultPort()));
    381     strUsage += HelpMessageOpt("-proxy=<ip:port>", _("Connect through SOCKS5 proxy"));
    382     strUsage += HelpMessageOpt("-proxyrandomize", strprintf(_("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)"), DEFAULT_PROXYRANDOMIZE));
    383+    strUsage += HelpMessageOpt("-rpcserialversion", strprintf(_("Sets the serialization of raw transaction or block hex returned in non-verbose mode, non-segwit(0) or segwit(>0) (default: %d)"), DEFAULT_RPC_SERIALIZE_VERSION));
    


    sipa commented at 7:21 am on December 6, 2016:
    I think you should say (1) specifically, and not just (>0). If a value is passed that the node doesn’t understand, it should complain, because it means the user is asking to serialize in a way it does not know about.
  68. laanwj merged this on Dec 6, 2016
  69. laanwj closed this on Dec 6, 2016

  70. laanwj referenced this in commit ed8d693c71 on Dec 6, 2016
  71. laanwj referenced this in commit 21ccb9f253 on Dec 6, 2016
  72. laanwj referenced this in commit f26dab7e90 on Dec 6, 2016
  73. MarcoFalke removed the label Needs backport on Dec 14, 2016
  74. MarcoFalke commented at 11:56 am on December 14, 2016: member

    Removing label “Needs backport”. This was backported in f26dab7 and 21ccb9f

    Still needs release notes.

  75. sipa removed the label Needs release notes on Aug 14, 2018
  76. PastaPastaPasta referenced this in commit 511fae8959 on Sep 19, 2019
  77. MarcoFalke locked this on Sep 8, 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-09-29 01:12 UTC

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