Skip to content

Conversation

instagibbs
Copy link
Member

@instagibbs instagibbs commented Nov 20, 2016

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.

@instagibbs
Copy link
Member Author

I also think this is a PR worthy of backport.

@gmaxwell
Copy link
Contributor

Concept ACK, and I also think it would be worth considering for backport.

@sipa
Copy link
Member

sipa commented Nov 20, 2016 via email

@instagibbs
Copy link
Member Author

@sipa Version argument? I'm willing to put in more work if there are better ideas.

@luke-jr
Copy link
Member

luke-jr commented Nov 20, 2016

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...)

@gmaxwell
Copy link
Contributor

Turn the existing boolean argument into something else instead? true/false/stripped

@instagibbs
Copy link
Member Author

@luke-jr (may be misunderstanding you) older libraries/nodes expect older serialization, not witness serialization minus signatures?

@sipa
Copy link
Member

sipa commented Nov 20, 2016 via email

@luke-jr
Copy link
Member

luke-jr commented Nov 20, 2016

@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.

@sipa
Copy link
Member

sipa commented Nov 20, 2016 via email

@sdaftuar
Copy link
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.

@luke-jr
Copy link
Member

luke-jr commented Nov 20, 2016

@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...

@instagibbs
Copy link
Member Author

instagibbs commented Nov 20, 2016

@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.

@sipa
Copy link
Member

sipa commented Nov 20, 2016 via email

@instagibbs
Copy link
Member Author

instagibbs commented Nov 21, 2016

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.

@instagibbs instagibbs force-pushed the nonswserialrpc branch 2 times, most recently from 273f1c2 to 165dd28 Compare November 21, 2016 19:07
@@ -116,9 +116,9 @@ string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode)
return str;
}

string EncodeHexTx(const CTransaction& tx)
string EncodeHexTx(const CTransaction& tx, const bool fNonWitnessTx)
Copy link
Member Author

@instagibbs instagibbs Nov 21, 2016

Choose a reason for hiding this comment

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

Perhaps a serialize flag directly here is more appropriate and would effortlessly extend if we have additional serialization flags.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, I think thats a good idea-- and consistent with how things are done for p2p.

@instagibbs instagibbs changed the title Add flags to getrawtransaction and getblock to return non-segwit seri… Add option to return non-segwit serialization via rpc Nov 22, 2016
@instagibbs instagibbs force-pushed the nonswserialrpc branch 2 times, most recently from 676b293 to 0d757f0 Compare November 22, 2016 14:51
@instagibbs
Copy link
Member Author

Updated EncodeHexTx to take serialization flag directly, gettransaction["hex"] is now affected, and added more testing.

@sdaftuar
Copy link
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.

@instagibbs instagibbs force-pushed the nonswserialrpc branch 4 times, most recently from 071f146 to 742f1ac Compare November 22, 2016 21:20
@instagibbs
Copy link
Member Author

updated as per @sdaftuar's reasonable request

@@ -228,7 +228,7 @@ static bool rest_block(HTTPRequest* req,
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
}

CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION);
CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION | (GetArg("-rpcserialversion", DEFAULT_RPC_SERIALIZE_VERSION) == 0) ? SERIALIZE_TRANSACTION_NO_WITNESS : 0);
Copy link
Member

Choose a reason for hiding this comment

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

Can you extract out this conditional expression into a utility function?

Copy link
Member Author

Choose a reason for hiding this comment

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

done

@jtimon
Copy link
Contributor

jtimon commented Dec 1, 2016

utACK ebe6c30

@sipa
Copy link
Member

sipa commented Dec 1, 2016

utACK ebe6c30a2763a281425de35fd7b2f5dc87f48199

assert(self.nodes[2].getrawtransaction(segwit_tx_list[i]) != self.nodes[0].getrawtransaction(segwit_tx_list[i]))
assert(self.nodes[1].getrawtransaction(segwit_tx_list[i], 0) == self.nodes[2].getrawtransaction(segwit_tx_list[i]))
assert(self.nodes[0].getrawtransaction(segwit_tx_list[i]) != self.nodes[2].gettransaction(segwit_tx_list[i])["hex"])
assert(self.nodes[1].getrawtransaction(segwit_tx_list[i]) == self.nodes[2].gettransaction(segwit_tx_list[i])["hex"])
Copy link
Member

Choose a reason for hiding this comment

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

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.)

Copy link
Member

Choose a reason for hiding this comment

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

FYI this did the trick for me:

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

Copy link
Member Author

Choose a reason for hiding this comment

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

thanks, included!

@sdaftuar
Copy link
Member

sdaftuar commented Dec 1, 2016

"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.

@laanwj laanwj modified the milestones: 0.13.2, 0.14.0 Dec 2, 2016
@maflcko
Copy link
Member

maflcko commented Dec 2, 2016

Note: Needs release notes for 0.13.2 after merge.

@laanwj
Copy link
Member

laanwj commented Dec 5, 2016

Needs rebase.

@instagibbs
Copy link
Member Author

rebased

@gmaxwell
Copy link
Contributor

gmaxwell commented Dec 6, 2016

ACK (however I did not test rest/ZMQ).

@@ -380,6 +380,7 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += HelpMessageOpt("-port=<port>", strprintf(_("Listen for connections on <port> (default: %u or testnet: %u)"), Params(CBaseChainParams::MAIN).GetDefaultPort(), Params(CBaseChainParams::TESTNET).GetDefaultPort()));
strUsage += HelpMessageOpt("-proxy=<ip:port>", _("Connect through SOCKS5 proxy"));
strUsage += HelpMessageOpt("-proxyrandomize", strprintf(_("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)"), DEFAULT_PROXYRANDOMIZE));
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));
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 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.

@laanwj laanwj merged commit 412bab2 into bitcoin:master Dec 6, 2016
laanwj added a commit that referenced this pull request Dec 6, 2016
412bab2 Adapt ZMQ/rest serialization to take rpcserialversion arg (instagibbs)
bc7ff8d Add option to return non-segwit serialization via rpc (Gregory Sanders)
laanwj pushed a commit to laanwj/bitcoin that referenced this pull request Dec 6, 2016
Github-Pull: bitcoin#9194
Rebased-From: 835c75acaac004c3315395dcd7d1f193dfb9e5da
laanwj pushed a commit to laanwj/bitcoin that referenced this pull request Dec 6, 2016
Github-Pull: bitcoin#9194
Rebased-From: ad5c4c93cae53a2a6f74880ca11b4d788677a378
@laanwj laanwj mentioned this pull request Dec 6, 2016
@maflcko
Copy link
Member

maflcko commented Dec 14, 2016

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

Still needs release notes.

PastaPastaPasta pushed a commit to PastaPastaPasta/dash that referenced this pull request Sep 19, 2019
… rpc

412bab2 Adapt ZMQ/rest serialization to take rpcserialversion arg (instagibbs)
bc7ff8d Add option to return non-segwit serialization via rpc (Gregory Sanders)
@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.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants