RPC: Add parameter to addmultisigaddress / createmultisig to sort public keys #8751

Open
wants to merge 1 commit into
from

Projects

None yet

7 participants

@afk11
Contributor
afk11 commented Sep 17, 2016

I figured it may be useful for these RPC methods to allow sorting public keys (BIP67) The PR adds a new boolean to createmultisig / addmultisigaddress at the end of their parameter list. By default, this is set to false to avoid a BC break.

I added a RPC test file sort_multisig.py for testing createmultisig. Tests for addmultisigaddress went in wallet-accounts.py.

Note: Code to check whether sorting is desired had to be replicated in both RPC methods (not in _createmultisig_redeemScript) because addmultisigaddress already takes a parameter at position 3.

@dcousens
Contributor

concept ACK

@laanwj
Member
laanwj commented Sep 22, 2016 edited

Concept ACK, although I really don't like multiple-optional-positional-boolean APIs. Wish we switched to named arguments any day.

One nit: the RPC help should mention BIP67 by name.

@MarcoFalke
Member

Needs rebase

@afk11
Contributor
afk11 commented Nov 8, 2016

@MarcoFalke thanks, done. @laanwj I should have mentioned, nits addressed.

One travis run failed due to the compactblocks RPC test.

@ryanofsky
Contributor

I can't see anything on travis right now (503 errors), but the compactblocks error is probably just the spurious #8842 / #9058 failures.

+class SortMultisigTest(BitcoinTestFramework):
+ def __init__(self):
+ super().__init__()
+ self.num_nodes = 4
@MarcoFalke
MarcoFalke Nov 8, 2016 Member

Nit: A single node should be enough?

@MarcoFalke
Member

Concept ACK 7d7a647

src/rpc/misc.cpp
@@ -293,6 +294,7 @@ UniValue createmultisig(const JSONRPCRequest& request)
" \"key\" (string) bitcoin address or hex-encoded public key\n"
" ,...\n"
" ]\n"
+ "3. \"fSort\" (bool, optional) Whether to sort public keys according to BIP67. Default setting is false.\n"
@luke-jr
luke-jr Nov 24, 2016 Member

Is it a string or a boolean?

@afk11
afk11 Nov 24, 2016 Contributor

It should be a boolean. Just observed they aren't usually quoted in RPC output, fixing now.

@afk11 afk11 RPC: addmultisigaddress / createmultisig: parameterize _createmultisi…
…g_redeemScript to allow sorting of public keys (BIP67)

addmultisig/createmultisig RPC documentation: Remove stray quotes from fSort parameter
7439562
@afk11
Contributor
afk11 commented Nov 24, 2016

I probably shouldn't have squashed @MarcoFalke, I'm sorry for rebasing out the commit you reviewed. The only thing to change this time was the removal of "'s from the RPC help message.

@luke-jr

Code looks reasonably correct, just a few nits. Did not verify tests.

"2. \"keys\" (string, required) A json array of keys which are bitcoin addresses or hex-encoded public keys\n"
" [\n"
" \"key\" (string) bitcoin address or hex-encoded public key\n"
" ,...\n"
" ]\n"
+ "3. fSort (bool, optional) Whether to sort public keys according to BIP67. Default setting is false.\n"
@luke-jr
luke-jr Nov 25, 2016 Member

Rather have a named-options Object interface here.

- CScript script;
+ int nEncoded = 0;
+ std::vector<std::vector<unsigned char>> vEncoded;
+ vEncoded.resize(keys.size());
@luke-jr
luke-jr Nov 25, 2016 Member

Wouldn't it be better to reserve and then emplace_back?

+ vEncoded.resize(keys.size());
+ BOOST_FOREACH(const CPubKey& key, keys) {
+ vEncoded[nEncoded++] = ToByteVector(key);
+ }
@luke-jr
luke-jr Nov 25, 2016 edited Member

Seems like the loop would be better as:

for (size_t n = 0; n < keys.size(); ++n) {
    vEncoded[n] = ToByteVector(keys[n]);
}
+ }
+
+ if (fSorted) {
+ std::sort(vEncoded.begin(), vEncoded.end());
@luke-jr
luke-jr Nov 25, 2016 Member

I think this should do what BIP 67 requires, but someone more familiar with C++ and its locale support (or lack thereof) should probably confirm.

@@ -78,7 +78,7 @@ bool ExtractDestinations(const CScript& scriptPubKey, txnouttype& typeRet, std::
CScript GetScriptForDestination(const CTxDestination& dest);
CScript GetScriptForRawPubKey(const CPubKey& pubkey);
-CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys);
+CScript GetScriptForMultisig(int nRequired, const std::vector<CPubKey>& keys, bool fSorted);
@luke-jr
luke-jr Nov 25, 2016 Member

Maybe default fSorted to false here rather than modify all the tests?

"2. \"keysobject\" (string, required) A json array of bitcoin addresses or hex-encoded public keys\n"
" [\n"
" \"address\" (string) bitcoin address or hex-encoded public key\n"
" ...,\n"
" ]\n"
"3. \"account\" (string, optional) DEPRECATED. An account to assign the addresses to.\n"
+ "4. fSort (bool, optional) Whether to sort public keys according to BIP67. Default setting is false.\n"
@luke-jr
luke-jr Nov 25, 2016 Member

As before, rather turn param 3 into an options Object.

@luke-jr luke-jr added a commit to bitcoinknots/bitcoin that referenced this pull request Dec 21, 2016
@afk11 @luke-jr afk11 + luke-jr RPC: addmultisigaddress / createmultisig: parameterize _createmultisi…
…g_redeemScript to allow sorting of public keys (BIP67)

addmultisig/createmultisig RPC documentation: Remove stray quotes from fSort parameter

Github-Pull: #8751
Rebased-From: 7439562
0b0f4f7
@luke-jr
Member
luke-jr commented Dec 21, 2016

Should update doc/bips.md also.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment