From 3f8b8a6c5f219b6b23dece2990c32f7a75ec69b9 Mon Sep 17 00:00:00 2001 From: Xinxi Wang Date: Sun, 4 Mar 2018 18:18:50 +0000 Subject: [PATCH] Litecoin: M prefix added for script addresses --- contrib/testgen/gen_base58_test_vectors.py | 4 + src/base58.cpp | 12 ++- src/test/data/base58_keys_valid.json | 26 +++--- test/functional/test_framework/address.py | 2 +- test/functional/test_runner.py | 1 + test/functional/wallet_scriptaddress2.py | 98 ++++++++++++++++++++++ test/util/data/txcreatemultisig2.json | 2 +- test/util/data/txcreatemultisig4.json | 2 +- test/util/data/txcreatemultisig5.json | 2 +- test/util/data/txcreateoutpubkey3.json | 2 +- test/util/data/txcreatescript2.json | 2 +- test/util/data/txcreatescript4.json | 2 +- 12 files changed, 133 insertions(+), 22 deletions(-) create mode 100755 test/functional/wallet_scriptaddress2.py diff --git a/contrib/testgen/gen_base58_test_vectors.py b/contrib/testgen/gen_base58_test_vectors.py index 0d507738a..635c0a6be 100755 --- a/contrib/testgen/gen_base58_test_vectors.py +++ b/contrib/testgen/gen_base58_test_vectors.py @@ -20,8 +20,10 @@ from binascii import b2a_hex # key types PUBKEY_ADDRESS = 48 SCRIPT_ADDRESS = 5 +SCRIPT_ADDRESS2 = 50 PUBKEY_ADDRESS_TEST = 111 SCRIPT_ADDRESS_TEST = 196 +SCRIPT_ADDRESS_TEST2 = 58 PRIVKEY = 176 PRIVKEY_TEST = 239 @@ -32,8 +34,10 @@ templates = [ # None = N/A ((PUBKEY_ADDRESS,), 20, (), (False, False, 'pubkey', None)), ((SCRIPT_ADDRESS,), 20, (), (False, False, 'script', None)), + ((SCRIPT_ADDRESS2,), 20, (), (False, False, 'script', None)), ((PUBKEY_ADDRESS_TEST,), 20, (), (False, True, 'pubkey', None)), ((SCRIPT_ADDRESS_TEST,), 20, (), (False, True, 'script', None)), + ((SCRIPT_ADDRESS_TEST2,), 20, (), (False, True, 'script', None)), ((PRIVKEY,), 32, (), (True, False, None, False)), ((PRIVKEY,), 32, (1,), (True, False, None, True)), ((PRIVKEY_TEST,), 32, (), (True, True, None, False)), diff --git a/src/base58.cpp b/src/base58.cpp index 499afbe38..ef5abc834 100644 --- a/src/base58.cpp +++ b/src/base58.cpp @@ -232,7 +232,7 @@ public: std::string operator()(const CScriptID& id) const { - std::vector data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS); + std::vector data = m_params.Base58Prefix(CChainParams::SCRIPT_ADDRESS2); data.insert(data.end(), id.begin(), id.end()); return EncodeBase58Check(data); } @@ -277,13 +277,21 @@ CTxDestination DecodeDestination(const std::string& str, const CChainParams& par std::copy(data.begin() + pubkey_prefix.size(), data.end(), hash.begin()); return CKeyID(hash); } - // Script-hash-addresses have version 5 (or 196 testnet). + // Script-hash-addresses have version 5 for 3 prefix (or 196 testnet). // The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script. const std::vector& script_prefix = params.Base58Prefix(CChainParams::SCRIPT_ADDRESS); if (data.size() == hash.size() + script_prefix.size() && std::equal(script_prefix.begin(), script_prefix.end(), data.begin())) { std::copy(data.begin() + script_prefix.size(), data.end(), hash.begin()); return CScriptID(hash); } + + // Script-hash-addresses have version 5 for M prefix (or 196 testnet). + // The data vector contains RIPEMD160(SHA256(cscript)), where cscript is the serialized redemption script. + const std::vector& script_prefix2 = params.Base58Prefix(CChainParams::SCRIPT_ADDRESS2); + if (data.size() == hash.size() + script_prefix2.size() && std::equal(script_prefix2.begin(), script_prefix2.end(), data.begin())) { + std::copy(data.begin() + script_prefix2.size(), data.end(), hash.begin()); + return CScriptID(hash); + } } data.clear(); auto bech = bech32::Decode(str); diff --git a/src/test/data/base58_keys_valid.json b/src/test/data/base58_keys_valid.json index 3978dd7ea..4656f8f09 100644 --- a/src/test/data/base58_keys_valid.json +++ b/src/test/data/base58_keys_valid.json @@ -8,7 +8,7 @@ } ], [ - "37cTNRYxg6TKK31B5d1Xf2cvYwSv7AF7fR", + "MDpbgJxvdDJk7YH5BVzsUfsKse3N9YCE3o", "a91440f3ea941f260592f9c9433f0250dfe7e5fb128e87", { "isPrivkey": false, @@ -32,7 +32,7 @@ } ], [ - "2NCfHYPmkXdYQub31jnGCH48SN2Ew4KKfzE", + "Qg23fQdzYjbW3mo4MtJDMkZsWQgm3kVemM", "a914d4f756e1a19ede4011f5839e309da0c43fbee4e887", { "isPrivkey": false, @@ -102,7 +102,7 @@ } ], [ - "3AejjPrJLpUf83mkWL1HXbMNTYjAFWfowj", + "MGrt3HGGHwL5vZ3ecCzdMEbmnFKcE9EeJW", "a914624ac89642e04d39ce36976e861a022742cc127a87", { "isPrivkey": false, @@ -118,7 +118,7 @@ } ], [ - "2NAMtME59NepzTTip2onh56JHaTYzXR7QTH", + "QdieUEwPPkt5beUreupi9njiiqzpPqTKWP", "a914bbbca803acbbe7a2153f0cac05491b624c72426b87", { "isPrivkey": false, @@ -170,7 +170,7 @@ } ], [ - "3DhmeSnrhxFeeH6Ci2iKf8XpDuLXJRMQre", + "MKuuxLCpf575SnN6ouhfUmnDYbvyDTQBet", "a91483c601cee58d9324d8797e04c360971a7222a25387", { "isPrivkey": false, @@ -186,7 +186,7 @@ } ], [ - "2N75C1JVmQgdzwq7ovUqoW8aWZ1wodNCy84", + "QaRx8KN1Rnh661srYaspaq1whQPdUpq4pF", "a91497abf24db1094d659b319fafbdb5995ffc6e5ff487", { "isPrivkey": false, @@ -238,7 +238,7 @@ } ], [ - "3JeorZ28ejxcnfB5ideySCCnvuKrRMSrRD", + "MQrxASS6brp3bASypWeKFqTCFbvJLcwQPE", "a914ba0f3b5ba0efb58cda3e55f13b18462c971e6df987", { "isPrivkey": false, @@ -254,7 +254,7 @@ } ], [ - "2MwSJjJUSxjh6C57PcQDqbVWR8mCSsbhfG9", + "QQo4rKLgyqkBLFsSEWFrgBwrH9eGhmcfbT", "a9142df90970f496d9e6e165a69dacd1417f082c5cf587", { "isPrivkey": false, @@ -315,7 +315,7 @@ } ], [ - "3JDygZLWw2YBo7RhhJFQrVsGnsDHMghUTJ", + "MQS7zSkUt9PcbchboBEkg97g7ZojRxoXPW", "a914b55d095bc6c28b86d87b313442aa3ee454e49cce87", { "isPrivkey": false, @@ -331,7 +331,7 @@ } ], [ - "2N1ihb5sKJAM9y2McELzcg7p6Wf2rj9sedy", + "QV5Ti6jZKGQF7D7erT2dkpFXf3UgfKAw9h", "a9145cf346cd43ff078ca1d8dc62e39207470e2a496b87", { "isPrivkey": false, @@ -383,7 +383,7 @@ } ], [ - "31jGHN3LcY7TwWKqVdcfnPGH44aH3KraGB", + "M7wQbFTJZextk1bjbWc1c2WgNmAj41meXv", "a914006cd1745e13749236c7064614d93d4650a79e4887", { "isPrivkey": false, @@ -399,7 +399,7 @@ } ], [ - "2NAsiEa8cV97iyHhtfavP4t4TUqyEfT4vWf", + "QeEUMazrWFAp7UTwHgxQ9aVtdER4e4E9aY", "a914c160b11a8a042e801487f9f0c13be0246adff58687", { "isPrivkey": false, @@ -451,7 +451,7 @@ } ], [ - "31owTMbdP5CGappffhFA1unRVCsdpwKuWF", + "M825mF1bLC3hPL6ZmaEVqZ2pouU5iRE72D", "a914014f2e7072e9907c7f636d937759b8ceb1053feb87", { "isPrivkey": false, diff --git a/test/functional/test_framework/address.py b/test/functional/test_framework/address.py index e094346a5..2f1bfb30e 100644 --- a/test/functional/test_framework/address.py +++ b/test/functional/test_framework/address.py @@ -35,7 +35,7 @@ def keyhash_to_p2pkh(hash, main = False): def scripthash_to_p2sh(hash, main = False): assert (len(hash) == 20) - version = 5 if main else 196 + version = 5 if main else 58 return byte_to_base58(hash, version) def key_to_p2pkh(key, main = False): diff --git a/test/functional/test_runner.py b/test/functional/test_runner.py index 8f7beb9e2..9bae23844 100755 --- a/test/functional/test_runner.py +++ b/test/functional/test_runner.py @@ -122,6 +122,7 @@ BASE_SCRIPTS= [ 'wallet_listsinceblock.py', 'p2p_leak.py', 'wallet_encryption.py', + 'wallet_scriptaddress2.py', 'feature_dersig.py', 'feature_cltv.py', 'rpc_uptime.py', diff --git a/test/functional/wallet_scriptaddress2.py b/test/functional/wallet_scriptaddress2.py new file mode 100755 index 000000000..89a0ab7ea --- /dev/null +++ b/test/functional/wallet_scriptaddress2.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python3 +# Copyright (c) 2015-2016 The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or http://www.opensource.org/licenses/mit-license.php. + +# +# Test new Litecoin multisig prefix functionality. +# + +from test_framework.test_framework import BitcoinTestFramework +from test_framework.util import * +import decimal + +class ScriptAddress2Test(BitcoinTestFramework): + def set_test_params(self): + self.num_nodes = 3 + self.setup_clean_chain = False + self.extra_args = [['-addresstype=legacy'], [], []] + + def setup_network(self, split=False): + self.setup_nodes() + connect_nodes(self.nodes[1], 0) + connect_nodes(self.nodes[2], 0) + self.sync_all() + + def run_test(self): + cnt = self.nodes[0].getblockcount() + + # Mine some blocks + self.nodes[1].generate(101) + self.sync_all() + if (self.nodes[0].getblockcount() != cnt + 101): + raise AssertionError("Failed to mine 100 blocks") + + addr = self.nodes[0].getnewaddress() + addr2 = self.nodes[0].getnewaddress() + + multisig_addr = self.nodes[0].addmultisigaddress(2, [addr, addr2], "multisigaccount")['address'] + assert_equal(multisig_addr[0], 'Q') + + # Send to a new multisig address + txid = self.nodes[1].sendtoaddress(multisig_addr, 1) + block = self.nodes[1].generate(3) + self.sync_all() + tx = self.nodes[2].getrawtransaction(txid, 1) + dest_addrs = [tx["vout"][0]['scriptPubKey']['addresses'][0], + tx["vout"][1]['scriptPubKey']['addresses'][0]] + assert(multisig_addr in dest_addrs) + + # Spend from the new multisig address + addr3 = self.nodes[1].getnewaddress() + txid = self.nodes[0].sendfrom("multisigaccount", addr3, 0.8) + block = self.nodes[0].generate(2) + self.sync_all() + assert(self.nodes[0].getbalance("multisigaccount", 1) < 0.2) + assert(self.nodes[1].listtransactions()[-1]['address'] == addr3) + + # Send to an old multisig address. The api addmultisigaddress + # can only generate a new address so we manually compute + # multisig_addr_old beforehand using an old client. + priv_keys = ["cU7eeLPKzXeKMeZvnEJhvZZ3tLqVF3XGeo1BbM8dnbmV7pP3Qg89", + "cTw7mRhSvTfzqCt6MFgBoTBqwBpYu2rWugisXcwjv4cAASh3iqPt"] + + addrs = ["mj6gNGRXPXrD69R5ApjcsDerZGrYKSfb6v", + "mqET4JA3L7P7FoUjUP3F6m6YsLpCkyzzou"] + + self.nodes[0].importprivkey(priv_keys[0]) + self.nodes[0].importprivkey(priv_keys[1]) + + multisig_addr_new = self.nodes[0].addmultisigaddress(2, addrs, "multisigaccount2")['address'] + assert_equal(multisig_addr_new, 'QZ974ZrPrmqMmm1PSVp4m8YEgo3bCQZBbe') + multisig_addr_old = "2N5nLwYz9qfnGdaFLpPn3gS6oYQbmLTWPjq" + + ## Let's send to the old address. We can then find it in the + ## new address with the new client. So basically the old + ## address and the new one are the same thing. + txid = self.nodes[1].sendtoaddress(multisig_addr_old, 1) + block = self.nodes[1].generate(1) + self.sync_all() + tx = self.nodes[2].getrawtransaction(txid, 1) + dest_addrs = [tx["vout"][0]['scriptPubKey']['addresses'][0], + tx["vout"][1]['scriptPubKey']['addresses'][0]] + + assert(multisig_addr_new in dest_addrs) + assert(multisig_addr_old not in dest_addrs) + + # Spend from the new multisig address + addr4 = self.nodes[1].getnewaddress() + txid = self.nodes[0].sendfrom("multisigaccount2", addr4, 0.8) + block = self.nodes[0].generate(2) + self.sync_all() + assert(self.nodes[0].getbalance("multisigaccount2", 1) < 0.2) + assert(self.nodes[1].listtransactions()[-1]['address'] == addr4) + + + +if __name__ == '__main__': + ScriptAddress2Test().main() \ No newline at end of file diff --git a/test/util/data/txcreatemultisig2.json b/test/util/data/txcreatemultisig2.json index 7d94ce739..aece99739 100644 --- a/test/util/data/txcreatemultisig2.json +++ b/test/util/data/txcreatemultisig2.json @@ -17,7 +17,7 @@ "reqSigs": 1, "type": "scripthash", "addresses": [ - "34HNh57oBCRKkxNyjTuWAJkTbuGh6jg2Ms" + "MAVWzxXm8KGkZTesqLtqywzrvbs96FEoKy" ] } } diff --git a/test/util/data/txcreatemultisig4.json b/test/util/data/txcreatemultisig4.json index 9a5d2f4a0..93963f1aa 100644 --- a/test/util/data/txcreatemultisig4.json +++ b/test/util/data/txcreatemultisig4.json @@ -17,7 +17,7 @@ "reqSigs": 1, "type": "scripthash", "addresses": [ - "3BoFUz1StqcNcgUTZE5cC1eFhuYFzj3fGH" + "MJ1PnsRQqxToRBkMf74x1etf2c8i2imj3Y" ] } } diff --git a/test/util/data/txcreatemultisig5.json b/test/util/data/txcreatemultisig5.json index 20e9bb077..dd6a0ba28 100644 --- a/test/util/data/txcreatemultisig5.json +++ b/test/util/data/txcreatemultisig5.json @@ -17,7 +17,7 @@ "reqSigs": 1, "type": "scripthash", "addresses": [ - "3GeGs1eHUxPz5YyuFe9WPpXid2UsUb5Jos" + "MNrRAu4FS5FQt4FoMX8rDTn7wj5KUunnGr" ] } } diff --git a/test/util/data/txcreateoutpubkey3.json b/test/util/data/txcreateoutpubkey3.json index 0a5d489e1..fb56ab401 100644 --- a/test/util/data/txcreateoutpubkey3.json +++ b/test/util/data/txcreateoutpubkey3.json @@ -17,7 +17,7 @@ "reqSigs": 1, "type": "scripthash", "addresses": [ - "3GnzN8FqgvYGYdhj8NW6UNxxVv3Uj1ApQn" + "MP18g1foe3PhM8ydEFVSJ2DMpcdvhLebXR" ] } } diff --git a/test/util/data/txcreatescript2.json b/test/util/data/txcreatescript2.json index 94b669ffb..1c7ccc2d2 100644 --- a/test/util/data/txcreatescript2.json +++ b/test/util/data/txcreatescript2.json @@ -17,7 +17,7 @@ "reqSigs": 1, "type": "scripthash", "addresses": [ - "3C5QarEGh9feKbDJ3QbMf2YNjnMoiPDhNp" + "MJHYtjeEeGX586VC9HahUfnn4UxFmqozk8" ] } } diff --git a/test/util/data/txcreatescript4.json b/test/util/data/txcreatescript4.json index eecdf858b..e6ea4a9d2 100644 --- a/test/util/data/txcreatescript4.json +++ b/test/util/data/txcreatescript4.json @@ -17,7 +17,7 @@ "reqSigs": 1, "type": "scripthash", "addresses": [ - "3BNQbeFeJJGMAyDxPwWPuqxPMrjsFLjk3f" + "MHaYuXfcFR7myUVrVpVjjVCngZLKDuRbn3" ] } }