Skip to content

Commit a737735

Browse files
wangxinxithrasher-
authored andcommitted
Litecoin: M prefix added for script addresses
1 parent cc5e7b8 commit a737735

File tree

5 files changed

+121
-12
lines changed

5 files changed

+121
-12
lines changed

src/base58.cpp

+20-9
Original file line numberDiff line numberDiff line change
@@ -216,12 +216,18 @@ class CBitcoinAddressVisitor : public boost::static_visitor<bool>
216216
{
217217
private:
218218
CBitcoinAddress* addr;
219+
CChainParams::Base58Type script_type_;
219220

220221
public:
221-
CBitcoinAddressVisitor(CBitcoinAddress* addrIn) : addr(addrIn) {}
222+
CBitcoinAddressVisitor(CBitcoinAddress* addrIn, CChainParams::Base58Type script_type)
223+
: addr(addrIn), script_type_(script_type)
224+
{
225+
assert(script_type == CChainParams::SCRIPT_ADDRESS ||
226+
script_type == CChainParams::SCRIPT_ADDRESS2);
227+
}
222228

223229
bool operator()(const CKeyID& id) const { return addr->Set(id); }
224-
bool operator()(const CScriptID& id) const { return addr->Set(id); }
230+
bool operator()(const CScriptID& id) const { return addr->Set(id, script_type_); }
225231
bool operator()(const CNoDestination& no) const { return false; }
226232
};
227233

@@ -233,15 +239,17 @@ bool CBitcoinAddress::Set(const CKeyID& id)
233239
return true;
234240
}
235241

236-
bool CBitcoinAddress::Set(const CScriptID& id)
242+
bool CBitcoinAddress::Set(const CScriptID& id, CChainParams::Base58Type type)
237243
{
238-
SetData(Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS), &id, 20);
244+
assert(type == CChainParams::SCRIPT_ADDRESS || type == CChainParams::SCRIPT_ADDRESS2);
245+
SetData(Params().Base58Prefix(type), &id, 20);
239246
return true;
240247
}
241248

242-
bool CBitcoinAddress::Set(const CTxDestination& dest)
249+
bool CBitcoinAddress::Set(const CTxDestination& dest, CChainParams::Base58Type type)
243250
{
244-
return boost::apply_visitor(CBitcoinAddressVisitor(this), dest);
251+
assert(type == CChainParams::SCRIPT_ADDRESS || type == CChainParams::SCRIPT_ADDRESS2);
252+
return boost::apply_visitor(CBitcoinAddressVisitor(this, type), dest);
245253
}
246254

247255
bool CBitcoinAddress::IsValid() const
@@ -253,7 +261,8 @@ bool CBitcoinAddress::IsValid(const CChainParams& params) const
253261
{
254262
bool fCorrectSize = vchData.size() == 20;
255263
bool fKnownVersion = vchVersion == params.Base58Prefix(CChainParams::PUBKEY_ADDRESS) ||
256-
vchVersion == params.Base58Prefix(CChainParams::SCRIPT_ADDRESS);
264+
vchVersion == params.Base58Prefix(CChainParams::SCRIPT_ADDRESS) ||
265+
vchVersion == params.Base58Prefix(CChainParams::SCRIPT_ADDRESS2);
257266
return fCorrectSize && fKnownVersion;
258267
}
259268

@@ -265,7 +274,8 @@ CTxDestination CBitcoinAddress::Get() const
265274
memcpy(&id, vchData.data(), 20);
266275
if (vchVersion == Params().Base58Prefix(CChainParams::PUBKEY_ADDRESS))
267276
return CKeyID(id);
268-
else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS))
277+
else if (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS) ||
278+
vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS2))
269279
return CScriptID(id);
270280
else
271281
return CNoDestination();
@@ -283,7 +293,8 @@ bool CBitcoinAddress::GetKeyID(CKeyID& keyID) const
283293

284294
bool CBitcoinAddress::IsScript() const
285295
{
286-
return IsValid() && vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS);
296+
return IsValid() && (vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS) ||
297+
vchVersion == Params().Base58Prefix(CChainParams::SCRIPT_ADDRESS2));
287298
}
288299

289300
void CBitcoinSecret::SetKey(const CKey& vchSecret)

src/base58.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,8 @@ class CBase58Data
104104
class CBitcoinAddress : public CBase58Data {
105105
public:
106106
bool Set(const CKeyID &id);
107-
bool Set(const CScriptID &id);
108-
bool Set(const CTxDestination &dest);
107+
bool Set(const CScriptID &id, CChainParams::Base58Type type=CChainParams::SCRIPT_ADDRESS2);
108+
bool Set(const CTxDestination &dest, CChainParams::Base58Type type=CChainParams::SCRIPT_ADDRESS2);
109109
bool IsValid() const;
110110
bool IsValid(const CChainParams &params) const;
111111

src/test/base58_tests.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ BOOST_AUTO_TEST_CASE(base58_keys_valid_gen)
227227
continue;
228228
}
229229
CBitcoinAddress addrOut;
230-
BOOST_CHECK_MESSAGE(addrOut.Set(dest), "encode dest: " + strTest);
230+
BOOST_CHECK_MESSAGE(addrOut.Set(dest, CChainParams::SCRIPT_ADDRESS), "encode dest: " + strTest);
231231
BOOST_CHECK_MESSAGE(addrOut.ToString() == exp_base58string, "mismatch: " + strTest);
232232
}
233233
}

test/functional/test_runner.py

+1
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@
106106
'invalidtxrequest.py',
107107
'p2p-versionbits-warning.py',
108108
'preciousblock.py',
109+
'test_script_address2.py',
109110
'importprunedfunds.py',
110111
'signmessages.py',
111112
'nulldummy.py',
+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) 2015-2016 The Bitcoin Core developers
3+
# Distributed under the MIT software license, see the accompanying
4+
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5+
6+
#
7+
# Test new Litecoin multisig prefix functionality.
8+
#
9+
10+
from test_framework.test_framework import BitcoinTestFramework
11+
from test_framework.util import *
12+
import decimal
13+
14+
class ScriptAddress2Test(BitcoinTestFramework):
15+
def __init__(self):
16+
super().__init__()
17+
self.num_nodes = 3
18+
self.setup_clean_chain = False
19+
20+
def setup_network(self):
21+
self.nodes = self.start_nodes(self.num_nodes, self.options.tmpdir)
22+
connect_nodes(self.nodes[1], 0)
23+
connect_nodes(self.nodes[2], 0)
24+
self.is_network_split = False
25+
self.sync_all()
26+
27+
def run_test(self):
28+
cnt = self.nodes[0].getblockcount()
29+
30+
# Mine some blocks
31+
self.nodes[1].generate(100)
32+
self.sync_all()
33+
if (self.nodes[0].getblockcount() != cnt + 100):
34+
raise AssertionError("Failed to mine 100 blocks")
35+
36+
addr = self.nodes[0].getnewaddress()
37+
addr2 = self.nodes[0].getnewaddress()
38+
multisig_addr = self.nodes[0].addmultisigaddress(2, [addr, addr2], "multisigaccount")
39+
assert_equal(multisig_addr[0], 'Q')
40+
41+
# Send to a new multisig address
42+
txid = self.nodes[1].sendtoaddress(multisig_addr, 1)
43+
block = self.nodes[1].generate(3)
44+
self.sync_all()
45+
tx = self.nodes[2].getrawtransaction(txid, 1)
46+
dest_addrs = [tx["vout"][0]['scriptPubKey']['addresses'][0],
47+
tx["vout"][1]['scriptPubKey']['addresses'][0]]
48+
assert(multisig_addr in dest_addrs)
49+
50+
# Spend from the new multisig address
51+
addr3 = self.nodes[1].getnewaddress()
52+
txid = self.nodes[0].sendfrom("multisigaccount", addr3, 0.8)
53+
block = self.nodes[0].generate(2)
54+
self.sync_all()
55+
assert(self.nodes[0].getbalance("multisigaccount", 1) < 0.2)
56+
assert(self.nodes[1].listtransactions()[-1]['address'] == addr3)
57+
58+
# Send to an old multisig address. The api addmultisigaddress
59+
# can only generate a new address so we manually compute
60+
# multisig_addr_old beforehand using an old client.
61+
priv_keys = ["cU7eeLPKzXeKMeZvnEJhvZZ3tLqVF3XGeo1BbM8dnbmV7pP3Qg89",
62+
"cTw7mRhSvTfzqCt6MFgBoTBqwBpYu2rWugisXcwjv4cAASh3iqPt"]
63+
64+
addrs = ["mj6gNGRXPXrD69R5ApjcsDerZGrYKSfb6v",
65+
"mqET4JA3L7P7FoUjUP3F6m6YsLpCkyzzou"]
66+
67+
self.nodes[0].importprivkey(priv_keys[0])
68+
self.nodes[0].importprivkey(priv_keys[1])
69+
70+
multisig_addr_new = self.nodes[0].addmultisigaddress(2, addrs, "multisigaccount2")
71+
assert_equal(multisig_addr_new, "QZ974ZrPrmqMmm1PSVp4m8YEgo3bCQZBbe")
72+
multisig_addr_old = "2N5nLwYz9qfnGdaFLpPn3gS6oYQbmLTWPjq"
73+
74+
## Let's send to the old address. We can then find it in the
75+
## new address with the new client. So basically the old
76+
## address and the new one are the same thing.
77+
txid = self.nodes[1].sendtoaddress(multisig_addr_old, 1)
78+
block = self.nodes[1].generate(1)
79+
self.sync_all()
80+
tx = self.nodes[2].getrawtransaction(txid, 1)
81+
dest_addrs = [tx["vout"][0]['scriptPubKey']['addresses'][0],
82+
tx["vout"][1]['scriptPubKey']['addresses'][0]]
83+
assert(multisig_addr_new in dest_addrs)
84+
assert(multisig_addr_old not in dest_addrs)
85+
86+
# Spend from the new multisig address
87+
addr4 = self.nodes[1].getnewaddress()
88+
txid = self.nodes[0].sendfrom("multisigaccount2", addr4, 0.8)
89+
block = self.nodes[0].generate(2)
90+
self.sync_all()
91+
assert(self.nodes[0].getbalance("multisigaccount2", 1) < 0.2)
92+
assert(self.nodes[1].listtransactions()[-1]['address'] == addr4)
93+
94+
95+
96+
if __name__ == '__main__':
97+
ScriptAddress2Test().main()

0 commit comments

Comments
 (0)